浏览代码

Fix login error when login to an azure account having no associated tenant.
This was encountered by @lorenrh with stack :
```
docker login azure
panic: runtime error: index out of range [0] with length 0
goroutine 1 [running]:
github.com/docker/api/azure/login.AzureLoginService.Login(0xc0004cc2a0, 0x2d, 0xe8b8a0, 0x1476830, 0xe8e4e0, 0xc000498ff0, 0x0, 0x0)
github.com/docker/api/azure/login/login.go:130 +0x1057
github.com/docker/api/azure.(*aciCloudService).Login(0xc0004888c0, 0xe8e4e0, 0xc000498ff0, 0x0, 0xe82720, 0xc0004888c0)
github.com/docker/api/azure/backend.go:283 +0x64
github.com/docker/api/cli/cmd/login.cloudLogin(0xc0004eb600, 0xd422a4, 0x3, 0x1, 0xffffffffffffffff)
github.com/docker/api/cli/cmd/login/login.go:53 +0xae
github.com/docker/api/cli/cmd/login.runLogin(0xc0004eb600, 0xc00049c5f0, 0x1, 0x1, 0x0, 0x0)
github.com/docker/api/cli/cmd/login/login.go:39 +0x15e
github.com/spf13/cobra.(*Command).execute(0xc0004eb600, 0xc00049c5d0, 0x1, 0x1, 0xc0004eb600, 0xc00049c5d0)
github.com/spf13/[email protected]/command.go:842 +0x45a
github.com/spf13/cobra.(*Command).ExecuteC(0xc0004a8580, 0xc000498fc0, 0xc41160, 0x1476830)
github.com/spf13/[email protected]/command.go:950 +0x350
github.com/spf13/cobra.(*Command).Execute(...)
github.com/spf13/[email protected]/command.go:887
github.com/spf13/cobra.(*Command).ExecuteContext(...)
github.com/spf13/[email protected]/command.go:880
main.main()
github.com/docker/api/cli/main.go:167 +0x68f
```

Guillaume Tardif 5 年之前
父节点
当前提交
819a7389f7
共有 2 个文件被更改,包括 37 次插入3 次删除
  1. 3 0
      azure/login/login.go
  2. 34 3
      azure/login/login_test.go

+ 3 - 0
azure/login/login.go

@@ -127,6 +127,9 @@ func (login AzureLoginService) Login(ctx context.Context) error {
 			if err := json.Unmarshal(bits, &t); err != nil {
 				return errors.Wrapf(errdefs.ErrLoginFailed, "unable to unmarshal tenant: %s", err)
 			}
+			if len(t.Value) < 1 {
+				return errors.Wrap(errdefs.ErrLoginFailed, "could not find azure tenant")
+			}
 			tID := t.Value[0].TenantID
 			tToken, err := login.refreshToken(token.RefreshToken, tID)
 			if err != nil {

+ 34 - 3
azure/login/login_test.go

@@ -50,7 +50,6 @@ func (suite *LoginSuite) TestRefreshInValidToken() {
 		Foci:         "1",
 	}, nil)
 
-	//nolint copylocks
 	azureLogin, err := newAzureLoginServiceFromPath(filepath.Join(suite.dir, tokenStoreFilename), suite.mockHelper)
 	Expect(err).To(BeNil())
 	suite.azureLogin = azureLogin
@@ -102,7 +101,6 @@ func (suite *LoginSuite) TestInvalidLogin() {
 		Expect(err).To(BeNil())
 	})
 
-	//nolint copylocks
 	azureLogin, err := newAzureLoginServiceFromPath(filepath.Join(suite.dir, tokenStoreFilename), suite.mockHelper)
 	Expect(err).To(BeNil())
 
@@ -144,7 +142,6 @@ func (suite *LoginSuite) TestValidLogin() {
 		ExpiresIn:    3600,
 		Foci:         "1",
 	}, nil)
-	//nolint copylocks
 	azureLogin, err := newAzureLoginServiceFromPath(filepath.Join(suite.dir, tokenStoreFilename), suite.mockHelper)
 	Expect(err).To(BeNil())
 
@@ -160,6 +157,40 @@ func (suite *LoginSuite) TestValidLogin() {
 	Expect(loginToken.Token.Type()).To(Equal("Bearer"))
 }
 
+func (suite *LoginSuite) TestLoginNoTenant() {
+	var redirectURL string
+	suite.mockHelper.On("openAzureLoginPage", mock.AnythingOfType("string")).Run(func(args mock.Arguments) {
+		redirectURL = args.Get(0).(string)
+		err := queryKeyValue(redirectURL, "code", "123456879")
+		Expect(err).To(BeNil())
+	})
+
+	suite.mockHelper.On("queryToken", mock.MatchedBy(func(data url.Values) bool {
+		//Need a matcher here because the value of redirectUrl is not known until executing openAzureLoginPage
+		return reflect.DeepEqual(data, url.Values{
+			"grant_type":   []string{"authorization_code"},
+			"client_id":    []string{clientID},
+			"code":         []string{"123456879"},
+			"scope":        []string{scopes},
+			"redirect_uri": []string{redirectURL},
+		})
+	}), "organizations").Return(azureToken{
+		RefreshToken: "firstRefreshToken",
+		AccessToken:  "firstAccessToken",
+		ExpiresIn:    3600,
+		Foci:         "1",
+	}, nil)
+
+	authBody := `{"value":[]}`
+	suite.mockHelper.On("queryAuthorizationAPI", authorizationURL, "Bearer firstAccessToken").Return([]byte(authBody), 200, nil)
+
+	azureLogin, err := newAzureLoginServiceFromPath(filepath.Join(suite.dir, tokenStoreFilename), suite.mockHelper)
+	Expect(err).To(BeNil())
+
+	err = azureLogin.Login(context.TODO())
+	Expect(err.Error()).To(BeEquivalentTo("could not find azure tenant: login failed"))
+}
+
 func (suite *LoginSuite) TestLoginAuthorizationFailed() {
 	var redirectURL string
 	suite.mockHelper.On("openAzureLoginPage", mock.AnythingOfType("string")).Run(func(args mock.Arguments) {