Skip to content

Commit 50f3a78

Browse files
committed
migrate to azidentity for azure login
supports also workload identity Signed-off-by: Markus Blaschke <mblaschke82@gmail.com>
1 parent 9c9b703 commit 50f3a78

File tree

4 files changed

+72
-118
lines changed

4 files changed

+72
-118
lines changed

azure-devops-client/main.go

Lines changed: 27 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package AzureDevopsClient
22

33
import (
4-
"encoding/json"
4+
"context"
55
"errors"
66
"fmt"
77
"net/url"
@@ -10,11 +10,17 @@ import (
1010
"sync/atomic"
1111
"time"
1212

13+
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
14+
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
1315
resty "github.com/go-resty/resty/v2"
1416
"github.com/prometheus/client_golang/prometheus"
1517
"go.uber.org/zap"
1618
)
1719

20+
const (
21+
AZURE_DEVOPS_SCOPE = "499b84ac-1321-427f-aa17-267ca6975798/.default"
22+
)
23+
1824
type AzureDevopsClient struct {
1925
logger *zap.SugaredLogger
2026

@@ -26,13 +32,11 @@ type AzureDevopsClient struct {
2632
organization *string
2733
collection *string
2834

29-
// we can either use a PAT token for authentication ...
35+
// we can either use a PAT token for authentication
3036
accessToken *string
3137

32-
// ... or client id and secret
33-
tenantId *string
34-
clientId *string
35-
clientSecret *string
38+
// azure auth
39+
azcreds *azidentity.DefaultAzureCredential
3640

3741
entraIdToken *EntraIdToken
3842
entraIdTokenLastRefreshed int64
@@ -145,86 +149,10 @@ func (c *AzureDevopsClient) SetAccessToken(token string) {
145149
c.accessToken = &token
146150
}
147151

148-
func (c *AzureDevopsClient) SetTenantId(tenantId string) {
149-
c.tenantId = &tenantId
150-
}
151-
152-
func (c *AzureDevopsClient) SetClientId(clientId string) {
153-
c.clientId = &clientId
154-
}
155-
156-
func (c *AzureDevopsClient) SetClientSecret(clientSecret string) {
157-
c.clientSecret = &clientSecret
158-
}
159-
160152
func (c *AzureDevopsClient) SupportsPatAuthentication() bool {
161153
return c.accessToken != nil && len(*c.accessToken) > 0
162154
}
163155

164-
func (c *AzureDevopsClient) SupportsServicePrincipalAuthentication() bool {
165-
return c.tenantId != nil && len(*c.tenantId) > 0 &&
166-
c.clientId != nil && len(*c.clientId) > 0 &&
167-
c.clientSecret != nil && len(*c.clientSecret) > 0
168-
}
169-
170-
func (c *AzureDevopsClient) HasExpiredEntraIdAccessToken() bool {
171-
var currentUnix = time.Now().Unix()
172-
173-
// subtract 60 seconds of offset (should be enough time to use fire all requests)
174-
return (c.entraIdToken == nil || currentUnix >= c.entraIdTokenLastRefreshed+*c.entraIdToken.ExpiresIn-60)
175-
}
176-
177-
func (c *AzureDevopsClient) RefreshEntraIdAccessToken() (string, error) {
178-
var restClient = resty.New()
179-
180-
restClient.SetBaseURL(fmt.Sprintf("https://login.microsoftonline.com/%v/oauth2/v2.0/token", *c.tenantId))
181-
182-
restClient.SetFormData(map[string]string{
183-
"client_id": *c.clientId,
184-
"client_secret": *c.clientSecret,
185-
"grant_type": "client_credentials",
186-
"scope": "499b84ac-1321-427f-aa17-267ca6975798/.default", // the scope is always the same for Azure DevOps
187-
})
188-
189-
restClient.SetHeader("Content-Type", "application/x-www-form-urlencoded")
190-
restClient.SetHeader("Accept", "application/json")
191-
restClient.SetRetryCount(c.RequestRetries)
192-
193-
var response, err = restClient.R().Post("")
194-
195-
if err != nil {
196-
return "", err
197-
}
198-
199-
var responseBody = response.Body()
200-
201-
var errorResponse *EntraIdErrorResponse
202-
203-
err = json.Unmarshal(responseBody, &errorResponse)
204-
205-
if err != nil {
206-
return "", err
207-
}
208-
209-
if errorResponse.Error != nil && len(*errorResponse.Error) > 0 {
210-
return "", fmt.Errorf("could not request a token, error: %v %v", *errorResponse.Error, *errorResponse.ErrorDescription)
211-
}
212-
213-
err = json.Unmarshal(responseBody, &c.entraIdToken)
214-
215-
if err != nil {
216-
return "", err
217-
}
218-
219-
if c.entraIdToken == nil || c.entraIdToken.AccessToken == nil {
220-
return "", errors.New("could not request an access token")
221-
}
222-
223-
c.entraIdTokenLastRefreshed = time.Now().Unix()
224-
225-
return *c.entraIdToken.AccessToken, nil
226-
}
227-
228156
func (c *AzureDevopsClient) rest() *resty.Client {
229157
var client, err = c.restWithAuthentication("dev.azure.com")
230158

@@ -252,18 +180,27 @@ func (c *AzureDevopsClient) restWithAuthentication(domain string) (*resty.Client
252180

253181
if c.SupportsPatAuthentication() {
254182
c.restClient.SetBasicAuth("", *c.accessToken)
255-
} else if c.SupportsServicePrincipalAuthentication() {
256-
if c.HasExpiredEntraIdAccessToken() {
257-
var accessToken, err = c.RefreshEntraIdAccessToken()
258-
183+
} else {
184+
if c.azcreds == nil {
185+
opts := azidentity.DefaultAzureCredentialOptions{}
186+
cred, err := azidentity.NewDefaultAzureCredential(&opts)
259187
if err != nil {
260-
return nil, err
188+
panic(err)
261189
}
262190

263-
c.restClient.SetBasicAuth("", accessToken)
191+
c.azcreds = cred
264192
}
265-
} else {
266-
return nil, errors.New("no valid authentication method provided")
193+
194+
ctx := context.Background()
195+
opts := policy.TokenRequestOptions{
196+
Scopes: []string{AZURE_DEVOPS_SCOPE},
197+
}
198+
accessToken, err := c.azcreds.GetToken(ctx, opts)
199+
if err != nil {
200+
panic(err)
201+
}
202+
203+
c.restClient.SetBasicAuth("", accessToken.Token)
267204
}
268205

269206
return c.restClient, nil

go.mod

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@ require (
99
github.com/prometheus/common v0.47.0 // indirect
1010
github.com/prometheus/procfs v0.12.0 // indirect
1111
github.com/sirupsen/logrus v1.9.3
12-
golang.org/x/net v0.21.0 // indirect
13-
golang.org/x/sys v0.17.0 // indirect
12+
golang.org/x/net v0.22.0 // indirect
13+
golang.org/x/sys v0.18.0 // indirect
1414
google.golang.org/protobuf v1.32.0 // indirect
1515
)
1616

1717
require (
18+
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.10.0
19+
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1
1820
github.com/jessevdk/go-flags v1.5.0
1921
github.com/patrickmn/go-cache v2.1.0+incompatible
2022
github.com/remeh/sizedwaitgroup v1.0.0
@@ -23,14 +25,12 @@ require (
2325
)
2426

2527
require (
26-
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.2 // indirect
27-
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1 // indirect
2828
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2 // indirect
2929
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph v0.9.0 // indirect
3030
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 // indirect
3131
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions v1.3.0 // indirect
3232
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.0 // indirect
33-
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 // indirect
33+
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
3434
github.com/beorn7/perks v1.0.1 // indirect
3535
github.com/cespare/xxhash/v2 v2.2.0 // indirect
3636
github.com/davecgh/go-spew v1.1.1 // indirect
@@ -40,7 +40,7 @@ require (
4040
github.com/go-openapi/jsonreference v0.20.4 // indirect
4141
github.com/go-openapi/swag v0.22.9 // indirect
4242
github.com/gogo/protobuf v1.3.2 // indirect
43-
github.com/golang-jwt/jwt/v5 v5.2.0 // indirect
43+
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
4444
github.com/google/gnostic-models v0.6.8 // indirect
4545
github.com/google/gofuzz v1.2.0 // indirect
4646
github.com/google/uuid v1.6.0 // indirect
@@ -55,9 +55,9 @@ require (
5555
github.com/prometheus/client_model v0.6.0 // indirect
5656
github.com/robfig/cron v1.2.0 // indirect
5757
go.uber.org/multierr v1.11.0 // indirect
58-
golang.org/x/crypto v0.19.0 // indirect
58+
golang.org/x/crypto v0.21.0 // indirect
5959
golang.org/x/oauth2 v0.17.0 // indirect
60-
golang.org/x/term v0.17.0 // indirect
60+
golang.org/x/term v0.18.0 // indirect
6161
golang.org/x/text v0.14.0 // indirect
6262
golang.org/x/time v0.5.0 // indirect
6363
google.golang.org/appengine v1.6.8 // indirect

go.sum

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.2 h1:c4k2FIYIh4xtwqrQwV0Ct1v5+ehlNXj5NI/MWVsiTkQ=
2-
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.2/go.mod h1:5FDJtLEO/GxwNgUxbwrY3LP0pEoThTQJtk2oysdXHxM=
1+
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.10.0 h1:n1DH8TPV4qqPTje2RcUBYwtrTWlabVp4n46+74X2pn4=
2+
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.10.0/go.mod h1:HDcZnuGbiyppErN6lB+idp4CKhjbc8gwjto6OPpyggM=
33
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1 h1:sO0/P7g68FrryJzljemN+6GTssUXdANk6aJ7T1ZxnsQ=
44
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1/go.mod h1:h8hyGFDsU5HMivxiS2iYFZsgDbU9OnnJ163x5UGVKYo=
55
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2 h1:LqbJ/WzJUwBf8UiaSzgX7aMclParm9/5Vgp+TY51uBQ=
@@ -18,8 +18,8 @@ github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.5.0
1818
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.5.0/go.mod h1:T5RfihdXtBDxt1Ch2wobif3TvzTdumDy29kahv6AV9A=
1919
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.0 h1:IfFdxTUDiV58iZqPKgyWiz4X4fCxZeQ1pTQPImLYXpY=
2020
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.0/go.mod h1:SUZc9YRRHfx2+FAQKNDGrssXehqLpxmwRv2mC/5ntj4=
21-
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 h1:DzHpqpoJVaCgOUdVHxE8QB52S6NiVdDQvGlny1qvPqA=
22-
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
21+
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU=
22+
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
2323
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
2424
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
2525
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
@@ -45,8 +45,8 @@ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEe
4545
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
4646
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
4747
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
48-
github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
49-
github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
48+
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
49+
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
5050
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
5151
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
5252
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
@@ -136,8 +136,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
136136
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
137137
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
138138
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
139-
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
140-
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
139+
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
140+
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
141141
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
142142
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
143143
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
@@ -151,8 +151,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
151151
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
152152
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
153153
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
154-
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
155-
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
154+
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
155+
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
156156
golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ=
157157
golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA=
158158
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -173,15 +173,15 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
173173
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
174174
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
175175
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
176-
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
177-
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
176+
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
177+
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
178178
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
179179
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
180180
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
181181
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
182182
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
183-
golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
184-
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
183+
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
184+
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
185185
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
186186
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
187187
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=

main.go

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ func initArgparser() {
8282
}
8383
}
8484

85-
if len(opts.AzureDevops.AccessToken) == 0 && (len(opts.AzureDevops.TenantId) == 0 || len(opts.AzureDevops.ClientId) == 0 || len(opts.AzureDevops.ClientSecret) == 0) {
86-
logger.Fatalf("neither an Azure DevOps PAT token nor client credentials (tenant ID, client ID, client secret) for service principal authentication have been provided")
85+
if len(opts.AzureDevops.AccessToken) == 0 && (len(opts.AzureDevops.TenantId) == 0 || len(opts.AzureDevops.ClientId) == 0) {
86+
logger.Fatalf("neither an Azure DevOps PAT token nor client credentials (tenant ID, client ID) for service principal authentication have been provided")
8787
}
8888

8989
// ensure query paths and projects are splitted by '@'
@@ -158,11 +158,28 @@ func initAzureDevOpsConnection() {
158158
logger.Infof("using concurrency: %v", opts.Request.ConcurrencyLimit)
159159
logger.Infof("using retries: %v", opts.Request.Retries)
160160

161+
if opts.AzureDevops.TenantId != "" {
162+
if err := os.Setenv("AZURE_TENANT_ID", opts.AzureDevops.TenantId); err != nil {
163+
panic(err)
164+
}
165+
}
166+
167+
if opts.AzureDevops.ClientId != "" {
168+
if err := os.Setenv("AZURE_CLIENT_ID", opts.AzureDevops.ClientId); err != nil {
169+
panic(err)
170+
}
171+
}
172+
173+
if opts.AzureDevops.ClientSecret != "" {
174+
if err := os.Setenv("AZURE_CLIENT_SECRET", opts.AzureDevops.ClientSecret); err != nil {
175+
panic(err)
176+
}
177+
}
178+
161179
AzureDevopsClient.SetOrganization(opts.AzureDevops.Organisation)
162-
AzureDevopsClient.SetAccessToken(opts.AzureDevops.AccessToken)
163-
AzureDevopsClient.SetTenantId(opts.AzureDevops.TenantId)
164-
AzureDevopsClient.SetClientId(opts.AzureDevops.ClientId)
165-
AzureDevopsClient.SetClientSecret(opts.AzureDevops.ClientSecret)
180+
if opts.AzureDevops.AccessToken != "" {
181+
AzureDevopsClient.SetAccessToken(opts.AzureDevops.AccessToken)
182+
}
166183
AzureDevopsClient.SetApiVersion(opts.AzureDevops.ApiVersion)
167184
AzureDevopsClient.SetConcurrency(opts.Request.ConcurrencyLimit)
168185
AzureDevopsClient.SetRetries(opts.Request.Retries)

0 commit comments

Comments
 (0)