github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+incompatible/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.FakeAuthActor 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.FakeAuthActor) 32 fakeConfig = new(commandfakes.FakeConfig) 33 34 cmd = AuthCommand{ 35 UI: testUI, 36 Config: fakeConfig, 37 Actor: fakeActor, 38 } 39 40 binaryName = "faceman" 41 fakeConfig.BinaryNameReturns(binaryName) 42 }) 43 44 JustBeforeEach(func() { 45 err = cmd.Execute(nil) 46 }) 47 48 When("--origin are set", func() { 49 BeforeEach(func() { 50 cmd.Origin = "some-origin" 51 }) 52 53 When("the UAA is below the minimum API version", func() { 54 BeforeEach(func() { 55 fakeActor.UAAAPIVersionReturns(uaaversion.MinUAAClientVersion) 56 }) 57 58 It("returns an API version error", func() { 59 Expect(err).To(MatchError(translatableerror.MinimumUAAAPIVersionNotMetError{ 60 Command: "Option '--origin'", 61 MinimumVersion: uaaversion.MinVersionOrigin, 62 })) 63 }) 64 }) 65 66 When("--client-credentials set", func() { 67 BeforeEach(func() { 68 cmd.ClientCredentials = true 69 fakeActor.UAAAPIVersionReturns(uaaversion.MinVersionOrigin) 70 }) 71 72 It("returns an ArgumentCombinationError", func() { 73 Expect(err).To(MatchError(translatableerror.ArgumentCombinationError{ 74 Args: []string{"--client-credentials", "--origin"}, 75 })) 76 }) 77 }) 78 79 When("when the UAA is above the minimum API version", func() { 80 BeforeEach(func() { 81 cmd.RequiredArgs.Username = "doesn't matter" 82 cmd.RequiredArgs.Password = "doesn't matter" 83 fakeActor.UAAAPIVersionReturns(uaaversion.MinVersionOrigin) 84 }) 85 86 It("authenticates with the values from the command line args", func() { 87 Expect(err).ToNot(HaveOccurred()) 88 89 Expect(fakeActor.AuthenticateCallCount()).To(Equal(1)) 90 _, origin, _ := fakeActor.AuthenticateArgsForCall(0) 91 Expect(origin).To(Equal("some-origin")) 92 }) 93 }) 94 }) 95 96 When("credentials are missing", func() { 97 When("username and password are both missing", func() { 98 It("raises an error", func() { 99 Expect(err).To(MatchError(translatableerror.MissingCredentialsError{ 100 MissingUsername: true, 101 MissingPassword: true, 102 })) 103 }) 104 }) 105 106 When("username is missing", func() { 107 BeforeEach(func() { 108 cmd.RequiredArgs.Password = "mypassword" 109 }) 110 111 It("raises an error", func() { 112 Expect(err).To(MatchError(translatableerror.MissingCredentialsError{ 113 MissingUsername: true, 114 })) 115 }) 116 }) 117 118 When("password is missing", func() { 119 BeforeEach(func() { 120 cmd.RequiredArgs.Username = "myuser" 121 }) 122 123 It("raises an error", func() { 124 Expect(err).To(MatchError(translatableerror.MissingCredentialsError{ 125 MissingPassword: true, 126 })) 127 }) 128 }) 129 }) 130 131 When("there is an auth error", func() { 132 BeforeEach(func() { 133 cmd.RequiredArgs.Username = "foo" 134 cmd.RequiredArgs.Password = "bar" 135 136 fakeConfig.TargetReturns("some-api-target") 137 fakeActor.AuthenticateReturns(uaa.UnauthorizedError{Message: "some message"}) 138 }) 139 140 It("returns a BadCredentialsError", func() { 141 Expect(err).To(MatchError(uaa.UnauthorizedError{Message: "some message"})) 142 }) 143 }) 144 145 When("there is an account locked error", func() { 146 BeforeEach(func() { 147 cmd.RequiredArgs.Username = "foo" 148 cmd.RequiredArgs.Password = "bar" 149 150 fakeConfig.TargetReturns("some-api-target") 151 fakeActor.AuthenticateReturns(uaa.AccountLockedError{Message: "some message"}) 152 }) 153 154 It("returns a BadCredentialsError", func() { 155 Expect(err).To(MatchError(uaa.AccountLockedError{Message: "some message"})) 156 }) 157 }) 158 159 When("there is a non-auth error", func() { 160 var expectedError error 161 162 BeforeEach(func() { 163 cmd.RequiredArgs.Username = "foo" 164 cmd.RequiredArgs.Password = "bar" 165 166 fakeConfig.TargetReturns("some-api-target") 167 expectedError = errors.New("my humps") 168 169 fakeActor.AuthenticateReturns(expectedError) 170 }) 171 172 It("returns the error", func() { 173 Expect(err).To(MatchError(expectedError)) 174 }) 175 }) 176 177 Describe("it checks the CLI version", func() { 178 var ( 179 apiVersion string 180 minCLIVersion string 181 binaryVersion string 182 ) 183 184 BeforeEach(func() { 185 apiVersion = "1.2.3" 186 fakeActor.CloudControllerAPIVersionReturns(apiVersion) 187 minCLIVersion = "1.0.0" 188 fakeConfig.MinCLIVersionReturns(minCLIVersion) 189 190 cmd.RequiredArgs.Username = "user" 191 cmd.RequiredArgs.Password = "password" 192 }) 193 194 Context("the CLI version is older than the minimum version required by the API", func() { 195 BeforeEach(func() { 196 binaryVersion = "0.0.0" 197 fakeConfig.BinaryVersionReturns(binaryVersion) 198 }) 199 200 It("displays a recommendation to update the CLI version", func() { 201 Expect(err).ToNot(HaveOccurred()) 202 Expect(testUI.Err).To(Say("Cloud Foundry API version %s requires CLI version %s. You are currently on version %s. To upgrade your CLI, please visit: https://github.com/cloudfoundry/cli#downloads", apiVersion, minCLIVersion, binaryVersion)) 203 }) 204 }) 205 206 Context("the CLI version satisfies the API's minimum version requirements", func() { 207 BeforeEach(func() { 208 binaryVersion = "1.0.0" 209 fakeConfig.BinaryVersionReturns(binaryVersion) 210 }) 211 212 It("does not display a recommendation to update the CLI version", func() { 213 Expect(err).ToNot(HaveOccurred()) 214 Expect(testUI.Err).ToNot(Say("Cloud Foundry API version %s requires CLI version %s. You are currently on version %s. To upgrade your CLI, please visit: https://github.com/cloudfoundry/cli#downloads", apiVersion, minCLIVersion, binaryVersion)) 215 }) 216 }) 217 218 When("the CLI version is invalid", func() { 219 BeforeEach(func() { 220 fakeConfig.BinaryVersionReturns("&#%") 221 }) 222 223 It("returns an error", func() { 224 Expect(err).To(HaveOccurred()) 225 Expect(err.Error()).To(Equal("No Major.Minor.Patch elements found")) 226 }) 227 }) 228 }) 229 230 When("there are no input errors", func() { 231 var ( 232 testID string 233 testSecret string 234 ) 235 236 BeforeEach(func() { 237 testID = "hello" 238 testSecret = "goodbye" 239 240 fakeConfig.TargetReturns("some-api-target") 241 }) 242 243 When("--client-credentials is set", func() { 244 BeforeEach(func() { 245 cmd.ClientCredentials = true 246 cmd.RequiredArgs.Username = testID 247 cmd.RequiredArgs.Password = testSecret 248 }) 249 250 It("outputs API target information and clears the targeted org and space", func() { 251 Expect(err).ToNot(HaveOccurred()) 252 253 Expect(testUI.Out).To(Say("API endpoint: %s", fakeConfig.Target())) 254 Expect(testUI.Out).To(Say(`Authenticating\.\.\.`)) 255 Expect(testUI.Out).To(Say("OK")) 256 Expect(testUI.Out).To(Say("Use '%s target' to view or set your target org and space", binaryName)) 257 258 Expect(fakeActor.AuthenticateCallCount()).To(Equal(1)) 259 credentials, origin, grantType := fakeActor.AuthenticateArgsForCall(0) 260 ID := credentials["client_id"] 261 secret := credentials["client_secret"] 262 Expect(ID).To(Equal(testID)) 263 Expect(secret).To(Equal(testSecret)) 264 Expect(origin).To(BeEmpty()) 265 Expect(grantType).To(Equal(constant.GrantTypeClientCredentials)) 266 }) 267 }) 268 269 When("--client-credentials is not set", func() { 270 When("username and password are only provided as arguments", func() { 271 BeforeEach(func() { 272 cmd.RequiredArgs.Username = testID 273 cmd.RequiredArgs.Password = testSecret 274 }) 275 276 It("outputs API target information and clears the targeted org and space", func() { 277 Expect(err).ToNot(HaveOccurred()) 278 279 Expect(testUI.Out).To(Say("API endpoint: %s", fakeConfig.Target())) 280 Expect(testUI.Out).To(Say(`Authenticating\.\.\.`)) 281 Expect(testUI.Out).To(Say("OK")) 282 Expect(testUI.Out).To(Say("Use '%s target' to view or set your target org and space", binaryName)) 283 284 Expect(fakeActor.AuthenticateCallCount()).To(Equal(1)) 285 credentials, origin, grantType := fakeActor.AuthenticateArgsForCall(0) 286 username := credentials["username"] 287 password := credentials["password"] 288 Expect(username).To(Equal(testID)) 289 Expect(password).To(Equal(testSecret)) 290 Expect(origin).To(BeEmpty()) 291 Expect(grantType).To(Equal(constant.GrantTypePassword)) 292 }) 293 }) 294 295 When("the username and password are provided in env variables", func() { 296 var ( 297 envUsername string 298 envPassword string 299 ) 300 301 BeforeEach(func() { 302 envUsername = "banana" 303 envPassword = "potato" 304 fakeConfig.CFUsernameReturns(envUsername) 305 fakeConfig.CFPasswordReturns(envPassword) 306 }) 307 308 When("username and password are not also provided as arguments", func() { 309 It("authenticates with the values in the env variables", func() { 310 Expect(err).ToNot(HaveOccurred()) 311 312 Expect(fakeActor.AuthenticateCallCount()).To(Equal(1)) 313 credentials, origin, _ := fakeActor.AuthenticateArgsForCall(0) 314 username := credentials["username"] 315 password := credentials["password"] 316 Expect(username).To(Equal(envUsername)) 317 Expect(password).To(Equal(envPassword)) 318 Expect(origin).To(BeEmpty()) 319 }) 320 }) 321 322 When("username and password are also provided as arguments", func() { 323 BeforeEach(func() { 324 cmd.RequiredArgs.Username = testID 325 cmd.RequiredArgs.Password = testSecret 326 }) 327 328 It("authenticates with the values from the command line args", func() { 329 Expect(err).ToNot(HaveOccurred()) 330 331 Expect(fakeActor.AuthenticateCallCount()).To(Equal(1)) 332 credentials, origin, _ := fakeActor.AuthenticateArgsForCall(0) 333 username := credentials["username"] 334 password := credentials["password"] 335 Expect(username).To(Equal(testID)) 336 Expect(password).To(Equal(testSecret)) 337 Expect(origin).To(BeEmpty()) 338 }) 339 }) 340 }) 341 }) 342 343 When("client id or client secret are in the config.json", func() { 344 BeforeEach(func() { 345 fakeConfig.UAAOAuthClientReturns("AClientsId") 346 }) 347 When("using --client-credentials", func() { 348 BeforeEach(func() { 349 cmd.ClientCredentials = true 350 cmd.RequiredArgs.Username = "some-client-id" 351 cmd.RequiredArgs.Password = "some-client-secret" 352 353 }) 354 It("does not output a deprecation warning", func() { 355 Expect(testUI.Err).ToNot(Say("Deprecation warning")) 356 }) 357 }) 358 When("logging in as a user", func() { 359 BeforeEach(func() { 360 cmd.ClientCredentials = false 361 cmd.RequiredArgs.Username = "some-username" 362 cmd.RequiredArgs.Password = "some-password" 363 }) 364 It("outputs a deprecation warning", func() { 365 Expect(testUI.Err).To(Say("Deprecation warning: Manually writing your client credentials to the config.json is deprecated and will be removed in the future. For similar functionality, please use the `cf auth --client-credentials` command instead.")) 366 }) 367 }) 368 }) 369 }) 370 371 When("already logged in via client credentials", func() { 372 BeforeEach(func() { 373 fakeConfig.UAAGrantTypeReturns("client_credentials") 374 }) 375 376 When("authenticating as a user", func() { 377 BeforeEach(func() { 378 cmd.ClientCredentials = false 379 cmd.RequiredArgs.Username = "some-username" 380 cmd.RequiredArgs.Password = "some-password" 381 }) 382 383 It("returns an already logged in error", func() { 384 Expect(err).To(MatchError("Service account currently logged in. Use 'cf logout' to log out service account and try again.")) 385 Expect(fakeConfig.UAAGrantTypeCallCount()).To(Equal(1)) 386 }) 387 388 It("the returned error is translatable", func() { 389 Expect(err).To(MatchError(translatableerror.PasswordGrantTypeLogoutRequiredError{})) 390 }) 391 }) 392 393 When("authenticating as a client", func() { 394 BeforeEach(func() { 395 cmd.ClientCredentials = true 396 cmd.RequiredArgs.Username = "some-client-id" 397 cmd.RequiredArgs.Password = "some-client-secret" 398 }) 399 It("does not error", func() { 400 Expect(err).ToNot(HaveOccurred()) 401 Expect(fakeConfig.UAAGrantTypeCallCount()).To(Equal(0)) 402 }) 403 }) 404 }) 405 })