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