docker_cli_registry_user_agent_test.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package main
  2. import (
  3. "net/http"
  4. "os"
  5. "regexp"
  6. "testing"
  7. "github.com/docker/docker/testutil"
  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. ctx := testutil.GetContext(c)
  62. var ua string
  63. reg, err := registry.NewMock(c)
  64. assert.NilError(c, err)
  65. defer reg.Close()
  66. registerUserAgentHandler(reg, &ua)
  67. imgRepo := reg.URL() + "/busybox"
  68. s.d.StartWithBusybox(ctx, c, "--insecure-registry", reg.URL())
  69. tmp, err := os.MkdirTemp("", "integration-cli-")
  70. assert.NilError(c, err)
  71. defer os.RemoveAll(tmp)
  72. dockerfile, err := makefile(tmp, "FROM "+imgRepo)
  73. assert.NilError(c, err, "Unable to create test dockerfile")
  74. s.d.Cmd("build", "--file", dockerfile, tmp)
  75. regexpCheckUA(c, ua)
  76. s.d.Cmd("login", "-u", "richard", "-p", "testtest", reg.URL())
  77. regexpCheckUA(c, ua)
  78. s.d.Cmd("pull", imgRepo)
  79. regexpCheckUA(c, ua)
  80. s.d.Cmd("tag", "busybox", imgRepo)
  81. s.d.Cmd("push", imgRepo)
  82. regexpCheckUA(c, ua)
  83. }