docker_cli_registry_user_agent_test.go 3.1 KB

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