|
1 | 1 | package registry
|
2 | 2 |
|
3 | 3 | import (
|
| 4 | + "encoding/base64" |
| 5 | + "strings" |
4 | 6 | "testing"
|
5 | 7 |
|
6 | 8 | "gotest.tools/v3/assert"
|
| 9 | + is "gotest.tools/v3/assert/cmp" |
7 | 10 | )
|
8 | 11 |
|
9 |
| -const ( |
10 |
| - unencoded = `{"username":"testuser","password":"testpassword","serveraddress":"example.com"}` |
11 |
| - encoded = `eyJ1c2VybmFtZSI6InRlc3R1c2VyIiwicGFzc3dvcmQiOiJ0ZXN0cGFzc3dvcmQiLCJzZXJ2ZXJhZGRyZXNzIjoiZXhhbXBsZS5jb20ifQ==` |
12 |
| - encodedNoPadding = `eyJ1c2VybmFtZSI6InRlc3R1c2VyIiwicGFzc3dvcmQiOiJ0ZXN0cGFzc3dvcmQiLCJzZXJ2ZXJhZGRyZXNzIjoiZXhhbXBsZS5jb20ifQ` |
13 |
| -) |
| 12 | +func TestDecodeAuthConfig(t *testing.T) { |
| 13 | + tests := []struct { |
| 14 | + doc string |
| 15 | + input string |
| 16 | + inputBase64 string |
| 17 | + expected AuthConfig |
| 18 | + expectedErr string |
| 19 | + }{ |
| 20 | + { |
| 21 | + doc: "empty", |
| 22 | + input: ``, |
| 23 | + inputBase64: ``, |
| 24 | + expected: AuthConfig{}, |
| 25 | + }, |
| 26 | + { |
| 27 | + doc: "empty JSON", |
| 28 | + input: `{}`, |
| 29 | + inputBase64: `e30=`, |
| 30 | + expected: AuthConfig{}, |
| 31 | + }, |
| 32 | + { |
| 33 | + doc: "malformed JSON", |
| 34 | + input: `{`, |
| 35 | + inputBase64: `ew==`, |
| 36 | + expected: AuthConfig{}, |
| 37 | + expectedErr: `invalid X-Registry-Auth header: unexpected EOF`, |
| 38 | + }, |
| 39 | + { |
| 40 | + doc: "test authConfig", |
| 41 | + input: `{"username":"testuser","password":"testpassword","serveraddress":"example.com"}`, |
| 42 | + inputBase64: `eyJ1c2VybmFtZSI6InRlc3R1c2VyIiwicGFzc3dvcmQiOiJ0ZXN0cGFzc3dvcmQiLCJzZXJ2ZXJhZGRyZXNzIjoiZXhhbXBsZS5jb20ifQ==`, |
| 43 | + expected: AuthConfig{ |
| 44 | + Username: "testuser", |
| 45 | + Password: "testpassword", |
| 46 | + ServerAddress: "example.com", |
| 47 | + }, |
| 48 | + }, |
| 49 | + { |
| 50 | + // FIXME(thaJeztah): we should not accept multiple JSON documents. |
| 51 | + doc: "multiple authConfig", |
| 52 | + input: `{"username":"testuser","password":"testpassword","serveraddress":"example.com"}{"username":"testuser2","password":"testpassword2","serveraddress":"example.org"}`, |
| 53 | + inputBase64: `eyJ1c2VybmFtZSI6InRlc3R1c2VyIiwicGFzc3dvcmQiOiJ0ZXN0cGFzc3dvcmQiLCJzZXJ2ZXJhZGRyZXNzIjoiZXhhbXBsZS5jb20ifXsidXNlcm5hbWUiOiJ0ZXN0dXNlcjIiLCJwYXNzd29yZCI6InRlc3RwYXNzd29yZDIiLCJzZXJ2ZXJhZGRyZXNzIjoiZXhhbXBsZS5vcmcifQ==`, |
| 54 | + expected: AuthConfig{ |
| 55 | + Username: "testuser", |
| 56 | + Password: "testpassword", |
| 57 | + ServerAddress: "example.com", |
| 58 | + }, |
| 59 | + }, |
| 60 | + // We currently only support base64url encoding with padding, so |
| 61 | + // un-padded should produce an error. |
| 62 | + // |
| 63 | + // RFC4648, section 5: https://tools.ietf.org/html/rfc4648#section-5 |
| 64 | + // RFC4648, section 3.2: https://tools.ietf.org/html/rfc4648#section-3.2 |
| 65 | + { |
| 66 | + doc: "empty JSON no padding", |
| 67 | + input: `{}`, |
| 68 | + inputBase64: `e30`, |
| 69 | + expected: AuthConfig{}, |
| 70 | + expectedErr: `invalid X-Registry-Auth header: unexpected EOF`, |
| 71 | + }, |
| 72 | + { |
| 73 | + doc: "test authConfig", |
| 74 | + input: `{"username":"testuser","password":"testpassword","serveraddress":"example.com"}`, |
| 75 | + inputBase64: `eyJ1c2VybmFtZSI6InRlc3R1c2VyIiwicGFzc3dvcmQiOiJ0ZXN0cGFzc3dvcmQiLCJzZXJ2ZXJhZGRyZXNzIjoiZXhhbXBsZS5jb20ifQ`, |
| 76 | + expected: AuthConfig{}, |
| 77 | + expectedErr: `invalid X-Registry-Auth header: unexpected EOF`, |
| 78 | + }, |
| 79 | + } |
14 | 80 |
|
15 |
| -var expected = AuthConfig{ |
16 |
| - Username: "testuser", |
17 |
| - Password: "testpassword", |
18 |
| - ServerAddress: "example.com", |
19 |
| -} |
| 81 | + for _, tc := range tests { |
| 82 | + t.Run(tc.doc, func(t *testing.T) { |
| 83 | + // Sanity check to make sure our fixtures are correct. |
| 84 | + b64 := base64.URLEncoding.EncodeToString([]byte(tc.input)) |
| 85 | + if !strings.HasSuffix(tc.inputBase64, "=") { |
| 86 | + b64 = strings.TrimRight(b64, "=") |
| 87 | + } |
| 88 | + assert.Check(t, is.Equal(b64, tc.inputBase64)) |
20 | 89 |
|
21 |
| -func TestDecodeAuthConfig(t *testing.T) { |
22 |
| - t.Run("valid", func(t *testing.T) { |
23 |
| - token, err := DecodeAuthConfig(encoded) |
24 |
| - assert.NilError(t, err) |
25 |
| - assert.Equal(t, *token, expected) |
26 |
| - }) |
27 |
| - |
28 |
| - t.Run("empty", func(t *testing.T) { |
29 |
| - token, err := DecodeAuthConfig("") |
30 |
| - assert.NilError(t, err) |
31 |
| - assert.Equal(t, *token, AuthConfig{}) |
32 |
| - }) |
33 |
| - |
34 |
| - // We currently only support base64url encoding with padding, so |
35 |
| - // un-padded should produce an error. |
36 |
| - // |
37 |
| - // RFC4648, section 5: https://tools.ietf.org/html/rfc4648#section-5 |
38 |
| - // RFC4648, section 3.2: https://tools.ietf.org/html/rfc4648#section-3.2 |
39 |
| - t.Run("invalid encoding", func(t *testing.T) { |
40 |
| - token, err := DecodeAuthConfig(encodedNoPadding) |
41 |
| - |
42 |
| - assert.ErrorType(t, err, errInvalidParameter{}) |
43 |
| - assert.ErrorContains(t, err, "invalid X-Registry-Auth header: unexpected EOF") |
44 |
| - assert.Equal(t, *token, AuthConfig{}) |
45 |
| - }) |
| 90 | + out, err := DecodeAuthConfig(tc.inputBase64) |
| 91 | + if tc.expectedErr != "" { |
| 92 | + assert.Check(t, is.ErrorType(err, errInvalidParameter{})) |
| 93 | + assert.Check(t, is.Error(err, tc.expectedErr)) |
| 94 | + } else { |
| 95 | + assert.NilError(t, err) |
| 96 | + assert.Equal(t, *out, tc.expected) |
| 97 | + } |
| 98 | + }) |
| 99 | + } |
46 | 100 | }
|
47 | 101 |
|
48 | 102 | func TestEncodeAuthConfig(t *testing.T) {
|
49 |
| - token, err := EncodeAuthConfig(expected) |
50 |
| - assert.NilError(t, err) |
51 |
| - assert.Equal(t, token, encoded) |
| 103 | + tests := []struct { |
| 104 | + doc string |
| 105 | + input AuthConfig |
| 106 | + outBase64 string |
| 107 | + outPlain string |
| 108 | + }{ |
| 109 | + { |
| 110 | + doc: "empty", |
| 111 | + input: AuthConfig{}, |
| 112 | + outBase64: `e30=`, |
| 113 | + outPlain: `{}`, |
| 114 | + }, |
| 115 | + { |
| 116 | + doc: "test authConfig", |
| 117 | + input: AuthConfig{ |
| 118 | + Username: "testuser", |
| 119 | + Password: "testpassword", |
| 120 | + ServerAddress: "example.com", |
| 121 | + }, |
| 122 | + outBase64: `eyJ1c2VybmFtZSI6InRlc3R1c2VyIiwicGFzc3dvcmQiOiJ0ZXN0cGFzc3dvcmQiLCJzZXJ2ZXJhZGRyZXNzIjoiZXhhbXBsZS5jb20ifQ==`, |
| 123 | + outPlain: `{"username":"testuser","password":"testpassword","serveraddress":"example.com"}`, |
| 124 | + }, |
| 125 | + } |
| 126 | + for _, tc := range tests { |
| 127 | + // Sanity check to make sure our fixtures are correct. |
| 128 | + b64 := base64.URLEncoding.EncodeToString([]byte(tc.outPlain)) |
| 129 | + assert.Check(t, is.Equal(b64, tc.outBase64)) |
| 130 | + |
| 131 | + t.Run(tc.doc, func(t *testing.T) { |
| 132 | + out, err := EncodeAuthConfig(tc.input) |
| 133 | + assert.NilError(t, err) |
| 134 | + assert.Equal(t, out, tc.outBase64) |
| 135 | + |
| 136 | + authJSON, err := base64.URLEncoding.DecodeString(out) |
| 137 | + assert.NilError(t, err) |
| 138 | + assert.Equal(t, string(authJSON), tc.outPlain) |
| 139 | + }) |
| 140 | + } |
52 | 141 | }
|
0 commit comments