docker_cli_registry_user_agent_test.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. package main
  2. import (
  3. "fmt"
  4. "net/http"
  5. "os"
  6. "regexp"
  7. "testing"
  8. "github.com/docker/docker/testutil/registry"
  9. "gotest.tools/v3/assert"
  10. )
  11. // unescapeBackslashSemicolonParens unescapes \;()
  12. func unescapeBackslashSemicolonParens(s string) string {
  13. re := regexp.MustCompile(`\\;`)
  14. ret := re.ReplaceAll([]byte(s), []byte(";"))
  15. re = regexp.MustCompile(`\\\(`)
  16. ret = re.ReplaceAll(ret, []byte("("))
  17. re = regexp.MustCompile(`\\\)`)
  18. ret = re.ReplaceAll(ret, []byte(")"))
  19. re = regexp.MustCompile(`\\\\`)
  20. ret = re.ReplaceAll(ret, []byte(`\`))
  21. return string(ret)
  22. }
  23. func regexpCheckUA(c *testing.T, ua string) {
  24. re := regexp.MustCompile("(?P<dockerUA>.+) UpstreamClient(?P<upstreamUA>.+)")
  25. substrArr := re.FindStringSubmatch(ua)
  26. assert.Equal(c, len(substrArr), 3, "Expected 'UpstreamClient()' with upstream client UA")
  27. dockerUA := substrArr[1]
  28. upstreamUAEscaped := substrArr[2]
  29. // check dockerUA looks correct
  30. reDockerUA := regexp.MustCompile("^docker/[0-9A-Za-z+]")
  31. bMatchDockerUA := reDockerUA.MatchString(dockerUA)
  32. assert.Assert(c, bMatchDockerUA, "Docker Engine User-Agent malformed")
  33. // check upstreamUA looks correct
  34. // Expecting something like: Docker-Client/1.11.0-dev (linux)
  35. upstreamUA := unescapeBackslashSemicolonParens(upstreamUAEscaped)
  36. reUpstreamUA := regexp.MustCompile(`^\(Docker-Client/[0-9A-Za-z+]`)
  37. bMatchUpstreamUA := reUpstreamUA.MatchString(upstreamUA)
  38. assert.Assert(c, bMatchUpstreamUA, "(Upstream) Docker Client User-Agent malformed")
  39. }
  40. // registerUserAgentHandler registers a handler for the `/v2/*` endpoint.
  41. // Note that a 404 is returned to prevent the client to proceed.
  42. // We are only checking if the client sent a valid User Agent string along
  43. // with the request.
  44. func registerUserAgentHandler(reg *registry.Mock, result *string) {
  45. reg.RegisterHandler("/v2/", func(w http.ResponseWriter, r *http.Request) {
  46. w.WriteHeader(404)
  47. w.Write([]byte(`{"errors":[{"code": "UNSUPPORTED","message": "this is a mock registry"}]}`))
  48. var ua string
  49. for k, v := range r.Header {
  50. if k == "User-Agent" {
  51. ua = v[0]
  52. }
  53. }
  54. *result = ua
  55. })
  56. }
  57. // TestUserAgentPassThrough verifies that when an image is pulled from
  58. // a registry, the registry should see a User-Agent string of the form
  59. // [docker engine UA] UpstreamClientSTREAM-CLIENT([client UA])
  60. func (s *DockerRegistrySuite) TestUserAgentPassThrough(c *testing.T) {
  61. var ua string
  62. reg, err := registry.NewMock(c)
  63. assert.NilError(c, err)
  64. defer reg.Close()
  65. registerUserAgentHandler(reg, &ua)
  66. repoName := fmt.Sprintf("%s/busybox", reg.URL())
  67. s.d.StartWithBusybox(c, "--insecure-registry", reg.URL())
  68. tmp, err := os.MkdirTemp("", "integration-cli-")
  69. assert.NilError(c, err)
  70. defer os.RemoveAll(tmp)
  71. dockerfile, err := makefile(tmp, fmt.Sprintf("FROM %s", repoName))
  72. assert.NilError(c, err, "Unable to create test dockerfile")
  73. s.d.Cmd("build", "--file", dockerfile, tmp)
  74. regexpCheckUA(c, ua)
  75. s.d.Cmd("login", "-u", "richard", "-p", "testtest", reg.URL())
  76. regexpCheckUA(c, ua)
  77. s.d.Cmd("pull", repoName)
  78. regexpCheckUA(c, ua)
  79. s.d.Cmd("tag", "busybox", repoName)
  80. s.d.Cmd("push", repoName)
  81. regexpCheckUA(c, ua)
  82. }