Skip to content

Commit fd6f185

Browse files
authored
Add tracing spans to azidentity credentials (Azure#21885)
* Add tracing spans to azidentity credentials Replaced runtime.Pipelines with azcore.Clients. Removed the pipeline adapter. Now, the confidential and public clients satisfy the MSAL HTTPClient interface. * fix moduleName parameter * update to latest azcore * revert location of ClientOptions * fix copy/pasta
1 parent 6a4c2b1 commit fd6f185

18 files changed

+160
-55
lines changed

sdk/azidentity/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
### Features Added
66
* `DefaultAzureCredential` and `ManagedIdentityCredential` support Azure ML managed identity
7+
* Added spans for distributed tracing.
78

89
### Breaking Changes
910

sdk/azidentity/azidentity.go

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ const (
4141
organizationsTenantID = "organizations"
4242
developerSignOnClientID = "04b07795-8ddb-461a-bbee-02f9e1bf7b46"
4343
defaultSuffix = "/.default"
44+
45+
traceNamespace = "Microsoft.Entra"
46+
traceOpGetToken = "GetToken"
47+
traceOpAuthenticate = "Authenticate"
4448
)
4549

4650
var (
@@ -121,20 +125,7 @@ func validTenantID(tenantID string) bool {
121125
return true
122126
}
123127

124-
func newPipelineAdapter(opts *azcore.ClientOptions) pipelineAdapter {
125-
pl := runtime.NewPipeline(component, version, runtime.PipelineOptions{}, opts)
126-
return pipelineAdapter{pl: pl}
127-
}
128-
129-
type pipelineAdapter struct {
130-
pl runtime.Pipeline
131-
}
132-
133-
func (p pipelineAdapter) CloseIdleConnections() {
134-
// do nothing
135-
}
136-
137-
func (p pipelineAdapter) Do(r *http.Request) (*http.Response, error) {
128+
func doForClient(client *azcore.Client, r *http.Request) (*http.Response, error) {
138129
req, err := runtime.NewRequest(r.Context(), r.Method, r.URL.String())
139130
if err != nil {
140131
return nil, err
@@ -156,7 +147,7 @@ func (p pipelineAdapter) Do(r *http.Request) (*http.Response, error) {
156147
return nil, err
157148
}
158149
}
159-
resp, err := p.pl.Do(req)
150+
resp, err := client.Pipeline().Do(req)
160151
if err != nil {
161152
return nil, err
162153
}

sdk/azidentity/client_assertion_credential.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212

1313
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
1414
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
15+
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
1516
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential"
1617
)
1718

@@ -74,7 +75,11 @@ func NewClientAssertionCredential(tenantID, clientID string, getAssertion func(c
7475

7576
// GetToken requests an access token from Microsoft Entra ID. This method is called automatically by Azure SDK clients.
7677
func (c *ClientAssertionCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
77-
return c.client.GetToken(ctx, opts)
78+
var err error
79+
ctx, endSpan := runtime.StartSpan(ctx, credNameAssertion+"."+traceOpGetToken, c.client.azClient.Tracer(), nil)
80+
defer func() { endSpan(err) }()
81+
tk, err := c.client.GetToken(ctx, opts)
82+
return tk, err
7883
}
7984

8085
var _ azcore.TokenCredential = (*ClientAssertionCredential)(nil)

sdk/azidentity/client_certificate_credential.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515

1616
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
1717
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
18+
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
1819
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential"
1920
"golang.org/x/crypto/pkcs12"
2021
)
@@ -78,7 +79,11 @@ func NewClientCertificateCredential(tenantID string, clientID string, certs []*x
7879

7980
// GetToken requests an access token from Microsoft Entra ID. This method is called automatically by Azure SDK clients.
8081
func (c *ClientCertificateCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
81-
return c.client.GetToken(ctx, opts)
82+
var err error
83+
ctx, endSpan := runtime.StartSpan(ctx, credNameCert+"."+traceOpGetToken, c.client.azClient.Tracer(), nil)
84+
defer func() { endSpan(err) }()
85+
tk, err := c.client.GetToken(ctx, opts)
86+
return tk, err
8287
}
8388

8489
// ParseCertificates loads certificates and a private key, in PEM or PKCS12 format, for use with NewClientCertificateCredential.

sdk/azidentity/client_secret_credential.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
1313
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
14+
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
1415
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential"
1516
)
1617

@@ -59,12 +60,16 @@ func NewClientSecretCredential(tenantID string, clientID string, clientSecret st
5960
if err != nil {
6061
return nil, err
6162
}
62-
return &ClientSecretCredential{c}, nil
63+
return &ClientSecretCredential{client: c}, nil
6364
}
6465

6566
// GetToken requests an access token from Microsoft Entra ID. This method is called automatically by Azure SDK clients.
6667
func (c *ClientSecretCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
67-
return c.client.GetToken(ctx, opts)
68+
var err error
69+
ctx, endSpan := runtime.StartSpan(ctx, credNameSecret+"."+traceOpGetToken, c.client.azClient.Tracer(), nil)
70+
defer func() { endSpan(err) }()
71+
tk, err := c.client.GetToken(ctx, opts)
72+
return tk, err
6873
}
6974

7075
var _ azcore.TokenCredential = (*ClientSecretCredential)(nil)

sdk/azidentity/confidential_client.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"context"
1111
"errors"
1212
"fmt"
13+
"net/http"
1314
"os"
1415
"strings"
1516
"sync"
@@ -42,6 +43,7 @@ type confidentialClient struct {
4243
name string
4344
opts confidentialClientOptions
4445
region string
46+
azClient *azcore.Client
4547
}
4648

4749
func newConfidentialClient(tenantID, clientID, name string, cred confidential.Credential, opts confidentialClientOptions) (*confidentialClient, error) {
@@ -52,6 +54,14 @@ func newConfidentialClient(tenantID, clientID, name string, cred confidential.Cr
5254
if err != nil {
5355
return nil, err
5456
}
57+
client, err := azcore.NewClient(module, version, runtime.PipelineOptions{
58+
Tracing: runtime.TracingOptions{
59+
Namespace: traceNamespace,
60+
},
61+
}, &opts.ClientOptions)
62+
if err != nil {
63+
return nil, err
64+
}
5565
opts.AdditionallyAllowedTenants = resolveAdditionalTenants(opts.AdditionallyAllowedTenants)
5666
return &confidentialClient{
5767
caeMu: &sync.Mutex{},
@@ -64,6 +74,7 @@ func newConfidentialClient(tenantID, clientID, name string, cred confidential.Cr
6474
opts: opts,
6575
region: os.Getenv(azureRegionalAuthorityName),
6676
tenantID: tenantID,
77+
azClient: client,
6778
}, nil
6879
}
6980

@@ -142,7 +153,7 @@ func (c *confidentialClient) newMSALClient(enableCAE bool) (msalConfidentialClie
142153
o := []confidential.Option{
143154
confidential.WithAzureRegion(c.region),
144155
confidential.WithCache(cache),
145-
confidential.WithHTTPClient(newPipelineAdapter(&c.opts.ClientOptions)),
156+
confidential.WithHTTPClient(c),
146157
}
147158
if enableCAE {
148159
o = append(o, confidential.WithClientCapabilities(cp1))
@@ -161,3 +172,13 @@ func (c *confidentialClient) newMSALClient(enableCAE bool) (msalConfidentialClie
161172
func (c *confidentialClient) resolveTenant(specified string) (string, error) {
162173
return resolveTenant(c.tenantID, specified, c.name, c.opts.AdditionallyAllowedTenants)
163174
}
175+
176+
// these methods satisfy the MSAL ops.HTTPClient interface
177+
178+
func (c *confidentialClient) CloseIdleConnections() {
179+
// do nothing
180+
}
181+
182+
func (c *confidentialClient) Do(r *http.Request) (*http.Response, error) {
183+
return doForClient(c.azClient, r)
184+
}

sdk/azidentity/device_code_credential.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212

1313
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
1414
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
15+
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
1516
)
1617

1718
const credNameDeviceCode = "DeviceCodeCredential"
@@ -117,13 +118,21 @@ func NewDeviceCodeCredential(options *DeviceCodeCredentialOptions) (*DeviceCodeC
117118

118119
// Authenticate a user via the device code flow. Subsequent calls to GetToken will automatically use the returned AuthenticationRecord.
119120
func (c *DeviceCodeCredential) Authenticate(ctx context.Context, opts *policy.TokenRequestOptions) (AuthenticationRecord, error) {
120-
return c.client.Authenticate(ctx, opts)
121+
var err error
122+
ctx, endSpan := runtime.StartSpan(ctx, credNameDeviceCode+"."+traceOpAuthenticate, c.client.azClient.Tracer(), nil)
123+
defer func() { endSpan(err) }()
124+
tk, err := c.client.Authenticate(ctx, opts)
125+
return tk, err
121126
}
122127

123128
// GetToken requests an access token from Microsoft Entra ID. It will begin the device code flow and poll until the user completes authentication.
124129
// This method is called automatically by Azure SDK clients.
125130
func (c *DeviceCodeCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
126-
return c.client.GetToken(ctx, opts)
131+
var err error
132+
ctx, endSpan := runtime.StartSpan(ctx, credNameDeviceCode+"."+traceOpGetToken, c.client.azClient.Tracer(), nil)
133+
defer func() { endSpan(err) }()
134+
tk, err := c.client.GetToken(ctx, opts)
135+
return tk, err
127136
}
128137

129138
var _ azcore.TokenCredential = (*DeviceCodeCredential)(nil)

sdk/azidentity/go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ module github.com/Azure/azure-sdk-for-go/sdk/azidentity
33
go 1.18
44

55
require (
6-
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0
6+
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0
77
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.2.0
8-
github.com/Azure/azure-sdk-for-go/sdk/internal v1.4.0
8+
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.0
99
github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1
1010
github.com/golang-jwt/jwt/v5 v5.0.0
1111
github.com/google/uuid v1.3.1

sdk/azidentity/go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0 h1:9kDVnTz3vbfweTqAUmk/a/pH5pWFCHtvRpHYC0G/dcA=
2-
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0/go.mod h1:3Ug6Qzto9anB6mGlEdgYMDF5zHQ+wwhEaYR4s17PHMw=
1+
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0 h1:fb8kj/Dh4CSwgsOzHeZY4Xh68cFVbzXx+ONXGMY//4w=
2+
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0/go.mod h1:uReU2sSxZExRPBAg3qKzmAucSi51+SP1OhohieR821Q=
33
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.2.0 h1:xZaKaIde2fNBQ6cvgvsdlMMeD4OTpLaOQ1UTVDXGicI=
44
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.2.0/go.mod h1:veBEHsnzafwWVNkJ71OdC2tqipKKauNabOxdoi05Mhk=
5-
github.com/Azure/azure-sdk-for-go/sdk/internal v1.4.0 h1:TuEMD+E+1aTjjLICGQOW6vLe8UWES7kopac9mUXL56Y=
6-
github.com/Azure/azure-sdk-for-go/sdk/internal v1.4.0/go.mod h1:s4kgfzA0covAXNicZHDMN58jExvcng2mC/DepXiF1EI=
5+
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.0 h1:d81/ng9rET2YqdVkVwkb6EXeRrLJIwyGnJcAlAWKwhs=
6+
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.0/go.mod h1:s4kgfzA0covAXNicZHDMN58jExvcng2mC/DepXiF1EI=
77
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM=
88
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE=
99
github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 h1:WpB/QDNLpMw72xHJc34BNNykqSOeEJDAWkhf0u12/Jk=

sdk/azidentity/go.work.sum

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,34 @@
1-
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0 h1:9kDVnTz3vbfweTqAUmk/a/pH5pWFCHtvRpHYC0G/dcA=
2-
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0/go.mod h1:3Ug6Qzto9anB6mGlEdgYMDF5zHQ+wwhEaYR4s17PHMw=
3-
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM=
4-
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE=
5-
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
6-
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
1+
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0-beta.1 h1:ODs3brnqQM99Tq1PffODpAViYv3Bf8zOg464MU7p5ew=
2+
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0-beta.1/go.mod h1:3Ug6Qzto9anB6mGlEdgYMDF5zHQ+wwhEaYR4s17PHMw=
3+
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0 h1:fb8kj/Dh4CSwgsOzHeZY4Xh68cFVbzXx+ONXGMY//4w=
4+
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0/go.mod h1:uReU2sSxZExRPBAg3qKzmAucSi51+SP1OhohieR821Q=
5+
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM=
6+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
77
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
88
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
99
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
1010
github.com/montanaflynn/stats v0.7.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
11+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
12+
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
13+
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
1114
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
15+
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
16+
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
1217
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
13-
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
14-
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
1518
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
1619
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
1720
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
18-
golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
1921
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
2022
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
2123
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
2224
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
23-
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
24-
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
2525
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
2626
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
2727
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
2828
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
2929
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
3030
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
3131
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
32-
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
33-
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
3432
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
3533
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
34+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

0 commit comments

Comments
 (0)