github.com/LukasHeimann/cloudfoundrycli/v8@v8.4.4/command/v7/auth_command_test.go (about) 1 package v7_test 2 3 import ( 4 "github.com/LukasHeimann/cloudfoundrycli/v8/cf/configuration/coreconfig" 5 "errors" 6 7 "github.com/LukasHeimann/cloudfoundrycli/v8/api/uaa" 8 "github.com/LukasHeimann/cloudfoundrycli/v8/api/uaa/constant" 9 "github.com/LukasHeimann/cloudfoundrycli/v8/api/uaa/uaaversion" 10 "github.com/LukasHeimann/cloudfoundrycli/v8/command/commandfakes" 11 "github.com/LukasHeimann/cloudfoundrycli/v8/command/translatableerror" 12 . "github.com/LukasHeimann/cloudfoundrycli/v8/command/v7" 13 "github.com/LukasHeimann/cloudfoundrycli/v8/command/v7/v7fakes" 14 "github.com/LukasHeimann/cloudfoundrycli/v8/util/ui" 15 . "github.com/onsi/ginkgo" 16 . "github.com/onsi/gomega" 17 . "github.com/onsi/gomega/gbytes" 18 ) 19 20 var _ = Describe("auth Command", func() { 21 var ( 22 cmd AuthCommand 23 testUI *ui.UI 24 fakeActor *v7fakes.FakeActor 25 fakeConfig *commandfakes.FakeConfig 26 binaryName string 27 err error 28 k8sLoginPrompts map[string]coreconfig.AuthPrompt 29 ) 30 31 BeforeEach(func() { 32 testUI = ui.NewTestUI(nil, NewBuffer(), NewBuffer()) 33 fakeActor = new(v7fakes.FakeActor) 34 fakeConfig = new(commandfakes.FakeConfig) 35 36 cmd = AuthCommand{ 37 BaseCommand: BaseCommand{ 38 UI: testUI, 39 Config: fakeConfig, 40 Actor: fakeActor, 41 }, 42 } 43 44 binaryName = "faceman" 45 fakeConfig.BinaryNameReturns(binaryName) 46 fakeConfig.UAAOAuthClientReturns("cf") 47 fakeConfig.APIVersionReturns("3.99.0") 48 k8sLoginPrompts = map[string]coreconfig.AuthPrompt{ 49 "k8s-auth-info": { 50 Entries: []string{"myuser"}, 51 }, 52 } 53 }) 54 55 JustBeforeEach(func() { 56 err = cmd.Execute(nil) 57 }) 58 59 When("--origin are set", func() { 60 BeforeEach(func() { 61 cmd.Origin = "some-origin" 62 }) 63 64 When("the UAA is below the minimum API version", func() { 65 BeforeEach(func() { 66 fakeActor.GetUAAAPIVersionReturns(uaaversion.InvalidUAAClientVersion, nil) 67 }) 68 69 It("returns an API version error", func() { 70 Expect(err).To(MatchError(translatableerror.MinimumUAAAPIVersionNotMetError{ 71 Command: "Option '--origin'", 72 MinimumVersion: uaaversion.MinUAAClientVersion, 73 })) 74 }) 75 }) 76 77 When("--client-credentials set", func() { 78 BeforeEach(func() { 79 cmd.ClientCredentials = true 80 fakeActor.GetUAAAPIVersionReturns(uaaversion.MinUAAClientVersion, nil) 81 }) 82 83 It("returns an ArgumentCombinationError", func() { 84 Expect(err).To(MatchError(translatableerror.ArgumentCombinationError{ 85 Args: []string{"--client-credentials", "--origin"}, 86 })) 87 }) 88 }) 89 }) 90 91 When("credentials are missing", func() { 92 When("username and password are both missing", func() { 93 It("raises an error", func() { 94 Expect(err).To(MatchError(translatableerror.MissingCredentialsError{ 95 MissingUsername: true, 96 MissingPassword: true, 97 })) 98 }) 99 }) 100 101 When("username is missing", func() { 102 BeforeEach(func() { 103 cmd.RequiredArgs.Password = "mypassword" 104 }) 105 106 It("raises an error", func() { 107 Expect(err).To(MatchError(translatableerror.MissingCredentialsError{ 108 MissingUsername: true, 109 })) 110 }) 111 }) 112 113 When("password is missing", func() { 114 BeforeEach(func() { 115 cmd.RequiredArgs.Username = "myuser" 116 }) 117 118 It("raises an error", func() { 119 Expect(err).To(MatchError(translatableerror.MissingCredentialsError{ 120 MissingPassword: true, 121 })) 122 }) 123 124 When("authenticating against Korifi", func() { 125 BeforeEach(func() { 126 fakeConfig.IsCFOnK8sReturns(true) 127 fakeActor.GetLoginPromptsReturns(k8sLoginPrompts, nil) 128 }) 129 130 It("succeeds", func() { 131 Expect(err).NotTo(HaveOccurred()) 132 }) 133 }) 134 }) 135 }) 136 137 When("there is an auth error", func() { 138 BeforeEach(func() { 139 cmd.RequiredArgs.Username = "foo" 140 cmd.RequiredArgs.Password = "bar" 141 142 fakeConfig.TargetReturns("some-api-target") 143 fakeActor.AuthenticateReturns(uaa.UnauthorizedError{Message: "some message"}) 144 }) 145 146 It("returns a BadCredentialsError", func() { 147 Expect(err).To(MatchError(uaa.UnauthorizedError{Message: "some message"})) 148 }) 149 }) 150 151 When("there is an account locked error", func() { 152 BeforeEach(func() { 153 cmd.RequiredArgs.Username = "foo" 154 cmd.RequiredArgs.Password = "bar" 155 156 fakeConfig.TargetReturns("some-api-target") 157 fakeActor.AuthenticateReturns(uaa.AccountLockedError{Message: "some message"}) 158 }) 159 160 It("returns a BadCredentialsError", func() { 161 Expect(err).To(MatchError(uaa.AccountLockedError{Message: "some message"})) 162 }) 163 }) 164 165 When("there is a non-auth error", func() { 166 var expectedError error 167 168 BeforeEach(func() { 169 cmd.RequiredArgs.Username = "foo" 170 cmd.RequiredArgs.Password = "bar" 171 172 fakeConfig.TargetReturns("some-api-target") 173 expectedError = errors.New("my humps") 174 175 fakeActor.AuthenticateReturns(expectedError) 176 }) 177 178 It("returns the error", func() { 179 Expect(err).To(MatchError(expectedError)) 180 }) 181 }) 182 183 When("there are no input errors", func() { 184 var ( 185 testID string 186 testSecret string 187 ) 188 189 BeforeEach(func() { 190 testID = "hello" 191 testSecret = "goodbye" 192 193 fakeConfig.TargetReturns("some-api-target") 194 }) 195 196 When("--client-credentials is set", func() { 197 BeforeEach(func() { 198 cmd.ClientCredentials = true 199 cmd.RequiredArgs.Username = testID 200 cmd.RequiredArgs.Password = testSecret 201 }) 202 203 It("outputs API target information and clears the targeted org and space", func() { 204 Expect(err).ToNot(HaveOccurred()) 205 206 Expect(testUI.Out).To(Say("API endpoint: %s", fakeConfig.Target())) 207 Expect(testUI.Out).To(Say(`Authenticating\.\.\.`)) 208 Expect(testUI.Out).To(Say("OK")) 209 Expect(testUI.Out).To(Say("Use '%s target' to view or set your target org and space", binaryName)) 210 211 Expect(fakeActor.AuthenticateCallCount()).To(Equal(1)) 212 credentials, origin, grantType := fakeActor.AuthenticateArgsForCall(0) 213 ID := credentials["client_id"] 214 secret := credentials["client_secret"] 215 Expect(ID).To(Equal(testID)) 216 Expect(secret).To(Equal(testSecret)) 217 Expect(origin).To(BeEmpty()) 218 Expect(grantType).To(Equal(constant.GrantTypeClientCredentials)) 219 }) 220 }) 221 222 When("--client-credentials is not set", func() { 223 When("username and password are only provided as arguments", func() { 224 BeforeEach(func() { 225 cmd.RequiredArgs.Username = testID 226 cmd.RequiredArgs.Password = testSecret 227 }) 228 229 When("the API version is older than the minimum supported API version for the v7 CLI", func() { 230 BeforeEach(func() { 231 fakeConfig.APIVersionReturns("3.83.0") 232 }) 233 It("warns that the user is targeting an unsupported API version and that things may not work correctly", func() { 234 Expect(err).ToNot(HaveOccurred()) 235 Expect(testUI.Out).To(Say("API endpoint: %s", fakeConfig.Target())) 236 Expect(testUI.Err).To(Say("Warning: Your targeted API's version \\(3.83.0\\) is less than the minimum supported API version \\(3.99.0\\). Some commands may not function correctly.")) 237 }) 238 }) 239 240 When("the API version is empty", func() { 241 BeforeEach(func() { 242 fakeConfig.APIVersionReturns("") 243 }) 244 It("prints a warning message", func() { 245 Expect(err).ToNot(HaveOccurred()) 246 Expect(testUI.Err).To(Say("Warning: unable to determine whether targeted API's version meets minimum supported.")) 247 }) 248 }) 249 250 It("should NOT warn that the user is targeting an unsupported API version", func() { 251 Expect(testUI.Err).ToNot(Say("is less than the minimum supported API version")) 252 }) 253 254 It("outputs API target information and clears the targeted org and space", func() { 255 Expect(err).ToNot(HaveOccurred()) 256 257 Expect(testUI.Out).To(Say("API endpoint: %s", fakeConfig.Target())) 258 Expect(testUI.Out).To(Say(`Authenticating\.\.\.`)) 259 Expect(testUI.Out).To(Say("OK")) 260 Expect(testUI.Out).To(Say("Use '%s target' to view or set your target org and space", binaryName)) 261 262 Expect(fakeActor.AuthenticateCallCount()).To(Equal(1)) 263 credentials, origin, grantType := fakeActor.AuthenticateArgsForCall(0) 264 username := credentials["username"] 265 password := credentials["password"] 266 Expect(username).To(Equal(testID)) 267 Expect(password).To(Equal(testSecret)) 268 Expect(origin).To(BeEmpty()) 269 Expect(grantType).To(Equal(constant.GrantTypePassword)) 270 }) 271 }) 272 273 When("the username and password are provided in env variables", func() { 274 var ( 275 envUsername string 276 envPassword string 277 ) 278 279 BeforeEach(func() { 280 envUsername = "banana" 281 envPassword = "potato" 282 fakeConfig.CFUsernameReturns(envUsername) 283 fakeConfig.CFPasswordReturns(envPassword) 284 }) 285 286 When("username and password are not also provided as arguments", func() { 287 It("authenticates with the values in the env variables", func() { 288 Expect(err).ToNot(HaveOccurred()) 289 290 Expect(fakeActor.AuthenticateCallCount()).To(Equal(1)) 291 credentials, origin, _ := fakeActor.AuthenticateArgsForCall(0) 292 username := credentials["username"] 293 password := credentials["password"] 294 Expect(username).To(Equal(envUsername)) 295 Expect(password).To(Equal(envPassword)) 296 Expect(origin).To(BeEmpty()) 297 }) 298 }) 299 300 When("username and password are also provided as arguments", func() { 301 BeforeEach(func() { 302 cmd.RequiredArgs.Username = testID 303 cmd.RequiredArgs.Password = testSecret 304 }) 305 306 It("authenticates with the values from the command line args", func() { 307 Expect(err).ToNot(HaveOccurred()) 308 309 Expect(fakeActor.AuthenticateCallCount()).To(Equal(1)) 310 credentials, origin, _ := fakeActor.AuthenticateArgsForCall(0) 311 username := credentials["username"] 312 password := credentials["password"] 313 Expect(username).To(Equal(testID)) 314 Expect(password).To(Equal(testSecret)) 315 Expect(origin).To(BeEmpty()) 316 }) 317 }) 318 }) 319 320 When("authenticating against Korifi", func() { 321 BeforeEach(func() { 322 cmd.RequiredArgs.Username = "myuser" 323 fakeConfig.IsCFOnK8sReturns(true) 324 fakeActor.GetLoginPromptsReturns(k8sLoginPrompts, nil) 325 }) 326 327 When("the specified username doesn't match any k8s context", func() { 328 BeforeEach(func() { 329 cmd.RequiredArgs.Username = "some-unknown-user" 330 }) 331 332 It("errors", func() { 333 Expect(err).To(MatchError(errors.New("kubernetes user not found in configuration: some-unknown-user"))) 334 }) 335 }) 336 337 When("the prompts don't contain k8s authentication information", func() { 338 BeforeEach(func() { 339 k8sLoginPrompts = map[string]coreconfig.AuthPrompt{ 340 "some-other-auth-info": { 341 Entries: []string{"myuser"}, 342 }, 343 } 344 fakeActor.GetLoginPromptsReturns(k8sLoginPrompts, nil) 345 }) 346 347 It("errors", func() { 348 Expect(err).To(MatchError(errors.New("kubernetes login context is missing"))) 349 }) 350 351 }) 352 353 }) 354 }) 355 356 When("a user has manually added their client credentials to the config file", func() { 357 BeforeEach(func() { 358 fakeConfig.UAAOAuthClientReturns("AClientsId") 359 }) 360 361 When("the --client-credentials flag is not set", func() { 362 BeforeEach(func() { 363 cmd.ClientCredentials = false 364 cmd.RequiredArgs.Username = "some-username" 365 cmd.RequiredArgs.Password = "some-password" 366 }) 367 368 It("fails with an error indicating manual client credentials are no longer supported in the config file", func() { 369 Expect(err).To(MatchError(translatableerror.ManualClientCredentialsError{})) 370 }) 371 }) 372 }) 373 }) 374 375 When("already logged in via client credentials", func() { 376 BeforeEach(func() { 377 fakeConfig.UAAGrantTypeReturns("client_credentials") 378 }) 379 380 When("authenticating as a user", func() { 381 BeforeEach(func() { 382 cmd.ClientCredentials = false 383 cmd.RequiredArgs.Username = "some-username" 384 cmd.RequiredArgs.Password = "some-password" 385 }) 386 387 It("returns an already logged in error", func() { 388 Expect(err).To(MatchError("Service account currently logged in. Use 'cf logout' to log out service account and try again.")) 389 Expect(fakeConfig.UAAGrantTypeCallCount()).To(Equal(1)) 390 }) 391 392 It("the returned error is translatable", func() { 393 Expect(err).To(MatchError(translatableerror.PasswordGrantTypeLogoutRequiredError{})) 394 }) 395 }) 396 397 When("authenticating as a client", func() { 398 BeforeEach(func() { 399 cmd.ClientCredentials = true 400 cmd.RequiredArgs.Username = "some-client-id" 401 cmd.RequiredArgs.Password = "some-client-secret" 402 }) 403 It("does not error", func() { 404 Expect(err).ToNot(HaveOccurred()) 405 Expect(fakeConfig.UAAGrantTypeCallCount()).To(Equal(0)) 406 }) 407 }) 408 }) 409 })