config_test.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /*
  2. Copyright 2014 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package credentialprovider
  14. import (
  15. "encoding/base64"
  16. "encoding/json"
  17. "io/ioutil"
  18. "os"
  19. "path/filepath"
  20. "reflect"
  21. "testing"
  22. )
  23. func TestReadDockerConfigFile(t *testing.T) {
  24. configJsonFileName := "config.json"
  25. var fileInfo *os.File
  26. //test dockerconfig json
  27. inputDockerconfigJsonFile := "{ \"auths\": { \"http://foo.example.com\":{\"auth\":\"Zm9vOmJhcgo=\",\"email\":\"foo@example.com\"}}}"
  28. preferredPath, err := ioutil.TempDir("", "test_foo_bar_dockerconfigjson_")
  29. if err != nil {
  30. t.Fatalf("Creating tmp dir fail: %v", err)
  31. return
  32. }
  33. defer os.RemoveAll(preferredPath)
  34. absDockerConfigFileLocation, err := filepath.Abs(filepath.Join(preferredPath, configJsonFileName))
  35. if err != nil {
  36. t.Fatalf("While trying to canonicalize %s: %v", preferredPath, err)
  37. }
  38. if _, err := os.Stat(absDockerConfigFileLocation); os.IsNotExist(err) {
  39. //create test cfg file
  40. fileInfo, err = os.OpenFile(absDockerConfigFileLocation, os.O_CREATE|os.O_RDWR, 0664)
  41. if err != nil {
  42. t.Fatalf("While trying to create file %s: %v", absDockerConfigFileLocation, err)
  43. }
  44. defer fileInfo.Close()
  45. }
  46. fileInfo.WriteString(inputDockerconfigJsonFile)
  47. orgPreferredPath := GetPreferredDockercfgPath()
  48. SetPreferredDockercfgPath(preferredPath)
  49. defer SetPreferredDockercfgPath(orgPreferredPath)
  50. if _, err := ReadDockerConfigFile(); err != nil {
  51. t.Errorf("Getting docker config file fail : %v preferredPath : %q", err, preferredPath)
  52. }
  53. }
  54. func TestDockerConfigJsonJSONDecode(t *testing.T) {
  55. // Fake values for testing.
  56. input := []byte(`{"auths": {"http://foo.example.com":{"username": "foo", "password": "bar", "email": "foo@example.com"}, "http://bar.example.com":{"username": "bar", "password": "baz", "email": "bar@example.com"}}}`)
  57. expect := DockerConfigJson{
  58. Auths: DockerConfig(map[string]DockerConfigEntry{
  59. "http://foo.example.com": {
  60. Username: "foo",
  61. Password: "bar",
  62. Email: "foo@example.com",
  63. },
  64. "http://bar.example.com": {
  65. Username: "bar",
  66. Password: "baz",
  67. Email: "bar@example.com",
  68. },
  69. }),
  70. }
  71. var output DockerConfigJson
  72. err := json.Unmarshal(input, &output)
  73. if err != nil {
  74. t.Errorf("Received unexpected error: %v", err)
  75. }
  76. if !reflect.DeepEqual(expect, output) {
  77. t.Errorf("Received unexpected output. Expected %#v, got %#v", expect, output)
  78. }
  79. }
  80. func TestDockerConfigJSONDecode(t *testing.T) {
  81. // Fake values for testing.
  82. input := []byte(`{"http://foo.example.com":{"username": "foo", "password": "bar", "email": "foo@example.com"}, "http://bar.example.com":{"username": "bar", "password": "baz", "email": "bar@example.com"}}`)
  83. expect := DockerConfig(map[string]DockerConfigEntry{
  84. "http://foo.example.com": {
  85. Username: "foo",
  86. Password: "bar",
  87. Email: "foo@example.com",
  88. },
  89. "http://bar.example.com": {
  90. Username: "bar",
  91. Password: "baz",
  92. Email: "bar@example.com",
  93. },
  94. })
  95. var output DockerConfig
  96. err := json.Unmarshal(input, &output)
  97. if err != nil {
  98. t.Errorf("Received unexpected error: %v", err)
  99. }
  100. if !reflect.DeepEqual(expect, output) {
  101. t.Errorf("Received unexpected output. Expected %#v, got %#v", expect, output)
  102. }
  103. }
  104. func TestDockerConfigEntryJSONDecode(t *testing.T) {
  105. tests := []struct {
  106. input []byte
  107. expect DockerConfigEntry
  108. fail bool
  109. }{
  110. // simple case, just decode the fields
  111. {
  112. // Fake values for testing.
  113. input: []byte(`{"username": "foo", "password": "bar", "email": "foo@example.com"}`),
  114. expect: DockerConfigEntry{
  115. Username: "foo",
  116. Password: "bar",
  117. Email: "foo@example.com",
  118. },
  119. fail: false,
  120. },
  121. // auth field decodes to username & password
  122. {
  123. input: []byte(`{"auth": "Zm9vOmJhcg==", "email": "foo@example.com"}`),
  124. expect: DockerConfigEntry{
  125. Username: "foo",
  126. Password: "bar",
  127. Email: "foo@example.com",
  128. },
  129. fail: false,
  130. },
  131. // auth field overrides username & password
  132. {
  133. // Fake values for testing.
  134. input: []byte(`{"username": "foo", "password": "bar", "auth": "cGluZzpwb25n", "email": "foo@example.com"}`),
  135. expect: DockerConfigEntry{
  136. Username: "ping",
  137. Password: "pong",
  138. Email: "foo@example.com",
  139. },
  140. fail: false,
  141. },
  142. // poorly-formatted auth causes failure
  143. {
  144. input: []byte(`{"auth": "pants", "email": "foo@example.com"}`),
  145. expect: DockerConfigEntry{
  146. Username: "",
  147. Password: "",
  148. Email: "foo@example.com",
  149. },
  150. fail: true,
  151. },
  152. // invalid JSON causes failure
  153. {
  154. input: []byte(`{"email": false}`),
  155. expect: DockerConfigEntry{
  156. Username: "",
  157. Password: "",
  158. Email: "",
  159. },
  160. fail: true,
  161. },
  162. }
  163. for i, tt := range tests {
  164. var output DockerConfigEntry
  165. err := json.Unmarshal(tt.input, &output)
  166. if (err != nil) != tt.fail {
  167. t.Errorf("case %d: expected fail=%t, got err=%v", i, tt.fail, err)
  168. }
  169. if !reflect.DeepEqual(tt.expect, output) {
  170. t.Errorf("case %d: expected output %#v, got %#v", i, tt.expect, output)
  171. }
  172. }
  173. }
  174. func TestDecodeDockerConfigFieldAuth(t *testing.T) {
  175. tests := []struct {
  176. input string
  177. username string
  178. password string
  179. fail bool
  180. }{
  181. // auth field decodes to username & password
  182. {
  183. input: "Zm9vOmJhcg==",
  184. username: "foo",
  185. password: "bar",
  186. },
  187. // some test as before but with field not well padded
  188. {
  189. input: "Zm9vOmJhcg",
  190. username: "foo",
  191. password: "bar",
  192. },
  193. // some test as before but with new line characters
  194. {
  195. input: "Zm9vOm\nJhcg==\n",
  196. username: "foo",
  197. password: "bar",
  198. },
  199. // standard encoding (with padding)
  200. {
  201. input: base64.StdEncoding.EncodeToString([]byte("foo:bar")),
  202. username: "foo",
  203. password: "bar",
  204. },
  205. // raw encoding (without padding)
  206. {
  207. input: base64.RawStdEncoding.EncodeToString([]byte("foo:bar")),
  208. username: "foo",
  209. password: "bar",
  210. },
  211. // the input is encoded with encodeDockerConfigFieldAuth (standard encoding)
  212. {
  213. input: encodeDockerConfigFieldAuth("foo", "bar"),
  214. username: "foo",
  215. password: "bar",
  216. },
  217. // good base64 data, but no colon separating username & password
  218. {
  219. input: "cGFudHM=",
  220. fail: true,
  221. },
  222. // only new line characters are ignored
  223. {
  224. input: "Zm9vOmJhcg== ",
  225. fail: true,
  226. },
  227. // bad base64 data
  228. {
  229. input: "pants",
  230. fail: true,
  231. },
  232. }
  233. for i, tt := range tests {
  234. username, password, err := decodeDockerConfigFieldAuth(tt.input)
  235. if (err != nil) != tt.fail {
  236. t.Errorf("case %d: expected fail=%t, got err=%v", i, tt.fail, err)
  237. }
  238. if tt.username != username {
  239. t.Errorf("case %d: expected username %q, got %q", i, tt.username, username)
  240. }
  241. if tt.password != password {
  242. t.Errorf("case %d: expected password %q, got %q", i, tt.password, password)
  243. }
  244. }
  245. }
  246. func TestDockerConfigEntryJSONCompatibleEncode(t *testing.T) {
  247. tests := []struct {
  248. input DockerConfigEntry
  249. expect []byte
  250. }{
  251. // simple case, just decode the fields
  252. {
  253. // Fake values for testing.
  254. expect: []byte(`{"username":"foo","password":"bar","email":"foo@example.com","auth":"Zm9vOmJhcg=="}`),
  255. input: DockerConfigEntry{
  256. Username: "foo",
  257. Password: "bar",
  258. Email: "foo@example.com",
  259. },
  260. },
  261. }
  262. for i, tt := range tests {
  263. actual, err := json.Marshal(tt.input)
  264. if err != nil {
  265. t.Errorf("case %d: unexpected error: %v", i, err)
  266. }
  267. if string(tt.expect) != string(actual) {
  268. t.Errorf("case %d: expected %v, got %v", i, string(tt.expect), string(actual))
  269. }
  270. }
  271. }