github.com/rkt/rkt@v1.30.1-0.20200224141603-171c416fac02/tests/rkt_auth_test.go (about) 1 // Copyright 2015 The rkt Authors 2 // 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 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // +build host coreos src kvm 16 17 package main 18 19 import ( 20 "fmt" 21 "os" 22 "path/filepath" 23 "strings" 24 "testing" 25 26 "github.com/rkt/rkt/tests/testutils" 27 taas "github.com/rkt/rkt/tests/testutils/aci-server" 28 ) 29 30 func TestAuthSanity(t *testing.T) { 31 ctx := testutils.NewRktRunCtx() 32 defer ctx.Cleanup() 33 server, image := runAuthServer(t, taas.AuthNone) 34 defer authCleanup(server, image) 35 expectedRunRkt(ctx, t, server.URL, "sanity", authSuccessfulDownload) 36 } 37 38 const ( 39 // It cannot have any spaces, because of an actool limitation 40 // - if we pass an `--exec=/inspect 41 // --print-msg='Authentication succeeded.'` string to actool 42 // it will split the --exec value by spaces, disregarding the 43 // single quotes around "Authentication succeeded.". The 44 // result is that /inspect receives two parameters - 45 // "--print-msg='Authentication" and "succeeded.'" 46 authSuccessfulDownload = "AuthenticationSucceeded." 47 authFailedDownload = "bad HTTP status code: 401" 48 authACIName = "rkt-inspect-auth-test.aci" 49 ) 50 51 type authConfDir int 52 53 const ( 54 authConfDirNone authConfDir = iota 55 authConfDirLocal 56 authConfDirSystem 57 ) 58 59 type genericAuthTest struct { 60 name string 61 confDir authConfDir 62 expectedLine string 63 } 64 65 func TestAuthBasic(t *testing.T) { 66 tests := []genericAuthTest{ 67 {"basic-no-config", authConfDirNone, authFailedDownload}, 68 {"basic-local-config", authConfDirLocal, authSuccessfulDownload}, 69 {"basic-system-config", authConfDirSystem, authSuccessfulDownload}, 70 } 71 testAuthGeneric(t, taas.AuthBasic, tests) 72 } 73 74 func TestAuthOauth(t *testing.T) { 75 tests := []genericAuthTest{ 76 {"oauth-no-config", authConfDirNone, authFailedDownload}, 77 {"oauth-local-config", authConfDirLocal, authSuccessfulDownload}, 78 {"oauth-system-config", authConfDirSystem, authSuccessfulDownload}, 79 } 80 testAuthGeneric(t, taas.AuthOauth, tests) 81 } 82 83 func testAuthGeneric(t *testing.T, auth taas.AuthType, tests []genericAuthTest) { 84 server, image := runAuthServer(t, auth) 85 defer authCleanup(server, image) 86 ctx := testutils.NewRktRunCtx() 87 defer ctx.Cleanup() 88 for _, tt := range tests { 89 switch tt.confDir { 90 case authConfDirNone: 91 // no config to write 92 case authConfDirLocal: 93 writeConfig(t, authDir(ctx.LocalDir()), "test.json", server.Conf) 94 case authConfDirSystem: 95 writeConfig(t, authDir(ctx.SystemDir()), "test.json", server.Conf) 96 default: 97 panic("Wrong config directory") 98 } 99 expectedRunRkt(ctx, t, server.URL, tt.name, tt.expectedLine) 100 ctx.Reset() 101 } 102 } 103 104 func TestAuthOverride(t *testing.T) { 105 ctx := testutils.NewRktRunCtx() 106 defer ctx.Cleanup() 107 server, image := runAuthServer(t, taas.AuthOauth) 108 defer authCleanup(server, image) 109 hash := "sha512-" + getHashOrPanic(image) 110 tests := []struct { 111 systemConfig string 112 localConfig string 113 name string 114 resultBeforeOverride string 115 resultAfterOverride string 116 }{ 117 {server.Conf, getInvalidOAuthConfig(server.Conf), "valid-system-invalid-local", authSuccessfulDownload, authFailedDownload}, 118 {getInvalidOAuthConfig(server.Conf), server.Conf, "invalid-system-valid-local", authFailedDownload, authSuccessfulDownload}, 119 } 120 for _, tt := range tests { 121 writeConfig(t, authDir(ctx.SystemDir()), "test.json", tt.systemConfig) 122 expectedRunRkt(ctx, t, server.URL, tt.name+"-1", tt.resultBeforeOverride) 123 if tt.resultBeforeOverride == authSuccessfulDownload { 124 // Remove the image from the store since it was fetched in the 125 // previous run and the test aci-server returns a 126 // Cache-Control max-age header 127 removeFromCas(t, ctx, hash) 128 } 129 writeConfig(t, authDir(ctx.LocalDir()), "test.json", tt.localConfig) 130 expectedRunRkt(ctx, t, server.URL, tt.name+"-2", tt.resultAfterOverride) 131 ctx.Reset() 132 } 133 } 134 135 func TestAuthIgnore(t *testing.T) { 136 server, image := runAuthServer(t, taas.AuthOauth) 137 defer authCleanup(server, image) 138 testAuthIgnoreBogusFiles(t, server) 139 testAuthIgnoreSubdirectories(t, server) 140 } 141 142 func testAuthIgnoreBogusFiles(t *testing.T, server *taas.Server) { 143 ctx := testutils.NewRktRunCtx() 144 defer ctx.Cleanup() 145 writeConfig(t, authDir(ctx.SystemDir()), "README", "This is system config") 146 writeConfig(t, authDir(ctx.LocalDir()), "README", "This is local config") 147 writeConfig(t, authDir(ctx.SystemDir()), "test.notjson", server.Conf) 148 writeConfig(t, authDir(ctx.LocalDir()), "test.notjson", server.Conf) 149 expectedRunRkt(ctx, t, server.URL, "oauth-bogus-files", authFailedDownload) 150 } 151 152 func testAuthIgnoreSubdirectories(t *testing.T, server *taas.Server) { 153 ctx := testutils.NewRktRunCtx() 154 defer ctx.Cleanup() 155 localSubdir := filepath.Join(ctx.LocalDir(), "subdir") 156 systemSubdir := filepath.Join(ctx.SystemDir(), "subdir") 157 writeConfig(t, authDir(localSubdir), "test.json", server.Conf) 158 writeConfig(t, authDir(systemSubdir), "test.json", server.Conf) 159 expectedRunRkt(ctx, t, server.URL, "oauth-subdirectories", authFailedDownload) 160 } 161 162 func runAuthServer(t *testing.T, auth taas.AuthType) (*taas.Server, string) { 163 setup := taas.GetDefaultServerSetup() 164 setup.Auth = auth 165 setup.Port = taas.PortRandom 166 server := runServer(t, setup) 167 image := patchTestACI(authACIName, fmt.Sprintf("--exec=/inspect --print-msg='%s'", authSuccessfulDownload)) 168 fileSet := make(map[string]string, 1) 169 fileSet[authACIName] = image 170 if err := server.UpdateFileSet(fileSet); err != nil { 171 t.Fatalf("Failed to populate a file list in test aci server: %v", err) 172 } 173 return server, image 174 } 175 176 func authCleanup(server *taas.Server, image string) { 177 server.Close() 178 _ = os.Remove(image) 179 } 180 181 // expectedRunRkt tries to fetch and run an auth test ACI from host. 182 func expectedRunRkt(ctx *testutils.RktRunCtx, t *testing.T, host, testName, line string) { 183 t.Logf("test name: %s", testName) 184 // First, check that --insecure-options=image,tls is required 185 // The server does not provide signatures for now. 186 cmd := fmt.Sprintf(`%s --debug run --no-store --mds-register=false %s/%s`, ctx.Cmd(), host, authACIName) 187 child := spawnOrFail(t, cmd) 188 defer child.Wait() 189 signatureErrorLine := "error downloading the signature file" 190 if err := expectWithOutput(child, signatureErrorLine); err != nil { 191 t.Fatalf("Didn't receive expected output %q: %v", signatureErrorLine, err) 192 } 193 194 // Then, run with --insecure-options=image,tls 195 cmd = fmt.Sprintf(`%s --debug --insecure-options=image,tls run --no-store --mds-register=false %s/%s`, ctx.Cmd(), host, authACIName) 196 child = spawnOrFail(t, cmd) 197 defer child.Wait() 198 if err := expectWithOutput(child, line); err != nil { 199 t.Fatalf("Didn't receive expected output %q: %v", line, err) 200 } 201 } 202 203 func getInvalidOAuthConfig(conf string) string { 204 return strings.Replace(conf, "sometoken", "someobviouslywrongtoken", 1) 205 }