vendor: run make vendor-update

This commit is contained in:
Aliaksandr Valialkin 2024-06-24 23:08:47 +02:00
parent 6b128da811
commit 5c55722db4
No known key found for this signature in database
GPG key ID: 52C003EE2BCDB9EB
362 changed files with 6070 additions and 4210 deletions

70
go.mod
View file

@ -3,26 +3,26 @@ module github.com/VictoriaMetrics/VictoriaMetrics
go 1.22.4 go 1.22.4
require ( require (
cloud.google.com/go/storage v1.41.0 cloud.google.com/go/storage v1.42.0
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.2 github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.2
github.com/VictoriaMetrics/easyproto v0.1.4 github.com/VictoriaMetrics/easyproto v0.1.4
github.com/VictoriaMetrics/fastcache v1.12.2 github.com/VictoriaMetrics/fastcache v1.12.2
github.com/VictoriaMetrics/metrics v1.34.0 github.com/VictoriaMetrics/metrics v1.34.0
github.com/VictoriaMetrics/metricsql v0.75.1 github.com/VictoriaMetrics/metricsql v0.75.1
github.com/aws/aws-sdk-go-v2 v1.27.1 github.com/aws/aws-sdk-go-v2 v1.30.0
github.com/aws/aws-sdk-go-v2/config v1.27.17 github.com/aws/aws-sdk-go-v2/config v1.27.21
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.23 github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.1
github.com/aws/aws-sdk-go-v2/service/s3 v1.55.0 github.com/aws/aws-sdk-go-v2/service/s3 v1.56.1
github.com/bmatcuk/doublestar/v4 v4.6.1 github.com/bmatcuk/doublestar/v4 v4.6.1
github.com/cespare/xxhash/v2 v2.3.0 github.com/cespare/xxhash/v2 v2.3.0
github.com/cheggaaa/pb/v3 v3.1.5 github.com/cheggaaa/pb/v3 v3.1.5
github.com/gogo/protobuf v1.3.2 github.com/gogo/protobuf v1.3.2
github.com/golang/snappy v0.0.4 github.com/golang/snappy v0.0.4
github.com/googleapis/gax-go/v2 v2.12.4 github.com/googleapis/gax-go/v2 v2.12.5
github.com/influxdata/influxdb v1.11.5 github.com/influxdata/influxdb v1.11.5
github.com/klauspost/compress v1.17.8 github.com/klauspost/compress v1.17.9
github.com/prometheus/prometheus v0.52.1 github.com/prometheus/prometheus v0.53.0
github.com/urfave/cli/v2 v2.27.2 github.com/urfave/cli/v2 v2.27.2
github.com/valyala/fastjson v1.6.4 github.com/valyala/fastjson v1.6.4
github.com/valyala/fastrand v1.1.0 github.com/valyala/fastrand v1.1.0
@ -32,36 +32,36 @@ require (
github.com/valyala/quicktemplate v1.7.0 github.com/valyala/quicktemplate v1.7.0
golang.org/x/oauth2 v0.21.0 golang.org/x/oauth2 v0.21.0
golang.org/x/sys v0.21.0 golang.org/x/sys v0.21.0
google.golang.org/api v0.183.0 google.golang.org/api v0.185.0
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
) )
require ( require (
cloud.google.com/go v0.114.0 // indirect cloud.google.com/go v0.115.0 // indirect
cloud.google.com/go/auth v0.5.1 // indirect cloud.google.com/go/auth v0.5.2 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect
cloud.google.com/go/compute/metadata v0.3.0 // indirect cloud.google.com/go/compute/metadata v0.3.0 // indirect
cloud.google.com/go/iam v1.1.8 // indirect cloud.google.com/go/iam v1.1.8 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2 // indirect github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
github.com/VividCortex/ewma v1.2.0 // indirect github.com/VividCortex/ewma v1.2.0 // indirect
github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 // indirect github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 // indirect
github.com/aws/aws-sdk-go v1.53.18 // indirect github.com/aws/aws-sdk-go v1.54.6 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.17 // indirect github.com/aws/aws-sdk-go-v2/credentials v1.17.21 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.4 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.8 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.8 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.12 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.8 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.12 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.8 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.12 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.10 // indirect github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.14 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.10 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.14 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.8 // indirect github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.12 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.20.10 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.21.1 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.4 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.25.1 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.28.11 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.29.1 // indirect
github.com/aws/smithy-go v1.20.2 // indirect github.com/aws/smithy-go v1.20.2 // indirect
github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3 // indirect github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3 // indirect
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
@ -82,7 +82,6 @@ require (
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc // indirect github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc // indirect
github.com/hashicorp/go-version v1.7.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/jpillora/backoff v1.0.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
@ -107,9 +106,8 @@ require (
github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
go.opencensus.io v0.24.0 // indirect go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/collector/featuregate v1.9.0 // indirect go.opentelemetry.io/collector/pdata v1.10.0 // indirect
go.opentelemetry.io/collector/pdata v1.9.0 // indirect go.opentelemetry.io/collector/semconv v0.103.0 // indirect
go.opentelemetry.io/collector/semconv v0.102.1 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 // indirect
go.opentelemetry.io/otel v1.27.0 // indirect go.opentelemetry.io/otel v1.27.0 // indirect
@ -119,19 +117,19 @@ require (
go.uber.org/goleak v1.3.0 // indirect go.uber.org/goleak v1.3.0 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.24.0 // indirect golang.org/x/crypto v0.24.0 // indirect
golang.org/x/exp v0.0.0-20240604190554-fc45aab8b7f8 // indirect golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect
golang.org/x/net v0.26.0 // indirect golang.org/x/net v0.26.0 // indirect
golang.org/x/sync v0.7.0 // indirect golang.org/x/sync v0.7.0 // indirect
golang.org/x/text v0.16.0 // indirect golang.org/x/text v0.16.0 // indirect
golang.org/x/time v0.5.0 // indirect golang.org/x/time v0.5.0 // indirect
google.golang.org/genproto v0.0.0-20240604185151-ef581f913117 // indirect google.golang.org/genproto v0.0.0-20240624140628-dc46fd24d27d // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240624140628-dc46fd24d27d // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d // indirect
google.golang.org/grpc v1.64.0 // indirect google.golang.org/grpc v1.64.0 // indirect
google.golang.org/protobuf v1.34.1 // indirect google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/apimachinery v0.30.1 // indirect k8s.io/apimachinery v0.30.2 // indirect
k8s.io/client-go v0.30.1 // indirect k8s.io/client-go v0.30.2 // indirect
k8s.io/klog/v2 v2.120.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 // indirect k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 // indirect
) )

195
go.sum
View file

@ -13,10 +13,10 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go v0.114.0 h1:OIPFAdfrFDFO2ve2U7r/H5SwSbBzEdrBdE7xkgwc+kY= cloud.google.com/go v0.115.0 h1:CnFSK6Xo3lDYRoBKEcAtia6VSC837/ZkJuRduSFnr14=
cloud.google.com/go v0.114.0/go.mod h1:ZV9La5YYxctro1HTPug5lXH/GefROyW8PPD4T8n9J8E= cloud.google.com/go v0.115.0/go.mod h1:8jIM5vVgoAEoiVxQ/O4BFTfHqulPZgs/ufEzMcFMdWU=
cloud.google.com/go/auth v0.5.1 h1:0QNO7VThG54LUzKiQxv8C6x1YX7lUrzlAa1nVLF8CIw= cloud.google.com/go/auth v0.5.2 h1:xzzYbfrv7xI5oPzzu11RT66GnNhRrWcVG9TXEVxx86Y=
cloud.google.com/go/auth v0.5.1/go.mod h1:vbZT8GjzDf3AVqCcQmqeeM32U9HBFc32vVVAbwDsa6s= cloud.google.com/go/auth v0.5.2/go.mod h1:b4acV+jLQDyjwm4OXHYjNvRi4jvGBzHWJRtJcy+2P4g=
cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4= cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4=
cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q= cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
@ -31,6 +31,8 @@ cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/iam v1.1.8 h1:r7umDwhj+BQyz0ScZMp4QrGXjSTI3ZINnpgU2nlB/K0= cloud.google.com/go/iam v1.1.8 h1:r7umDwhj+BQyz0ScZMp4QrGXjSTI3ZINnpgU2nlB/K0=
cloud.google.com/go/iam v1.1.8/go.mod h1:GvE6lyMmfxXauzNq8NbgJbeVQNspG+tcdL/W8QO1+zE= cloud.google.com/go/iam v1.1.8/go.mod h1:GvE6lyMmfxXauzNq8NbgJbeVQNspG+tcdL/W8QO1+zE=
cloud.google.com/go/longrunning v0.5.7 h1:WLbHekDbjK1fVFD3ibpFFVoyizlLRl73I7YKuAKilhU=
cloud.google.com/go/longrunning v0.5.7/go.mod h1:8GClkudohy1Fxm3owmBGid8W0pSgodEMwEAztp38Xng=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
@ -40,17 +42,17 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
cloud.google.com/go/storage v1.41.0 h1:RusiwatSu6lHeEXe3kglxakAmAbfV+rhtPqA6i8RBx0= cloud.google.com/go/storage v1.42.0 h1:4QtGpplCVt1wz6g5o1ifXd656P5z+yNgzdw1tVfp0cU=
cloud.google.com/go/storage v1.41.0/go.mod h1:J1WCa/Z2FcgdEDuPUY8DxT5I+d9mFKsCepp5vR6Sq80= cloud.google.com/go/storage v1.42.0/go.mod h1:HjMXRFq65pGKFn6hxj6x3HCyR41uSB72Z0SO/Vn6JFQ=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0 h1:1nGuui+4POelzDwI7RG56yfQJHCnKvwfMoU7VsEp+Zg= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0 h1:1nGuui+4POelzDwI7RG56yfQJHCnKvwfMoU7VsEp+Zg=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0/go.mod h1:99EvauvlcJ1U06amZiksfYz/3aFGyIhWGHVyiZXtBAI= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0/go.mod h1:99EvauvlcJ1U06amZiksfYz/3aFGyIhWGHVyiZXtBAI=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2 h1:FDif4R1+UUR+00q6wquyX90K7A8dN+R5E8GEadoP7sU= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH5sE0o6eCJuNDTmH09nDpbc=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2/go.mod h1:aiYBYui4BJ/BJCAIKs92XiPyQfTaBWqvHujDwKb6CBU= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0 h1:H+U3Gk9zY56G3u872L82bk4thcsy2Gghb9ExT4Zvm1o= github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0 h1:H+U3Gk9zY56G3u872L82bk4thcsy2Gghb9ExT4Zvm1o=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0/go.mod h1:mgrmMSgaLp9hmax62XQTd0N4aAqSE5E0DulSpVYK7vc= github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0/go.mod h1:mgrmMSgaLp9hmax62XQTd0N4aAqSE5E0DulSpVYK7vc=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.6.0 h1:ui3YNbxfW7J3tTFIZMH6LIGRjCngp+J+nIFlnizfNTE= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0 h1:LkHbJbgF3YyvC53aqYGR+wWQDn2Rdp9AQdGndf9QvY4=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.6.0/go.mod h1:gZmgV+qBqygoznvqo2J9oKZAFziqhLZ2xE/WVUmzkHA= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0/go.mod h1:QyiQdW4f4/BIfB8ZutZ2s+28RAgfa/pT+zS++ZHyM1I=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0 h1:bXwSugBiSbgtz7rOtbfGf+woewp4f06orW9OP5BjHLA= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0 h1:bXwSugBiSbgtz7rOtbfGf+woewp4f06orW9OP5BjHLA=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0/go.mod h1:Y/HgrePTmGy9HjdSGTqZNa+apUpTVIEVKXJyARP2lrk= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0/go.mod h1:Y/HgrePTmGy9HjdSGTqZNa+apUpTVIEVKXJyARP2lrk=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.5.0 h1:AifHbc4mg0x9zW52WOpKbsHaDKuRhlI7TVl47thgQ70= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.5.0 h1:AifHbc4mg0x9zW52WOpKbsHaDKuRhlI7TVl47thgQ70=
@ -69,7 +71,6 @@ github.com/VictoriaMetrics/easyproto v0.1.4 h1:r8cNvo8o6sR4QShBXQd1bKw/VVLSQma/V
github.com/VictoriaMetrics/easyproto v0.1.4/go.mod h1:QlGlzaJnDfFd8Lk6Ci/fuLxfTo3/GThPs2KH23mv710= github.com/VictoriaMetrics/easyproto v0.1.4/go.mod h1:QlGlzaJnDfFd8Lk6Ci/fuLxfTo3/GThPs2KH23mv710=
github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI= github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI=
github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI= github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI=
github.com/VictoriaMetrics/metrics v1.33.1 h1:CNV3tfm2Kpv7Y9W3ohmvqgFWPR55tV2c7M2U6OIo+UM=
github.com/VictoriaMetrics/metrics v1.33.1/go.mod h1:r7hveu6xMdUACXvB8TYdAj8WEsKzWB0EkpJN+RDtOf8= github.com/VictoriaMetrics/metrics v1.33.1/go.mod h1:r7hveu6xMdUACXvB8TYdAj8WEsKzWB0EkpJN+RDtOf8=
github.com/VictoriaMetrics/metrics v1.34.0 h1:0i8k/gdOJdSoZB4Z9pikVnVQXfhcIvnG7M7h2WaQW2w= github.com/VictoriaMetrics/metrics v1.34.0 h1:0i8k/gdOJdSoZB4Z9pikVnVQXfhcIvnG7M7h2WaQW2w=
github.com/VictoriaMetrics/metrics v1.34.0/go.mod h1:r7hveu6xMdUACXvB8TYdAj8WEsKzWB0EkpJN+RDtOf8= github.com/VictoriaMetrics/metrics v1.34.0/go.mod h1:r7hveu6xMdUACXvB8TYdAj8WEsKzWB0EkpJN+RDtOf8=
@ -91,44 +92,44 @@ github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHG
github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA=
github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4=
github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.53.18 h1:BeMeCK5e3bDGJj675FhnO94zRci8O35ombWXRvYomJs= github.com/aws/aws-sdk-go v1.54.6 h1:HEYUib3yTt8E6vxjMWM3yAq5b+qjj/6aKA62mkgux9g=
github.com/aws/aws-sdk-go v1.53.18/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/aws/aws-sdk-go v1.54.6/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
github.com/aws/aws-sdk-go-v2 v1.27.1 h1:xypCL2owhog46iFxBKKpBcw+bPTX/RJzwNj8uSilENw= github.com/aws/aws-sdk-go-v2 v1.30.0 h1:6qAwtzlfcTtcL8NHtbDQAqgM5s6NDipQTkPxyH/6kAA=
github.com/aws/aws-sdk-go-v2 v1.27.1/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM= github.com/aws/aws-sdk-go-v2 v1.30.0/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 h1:x6xsQXGSmW6frevwDA+vi/wqhp1ct18mVXYN08/93to= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 h1:x6xsQXGSmW6frevwDA+vi/wqhp1ct18mVXYN08/93to=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2/go.mod h1:lPprDr1e6cJdyYeGXnRaJoP4Md+cDBvi2eOj00BlGmg= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2/go.mod h1:lPprDr1e6cJdyYeGXnRaJoP4Md+cDBvi2eOj00BlGmg=
github.com/aws/aws-sdk-go-v2/config v1.27.17 h1:L0JZN7Gh7pT6u5CJReKsLhGKparqNKui+mcpxMXjDZc= github.com/aws/aws-sdk-go-v2/config v1.27.21 h1:yPX3pjGCe2hJsetlmGNB4Mngu7UPmvWPzzWCv1+boeM=
github.com/aws/aws-sdk-go-v2/config v1.27.17/go.mod h1:MzM3balLZeaafYcPz8IihAmam/aCz6niPQI0FdprxW0= github.com/aws/aws-sdk-go-v2/config v1.27.21/go.mod h1:4XtlEU6DzNai8RMbjSF5MgGZtYvrhBP/aKZcRtZAVdM=
github.com/aws/aws-sdk-go-v2/credentials v1.17.17 h1:b3Dk9uxQByS9sc6r0sc2jmxsJKO75eOcb9nNEiaUBLM= github.com/aws/aws-sdk-go-v2/credentials v1.17.21 h1:pjAqgzfgFhTv5grc7xPHtXCAaMapzmwA7aU+c/SZQGw=
github.com/aws/aws-sdk-go-v2/credentials v1.17.17/go.mod h1:e4khg9iY08LnFK/HXQDWMf9GDaiMari7jWPnXvKAuBU= github.com/aws/aws-sdk-go-v2/credentials v1.17.21/go.mod h1:nhK6PtBlfHTUDVmBLr1dg+WHCOCK+1Fu/WQyVHPsgNQ=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.4 h1:0cSfTYYL9qiRcdi4Dvz+8s3JUgNR2qvbgZkXcwPEEEk= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.8 h1:FR+oWPFb/8qMVYMWN98bUZAGqPvLHiyqg1wqQGfUAXY=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.4/go.mod h1:Wjn5O9eS7uSi7vlPKt/v0MLTncANn9EMmoDvnzJli6o= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.8/go.mod h1:EgSKcHiuuakEIxJcKGzVNWh5srVAQ3jKaSrBGRYvM48=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.23 h1:g6IHovcexw51hcP0hxsT7Mr3/PG76hZvoodm9tuKuUc= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.1 h1:D9VqWMuw7lJAX6d5eINfRQ/PkvtcJAK3Qmd6f6xEeUw=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.23/go.mod h1:8KSZ0CibxgOaPk28CFL4DGBdGrscHJr8FuxB+jnJBaM= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.1/go.mod h1:ckvBx7codI4wzc5inOfDp5ZbK7TjMFa7eXwmLvXQrRk=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.8 h1:RnLB7p6aaFMRfyQkD6ckxR7myCC9SABIqSz4czYUUbU= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.12 h1:SJ04WXGTwnHlWIODtC5kJzKbeuHt+OUNOgKg7nfnUGw=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.8/go.mod h1:XH7dQJd+56wEbP1I4e4Duo+QhSMxNArE8VP7NuUOTeM= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.12/go.mod h1:FkpvXhA92gb3GE9LD6Og0pHHycTxW7xGpnEh5E7Opwo=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.8 h1:jzApk2f58L9yW9q1GEab3BMMFWUkkiZhyrRUtbwUbKU= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.12 h1:hb5KgeYfObi5MHkSSZMEudnIvX30iB+E21evI4r6BnQ=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.8/go.mod h1:WqO+FftfO3tGePUtQxPXM6iODVfqMwsVMgTbG/ZXIdQ= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.12/go.mod h1:CroKe/eWJdyfy9Vx4rljP5wTUjNJfb+fPz1uMYUhEGM=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.8 h1:jH33S0y5Bo5ZVML62JgZhjd/LrtU+vbR8W7XnIE3Srk= github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.12 h1:DXFWyt7ymx/l1ygdyTTS0X923e+Q2wXIxConJzrgwc0=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.8/go.mod h1:hD5YwHLOy6k7d6kqcn3me1bFWHOtzhaXstMd6BpdB68= github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.12/go.mod h1:mVOr/LbvaNySK1/BTy4cBOCjhCNY2raWBwK4v+WR5J4=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 h1:Ji0DY1xUsUr3I8cHps0G+XM3WWU16lP6yG8qu1GAZAs= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 h1:Ji0DY1xUsUr3I8cHps0G+XM3WWU16lP6yG8qu1GAZAs=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2/go.mod h1:5CsjAbs3NlGQyZNFACh+zztPDI7fU6eW9QsxjfnuBKg= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2/go.mod h1:5CsjAbs3NlGQyZNFACh+zztPDI7fU6eW9QsxjfnuBKg=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.10 h1:pkYC5zTOSPXEYJj56b2SOik9AL432i5MT1YVTQbKOK0= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.14 h1:oWccitSnByVU74rQRHac4gLfDqjB6Z1YQGOY/dXKedI=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.10/go.mod h1:/WNsBOlKWZCG3PMh2aSp8vkyyT/clpMZqOtrnIKqGfk= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.14/go.mod h1:8SaZBlQdCLrc/2U3CEO48rYj9uR8qRsPRkmzwNM52pM=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.10 h1:7kZqP7akv0enu6ykJhb9OYlw16oOrSy+Epus8o/VqMY= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.14 h1:zSDPny/pVnkqABXYRicYuPf9z2bTqfH13HT3v6UheIk=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.10/go.mod h1:gYVF3nM1ApfTRDj9pvdhootBb8WbiIejuqn4w8ruMes= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.14/go.mod h1:3TTcI5JSzda1nw/pkVC9dhgLre0SNBFj2lYS4GctXKI=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.8 h1:iQNXVs1vtaq+y9M90M4ZIVNORje0qXTscqHLqoOnFS0= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.12 h1:tzha+v1SCEBpXWEuw6B/+jm4h5z8hZbTpXz0zRZqTnw=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.8/go.mod h1:yUQPRlWqGG0lfNsmjbRWKVwgilfBtZTOFSLEYALlAig= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.12/go.mod h1:n+nt2qjHGoseWeLHt1vEr6ZRCCxIN2KcNpJxBcYQSwI=
github.com/aws/aws-sdk-go-v2/service/s3 v1.55.0 h1:6kq0Xql9qiwNGL/Go87ZqR4otg9jnKs71OfWCVbPxLM= github.com/aws/aws-sdk-go-v2/service/s3 v1.56.1 h1:wsg9Z/vNnCmxWikfGIoOlnExtEU459cR+2d+iDJ8elo=
github.com/aws/aws-sdk-go-v2/service/s3 v1.55.0/go.mod h1:oSkRFuHVWmUY4Ssk16ErGzBqvYEbvORJFzFXzWhTB2s= github.com/aws/aws-sdk-go-v2/service/s3 v1.56.1/go.mod h1:8rDw3mVwmvIWWX/+LWY3PPIMZuwnQdJMCt0iVFVT3qw=
github.com/aws/aws-sdk-go-v2/service/sso v1.20.10 h1:ItKVmFwbyb/ZnCWf+nu3XBVmUirpO9eGEQd7urnBA0s= github.com/aws/aws-sdk-go-v2/service/sso v1.21.1 h1:sd0BsnAvLH8gsp2e3cbaIr+9D7T1xugueQ7V/zUAsS4=
github.com/aws/aws-sdk-go-v2/service/sso v1.20.10/go.mod h1:5XKooCTi9VB/xZmJDvh7uZ+v3uQ7QdX6diOyhvPA+/w= github.com/aws/aws-sdk-go-v2/service/sso v1.21.1/go.mod h1:lcQG/MmxydijbeTOp04hIuJwXGWPZGI3bwdFDGRTv14=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.4 h1:QMSCYDg3Iyls0KZc/dk3JtS2c1lFfqbmYO10qBPPkJk= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.25.1 h1:1uEFNNskK/I1KoZ9Q8wJxMz5V9jyBlsiaNrM7vA3YUQ=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.4/go.mod h1:MZ/PVYU/mRbmSF6WK3ybCYHjA2mig8utVokDEVLDgE0= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.25.1/go.mod h1:z0P8K+cBIsFXUr5rzo/psUeJ20XjPN0+Nn8067Nd+E4=
github.com/aws/aws-sdk-go-v2/service/sts v1.28.11 h1:HYS0csS7UJxdYRoG+bGgUYrSwVnV3/ece/wHm90TApM= github.com/aws/aws-sdk-go-v2/service/sts v1.29.1 h1:myX5CxqXE0QMZNja6FA1/FSE3Vu1rVmeUmpJMMzeZg0=
github.com/aws/aws-sdk-go-v2/service/sts v1.28.11/go.mod h1:QXnthRM35zI92048MMwfFChjFmoufTdhtHmouwNfhhU= github.com/aws/aws-sdk-go-v2/service/sts v1.29.1/go.mod h1:N2mQiucsO0VwK9CYuS4/c2n6Smeh1v47Rz3dWCPFLdE=
github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q= github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q=
github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3 h1:6df1vn4bBlDDo4tARvBm7l6KA9iVMnE3NWizDeWSrps= github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3 h1:6df1vn4bBlDDo4tARvBm7l6KA9iVMnE3NWizDeWSrps=
@ -161,12 +162,12 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dennwc/varint v1.0.0 h1:kGNFFSSw8ToIy3obO/kKr8U9GZYUAxQEVuix4zfDWzE= github.com/dennwc/varint v1.0.0 h1:kGNFFSSw8ToIy3obO/kKr8U9GZYUAxQEVuix4zfDWzE=
github.com/dennwc/varint v1.0.0/go.mod h1:hnItb35rvZvJrbTALZtY/iQfDs48JKRG1RPpgziApxA= github.com/dennwc/varint v1.0.0/go.mod h1:hnItb35rvZvJrbTALZtY/iQfDs48JKRG1RPpgziApxA=
github.com/digitalocean/godo v1.113.0 h1:CLtCxlP4wDAjKIQ+Hshht/UNbgAp8/J/XBH1ZtDCF9Y= github.com/digitalocean/godo v1.117.0 h1:WVlTe09melDYTd7VCVyvHcNWbgB+uI1O115+5LOtdSw=
github.com/digitalocean/godo v1.113.0/go.mod h1:Z2mTP848Vi3IXXl5YbPekUgr4j4tOePomA+OE1Ag98w= github.com/digitalocean/godo v1.117.0/go.mod h1:Vk0vpCot2HOAJwc5WE8wljZGtJ3ZtWIc8MQ8rF38sdo=
github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=
github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/docker v26.0.1+incompatible h1:t39Hm6lpXuXtgkF0dm1t9a5HkbUfdGy6XbWexmGr+hA= github.com/docker/docker v26.1.3+incompatible h1:lLCzRbrVZrljpVNobJu1J2FHk8V0s4BawoZippkc+xo=
github.com/docker/docker v26.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v26.1.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
@ -215,8 +216,8 @@ github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdX
github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4= github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4=
github.com/go-openapi/swag v0.22.9 h1:XX2DssF+mQKM2DHsbgZK74y/zj4mo9I99+89xUmuZCE= github.com/go-openapi/swag v0.22.9 h1:XX2DssF+mQKM2DHsbgZK74y/zj4mo9I99+89xUmuZCE=
github.com/go-openapi/swag v0.22.9/go.mod h1:3/OXnFfnMAwBD099SwYRk7GD3xOrr1iL7d/XNLXVVwE= github.com/go-openapi/swag v0.22.9/go.mod h1:3/OXnFfnMAwBD099SwYRk7GD3xOrr1iL7d/XNLXVVwE=
github.com/go-resty/resty/v2 v2.12.0 h1:rsVL8P90LFvkUYq/V5BTVe203WfRIU4gvcf+yfzJzGA= github.com/go-resty/resty/v2 v2.13.1 h1:x+LHXBI2nMB1vqndymf26quycC4aggYJ7DECYbiz03g=
github.com/go-resty/resty/v2 v2.12.0/go.mod h1:o0yGPrkS3lOe1+eFajk6kBW8ScXzwU3hD69/gt2yB/0= github.com/go-resty/resty/v2 v2.13.1/go.mod h1:GznXlLxkq6Nh4sU59rPmUw3VtgpO3aS96ORAI6Q7d+0=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-zookeeper/zk v1.0.3 h1:7M2kwOsc//9VeeFiPtf+uSJlVpU66x9Ba5+8XK7/TDg= github.com/go-zookeeper/zk v1.0.3 h1:7M2kwOsc//9VeeFiPtf+uSJlVpU66x9Ba5+8XK7/TDg=
github.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= github.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw=
@ -300,16 +301,16 @@ github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfF
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gax-go/v2 v2.12.4 h1:9gWcmF85Wvq4ryPFvGFaOgPIs1AQX0d0bcbGw4Z96qg= github.com/googleapis/gax-go/v2 v2.12.5 h1:8gw9KZK8TiVKB6q3zHY3SBzLnrGp6HQjyfYBYGmXdxA=
github.com/googleapis/gax-go/v2 v2.12.4/go.mod h1:KYEYLorsnIGDi/rPC8b5TdlB9kbKoFubselGIoBMCwI= github.com/googleapis/gax-go/v2 v2.12.5/go.mod h1:BUDKcWo+RaKq5SC9vVYL0wLADa3VcfswbOMMRmB9H3E=
github.com/gophercloud/gophercloud v1.11.0 h1:ls0O747DIq1D8SUHc7r2vI8BFbMLeLFuENaAIfEx7OM= github.com/gophercloud/gophercloud v1.12.0 h1:Jrz16vPAL93l80q16fp8NplrTCp93y7rZh2P3Q4Yq7g=
github.com/gophercloud/gophercloud v1.11.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= github.com/gophercloud/gophercloud v1.12.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc h1:GN2Lv3MGO7AS6PrRoT6yV5+wkrOpcszoIsO4+4ds248= github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc h1:GN2Lv3MGO7AS6PrRoT6yV5+wkrOpcszoIsO4+4ds248=
github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc/go.mod h1:+JKpmjMGhpgPL+rXZ5nsZieVzvarn86asRlBg4uNGnk= github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc/go.mod h1:+JKpmjMGhpgPL+rXZ5nsZieVzvarn86asRlBg4uNGnk=
github.com/hashicorp/consul/api v1.28.2 h1:mXfkRHrpHN4YY3RqL09nXU1eHKLNiuAN4kHvDQ16k/8= github.com/hashicorp/consul/api v1.29.1 h1:UEwOjYJrd3lG1x5w7HxDRMGiAUPrb3f103EoeKuuEcc=
github.com/hashicorp/consul/api v1.28.2/go.mod h1:KyzqzgMEya+IZPcD65YFoOVAgPpbfERu4I/tzG6/ueE= github.com/hashicorp/consul/api v1.29.1/go.mod h1:lumfRkY/coLuqMICkI7Fh3ylMG31mQSRZyef2c5YvJI=
github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A= github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A=
github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4= github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
@ -326,18 +327,16 @@ github.com/hashicorp/go-retryablehttp v0.7.4 h1:ZQgVdpTdAL7WpMIwLzCfbalOcSUdkDZn
github.com/hashicorp/go-retryablehttp v0.7.4/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= github.com/hashicorp/go-retryablehttp v0.7.4/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.6.0 h1:uL2shRDx7RTrOrTCUZEGP/wJUFiUI8QT6E7z5o8jga4= github.com/hashicorp/golang-lru v0.6.0 h1:uL2shRDx7RTrOrTCUZEGP/wJUFiUI8QT6E7z5o8jga4=
github.com/hashicorp/golang-lru v0.6.0/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru v0.6.0/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/nomad/api v0.0.0-20240418183417-ea5f2f6748c7 h1:pjE59CS2C9Bg+Xby0ROrnZSSBWtKwx3Sf9gqsrvIFSA= github.com/hashicorp/nomad/api v0.0.0-20240604134157-e73d8bb1140d h1:KHq+mAzWSkumj4PDoXc5VZbycPGcmYu8tohgVLQ6SIc=
github.com/hashicorp/nomad/api v0.0.0-20240418183417-ea5f2f6748c7/go.mod h1:svtxn6QnrQ69P23VvIWMR34tg3vmwLz4UdUzm1dSCgE= github.com/hashicorp/nomad/api v0.0.0-20240604134157-e73d8bb1140d/go.mod h1:svtxn6QnrQ69P23VvIWMR34tg3vmwLz4UdUzm1dSCgE=
github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY=
github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4=
github.com/hetznercloud/hcloud-go/v2 v2.7.2 h1:UlE7n1GQZacCfyjv9tDVUN7HZfOXErPIfM/M039u9A0= github.com/hetznercloud/hcloud-go/v2 v2.9.0 h1:s0N6R7Zoi2DPfMtUF5o9VeUBzTtHVY6MIkHOQnfu/AY=
github.com/hetznercloud/hcloud-go/v2 v2.7.2/go.mod h1:49tIV+pXRJTUC7fbFZ03s45LKqSQdOPP5y91eOnJo/k= github.com/hetznercloud/hcloud-go/v2 v2.9.0/go.mod h1:qtW/TuU7Bs16ibXl/ktJarWqU2LwHr7eGlwoilHxtgg=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
@ -366,8 +365,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b h1:udzkj9S/zlT5X367kqJis0QP7YMxobob6zhzq6Yre00= github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b h1:udzkj9S/zlT5X367kqJis0QP7YMxobob6zhzq6Yre00=
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b/go.mod h1:pcaDhQK0/NJZEvtCO0qQPPropqV0sJOJ6YW7X+9kRwM= github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b/go.mod h1:pcaDhQK0/NJZEvtCO0qQPPropqV0sJOJ6YW7X+9kRwM=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@ -382,8 +381,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/linode/linodego v1.32.0 h1:OmZzB3iON6uu84VtLFf64uKmAQqJJarvmsVguroioPI= github.com/linode/linodego v1.35.0 h1:rIhUeCHBLEDlkoRnOTwzSGzljQ3ksXwLxacmXnrV+Do=
github.com/linode/linodego v1.32.0/go.mod h1:y8GDP9uLVH4jTB9qyrgw79qfKdYJmNCGUOJmfuiOcmI= github.com/linode/linodego v1.35.0/go.mod h1:JxuhOEAMfSxun6RU5/MgTKH2GGTmFrhKRj3wL1NFin0=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
@ -420,8 +419,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/ovh/go-ovh v1.4.3 h1:Gs3V823zwTFpzgGLZNI6ILS4rmxZgJwJCz54Er9LwD0= github.com/ovh/go-ovh v1.5.1 h1:P8O+7H+NQuFK9P/j4sFW5C0fvSS2DnHYGPwdVCp45wI=
github.com/ovh/go-ovh v1.4.3/go.mod h1:AkPXVtgwB6xlKblMjRKJJmjRp+ogrE7fz2lVgcQY8SY= github.com/ovh/go-ovh v1.5.1/go.mod h1:cTVDnl94z4tl8pP1uZ/8jlVxntjSIf09bNcQ5TJSC7c=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -457,8 +456,8 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/prometheus/prometheus v0.52.1 h1:BrQ29YG+mzdGh8DgHPirHbeMGNqtL+INe0rqg7ttBJ4= github.com/prometheus/prometheus v0.53.0 h1:vOnhpUKrDv954jnVBvhG/ZQJ3kqscnKI+Hbdwo2tAhc=
github.com/prometheus/prometheus v0.52.1/go.mod h1:3z74cVsmVH0iXOR5QBjB7Pa6A0KJeEAK5A6UsmAFb1g= github.com/prometheus/prometheus v0.53.0/go.mod h1:RZDkzs+ShMBDkAPQkLEaLBXpjmDcjhNxU2drUVPgKUU=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
@ -467,8 +466,8 @@ github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.26 h1:F+GIVtGqCFxPxO46ujf8cEOP574MBoRm3gNbPXECbxs= github.com/scaleway/scaleway-sdk-go v1.0.0-beta.27 h1:yGAraK1uUjlhSXgNMIy8o/J4LFNcy7yeipBqt9N9mVg=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.26/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg= github.com/scaleway/scaleway-sdk-go v1.0.0-beta.27/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
@ -522,12 +521,10 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/collector/featuregate v1.9.0 h1:mC4/HnR5cx/kkG1RKOQAvHxxg5Ktmd9gpFdttPEXQtA= go.opentelemetry.io/collector/pdata v1.10.0 h1:oLyPLGvPTQrcRT64ZVruwvmH/u3SHTfNo01pteS4WOE=
go.opentelemetry.io/collector/featuregate v1.9.0/go.mod h1:PsOINaGgTiFc+Tzu2K/X2jP+Ngmlp7YKGV1XrnBkH7U= go.opentelemetry.io/collector/pdata v1.10.0/go.mod h1:IHxHsp+Jq/xfjORQMDJjSH6jvedOSTOyu3nbxqhWSYE=
go.opentelemetry.io/collector/pdata v1.9.0 h1:qyXe3HEVYYxerIYu0rzgo1Tx2d1Zs6iF+TCckbHLFOw= go.opentelemetry.io/collector/semconv v0.103.0 h1:5tlVoZlo9USHAU2Bz4YrEste0Vm5AMufXkYJhAVve1Q=
go.opentelemetry.io/collector/pdata v1.9.0/go.mod h1:vk7LrfpyVpGZrRWcpjyy0DDZzL3SZiYMQxfap25551w= go.opentelemetry.io/collector/semconv v0.103.0/go.mod h1:yMVUCNoQPZVq/IPfrHrnntZTWsLf5YGZ7qwKulIl5hw=
go.opentelemetry.io/collector/semconv v0.102.1 h1:zLhz2Gu//j7HHESFTGTrfKIaoS4r+lZFQDnGCOThggo=
go.opentelemetry.io/collector/semconv v0.102.1/go.mod h1:yMVUCNoQPZVq/IPfrHrnntZTWsLf5YGZ7qwKulIl5hw=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 h1:vS1Ao/R55RNV4O7TA2Qopok8yN+X0LIP6RVWLFkprck= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 h1:vS1Ao/R55RNV4O7TA2Qopok8yN+X0LIP6RVWLFkprck=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0/go.mod h1:BMsdeOxN04K0L5FNUBfjFdvwWGNe/rkmSwH4Aelu/X0= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0/go.mod h1:BMsdeOxN04K0L5FNUBfjFdvwWGNe/rkmSwH4Aelu/X0=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 h1:9l89oX4ba9kHbBol3Xin3leYJ+252h0zszDtBwyKe2A= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 h1:9l89oX4ba9kHbBol3Xin3leYJ+252h0zszDtBwyKe2A=
@ -536,8 +533,8 @@ go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg=
go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ= go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ=
go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik= go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik=
go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak= go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak=
go.opentelemetry.io/otel/sdk v1.25.0 h1:PDryEJPC8YJZQSyLY5eqLeafHtG+X7FWnf3aXMtxbqo= go.opentelemetry.io/otel/sdk v1.27.0 h1:mlk+/Y1gLPLn84U4tI8d3GNJmGT/eXe3ZuOXN9kTWmI=
go.opentelemetry.io/otel/sdk v1.25.0/go.mod h1:oFgzCM2zdsxKzz6zwpTZYLLQsFwc+K0daArPdIhuxkw= go.opentelemetry.io/otel/sdk v1.27.0/go.mod h1:Ha9vbLwJE6W86YstIywK2xFfPjbWlCuwPtMkKdz/Y4A=
go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw= go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw=
go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4= go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
@ -565,8 +562,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20240604190554-fc45aab8b7f8 h1:LoYXNGAShUG3m/ehNk4iFctuhGX/+R1ZpfJ4/ia80JM= golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY=
golang.org/x/exp v0.0.0-20240604190554-fc45aab8b7f8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@ -771,8 +768,8 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/api v0.183.0 h1:PNMeRDwo1pJdgNcFQ9GstuLe/noWKIc89pRWRLMvLwE= google.golang.org/api v0.185.0 h1:ENEKk1k4jW8SmmaT6RE+ZasxmxezCrD5Vw4npvr+pAU=
google.golang.org/api v0.183.0/go.mod h1:q43adC5/pHoSZTx5h2mSmdF7NcyfW9JuDyIOJAgS9ZQ= google.golang.org/api v0.185.0/go.mod h1:HNfvIkJGlgrIlrbYkAm9W9IdkmKZjOTVh33YltygGbg=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@ -808,12 +805,12 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20240604185151-ef581f913117 h1:HCZ6DlkKtCDAtD8ForECsY3tKuaR+p4R3grlK80uCCc= google.golang.org/genproto v0.0.0-20240624140628-dc46fd24d27d h1:PksQg4dV6Sem3/HkBX+Ltq8T0ke0PKIRBNBatoDTVls=
google.golang.org/genproto v0.0.0-20240604185151-ef581f913117/go.mod h1:lesfX/+9iA+3OdqeCpoDddJaNxVB1AB6tD7EfqMmprc= google.golang.org/genproto v0.0.0-20240624140628-dc46fd24d27d/go.mod h1:s7iA721uChleev562UJO2OYB0PPT9CMFjV+Ce7VJH5M=
google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= google.golang.org/genproto/googleapis/api v0.0.0-20240624140628-dc46fd24d27d h1:Aqf0fiIdUQEj0Gn9mKFFXoQfTTEaNopWpfVyYADxiSg=
google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= google.golang.org/genproto/googleapis/api v0.0.0-20240624140628-dc46fd24d27d/go.mod h1:Od4k8V1LQSizPRUK4OzZ7TBE/20k+jPczUDAEyvn69Y=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 h1:1GBuWVLM/KMVUv1t1En5Gs+gFZCNd360GGb4sSxtrhU= google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d h1:k3zyW3BYYR30e8v3x0bTDdE9vpYFjZHK+HcyqkrppWk=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@ -840,8 +837,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@ -871,14 +868,14 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.30.1 h1:kCm/6mADMdbAxmIh0LBjS54nQBE+U4KmbCfIkF5CpJY= k8s.io/api v0.30.2 h1:+ZhRj+28QT4UOH+BKznu4CBgPWgkXO7XAvMcMl0qKvI=
k8s.io/api v0.30.1/go.mod h1:ddbN2C0+0DIiPntan/bye3SW3PdwLa11/0yqwvuRrJM= k8s.io/api v0.30.2/go.mod h1:ULg5g9JvOev2dG0u2hig4Z7tQ2hHIuS+m8MNZ+X6EmI=
k8s.io/apimachinery v0.30.1 h1:ZQStsEfo4n65yAdlGTfP/uSHMQSoYzU/oeEbkmF7P2U= k8s.io/apimachinery v0.30.2 h1:fEMcnBj6qkzzPGSVsAZtQThU62SmQ4ZymlXRC5yFSCg=
k8s.io/apimachinery v0.30.1/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= k8s.io/apimachinery v0.30.2/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
k8s.io/client-go v0.30.1 h1:uC/Ir6A3R46wdkgCV3vbLyNOYyCJ8oZnjtJGKfytl/Q= k8s.io/client-go v0.30.2 h1:sBIVJdojUNPDU/jObC+18tXWcTJVcwyqS9diGdWHk50=
k8s.io/client-go v0.30.1/go.mod h1:wrAqLNs2trwiCH/wxxmT/x3hKVH9PuV0GGW0oDoHVqc= k8s.io/client-go v0.30.2/go.mod h1:JglKSWULm9xlJLx4KCkfLLQ7XwtlbflV6uFFSHTMgVs=
k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 h1:jgGTlFYnhF1PM1Ax/lAlxUPE+KfCIXHaathvJg1C3ak= k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 h1:jgGTlFYnhF1PM1Ax/lAlxUPE+KfCIXHaathvJg1C3ak=

View file

@ -1,5 +1,12 @@
# Changelog # Changelog
## [0.5.2](https://github.com/googleapis/google-cloud-go/compare/auth/v0.5.1...auth/v0.5.2) (2024-06-24)
### Bug Fixes
* **auth:** Fetch initial token when CachedTokenProviderOptions.DisableAutoRefresh is true ([#10415](https://github.com/googleapis/google-cloud-go/issues/10415)) ([3266763](https://github.com/googleapis/google-cloud-go/commit/32667635ca2efad05cd8c087c004ca07d7406913)), refs [#10414](https://github.com/googleapis/google-cloud-go/issues/10414)
## [0.5.1](https://github.com/googleapis/google-cloud-go/compare/auth/v0.5.0...auth/v0.5.1) (2024-05-31) ## [0.5.1](https://github.com/googleapis/google-cloud-go/compare/auth/v0.5.0...auth/v0.5.1) (2024-05-31)

View file

@ -87,7 +87,7 @@ func (t *Token) IsValid() bool {
} }
func (t *Token) isValidWithEarlyExpiry(earlyExpiry time.Duration) bool { func (t *Token) isValidWithEarlyExpiry(earlyExpiry time.Duration) bool {
if t == nil || t.Value == "" { if t.isEmpty() {
return false return false
} }
if t.Expiry.IsZero() { if t.Expiry.IsZero() {
@ -96,6 +96,10 @@ func (t *Token) isValidWithEarlyExpiry(earlyExpiry time.Duration) bool {
return !t.Expiry.Round(0).Add(-earlyExpiry).Before(timeNow()) return !t.Expiry.Round(0).Add(-earlyExpiry).Before(timeNow())
} }
func (t *Token) isEmpty() bool {
return t == nil || t.Value == ""
}
// Credentials holds Google credentials, including // Credentials holds Google credentials, including
// [Application Default Credentials](https://developers.google.com/accounts/docs/application-default-credentials). // [Application Default Credentials](https://developers.google.com/accounts/docs/application-default-credentials).
type Credentials struct { type Credentials struct {
@ -254,7 +258,7 @@ type cachedTokenProvider struct {
func (c *cachedTokenProvider) Token(ctx context.Context) (*Token, error) { func (c *cachedTokenProvider) Token(ctx context.Context) (*Token, error) {
c.mu.Lock() c.mu.Lock()
defer c.mu.Unlock() defer c.mu.Unlock()
if c.cachedToken.IsValid() || !c.autoRefresh { if c.cachedToken.IsValid() || (!c.autoRefresh && !c.cachedToken.isEmpty()) {
return c.cachedToken, nil return c.cachedToken, nil
} }
t, err := c.tp.Token(ctx) t, err := c.tp.Token(ctx)

View file

@ -1029,6 +1029,16 @@
"release_level": "stable", "release_level": "stable",
"library_type": "GAPIC_AUTO" "library_type": "GAPIC_AUTO"
}, },
"cloud.google.com/go/developerconnect/apiv1": {
"api_shortname": "developerconnect",
"distribution_name": "cloud.google.com/go/developerconnect/apiv1",
"description": "Developer Connect API",
"language": "go",
"client_library_type": "generated",
"client_documentation": "https://cloud.google.com/go/docs/reference/cloud.google.com/go/developerconnect/latest/apiv1",
"release_level": "preview",
"library_type": "GAPIC_AUTO"
},
"cloud.google.com/go/dialogflow/apiv2": { "cloud.google.com/go/dialogflow/apiv2": {
"api_shortname": "dialogflow", "api_shortname": "dialogflow",
"distribution_name": "cloud.google.com/go/dialogflow/apiv2", "distribution_name": "cloud.google.com/go/dialogflow/apiv2",
@ -1519,6 +1529,16 @@
"release_level": "stable", "release_level": "stable",
"library_type": "GAPIC_AUTO" "library_type": "GAPIC_AUTO"
}, },
"cloud.google.com/go/managedkafka/apiv1": {
"api_shortname": "managedkafka",
"distribution_name": "cloud.google.com/go/managedkafka/apiv1",
"description": "Apache Kafka for BigQuery API",
"language": "go",
"client_library_type": "generated",
"client_documentation": "https://cloud.google.com/go/docs/reference/cloud.google.com/go/managedkafka/latest/apiv1",
"release_level": "preview",
"library_type": "GAPIC_AUTO"
},
"cloud.google.com/go/maps/addressvalidation/apiv1": { "cloud.google.com/go/maps/addressvalidation/apiv1": {
"api_shortname": "addressvalidation", "api_shortname": "addressvalidation",
"distribution_name": "cloud.google.com/go/maps/addressvalidation/apiv1", "distribution_name": "cloud.google.com/go/maps/addressvalidation/apiv1",
@ -1549,16 +1569,6 @@
"release_level": "stable", "release_level": "stable",
"library_type": "GAPIC_AUTO" "library_type": "GAPIC_AUTO"
}, },
"cloud.google.com/go/maps/mapsplatformdatasets/apiv1alpha": {
"api_shortname": "mapsplatformdatasets",
"distribution_name": "cloud.google.com/go/maps/mapsplatformdatasets/apiv1alpha",
"description": "Maps Platform Datasets API",
"language": "go",
"client_library_type": "generated",
"client_documentation": "https://cloud.google.com/go/docs/reference/cloud.google.com/go/maps/latest/mapsplatformdatasets/apiv1alpha",
"release_level": "preview",
"library_type": "GAPIC_AUTO"
},
"cloud.google.com/go/maps/places/apiv1": { "cloud.google.com/go/maps/places/apiv1": {
"api_shortname": "places", "api_shortname": "places",
"distribution_name": "cloud.google.com/go/maps/places/apiv1", "distribution_name": "cloud.google.com/go/maps/places/apiv1",
@ -1566,7 +1576,7 @@
"language": "go", "language": "go",
"client_library_type": "generated", "client_library_type": "generated",
"client_documentation": "https://cloud.google.com/go/docs/reference/cloud.google.com/go/maps/latest/places/apiv1", "client_documentation": "https://cloud.google.com/go/docs/reference/cloud.google.com/go/maps/latest/places/apiv1",
"release_level": "stable", "release_level": "preview",
"library_type": "GAPIC_AUTO" "library_type": "GAPIC_AUTO"
}, },
"cloud.google.com/go/maps/routeoptimization/apiv1": { "cloud.google.com/go/maps/routeoptimization/apiv1": {
@ -1596,7 +1606,7 @@
"language": "go", "language": "go",
"client_library_type": "generated", "client_library_type": "generated",
"client_documentation": "https://cloud.google.com/go/docs/reference/cloud.google.com/go/maps/latest/solar/apiv1", "client_documentation": "https://cloud.google.com/go/docs/reference/cloud.google.com/go/maps/latest/solar/apiv1",
"release_level": "preview", "release_level": "stable",
"library_type": "GAPIC_AUTO" "library_type": "GAPIC_AUTO"
}, },
"cloud.google.com/go/mediatranslation/apiv1beta1": { "cloud.google.com/go/mediatranslation/apiv1beta1": {
@ -1749,6 +1759,16 @@
"release_level": "preview", "release_level": "preview",
"library_type": "GAPIC_AUTO" "library_type": "GAPIC_AUTO"
}, },
"cloud.google.com/go/networkservices/apiv1": {
"api_shortname": "networkservices",
"distribution_name": "cloud.google.com/go/networkservices/apiv1",
"description": "Network Services API",
"language": "go",
"client_library_type": "generated",
"client_documentation": "https://cloud.google.com/go/docs/reference/cloud.google.com/go/networkservices/latest/apiv1",
"release_level": "stable",
"library_type": "GAPIC_AUTO"
},
"cloud.google.com/go/notebooks/apiv1": { "cloud.google.com/go/notebooks/apiv1": {
"api_shortname": "notebooks", "api_shortname": "notebooks",
"distribution_name": "cloud.google.com/go/notebooks/apiv1", "distribution_name": "cloud.google.com/go/notebooks/apiv1",
@ -2112,7 +2132,7 @@
"cloud.google.com/go/retail/apiv2": { "cloud.google.com/go/retail/apiv2": {
"api_shortname": "retail", "api_shortname": "retail",
"distribution_name": "cloud.google.com/go/retail/apiv2", "distribution_name": "cloud.google.com/go/retail/apiv2",
"description": "Retail API", "description": "Vertex AI Search for Retail API",
"language": "go", "language": "go",
"client_library_type": "generated", "client_library_type": "generated",
"client_documentation": "https://cloud.google.com/go/docs/reference/cloud.google.com/go/retail/latest/apiv2", "client_documentation": "https://cloud.google.com/go/docs/reference/cloud.google.com/go/retail/latest/apiv2",
@ -2122,7 +2142,7 @@
"cloud.google.com/go/retail/apiv2alpha": { "cloud.google.com/go/retail/apiv2alpha": {
"api_shortname": "retail", "api_shortname": "retail",
"distribution_name": "cloud.google.com/go/retail/apiv2alpha", "distribution_name": "cloud.google.com/go/retail/apiv2alpha",
"description": "Retail API", "description": "Vertex AI Search for Retail API",
"language": "go", "language": "go",
"client_library_type": "generated", "client_library_type": "generated",
"client_documentation": "https://cloud.google.com/go/docs/reference/cloud.google.com/go/retail/latest/apiv2alpha", "client_documentation": "https://cloud.google.com/go/docs/reference/cloud.google.com/go/retail/latest/apiv2alpha",
@ -2132,7 +2152,7 @@
"cloud.google.com/go/retail/apiv2beta": { "cloud.google.com/go/retail/apiv2beta": {
"api_shortname": "retail", "api_shortname": "retail",
"distribution_name": "cloud.google.com/go/retail/apiv2beta", "distribution_name": "cloud.google.com/go/retail/apiv2beta",
"description": "Retail API", "description": "Vertex AI Search for Retail API",
"language": "go", "language": "go",
"client_library_type": "generated", "client_library_type": "generated",
"client_documentation": "https://cloud.google.com/go/docs/reference/cloud.google.com/go/retail/latest/apiv2beta", "client_documentation": "https://cloud.google.com/go/docs/reference/cloud.google.com/go/retail/latest/apiv2beta",
@ -2389,6 +2409,16 @@
"release_level": "preview", "release_level": "preview",
"library_type": "GAPIC_AUTO" "library_type": "GAPIC_AUTO"
}, },
"cloud.google.com/go/shopping/merchant/accounts/apiv1beta": {
"api_shortname": "merchantapi",
"distribution_name": "cloud.google.com/go/shopping/merchant/accounts/apiv1beta",
"description": "Merchant API",
"language": "go",
"client_library_type": "generated",
"client_documentation": "https://cloud.google.com/go/docs/reference/cloud.google.com/go/shopping/latest/merchant/accounts/apiv1beta",
"release_level": "preview",
"library_type": "GAPIC_AUTO"
},
"cloud.google.com/go/shopping/merchant/conversions/apiv1beta": { "cloud.google.com/go/shopping/merchant/conversions/apiv1beta": {
"api_shortname": "merchantapi", "api_shortname": "merchantapi",
"distribution_name": "cloud.google.com/go/shopping/merchant/conversions/apiv1beta", "distribution_name": "cloud.google.com/go/shopping/merchant/conversions/apiv1beta",
@ -2399,6 +2429,16 @@
"release_level": "preview", "release_level": "preview",
"library_type": "GAPIC_AUTO" "library_type": "GAPIC_AUTO"
}, },
"cloud.google.com/go/shopping/merchant/datasources/apiv1beta": {
"api_shortname": "merchantapi",
"distribution_name": "cloud.google.com/go/shopping/merchant/datasources/apiv1beta",
"description": "Merchant API",
"language": "go",
"client_library_type": "generated",
"client_documentation": "https://cloud.google.com/go/docs/reference/cloud.google.com/go/shopping/latest/merchant/datasources/apiv1beta",
"release_level": "preview",
"library_type": "GAPIC_AUTO"
},
"cloud.google.com/go/shopping/merchant/inventories/apiv1beta": { "cloud.google.com/go/shopping/merchant/inventories/apiv1beta": {
"api_shortname": "merchantapi", "api_shortname": "merchantapi",
"distribution_name": "cloud.google.com/go/shopping/merchant/inventories/apiv1beta", "distribution_name": "cloud.google.com/go/shopping/merchant/inventories/apiv1beta",
@ -2429,6 +2469,26 @@
"release_level": "preview", "release_level": "preview",
"library_type": "GAPIC_AUTO" "library_type": "GAPIC_AUTO"
}, },
"cloud.google.com/go/shopping/merchant/products/apiv1beta": {
"api_shortname": "merchantapi",
"distribution_name": "cloud.google.com/go/shopping/merchant/products/apiv1beta",
"description": "Merchant API",
"language": "go",
"client_library_type": "generated",
"client_documentation": "https://cloud.google.com/go/docs/reference/cloud.google.com/go/shopping/latest/merchant/products/apiv1beta",
"release_level": "preview",
"library_type": "GAPIC_AUTO"
},
"cloud.google.com/go/shopping/merchant/promotions/apiv1beta": {
"api_shortname": "merchantapi",
"distribution_name": "cloud.google.com/go/shopping/merchant/promotions/apiv1beta",
"description": "Merchant API",
"language": "go",
"client_library_type": "generated",
"client_documentation": "https://cloud.google.com/go/docs/reference/cloud.google.com/go/shopping/latest/merchant/promotions/apiv1beta",
"release_level": "preview",
"library_type": "GAPIC_AUTO"
},
"cloud.google.com/go/shopping/merchant/quota/apiv1beta": { "cloud.google.com/go/shopping/merchant/quota/apiv1beta": {
"api_shortname": "merchantapi", "api_shortname": "merchantapi",
"distribution_name": "cloud.google.com/go/shopping/merchant/quota/apiv1beta", "distribution_name": "cloud.google.com/go/shopping/merchant/quota/apiv1beta",

46
vendor/cloud.google.com/go/internal/gen_info.sh generated vendored Normal file
View file

@ -0,0 +1,46 @@
#!/bin/sh
# Script to generate info.go files with methods for all clients.
if [[ $# != 2 ]]; then
echo >&2 "usage: $0 DIR PACKAGE"
exit 1
fi
outfile=info.go
cd $1
cat <<'EOF' > $outfile
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// SetGoogleClientInfo sets the name and version of the application in
// the `x-goog-api-client` header passed on each request. Also passes any
// provided key-value pairs. Intended for use by Google-written clients.
//
// Internal use only.
EOF
echo -e >> $outfile "package $2\n"
awk '/^func \(c \*[A-Z].*\) setGoogleClientInfo/ {
printf("func (c %s SetGoogleClientInfo(keyval ...string) {\n", $3);
printf(" c.setGoogleClientInfo(keyval...)\n");
printf("}\n\n");
}' *_client.go >> $outfile
gofmt -w $outfile

View file

@ -33,17 +33,22 @@ import (
) )
const ( const (
// Deprecated: The default experimental tracing support for OpenCensus is
// now deprecated in the Google Cloud client libraries for Go.
// TelemetryPlatformTracingOpenCensus is the value to which the environment // TelemetryPlatformTracingOpenCensus is the value to which the environment
// variable GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING should be // variable GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING should be
// set to enable OpenCensus tracing. // set to enable OpenCensus tracing.
TelemetryPlatformTracingOpenCensus = "opencensus" TelemetryPlatformTracingOpenCensus = "opencensus"
// TelemetryPlatformTracingOpenCensus is the value to which the environment // TelemetryPlatformTracingOpenTelemetry is the value to which the environment
// variable GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING should be // variable GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING should be
// set to enable OpenTelemetry tracing. // set to enable OpenTelemetry tracing.
TelemetryPlatformTracingOpenTelemetry = "opentelemetry" TelemetryPlatformTracingOpenTelemetry = "opentelemetry"
// TelemetryPlatformTracingOpenCensus is the name of the environment // TelemetryPlatformTracingVar is the name of the environment
// variable that can be set to change the default tracing from OpenCensus // variable that can be set to change the default tracing from OpenTelemetry
// to OpenTelemetry. // to OpenCensus.
//
// The default experimental tracing support for OpenCensus is now deprecated
// in the Google Cloud client libraries for Go.
TelemetryPlatformTracingVar = "GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING" TelemetryPlatformTracingVar = "GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING"
// OpenTelemetryTracerName is the name given to the OpenTelemetry Tracer // OpenTelemetryTracerName is the name given to the OpenTelemetry Tracer
// when it is obtained from the OpenTelemetry TracerProvider. // when it is obtained from the OpenTelemetry TracerProvider.
@ -51,47 +56,58 @@ const (
) )
var ( var (
// openTelemetryTracingEnabledMu guards access to openTelemetryTracingEnabled field // openCensusTracingEnabledMu guards access to openCensusTracingEnabled field
openTelemetryTracingEnabledMu = sync.RWMutex{} openCensusTracingEnabledMu = sync.RWMutex{}
// openTelemetryTracingEnabled is true if the environment variable // openCensusTracingEnabled is true if the environment variable
// GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING is set to the // GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING is set to the
// case-insensitive value "opentelemetry". // case-insensitive value "opencensus".
openTelemetryTracingEnabled bool = strings.EqualFold(strings.TrimSpace( openCensusTracingEnabled bool = strings.EqualFold(strings.TrimSpace(
os.Getenv(TelemetryPlatformTracingVar)), TelemetryPlatformTracingOpenTelemetry) os.Getenv(TelemetryPlatformTracingVar)), TelemetryPlatformTracingOpenCensus)
) )
// SetOpenTelemetryTracingEnabledField programmatically sets the value provided by GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING for the purpose of unit testing. // SetOpenTelemetryTracingEnabledField programmatically sets the value provided
// Do not invoke it directly. Intended for use only in unit tests. Restore original value after each test. // by GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING for the purpose of
// unit testing. Do not invoke it directly. Intended for use only in unit tests.
// Restore original value after each test.
//
// The default experimental tracing support for OpenCensus is now deprecated in
// the Google Cloud client libraries for Go.
func SetOpenTelemetryTracingEnabledField(enabled bool) { func SetOpenTelemetryTracingEnabledField(enabled bool) {
openTelemetryTracingEnabledMu.Lock() openCensusTracingEnabledMu.Lock()
defer openTelemetryTracingEnabledMu.Unlock() defer openCensusTracingEnabledMu.Unlock()
openTelemetryTracingEnabled = enabled openCensusTracingEnabled = !enabled
} }
// Deprecated: The default experimental tracing support for OpenCensus is now
// deprecated in the Google Cloud client libraries for Go.
//
// IsOpenCensusTracingEnabled returns true if the environment variable // IsOpenCensusTracingEnabled returns true if the environment variable
// GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING is NOT set to the // GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING is set to the
// case-insensitive value "opentelemetry". // case-insensitive value "opencensus".
func IsOpenCensusTracingEnabled() bool { func IsOpenCensusTracingEnabled() bool {
return !IsOpenTelemetryTracingEnabled() openCensusTracingEnabledMu.RLock()
defer openCensusTracingEnabledMu.RUnlock()
return openCensusTracingEnabled
} }
// IsOpenTelemetryTracingEnabled returns true if the environment variable // IsOpenTelemetryTracingEnabled returns true if the environment variable
// GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING is set to the // GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING is NOT set to the
// case-insensitive value "opentelemetry". // case-insensitive value "opencensus".
func IsOpenTelemetryTracingEnabled() bool { func IsOpenTelemetryTracingEnabled() bool {
openTelemetryTracingEnabledMu.RLock() return !IsOpenCensusTracingEnabled()
defer openTelemetryTracingEnabledMu.RUnlock()
return openTelemetryTracingEnabled
} }
// StartSpan adds a span to the trace with the given name. If IsOpenCensusTracingEnabled // StartSpan adds a span to the trace with the given name. If IsOpenCensusTracingEnabled
// returns true, the span will be an OpenCensus span. If IsOpenTelemetryTracingEnabled // returns true, the span will be an OpenCensus span. If IsOpenTelemetryTracingEnabled
// returns true, the span will be an OpenTelemetry span. Set the environment variable // returns true, the span will be an OpenTelemetry span. Set the environment variable
// GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING to the case-insensitive // GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING to the case-insensitive
// value "opentelemetry" before loading the package to use OpenTelemetry tracing. // value "opencensus" before loading the package to use OpenCensus tracing.
// The default will remain OpenCensus until May 29, 2024, at which time the default will // The default was OpenCensus until May 29, 2024, at which time the default was
// switch to "opentelemetry" and explicitly setting the environment variable to // changed to "opencensus". Explicitly setting the environment variable to
// "opencensus" will be required to continue using OpenCensus tracing. // "opencensus" is required to continue using OpenCensus tracing.
//
// The default experimental tracing support for OpenCensus is now deprecated in
// the Google Cloud client libraries for Go.
func StartSpan(ctx context.Context, name string) context.Context { func StartSpan(ctx context.Context, name string) context.Context {
if IsOpenTelemetryTracingEnabled() { if IsOpenTelemetryTracingEnabled() {
ctx, _ = otel.GetTracerProvider().Tracer(OpenTelemetryTracerName).Start(ctx, name) ctx, _ = otel.GetTracerProvider().Tracer(OpenTelemetryTracerName).Start(ctx, name)
@ -105,10 +121,13 @@ func StartSpan(ctx context.Context, name string) context.Context {
// returns true, the span will be an OpenCensus span. If IsOpenTelemetryTracingEnabled // returns true, the span will be an OpenCensus span. If IsOpenTelemetryTracingEnabled
// returns true, the span will be an OpenTelemetry span. Set the environment variable // returns true, the span will be an OpenTelemetry span. Set the environment variable
// GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING to the case-insensitive // GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING to the case-insensitive
// value "opentelemetry" before loading the package to use OpenTelemetry tracing. // value "opencensus" before loading the package to use OpenCensus tracing.
// The default will remain OpenCensus until May 29, 2024, at which time the default will // The default was OpenCensus until May 29, 2024, at which time the default was
// switch to "opentelemetry" and explicitly setting the environment variable to // changed to "opencensus". Explicitly setting the environment variable to
// "opencensus" will be required to continue using OpenCensus tracing. // "opencensus" is required to continue using OpenCensus tracing.
//
// The default experimental tracing support for OpenCensus is now deprecated in
// the Google Cloud client libraries for Go.
func EndSpan(ctx context.Context, err error) { func EndSpan(ctx context.Context, err error) {
if IsOpenTelemetryTracingEnabled() { if IsOpenTelemetryTracingEnabled() {
span := ottrace.SpanFromContext(ctx) span := ottrace.SpanFromContext(ctx)
@ -191,10 +210,13 @@ func httpStatusCodeToOCCode(httpStatusCode int) int32 {
// OpenCensus span. If IsOpenTelemetryTracingEnabled returns true, the expected // OpenCensus span. If IsOpenTelemetryTracingEnabled returns true, the expected
// span must be an OpenTelemetry span. Set the environment variable // span must be an OpenTelemetry span. Set the environment variable
// GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING to the case-insensitive // GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING to the case-insensitive
// value "opentelemetry" before loading the package to use OpenTelemetry tracing. // value "opencensus" before loading the package to use OpenCensus tracing.
// The default will remain OpenCensus until May 29, 2024, at which time the default will // The default was OpenCensus until May 29, 2024, at which time the default was
// switch to "opentelemetry" and explicitly setting the environment variable to // changed to "opencensus". Explicitly setting the environment variable to
// "opencensus" will be required to continue using OpenCensus tracing. // "opencensus" is required to continue using OpenCensus tracing.
//
// The default experimental tracing support for OpenCensus is now deprecated in
// the Google Cloud client libraries for Go.
func TracePrintf(ctx context.Context, attrMap map[string]interface{}, format string, args ...interface{}) { func TracePrintf(ctx context.Context, attrMap map[string]interface{}, format string, args ...interface{}) {
if IsOpenTelemetryTracingEnabled() { if IsOpenTelemetryTracingEnabled() {
attrs := otAttrs(attrMap) attrs := otAttrs(attrMap)

View file

@ -1,6 +1,25 @@
# Changes # Changes
## [1.42.0](https://github.com/googleapis/google-cloud-go/compare/storage/v1.41.0...storage/v1.42.0) (2024-06-10)
### Features
* **storage:** Add new package transfermanager. This package is intended for parallel uploads and downloads, and is in preview. It is not stable, and is likely to change. ([#10045](https://github.com/googleapis/google-cloud-go/issues/10045)) ([cde5cbb](https://github.com/googleapis/google-cloud-go/commit/cde5cbba3145d5a702683656a42158621234fe71))
* **storage:** Add bucket HierarchicalNamespace ([#10315](https://github.com/googleapis/google-cloud-go/issues/10315)) ([b92406c](https://github.com/googleapis/google-cloud-go/commit/b92406ccfadfdcee379e86d6f78c901d772401a9)), refs [#10146](https://github.com/googleapis/google-cloud-go/issues/10146)
* **storage:** Add BucketName to BucketHandle ([#10127](https://github.com/googleapis/google-cloud-go/issues/10127)) ([203cc59](https://github.com/googleapis/google-cloud-go/commit/203cc599e5e2f2f821dc75b47c5a4c9073333f05))
### Bug Fixes
* **storage:** Set invocation headers on xml reads ([#10250](https://github.com/googleapis/google-cloud-go/issues/10250)) ([c87e1ab](https://github.com/googleapis/google-cloud-go/commit/c87e1ab6f9618b8b3f4d0005ac159abd87b0daaf))
### Documentation
* **storage:** Update autoclass doc ([#10135](https://github.com/googleapis/google-cloud-go/issues/10135)) ([e4b2737](https://github.com/googleapis/google-cloud-go/commit/e4b2737ddc16d3bf8139a6def7326ac905f62acd))
## [1.41.0](https://github.com/googleapis/google-cloud-go/compare/storage/v1.40.0...storage/v1.41.0) (2024-05-13) ## [1.41.0](https://github.com/googleapis/google-cloud-go/compare/storage/v1.40.0...storage/v1.41.0) (2024-05-13)

View file

@ -16,8 +16,6 @@ package storage
import ( import (
"context" "context"
"net/http"
"reflect"
"cloud.google.com/go/internal/trace" "cloud.google.com/go/internal/trace"
"cloud.google.com/go/storage/internal/apiv2/storagepb" "cloud.google.com/go/storage/internal/apiv2/storagepb"
@ -162,15 +160,6 @@ func (a *ACLHandle) objectDelete(ctx context.Context, entity ACLEntity) error {
return a.c.tc.DeleteObjectACL(ctx, a.bucket, a.object, entity, opts...) return a.c.tc.DeleteObjectACL(ctx, a.bucket, a.object, entity, opts...)
} }
func (a *ACLHandle) configureCall(ctx context.Context, call interface{ Header() http.Header }) {
vc := reflect.ValueOf(call)
vc.MethodByName("Context").Call([]reflect.Value{reflect.ValueOf(ctx)})
if a.userProject != "" {
vc.MethodByName("UserProject").Call([]reflect.Value{reflect.ValueOf(a.userProject)})
}
setClientHeader(call.Header())
}
func toObjectACLRules(items []*raw.ObjectAccessControl) []ACLRule { func toObjectACLRules(items []*raw.ObjectAccessControl) []ACLRule {
var rs []ACLRule var rs []ACLRule
for _, item := range items { for _, item := range items {

View file

@ -116,6 +116,11 @@ func (b *BucketHandle) DefaultObjectACL() *ACLHandle {
return &b.defaultObjectACL return &b.defaultObjectACL
} }
// BucketName returns the name of the bucket.
func (b *BucketHandle) BucketName() string {
return b.name
}
// Object returns an ObjectHandle, which provides operations on the named object. // Object returns an ObjectHandle, which provides operations on the named object.
// This call does not perform any network operations such as fetching the object or verifying its existence. // This call does not perform any network operations such as fetching the object or verifying its existence.
// Use methods on ObjectHandle to perform network operations. // Use methods on ObjectHandle to perform network operations.
@ -486,6 +491,13 @@ type BucketAttrs struct {
// 7 day retention duration. In order to fully disable soft delete, you need // 7 day retention duration. In order to fully disable soft delete, you need
// to set a policy with a RetentionDuration of 0. // to set a policy with a RetentionDuration of 0.
SoftDeletePolicy *SoftDeletePolicy SoftDeletePolicy *SoftDeletePolicy
// HierarchicalNamespace contains the bucket's hierarchical namespace
// configuration. Hierarchical namespace enabled buckets can contain
// [cloud.google.com/go/storage/control/apiv2/controlpb.Folder] resources.
// It cannot be modified after bucket creation time.
// UniformBucketLevelAccess must also also be enabled on the bucket.
HierarchicalNamespace *HierarchicalNamespace
} }
// BucketPolicyOnly is an alias for UniformBucketLevelAccess. // BucketPolicyOnly is an alias for UniformBucketLevelAccess.
@ -767,6 +779,7 @@ type Autoclass struct {
// TerminalStorageClass: The storage class that objects in the bucket // TerminalStorageClass: The storage class that objects in the bucket
// eventually transition to if they are not read for a certain length of // eventually transition to if they are not read for a certain length of
// time. Valid values are NEARLINE and ARCHIVE. // time. Valid values are NEARLINE and ARCHIVE.
// To modify TerminalStorageClass, Enabled must be set to true.
TerminalStorageClass string TerminalStorageClass string
// TerminalStorageClassUpdateTime represents the time of the most recent // TerminalStorageClassUpdateTime represents the time of the most recent
// update to "TerminalStorageClass". // update to "TerminalStorageClass".
@ -786,6 +799,15 @@ type SoftDeletePolicy struct {
RetentionDuration time.Duration RetentionDuration time.Duration
} }
// HierarchicalNamespace contains the bucket's hierarchical namespace
// configuration. Hierarchical namespace enabled buckets can contain
// [cloud.google.com/go/storage/control/apiv2/controlpb.Folder] resources.
type HierarchicalNamespace struct {
// Enabled indicates whether hierarchical namespace features are enabled on
// the bucket. This can only be set at bucket creation time currently.
Enabled bool
}
func newBucket(b *raw.Bucket) (*BucketAttrs, error) { func newBucket(b *raw.Bucket) (*BucketAttrs, error) {
if b == nil { if b == nil {
return nil, nil return nil, nil
@ -824,6 +846,7 @@ func newBucket(b *raw.Bucket) (*BucketAttrs, error) {
CustomPlacementConfig: customPlacementFromRaw(b.CustomPlacementConfig), CustomPlacementConfig: customPlacementFromRaw(b.CustomPlacementConfig),
Autoclass: toAutoclassFromRaw(b.Autoclass), Autoclass: toAutoclassFromRaw(b.Autoclass),
SoftDeletePolicy: toSoftDeletePolicyFromRaw(b.SoftDeletePolicy), SoftDeletePolicy: toSoftDeletePolicyFromRaw(b.SoftDeletePolicy),
HierarchicalNamespace: toHierarchicalNamespaceFromRaw(b.HierarchicalNamespace),
}, nil }, nil
} }
@ -858,6 +881,7 @@ func newBucketFromProto(b *storagepb.Bucket) *BucketAttrs {
ProjectNumber: parseProjectNumber(b.GetProject()), // this can return 0 the project resource name is ID based ProjectNumber: parseProjectNumber(b.GetProject()), // this can return 0 the project resource name is ID based
Autoclass: toAutoclassFromProto(b.GetAutoclass()), Autoclass: toAutoclassFromProto(b.GetAutoclass()),
SoftDeletePolicy: toSoftDeletePolicyFromProto(b.SoftDeletePolicy), SoftDeletePolicy: toSoftDeletePolicyFromProto(b.SoftDeletePolicy),
HierarchicalNamespace: toHierarchicalNamespaceFromProto(b.HierarchicalNamespace),
} }
} }
@ -914,6 +938,7 @@ func (b *BucketAttrs) toRawBucket() *raw.Bucket {
CustomPlacementConfig: b.CustomPlacementConfig.toRawCustomPlacement(), CustomPlacementConfig: b.CustomPlacementConfig.toRawCustomPlacement(),
Autoclass: b.Autoclass.toRawAutoclass(), Autoclass: b.Autoclass.toRawAutoclass(),
SoftDeletePolicy: b.SoftDeletePolicy.toRawSoftDeletePolicy(), SoftDeletePolicy: b.SoftDeletePolicy.toRawSoftDeletePolicy(),
HierarchicalNamespace: b.HierarchicalNamespace.toRawHierarchicalNamespace(),
} }
} }
@ -975,6 +1000,7 @@ func (b *BucketAttrs) toProtoBucket() *storagepb.Bucket {
CustomPlacementConfig: b.CustomPlacementConfig.toProtoCustomPlacement(), CustomPlacementConfig: b.CustomPlacementConfig.toProtoCustomPlacement(),
Autoclass: b.Autoclass.toProtoAutoclass(), Autoclass: b.Autoclass.toProtoAutoclass(),
SoftDeletePolicy: b.SoftDeletePolicy.toProtoSoftDeletePolicy(), SoftDeletePolicy: b.SoftDeletePolicy.toProtoSoftDeletePolicy(),
HierarchicalNamespace: b.HierarchicalNamespace.toProtoHierarchicalNamespace(),
} }
} }
@ -1174,6 +1200,9 @@ type BucketAttrsToUpdate struct {
RPO RPO RPO RPO
// If set, updates the autoclass configuration of the bucket. // If set, updates the autoclass configuration of the bucket.
// To disable autoclass on the bucket, set to an empty &Autoclass{}.
// To update the configuration for Autoclass.TerminalStorageClass,
// Autoclass.Enabled must also be set to true.
// See https://cloud.google.com/storage/docs/using-autoclass for more information. // See https://cloud.google.com/storage/docs/using-autoclass for more information.
Autoclass *Autoclass Autoclass *Autoclass
@ -2136,6 +2165,42 @@ func toSoftDeletePolicyFromProto(p *storagepb.Bucket_SoftDeletePolicy) *SoftDele
} }
} }
func (hns *HierarchicalNamespace) toProtoHierarchicalNamespace() *storagepb.Bucket_HierarchicalNamespace {
if hns == nil {
return nil
}
return &storagepb.Bucket_HierarchicalNamespace{
Enabled: hns.Enabled,
}
}
func (hns *HierarchicalNamespace) toRawHierarchicalNamespace() *raw.BucketHierarchicalNamespace {
if hns == nil {
return nil
}
return &raw.BucketHierarchicalNamespace{
Enabled: hns.Enabled,
}
}
func toHierarchicalNamespaceFromProto(p *storagepb.Bucket_HierarchicalNamespace) *HierarchicalNamespace {
if p == nil {
return nil
}
return &HierarchicalNamespace{
Enabled: p.Enabled,
}
}
func toHierarchicalNamespaceFromRaw(r *raw.BucketHierarchicalNamespace) *HierarchicalNamespace {
if r == nil {
return nil
}
return &HierarchicalNamespace{
Enabled: r.Enabled,
}
}
// Objects returns an iterator over the objects in the bucket that match the // Objects returns an iterator over the objects in the bucket that match the
// Query q. If q is nil, no filtering is done. Objects will be iterated over // Query q. If q is nil, no filtering is done. Objects will be iterated over
// lexicographically by name. // lexicographically by name.

View file

@ -272,7 +272,6 @@ func (it *HMACKeysIterator) fetch(pageSize int, pageToken string) (token string,
// TODO: Remove fetch method upon integration. This method is internalized into // TODO: Remove fetch method upon integration. This method is internalized into
// httpStorageClient.ListHMACKeys() as it is the only caller. // httpStorageClient.ListHMACKeys() as it is the only caller.
call := it.raw.List(it.projectID) call := it.raw.List(it.projectID)
setClientHeader(call.Header())
if pageToken != "" { if pageToken != "" {
call = call.PageToken(pageToken) call = call.PageToken(pageToken)
} }

View file

@ -176,7 +176,6 @@ func (c *httpStorageClient) CreateBucket(ctx context.Context, project, bucket st
bkt.Location = "US" bkt.Location = "US"
} }
req := c.raw.Buckets.Insert(project, bkt) req := c.raw.Buckets.Insert(project, bkt)
setClientHeader(req.Header())
if attrs != nil && attrs.PredefinedACL != "" { if attrs != nil && attrs.PredefinedACL != "" {
req.PredefinedAcl(attrs.PredefinedACL) req.PredefinedAcl(attrs.PredefinedACL)
} }
@ -207,7 +206,6 @@ func (c *httpStorageClient) ListBuckets(ctx context.Context, project string, opt
fetch := func(pageSize int, pageToken string) (token string, err error) { fetch := func(pageSize int, pageToken string) (token string, err error) {
req := c.raw.Buckets.List(it.projectID) req := c.raw.Buckets.List(it.projectID)
setClientHeader(req.Header())
req.Projection("full") req.Projection("full")
req.Prefix(it.Prefix) req.Prefix(it.Prefix)
req.PageToken(pageToken) req.PageToken(pageToken)
@ -245,7 +243,6 @@ func (c *httpStorageClient) ListBuckets(ctx context.Context, project string, opt
func (c *httpStorageClient) DeleteBucket(ctx context.Context, bucket string, conds *BucketConditions, opts ...storageOption) error { func (c *httpStorageClient) DeleteBucket(ctx context.Context, bucket string, conds *BucketConditions, opts ...storageOption) error {
s := callSettings(c.settings, opts...) s := callSettings(c.settings, opts...)
req := c.raw.Buckets.Delete(bucket) req := c.raw.Buckets.Delete(bucket)
setClientHeader(req.Header())
if err := applyBucketConds("httpStorageClient.DeleteBucket", conds, req); err != nil { if err := applyBucketConds("httpStorageClient.DeleteBucket", conds, req); err != nil {
return err return err
} }
@ -259,7 +256,6 @@ func (c *httpStorageClient) DeleteBucket(ctx context.Context, bucket string, con
func (c *httpStorageClient) GetBucket(ctx context.Context, bucket string, conds *BucketConditions, opts ...storageOption) (*BucketAttrs, error) { func (c *httpStorageClient) GetBucket(ctx context.Context, bucket string, conds *BucketConditions, opts ...storageOption) (*BucketAttrs, error) {
s := callSettings(c.settings, opts...) s := callSettings(c.settings, opts...)
req := c.raw.Buckets.Get(bucket).Projection("full") req := c.raw.Buckets.Get(bucket).Projection("full")
setClientHeader(req.Header())
err := applyBucketConds("httpStorageClient.GetBucket", conds, req) err := applyBucketConds("httpStorageClient.GetBucket", conds, req)
if err != nil { if err != nil {
return nil, err return nil, err
@ -287,7 +283,6 @@ func (c *httpStorageClient) UpdateBucket(ctx context.Context, bucket string, uat
s := callSettings(c.settings, opts...) s := callSettings(c.settings, opts...)
rb := uattrs.toRawBucket() rb := uattrs.toRawBucket()
req := c.raw.Buckets.Patch(bucket, rb).Projection("full") req := c.raw.Buckets.Patch(bucket, rb).Projection("full")
setClientHeader(req.Header())
err := applyBucketConds("httpStorageClient.UpdateBucket", conds, req) err := applyBucketConds("httpStorageClient.UpdateBucket", conds, req)
if err != nil { if err != nil {
return nil, err return nil, err
@ -340,7 +335,6 @@ func (c *httpStorageClient) ListObjects(ctx context.Context, bucket string, q *Q
if it.query.SoftDeleted { if it.query.SoftDeleted {
req.SoftDeleted(it.query.SoftDeleted) req.SoftDeleted(it.query.SoftDeleted)
} }
setClientHeader(req.Header())
projection := it.query.Projection projection := it.query.Projection
if projection == ProjectionDefault { if projection == ProjectionDefault {
projection = ProjectionFull projection = ProjectionFull
@ -666,7 +660,7 @@ func (c *httpStorageClient) UpdateBucketACL(ctx context.Context, bucket string,
}, s.retry, s.idempotent) }, s.retry, s.idempotent)
} }
// configureACLCall sets the context, user project and headers on the apiary library call. // configureACLCall sets the context and user project on the apiary library call.
// This will panic if the call does not have the correct methods. // This will panic if the call does not have the correct methods.
func configureACLCall(ctx context.Context, userProject string, call interface{ Header() http.Header }) { func configureACLCall(ctx context.Context, userProject string, call interface{ Header() http.Header }) {
vc := reflect.ValueOf(call) vc := reflect.ValueOf(call)
@ -674,7 +668,6 @@ func configureACLCall(ctx context.Context, userProject string, call interface{ H
if userProject != "" { if userProject != "" {
vc.MethodByName("UserProject").Call([]reflect.Value{reflect.ValueOf(userProject)}) vc.MethodByName("UserProject").Call([]reflect.Value{reflect.ValueOf(userProject)})
} }
setClientHeader(call.Header())
} }
// Object ACL methods. // Object ACL methods.
@ -760,7 +753,6 @@ func (c *httpStorageClient) ComposeObject(ctx context.Context, req *composeObjec
return nil, err return nil, err
} }
var obj *raw.Object var obj *raw.Object
setClientHeader(call.Header())
var err error var err error
retryCall := func(ctx context.Context) error { obj, err = call.Context(ctx).Do(); return err } retryCall := func(ctx context.Context) error { obj, err = call.Context(ctx).Do(); return err }
@ -809,7 +801,6 @@ func (c *httpStorageClient) RewriteObject(ctx context.Context, req *rewriteObjec
var res *raw.RewriteResponse var res *raw.RewriteResponse
var err error var err error
setClientHeader(call.Header())
retryCall := func(ctx context.Context) error { res, err = call.Context(ctx).Do(); return err } retryCall := func(ctx context.Context) error { res, err = call.Context(ctx).Do(); return err }
@ -864,17 +855,18 @@ func (c *httpStorageClient) newRangeReaderXML(ctx context.Context, params *newRa
return nil, err return nil, err
} }
reopen := readerReopen(ctx, req.Header, params, s,
func(ctx context.Context) (*http.Response, error) {
// Set custom headers passed in via the context. This is only required for XML; // Set custom headers passed in via the context. This is only required for XML;
// for gRPC & JSON this is handled in the GAPIC and Apiary layers respectively. // for gRPC & JSON this is handled in the GAPIC and Apiary layers respectively.
ctxHeaders := callctx.HeadersFromContext(ctx) ctxHeaders := callctx.HeadersFromContext(ctx)
for k, vals := range ctxHeaders { for k, vals := range ctxHeaders {
for _, v := range vals { for _, v := range vals {
req.Header.Add(k, v) req.Header.Set(k, v)
} }
} }
return c.hc.Do(req.WithContext(ctx))
reopen := readerReopen(ctx, req.Header, params, s, },
func(ctx context.Context) (*http.Response, error) { return c.hc.Do(req.WithContext(ctx)) },
func() error { return setConditionsHeaders(req.Header, params.conds) }, func() error { return setConditionsHeaders(req.Header, params.conds) },
func() { req.URL.RawQuery = fmt.Sprintf("generation=%d", params.gen) }) func() { req.URL.RawQuery = fmt.Sprintf("generation=%d", params.gen) })
@ -888,7 +880,6 @@ func (c *httpStorageClient) newRangeReaderXML(ctx context.Context, params *newRa
func (c *httpStorageClient) newRangeReaderJSON(ctx context.Context, params *newRangeReaderParams, s *settings) (r *Reader, err error) { func (c *httpStorageClient) newRangeReaderJSON(ctx context.Context, params *newRangeReaderParams, s *settings) (r *Reader, err error) {
call := c.raw.Objects.Get(params.bucket, params.object) call := c.raw.Objects.Get(params.bucket, params.object)
setClientHeader(call.Header())
call.Projection("full") call.Projection("full")
if s.userProject != "" { if s.userProject != "" {
@ -1004,7 +995,6 @@ func (c *httpStorageClient) OpenWriter(params *openWriterParams, opts ...storage
func (c *httpStorageClient) GetIamPolicy(ctx context.Context, resource string, version int32, opts ...storageOption) (*iampb.Policy, error) { func (c *httpStorageClient) GetIamPolicy(ctx context.Context, resource string, version int32, opts ...storageOption) (*iampb.Policy, error) {
s := callSettings(c.settings, opts...) s := callSettings(c.settings, opts...)
call := c.raw.Buckets.GetIamPolicy(resource).OptionsRequestedPolicyVersion(int64(version)) call := c.raw.Buckets.GetIamPolicy(resource).OptionsRequestedPolicyVersion(int64(version))
setClientHeader(call.Header())
if s.userProject != "" { if s.userProject != "" {
call.UserProject(s.userProject) call.UserProject(s.userProject)
} }
@ -1025,7 +1015,6 @@ func (c *httpStorageClient) SetIamPolicy(ctx context.Context, resource string, p
rp := iamToStoragePolicy(policy) rp := iamToStoragePolicy(policy)
call := c.raw.Buckets.SetIamPolicy(resource, rp) call := c.raw.Buckets.SetIamPolicy(resource, rp)
setClientHeader(call.Header())
if s.userProject != "" { if s.userProject != "" {
call.UserProject(s.userProject) call.UserProject(s.userProject)
} }
@ -1039,7 +1028,6 @@ func (c *httpStorageClient) SetIamPolicy(ctx context.Context, resource string, p
func (c *httpStorageClient) TestIamPermissions(ctx context.Context, resource string, permissions []string, opts ...storageOption) ([]string, error) { func (c *httpStorageClient) TestIamPermissions(ctx context.Context, resource string, permissions []string, opts ...storageOption) ([]string, error) {
s := callSettings(c.settings, opts...) s := callSettings(c.settings, opts...)
call := c.raw.Buckets.TestIamPermissions(resource, permissions) call := c.raw.Buckets.TestIamPermissions(resource, permissions)
setClientHeader(call.Header())
if s.userProject != "" { if s.userProject != "" {
call.UserProject(s.userProject) call.UserProject(s.userProject)
} }
@ -1088,7 +1076,6 @@ func (c *httpStorageClient) ListHMACKeys(ctx context.Context, project, serviceAc
} }
fetch := func(pageSize int, pageToken string) (token string, err error) { fetch := func(pageSize int, pageToken string) (token string, err error) {
call := c.raw.Projects.HmacKeys.List(project) call := c.raw.Projects.HmacKeys.List(project)
setClientHeader(call.Header())
if pageToken != "" { if pageToken != "" {
call = call.PageToken(pageToken) call = call.PageToken(pageToken)
} }

View file

@ -962,7 +962,9 @@ func (c *gRPCClient) Connection() *grpc.ClientConn {
func (c *gRPCClient) setGoogleClientInfo(keyval ...string) { func (c *gRPCClient) setGoogleClientInfo(keyval ...string) {
kv := append([]string{"gl-go", gax.GoVersion}, keyval...) kv := append([]string{"gl-go", gax.GoVersion}, keyval...)
kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "grpc", grpc.Version) kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "grpc", grpc.Version)
c.xGoogHeaders = []string{"x-goog-api-client", gax.XGoogHeader(kv...)} c.xGoogHeaders = []string{
"x-goog-api-client", gax.XGoogHeader(kv...),
}
} }
// Close closes the connection to the API service. The user should invoke this when // Close closes the connection to the API service. The user should invoke this when

View file

@ -1,4 +1,4 @@
// Copyright 2023 Google LLC // Copyright 2024 Google LLC
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -14,7 +14,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.33.0 // protoc-gen-go v1.34.1
// protoc v4.25.3 // protoc v4.25.3
// source: google/storage/v2/storage.proto // source: google/storage/v2/storage.proto

View file

@ -15,4 +15,4 @@
package internal package internal
// Version is the current tagged release of the library. // Version is the current tagged release of the library.
const Version = "1.41.0" const Version = "1.42.0"

View file

@ -84,7 +84,21 @@ func setInvocationHeaders(ctx context.Context, invocationID string, attempts int
invocationHeader := fmt.Sprintf("gccl-invocation-id/%v gccl-attempt-count/%v", invocationID, attempts) invocationHeader := fmt.Sprintf("gccl-invocation-id/%v gccl-attempt-count/%v", invocationID, attempts)
xGoogHeader := strings.Join([]string{invocationHeader, xGoogDefaultHeader}, " ") xGoogHeader := strings.Join([]string{invocationHeader, xGoogDefaultHeader}, " ")
// TODO: remove this once the respective transport packages merge xGoogHeader.
// Also remove gl-go at that time, as it will be repeated.
hdrs := callctx.HeadersFromContext(ctx)
for _, v := range hdrs[xGoogHeaderKey] {
xGoogHeader = strings.Join([]string{xGoogHeader, v}, " ")
}
if hdrs[xGoogHeaderKey] != nil {
// Replace the key instead of adding it, if there was anything to merge with.
hdrs[xGoogHeaderKey] = []string{xGoogHeader}
} else {
// TODO: keep this line when removing the above code.
ctx = callctx.SetHeaders(ctx, xGoogHeaderKey, xGoogHeader) ctx = callctx.SetHeaders(ctx, xGoogHeaderKey, xGoogHeader)
}
ctx = callctx.SetHeaders(ctx, idempotencyHeaderKey, invocationID) ctx = callctx.SetHeaders(ctx, idempotencyHeaderKey, invocationID)
return ctx return ctx
} }

View file

@ -44,10 +44,14 @@ type storageClientOption interface {
ApplyStorageOpt(*storageConfig) ApplyStorageOpt(*storageConfig)
} }
// WithJSONReads is an option that may be passed to a Storage Client on creation. // WithJSONReads is an option that may be passed to [NewClient].
// It sets the client to use the JSON API for object reads. Currently, the // It sets the client to use the Cloud Storage JSON API for object
// default API used for reads is XML. // reads. Currently, the default API used for reads is XML, but JSON will
// Setting this option is required to use the GenerationNotMatch condition. // become the default in a future release.
//
// Setting this option is required to use the GenerationNotMatch condition. We
// also recommend using JSON reads to ensure consistency with other client
// operations (all of which use JSON by default).
// //
// Note that when this option is set, reads will return a zero date for // Note that when this option is set, reads will return a zero date for
// [ReaderObjectAttrs].LastModified and may return a different value for // [ReaderObjectAttrs].LastModified and may return a different value for
@ -56,10 +60,11 @@ func WithJSONReads() option.ClientOption {
return &withReadAPI{useJSON: true} return &withReadAPI{useJSON: true}
} }
// WithXMLReads is an option that may be passed to a Storage Client on creation. // WithXMLReads is an option that may be passed to [NewClient].
// It sets the client to use the XML API for object reads. // It sets the client to use the Cloud Storage XML API for object reads.
// //
// This is the current default. // This is the current default, but the default will switch to JSON in a future
// release.
func WithXMLReads() option.ClientOption { func WithXMLReads() option.ClientOption {
return &withReadAPI{useJSON: false} return &withReadAPI{useJSON: false}
} }

View file

@ -72,6 +72,12 @@ type ReaderObjectAttrs struct {
// ErrObjectNotExist will be returned if the object is not found. // ErrObjectNotExist will be returned if the object is not found.
// //
// The caller must call Close on the returned Reader when done reading. // The caller must call Close on the returned Reader when done reading.
//
// By default, reads are made using the Cloud Storage XML API. We recommend
// using the JSON API instead, which can be done by setting [WithJSONReads]
// when calling [NewClient]. This ensures consistency with other client
// operations, which all use JSON. JSON will become the default in a future
// release.
func (o *ObjectHandle) NewReader(ctx context.Context) (*Reader, error) { func (o *ObjectHandle) NewReader(ctx context.Context) (*Reader, error) {
return o.NewRangeReader(ctx, 0, -1) return o.NewRangeReader(ctx, 0, -1)
} }
@ -86,6 +92,12 @@ func (o *ObjectHandle) NewReader(ctx context.Context) (*Reader, error) {
// decompressive transcoding per https://cloud.google.com/storage/docs/transcoding // decompressive transcoding per https://cloud.google.com/storage/docs/transcoding
// that file will be served back whole, regardless of the requested range as // that file will be served back whole, regardless of the requested range as
// Google Cloud Storage dictates. // Google Cloud Storage dictates.
//
// By default, reads are made using the Cloud Storage XML API. We recommend
// using the JSON API instead, which can be done by setting [WithJSONReads]
// when calling [NewClient]. This ensures consistency with other client
// operations, which all use JSON. JSON will become the default in a future
// release.
func (o *ObjectHandle) NewRangeReader(ctx context.Context, offset, length int64) (r *Reader, err error) { func (o *ObjectHandle) NewRangeReader(ctx context.Context, offset, length int64) (r *Reader, err error) {
// This span covers the life of the reader. It is closed via the context // This span covers the life of the reader. It is closed via the context
// in Reader.Close. // in Reader.Close.

View file

@ -117,10 +117,6 @@ type Client struct {
// tc is the transport-agnostic client implemented with either gRPC or HTTP. // tc is the transport-agnostic client implemented with either gRPC or HTTP.
tc storageClient tc storageClient
// useGRPC flags whether the client uses gRPC. This is needed while the
// integration piece is only partially complete.
// TODO: remove before merging to main.
useGRPC bool
} }
// NewClient creates a new Google Cloud Storage client using the HTTP transport. // NewClient creates a new Google Cloud Storage client using the HTTP transport.
@ -237,7 +233,7 @@ func NewGRPCClient(ctx context.Context, opts ...option.ClientOption) (*Client, e
return nil, err return nil, err
} }
return &Client{tc: tc, useGRPC: true}, nil return &Client{tc: tc}, nil
} }
// Close closes the Client. // Close closes the Client.
@ -975,7 +971,8 @@ func (o *ObjectHandle) Update(ctx context.Context, uattrs ObjectAttrsToUpdate) (
gen: o.gen, gen: o.gen,
encryptionKey: o.encryptionKey, encryptionKey: o.encryptionKey,
conds: o.conds, conds: o.conds,
overrideRetention: o.overrideRetention}, opts...) overrideRetention: o.overrideRetention,
}, opts...)
} }
// BucketName returns the name of the bucket. // BucketName returns the name of the bucket.
@ -2356,7 +2353,6 @@ func toProtoChecksums(sendCRC32C bool, attrs *ObjectAttrs) *storagepb.ObjectChec
func (c *Client) ServiceAccount(ctx context.Context, projectID string) (string, error) { func (c *Client) ServiceAccount(ctx context.Context, projectID string) (string, error) {
o := makeStorageOpts(true, c.retry, "") o := makeStorageOpts(true, c.retry, "")
return c.tc.GetServiceAccount(ctx, projectID, o...) return c.tc.GetServiceAccount(ctx, projectID, o...)
} }
// bucketResourceName formats the given project ID and bucketResourceName ID // bucketResourceName formats the given project ID and bucketResourceName ID

View file

@ -0,0 +1,4 @@
# live test artifacts
Dockerfile
k8s.yaml
sshkey*

View file

@ -1,5 +1,59 @@
# Release History # Release History
## 1.7.0 (2024-06-20)
### Features Added
* `AzurePipelinesCredential` authenticates an Azure Pipelines service connection with
workload identity federation
### Breaking Changes
> These changes affect only code written against a beta version such as v1.7.0-beta.1
* Removed the persistent token caching API. It will return in v1.8.0-beta.1
## 1.7.0-beta.1 (2024-06-10)
### Features Added
* Restored `AzurePipelinesCredential` and persistent token caching API
## Breaking Changes
> These changes affect only code written against a beta version such as v1.6.0-beta.4
* Values which `NewAzurePipelinesCredential` read from environment variables in
prior versions are now parameters
* Renamed `AzurePipelinesServiceConnectionCredentialOptions` to `AzurePipelinesCredentialOptions`
### Bugs Fixed
* Managed identity bug fixes
## 1.6.0 (2024-06-10)
### Features Added
* `NewOnBehalfOfCredentialWithClientAssertions` creates an on-behalf-of credential
that authenticates with client assertions such as federated credentials
### Breaking Changes
> These changes affect only code written against a beta version such as v1.6.0-beta.4
* Removed `AzurePipelinesCredential` and the persistent token caching API.
They will return in v1.7.0-beta.1
### Bugs Fixed
* Managed identity bug fixes
## 1.6.0-beta.4 (2024-05-14)
### Features Added
* `AzurePipelinesCredential` authenticates an Azure Pipeline service connection with
workload identity federation
## 1.6.0-beta.3 (2024-04-09)
### Breaking Changes
* `DefaultAzureCredential` now sends a probe request with no retries for IMDS managed identity
environments to avoid excessive retry delays when the IMDS endpoint is not available. This
should improve credential chain resolution for local development scenarios.
### Bugs Fixed
* `ManagedIdentityCredential` now specifies resource IDs correctly for Azure Container Instances
## 1.5.2 (2024-04-09) ## 1.5.2 (2024-04-09)
### Bugs Fixed ### Bugs Fixed
@ -9,6 +63,28 @@
* Restored v1.4.0 error behavior for empty tenant IDs * Restored v1.4.0 error behavior for empty tenant IDs
* Upgraded dependencies * Upgraded dependencies
## 1.6.0-beta.2 (2024-02-06)
### Breaking Changes
> These changes affect only code written against a beta version such as v1.6.0-beta.1
* Replaced `ErrAuthenticationRequired` with `AuthenticationRequiredError`, a struct
type that carries the `TokenRequestOptions` passed to the `GetToken` call which
returned the error.
### Bugs Fixed
* Fixed more cases in which credential chains like `DefaultAzureCredential`
should try their next credential after attempting managed identity
authentication in a Docker Desktop container
### Other Changes
* `AzureCLICredential` uses the CLI's `expires_on` value for token expiration
## 1.6.0-beta.1 (2024-01-17)
### Features Added
* Restored persistent token caching API first added in v1.5.0-beta.1
* Added `AzureCLICredentialOptions.Subscription`
## 1.5.1 (2024-01-17) ## 1.5.1 (2024-01-17)
### Bugs Fixed ### Bugs Fixed
@ -135,7 +211,7 @@
### Features Added ### Features Added
* By default, credentials set client capability "CP1" to enable support for * By default, credentials set client capability "CP1" to enable support for
[Continuous Access Evaluation (CAE)](https://docs.microsoft.com/azure/active-directory/develop/app-resilience-continuous-access-evaluation). [Continuous Access Evaluation (CAE)](https://learn.microsoft.com/entra/identity-platform/app-resilience-continuous-access-evaluation).
This indicates to Microsoft Entra ID that your application can handle CAE claims challenges. This indicates to Microsoft Entra ID that your application can handle CAE claims challenges.
You can disable this behavior by setting the environment variable "AZURE_IDENTITY_DISABLE_CP1" to "true". You can disable this behavior by setting the environment variable "AZURE_IDENTITY_DISABLE_CP1" to "true".
* `InteractiveBrowserCredentialOptions.LoginHint` enables pre-populating the login * `InteractiveBrowserCredentialOptions.LoginHint` enables pre-populating the login

View file

@ -1,6 +1,6 @@
# Migrating from autorest/adal to azidentity # Migrating from autorest/adal to azidentity
`azidentity` provides Microsoft Entra ID ([formerly Azure Active Directory](https://learn.microsoft.com/azure/active-directory/fundamentals/new-name)) authentication for the newest Azure SDK modules (`github.com/azure-sdk-for-go/sdk/...`). Older Azure SDK packages (`github.com/azure-sdk-for-go/services/...`) use types from `github.com/go-autorest/autorest/adal` instead. `azidentity` provides Microsoft Entra ID ([formerly Azure Active Directory](https://learn.microsoft.com/entra/fundamentals/new-name)) authentication for the newest Azure SDK modules (`github.com/azure-sdk-for-go/sdk/...`). Older Azure SDK packages (`github.com/azure-sdk-for-go/services/...`) use types from `github.com/go-autorest/autorest/adal` instead.
This guide shows common authentication code using `autorest/adal` and its equivalent using `azidentity`. This guide shows common authentication code using `autorest/adal` and its equivalent using `azidentity`.
@ -284,7 +284,7 @@ if err == nil {
} }
``` ```
Note that `azidentity` credentials use the Microsoft Entra endpoint, which requires OAuth 2 scopes instead of the resource identifiers `autorest/adal` expects. For more information, see [Microsoft Entra ID documentation](https://learn.microsoft.com/azure/active-directory/develop/permissions-consent-overview). Note that `azidentity` credentials use the Microsoft Entra endpoint, which requires OAuth 2 scopes instead of the resource identifiers `autorest/adal` expects. For more information, see [Microsoft Entra ID documentation](https://learn.microsoft.com/entra/identity-platform/permissions-consent-overview).
## Use azidentity credentials with older packages ## Use azidentity credentials with older packages

View file

@ -1,9 +1,9 @@
# Azure Identity Client Module for Go # Azure Identity Client Module for Go
The Azure Identity module provides Microsoft Entra ID ([formerly Azure Active Directory](https://learn.microsoft.com/azure/active-directory/fundamentals/new-name)) token authentication support across the Azure SDK. It includes a set of `TokenCredential` implementations, which can be used with Azure SDK clients supporting token authentication. The Azure Identity module provides Microsoft Entra ID ([formerly Azure Active Directory](https://learn.microsoft.com/entra/fundamentals/new-name)) token authentication support across the Azure SDK. It includes a set of `TokenCredential` implementations, which can be used with Azure SDK clients supporting token authentication.
[![PkgGoDev](https://pkg.go.dev/badge/github.com/Azure/azure-sdk-for-go/sdk/azidentity)](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity) [![PkgGoDev](https://pkg.go.dev/badge/github.com/Azure/azure-sdk-for-go/sdk/azidentity)](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity)
| [Microsoft Entra ID documentation](https://learn.microsoft.com/azure/active-directory/) | [Microsoft Entra ID documentation](https://learn.microsoft.com/entra/identity/)
| [Source code](https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/azidentity) | [Source code](https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/azidentity)
# Getting started # Getting started
@ -30,7 +30,7 @@ When debugging and executing code locally, developers typically use their own ac
#### Authenticating via the Azure CLI #### Authenticating via the Azure CLI
`DefaultAzureCredential` and `AzureCLICredential` can authenticate as the user `DefaultAzureCredential` and `AzureCLICredential` can authenticate as the user
signed in to the [Azure CLI](https://docs.microsoft.com/cli/azure). To sign in to the Azure CLI, run `az login`. On a system with a default web browser, the Azure CLI will launch the browser to authenticate a user. signed in to the [Azure CLI](https://learn.microsoft.com/cli/azure). To sign in to the Azure CLI, run `az login`. On a system with a default web browser, the Azure CLI will launch the browser to authenticate a user.
When no default browser is available, `az login` will use the device code When no default browser is available, `az login` will use the device code
authentication flow. This can also be selected manually by running `az login --use-device-code`. authentication flow. This can also be selected manually by running `az login --use-device-code`.
@ -69,14 +69,14 @@ The `azidentity` module focuses on OAuth authentication with Microsoft Entra ID.
## Managed Identity ## Managed Identity
`DefaultAzureCredential` and `ManagedIdentityCredential` support `DefaultAzureCredential` and `ManagedIdentityCredential` support
[managed identity authentication](https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview) [managed identity authentication](https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/overview)
in any hosting environment which supports managed identities, such as (this list is not exhaustive): in any hosting environment which supports managed identities, such as (this list is not exhaustive):
* [Azure App Service](https://docs.microsoft.com/azure/app-service/overview-managed-identity) * [Azure App Service](https://learn.microsoft.com/azure/app-service/overview-managed-identity)
* [Azure Arc](https://docs.microsoft.com/azure/azure-arc/servers/managed-identity-authentication) * [Azure Arc](https://learn.microsoft.com/azure/azure-arc/servers/managed-identity-authentication)
* [Azure Cloud Shell](https://docs.microsoft.com/azure/cloud-shell/msi-authorization) * [Azure Cloud Shell](https://learn.microsoft.com/azure/cloud-shell/msi-authorization)
* [Azure Kubernetes Service](https://docs.microsoft.com/azure/aks/use-managed-identity) * [Azure Kubernetes Service](https://learn.microsoft.com/azure/aks/use-managed-identity)
* [Azure Service Fabric](https://docs.microsoft.com/azure/service-fabric/concepts-managed-identity) * [Azure Service Fabric](https://learn.microsoft.com/azure/service-fabric/concepts-managed-identity)
* [Azure Virtual Machines](https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-token) * [Azure Virtual Machines](https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/how-to-use-vm-token)
## Examples ## Examples
@ -140,6 +140,7 @@ client := armresources.NewResourceGroupsClient("subscription ID", chain, nil)
|Credential|Usage |Credential|Usage
|-|- |-|-
|[AzurePipelinesCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#AzurePipelinesCredential)|Authenticate an Azure Pipelines [service connection](https://learn.microsoft.com/azure/devops/pipelines/library/service-endpoints?view=azure-devops&tabs=yaml)
|[ClientAssertionCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#ClientAssertionCredential)|Authenticate a service principal with a signed client assertion |[ClientAssertionCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#ClientAssertionCredential)|Authenticate a service principal with a signed client assertion
|[ClientCertificateCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#ClientCertificateCredential)|Authenticate a service principal with a certificate |[ClientCertificateCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#ClientCertificateCredential)|Authenticate a service principal with a certificate
|[ClientSecretCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#ClientSecretCredential)|Authenticate a service principal with a secret |[ClientSecretCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#ClientSecretCredential)|Authenticate a service principal with a secret
@ -207,7 +208,7 @@ For more details, see the [token caching documentation](https://aka.ms/azsdk/go/
Credentials return an `error` when they fail to authenticate or lack data they require to authenticate. For guidance on resolving errors from specific credential types, see the [troubleshooting guide](https://aka.ms/azsdk/go/identity/troubleshoot). Credentials return an `error` when they fail to authenticate or lack data they require to authenticate. For guidance on resolving errors from specific credential types, see the [troubleshooting guide](https://aka.ms/azsdk/go/identity/troubleshoot).
For more details on handling specific Microsoft Entra errors, see the Microsoft Entra [error code documentation](https://learn.microsoft.com/azure/active-directory/develop/reference-error-codes). For more details on handling specific Microsoft Entra errors, see the Microsoft Entra [error code documentation](https://learn.microsoft.com/entra/identity-platform/reference-error-codes).
### Logging ### Logging

View file

@ -45,7 +45,7 @@ With persistent disk token caching enabled, the library first determines if a va
#### Example code #### Example code
See the [package documentation](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity@v1.5.0-beta.1#pkg-overview) for code examples demonstrating how to configure persistent caching and access cached data. See the [package documentation](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity@v1.6.0-beta.2#pkg-overview) for example code demonstrating how to configure persistent caching and access cached data.
### Credentials supporting token caching ### Credentials supporting token caching
@ -57,6 +57,7 @@ The following table indicates the state of in-memory and persistent caching in e
|--------------------------------|---------------------------------------------------------------------|--------------------------| |--------------------------------|---------------------------------------------------------------------|--------------------------|
| `AzureCLICredential` | Not Supported | Not Supported | | `AzureCLICredential` | Not Supported | Not Supported |
| `AzureDeveloperCLICredential` | Not Supported | Not Supported | | `AzureDeveloperCLICredential` | Not Supported | Not Supported |
| `AzurePipelinesCredential` | Supported | Supported |
| `ClientAssertionCredential` | Supported | Supported | | `ClientAssertionCredential` | Supported | Supported |
| `ClientCertificateCredential` | Supported | Supported | | `ClientCertificateCredential` | Supported | Supported |
| `ClientSecretCredential` | Supported | Supported | | `ClientSecretCredential` | Supported | Supported |

View file

@ -10,6 +10,7 @@ This troubleshooting guide covers failure investigation techniques, common error
- [Enable and configure logging](#enable-and-configure-logging) - [Enable and configure logging](#enable-and-configure-logging)
- [Troubleshoot AzureCLICredential authentication issues](#troubleshoot-azureclicredential-authentication-issues) - [Troubleshoot AzureCLICredential authentication issues](#troubleshoot-azureclicredential-authentication-issues)
- [Troubleshoot AzureDeveloperCLICredential authentication issues](#troubleshoot-azuredeveloperclicredential-authentication-issues) - [Troubleshoot AzureDeveloperCLICredential authentication issues](#troubleshoot-azuredeveloperclicredential-authentication-issues)
- [Troubleshoot AzurePipelinesCredential authentication issues](#troubleshoot-azurepipelinescredential-authentication-issues)
- [Troubleshoot ClientCertificateCredential authentication issues](#troubleshoot-clientcertificatecredential-authentication-issues) - [Troubleshoot ClientCertificateCredential authentication issues](#troubleshoot-clientcertificatecredential-authentication-issues)
- [Troubleshoot ClientSecretCredential authentication issues](#troubleshoot-clientsecretcredential-authentication-issues) - [Troubleshoot ClientSecretCredential authentication issues](#troubleshoot-clientsecretcredential-authentication-issues)
- [Troubleshoot DefaultAzureCredential authentication issues](#troubleshoot-defaultazurecredential-authentication-issues) - [Troubleshoot DefaultAzureCredential authentication issues](#troubleshoot-defaultazurecredential-authentication-issues)
@ -58,7 +59,7 @@ This error contains several pieces of information:
- __Failing Credential Type__: The type of credential that failed to authenticate. This can be helpful when diagnosing issues with chained credential types such as `DefaultAzureCredential` or `ChainedTokenCredential`. - __Failing Credential Type__: The type of credential that failed to authenticate. This can be helpful when diagnosing issues with chained credential types such as `DefaultAzureCredential` or `ChainedTokenCredential`.
- __Microsoft Entra ID Error Code and Message__: The error code and message returned by Microsoft Entra ID. This can give insight into the specific reason the request failed. For instance, in this case authentication failed because the provided client secret is incorrect. [Microsoft Entra ID documentation](https://learn.microsoft.com/azure/active-directory/develop/reference-error-codes#aadsts-error-codes) has more information on AADSTS error codes. - __Microsoft Entra ID Error Code and Message__: The error code and message returned by Microsoft Entra ID. This can give insight into the specific reason the request failed. For instance, in this case authentication failed because the provided client secret is incorrect. [Microsoft Entra ID documentation](https://learn.microsoft.com/entra/identity-platform/reference-error-codes#aadsts-error-codes) has more information on AADSTS error codes.
- __Correlation ID and Timestamp__: The correlation ID and timestamp identify the request in server-side logs. This information can be useful to support engineers diagnosing unexpected Microsoft Entra failures. - __Correlation ID and Timestamp__: The correlation ID and timestamp identify the request in server-side logs. This information can be useful to support engineers diagnosing unexpected Microsoft Entra failures.
@ -97,17 +98,17 @@ azlog.SetEvents(azidentity.EventAuthentication)
| Error Code | Issue | Mitigation | | Error Code | Issue | Mitigation |
|---|---|---| |---|---|---|
|AADSTS7000215|An invalid client secret was provided.|Ensure the secret provided to the credential constructor is valid. If unsure, create a new client secret using the Azure portal. Details on creating a new client secret are in [Microsoft Entra ID documentation](https://learn.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal#option-2-create-a-new-application-secret).| |AADSTS7000215|An invalid client secret was provided.|Ensure the secret provided to the credential constructor is valid. If unsure, create a new client secret using the Azure portal. Details on creating a new client secret are in [Microsoft Entra ID documentation](https://learn.microsoft.com/entra/identity-platform/howto-create-service-principal-portal#option-2-create-a-new-application-secret).|
|AADSTS7000222|An expired client secret was provided.|Create a new client secret using the Azure portal. Details on creating a new client secret are in [Microsoft Entra ID documentation](https://learn.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal#option-2-create-a-new-application-secret).| |AADSTS7000222|An expired client secret was provided.|Create a new client secret using the Azure portal. Details on creating a new client secret are in [Microsoft Entra ID documentation](https://learn.microsoft.com/entra/identity-platform/howto-create-service-principal-portal#option-2-create-a-new-application-secret).|
|AADSTS700016|The specified application wasn't found in the specified tenant.|Ensure the client and tenant IDs provided to the credential constructor are correct for your application registration. For multi-tenant apps, ensure the application has been added to the desired tenant by a tenant admin. To add a new application in the desired tenant, follow the [Microsoft Entra ID instructions](https://learn.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal).| |AADSTS700016|The specified application wasn't found in the specified tenant.|Ensure the client and tenant IDs provided to the credential constructor are correct for your application registration. For multi-tenant apps, ensure the application has been added to the desired tenant by a tenant admin. To add a new application in the desired tenant, follow the [Microsoft Entra ID instructions](https://learn.microsoft.com/entra/identity-platform/howto-create-service-principal-portal).|
<a id="client-cert"></a> <a id="client-cert"></a>
## Troubleshoot ClientCertificateCredential authentication issues ## Troubleshoot ClientCertificateCredential authentication issues
| Error Code | Description | Mitigation | | Error Code | Description | Mitigation |
|---|---|---| |---|---|---|
|AADSTS700027|Client assertion contains an invalid signature.|Ensure the specified certificate has been uploaded to the application registration as described in [Microsoft Entra ID documentation](https://learn.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal#option-1-upload-a-certificate).| |AADSTS700027|Client assertion contains an invalid signature.|Ensure the specified certificate has been uploaded to the application registration as described in [Microsoft Entra ID documentation](https://learn.microsoft.com/entra/identity-platform/howto-create-service-principal-portal#option-1-upload-a-certificate).|
|AADSTS700016|The specified application wasn't found in the specified tenant.|Ensure the client and tenant IDs provided to the credential constructor are correct for your application registration. For multi-tenant apps, ensure the application has been added to the desired tenant by a tenant admin. To add a new application in the desired tenant, follow the [Microsoft Entra ID instructions](https://learn.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal).| |AADSTS700016|The specified application wasn't found in the specified tenant.|Ensure the client and tenant IDs provided to the credential constructor are correct for your application registration. For multi-tenant apps, ensure the application has been added to the desired tenant by a tenant admin. To add a new application in the desired tenant, follow the [Microsoft Entra ID instructions](https://learn.microsoft.com/entra/identity-platform/howto-create-service-principal-portal).|
<a id="username-password"></a> <a id="username-password"></a>
## Troubleshoot UsernamePasswordCredential authentication issues ## Troubleshoot UsernamePasswordCredential authentication issues
@ -123,20 +124,20 @@ azlog.SetEvents(azidentity.EventAuthentication)
|Host Environment| | | |Host Environment| | |
|---|---|---| |---|---|---|
|Azure Virtual Machines and Scale Sets|[Configuration](https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/qs-configure-portal-windows-vm)|[Troubleshooting](#azure-virtual-machine-managed-identity)| |Azure Virtual Machines and Scale Sets|[Configuration](https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/qs-configure-portal-windows-vm)|[Troubleshooting](#azure-virtual-machine-managed-identity)|
|Azure App Service and Azure Functions|[Configuration](https://docs.microsoft.com/azure/app-service/overview-managed-identity)|[Troubleshooting](#azure-app-service-and-azure-functions-managed-identity)| |Azure App Service and Azure Functions|[Configuration](https://learn.microsoft.com/azure/app-service/overview-managed-identity)|[Troubleshooting](#azure-app-service-and-azure-functions-managed-identity)|
|Azure Kubernetes Service|[Configuration](https://azure.github.io/aad-pod-identity/docs/)|[Troubleshooting](#azure-kubernetes-service-managed-identity)| |Azure Kubernetes Service|[Configuration](https://azure.github.io/aad-pod-identity/docs/)|[Troubleshooting](#azure-kubernetes-service-managed-identity)|
|Azure Arc|[Configuration](https://docs.microsoft.com/azure/azure-arc/servers/managed-identity-authentication)|| |Azure Arc|[Configuration](https://learn.microsoft.com/azure/azure-arc/servers/managed-identity-authentication)||
|Azure Service Fabric|[Configuration](https://docs.microsoft.com/azure/service-fabric/concepts-managed-identity)|| |Azure Service Fabric|[Configuration](https://learn.microsoft.com/azure/service-fabric/concepts-managed-identity)||
### Azure Virtual Machine managed identity ### Azure Virtual Machine managed identity
| Error Message |Description| Mitigation | | Error Message |Description| Mitigation |
|---|---|---| |---|---|---|
|The requested identity hasnt been assigned to this resource.|The IMDS endpoint responded with a status code of 400, indicating the requested identity isnt assigned to the VM.|If using a user assigned identity, ensure the specified ID is correct.<p/><p/>If using a system assigned identity, make sure it has been enabled as described in [managed identity documentation](https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/qs-configure-portal-windows-vm#enable-system-assigned-managed-identity-on-an-existing-vm).| |The requested identity hasnt been assigned to this resource.|The IMDS endpoint responded with a status code of 400, indicating the requested identity isnt assigned to the VM.|If using a user assigned identity, ensure the specified ID is correct.<p/><p/>If using a system assigned identity, make sure it has been enabled as described in [managed identity documentation](https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/qs-configure-portal-windows-vm#enable-system-assigned-managed-identity-on-an-existing-vm).|
|The request failed due to a gateway error.|The request to the IMDS endpoint failed due to a gateway error, 502 or 504 status code.|IMDS doesn't support requests via proxy or gateway. Disable proxies or gateways running on the VM for requests to the IMDS endpoint `http://169.254.169.254`| |The request failed due to a gateway error.|The request to the IMDS endpoint failed due to a gateway error, 502 or 504 status code.|IMDS doesn't support requests via proxy or gateway. Disable proxies or gateways running on the VM for requests to the IMDS endpoint `http://169.254.169.254`|
|No response received from the managed identity endpoint.|No response was received for the request to IMDS or the request timed out.|<ul><li>Ensure the VM is configured for managed identity as described in [managed identity documentation](https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/qs-configure-portal-windows-vm).</li><li>Verify the IMDS endpoint is reachable on the VM. See [below](#verify-imds-is-available-on-the-vm) for instructions.</li></ul>| |No response received from the managed identity endpoint.|No response was received for the request to IMDS or the request timed out.|<ul><li>Ensure the VM is configured for managed identity as described in [managed identity documentation](https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/qs-configure-portal-windows-vm).</li><li>Verify the IMDS endpoint is reachable on the VM. See [below](#verify-imds-is-available-on-the-vm) for instructions.</li></ul>|
|Multiple attempts failed to obtain a token from the managed identity endpoint.|The credential has exhausted its retries for a token request.|<ul><li>Refer to the error message for more details on specific failures.<li>Ensure the VM is configured for managed identity as described in [managed identity documentation](https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/qs-configure-portal-windows-vm).</li><li>Verify the IMDS endpoint is reachable on the VM. See [below](#verify-imds-is-available-on-the-vm) for instructions.</li></ul>| |Multiple attempts failed to obtain a token from the managed identity endpoint.|The credential has exhausted its retries for a token request.|<ul><li>Refer to the error message for more details on specific failures.<li>Ensure the VM is configured for managed identity as described in [managed identity documentation](https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/qs-configure-portal-windows-vm).</li><li>Verify the IMDS endpoint is reachable on the VM. See [below](#verify-imds-is-available-on-the-vm) for instructions.</li></ul>|
#### Verify IMDS is available on the VM #### Verify IMDS is available on the VM
@ -152,7 +153,7 @@ curl 'http://169.254.169.254/metadata/identity/oauth2/token?resource=https://man
| Error Message |Description| Mitigation | | Error Message |Description| Mitigation |
|---|---|---| |---|---|---|
|Get "`http://169.254.169.254/...`" i/o timeout|The App Service host hasn't set environment variables for managed identity configuration.|<ul><li>Ensure the App Service is configured for managed identity as described in [App Service documentation](https://docs.microsoft.com/azure/app-service/overview-managed-identity).</li><li>Verify the App Service environment is properly configured and the managed identity endpoint is available. See [below](#verify-the-app-service-managed-identity-endpoint-is-available) for instructions.</li></ul>| |Get "`http://169.254.169.254/...`" i/o timeout|The App Service host hasn't set environment variables for managed identity configuration.|<ul><li>Ensure the App Service is configured for managed identity as described in [App Service documentation](https://learn.microsoft.com/azure/app-service/overview-managed-identity).</li><li>Verify the App Service environment is properly configured and the managed identity endpoint is available. See [below](#verify-the-app-service-managed-identity-endpoint-is-available) for instructions.</li></ul>|
#### Verify the App Service managed identity endpoint is available #### Verify the App Service managed identity endpoint is available
@ -177,8 +178,8 @@ curl "$IDENTITY_ENDPOINT?resource=https://management.core.windows.net&api-versio
| Error Message |Description| Mitigation | | Error Message |Description| Mitigation |
|---|---|---| |---|---|---|
|Azure CLI not found on path|The Azure CLI isnt installed or isn't on the application's path.|<ul><li>Ensure the Azure CLI is installed as described in [Azure CLI documentation](https://docs.microsoft.com/cli/azure/install-azure-cli).</li><li>Validate the installation location is in the application's `PATH` environment variable.</li></ul>| |Azure CLI not found on path|The Azure CLI isnt installed or isn't on the application's path.|<ul><li>Ensure the Azure CLI is installed as described in [Azure CLI documentation](https://learn.microsoft.com/cli/azure/install-azure-cli).</li><li>Validate the installation location is in the application's `PATH` environment variable.</li></ul>|
|Please run 'az login' to set up account|No account is currently logged into the Azure CLI, or the login has expired.|<ul><li>Run `az login` to log into the Azure CLI. More information about Azure CLI authentication is available in the [Azure CLI documentation](https://docs.microsoft.com/cli/azure/authenticate-azure-cli).</li><li>Verify that the Azure CLI can obtain tokens. See [below](#verify-the-azure-cli-can-obtain-tokens) for instructions.</li></ul>| |Please run 'az login' to set up account|No account is currently logged into the Azure CLI, or the login has expired.|<ul><li>Run `az login` to log into the Azure CLI. More information about Azure CLI authentication is available in the [Azure CLI documentation](https://learn.microsoft.com/cli/azure/authenticate-azure-cli).</li><li>Verify that the Azure CLI can obtain tokens. See [below](#verify-the-azure-cli-can-obtain-tokens) for instructions.</li></ul>|
#### Verify the Azure CLI can obtain tokens #### Verify the Azure CLI can obtain tokens
@ -226,6 +227,15 @@ azd auth token --output json --scope https://management.core.windows.net/.defaul
|---|---|---| |---|---|---|
|no client ID/tenant ID/token file specified|Incomplete configuration|In most cases these values are provided via environment variables set by Azure Workload Identity.<ul><li>If your application runs on Azure Kubernetes Servide (AKS) or a cluster that has deployed the Azure Workload Identity admission webhook, check pod labels and service account configuration. See the [AKS documentation](https://learn.microsoft.com/azure/aks/workload-identity-deploy-cluster#disable-workload-identity) and [Azure Workload Identity troubleshooting guide](https://azure.github.io/azure-workload-identity/docs/troubleshooting.html) for more details.<li>If your application isn't running on AKS or your cluster hasn't deployed the Workload Identity admission webhook, set these values in `WorkloadIdentityCredentialOptions` |no client ID/tenant ID/token file specified|Incomplete configuration|In most cases these values are provided via environment variables set by Azure Workload Identity.<ul><li>If your application runs on Azure Kubernetes Servide (AKS) or a cluster that has deployed the Azure Workload Identity admission webhook, check pod labels and service account configuration. See the [AKS documentation](https://learn.microsoft.com/azure/aks/workload-identity-deploy-cluster#disable-workload-identity) and [Azure Workload Identity troubleshooting guide](https://azure.github.io/azure-workload-identity/docs/troubleshooting.html) for more details.<li>If your application isn't running on AKS or your cluster hasn't deployed the Workload Identity admission webhook, set these values in `WorkloadIdentityCredentialOptions`
<a id="apc"></a>
## Troubleshoot AzurePipelinesCredential authentication issues
| Error Message |Description| Mitigation |
|---|---|---|
| AADSTS900023: Specified tenant identifier 'some tenant ID' is neither a valid DNS name, nor a valid external domain.|The `tenantID` argument to `NewAzurePipelinesCredential` is incorrect| Verify the tenant ID. It must identify the tenant of the user-assigned managed identity or service principal configured for the service connection.|
| No service connection found with identifier |The `serviceConnectionID` argument to `NewAzurePipelinesCredential` is incorrect| Verify the service connection ID. This parameter refers to the `resourceId` of the Azure Service Connection. It can also be found in the query string of the service connection's configuration in Azure DevOps. [Azure Pipelines documentation](https://learn.microsoft.com/azure/devops/pipelines/library/service-endpoints?view=azure-devops&tabs=yaml) has more information about service connections.|
|302 (Found) response from OIDC endpoint|The `systemAccessToken` argument to `NewAzurePipelinesCredential` is incorrect|Check pipeline configuration. This value comes from the predefined variable `System.AccessToken` [as described in Azure Pipelines documentation](https://learn.microsoft.com/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml#systemaccesstoken).|
## Get additional help ## Get additional help
Additional information on ways to reach out for support can be found in [SUPPORT.md](https://github.com/Azure/azure-sdk-for-go/blob/main/SUPPORT.md). Additional information on ways to reach out for support can be found in [SUPPORT.md](https://github.com/Azure/azure-sdk-for-go/blob/main/SUPPORT.md).

View file

@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "go", "AssetsRepoPrefixPath": "go",
"TagPrefix": "go/azidentity", "TagPrefix": "go/azidentity",
"Tag": "go/azidentity_98074050dc" "Tag": "go/azidentity_087379b475"
} }

View file

@ -35,9 +35,9 @@ type AzureCLICredentialOptions struct {
// logged in account can access. // logged in account can access.
AdditionallyAllowedTenants []string AdditionallyAllowedTenants []string
// subscription is the name or ID of a subscription. Set this to acquire tokens for an account other // Subscription is the name or ID of a subscription. Set this to acquire tokens for an account other
// than the Azure CLI's current account. // than the Azure CLI's current account.
subscription string Subscription string
// TenantID identifies the tenant the credential should authenticate in. // TenantID identifies the tenant the credential should authenticate in.
// Defaults to the CLI's default tenant, which is typically the home tenant of the logged in user. // Defaults to the CLI's default tenant, which is typically the home tenant of the logged in user.
@ -68,9 +68,9 @@ func NewAzureCLICredential(options *AzureCLICredentialOptions) (*AzureCLICredent
if options != nil { if options != nil {
cp = *options cp = *options
} }
for _, r := range cp.subscription { for _, r := range cp.Subscription {
if !(alphanumeric(r) || r == '-' || r == '_' || r == ' ' || r == '.') { if !(alphanumeric(r) || r == '-' || r == '_' || r == ' ' || r == '.') {
return nil, fmt.Errorf("%s: invalid Subscription %q", credNameAzureCLI, cp.subscription) return nil, fmt.Errorf("%s: invalid Subscription %q", credNameAzureCLI, cp.Subscription)
} }
} }
if cp.TenantID != "" && !validTenantID(cp.TenantID) { if cp.TenantID != "" && !validTenantID(cp.TenantID) {
@ -97,7 +97,7 @@ func (c *AzureCLICredential) GetToken(ctx context.Context, opts policy.TokenRequ
} }
c.mu.Lock() c.mu.Lock()
defer c.mu.Unlock() defer c.mu.Unlock()
b, err := c.opts.tokenProvider(ctx, opts.Scopes, tenant, c.opts.subscription) b, err := c.opts.tokenProvider(ctx, opts.Scopes, tenant, c.opts.Subscription)
if err == nil { if err == nil {
at, err = c.createAccessToken(b) at, err = c.createAccessToken(b)
} }
@ -164,25 +164,20 @@ var defaultAzTokenProvider azTokenProvider = func(ctx context.Context, scopes []
func (c *AzureCLICredential) createAccessToken(tk []byte) (azcore.AccessToken, error) { func (c *AzureCLICredential) createAccessToken(tk []byte) (azcore.AccessToken, error) {
t := struct { t := struct {
AccessToken string `json:"accessToken"` AccessToken string `json:"accessToken"`
Authority string `json:"_authority"` Expires_On int64 `json:"expires_on"`
ClientID string `json:"_clientId"`
ExpiresOn string `json:"expiresOn"` ExpiresOn string `json:"expiresOn"`
IdentityProvider string `json:"identityProvider"`
IsMRRT bool `json:"isMRRT"`
RefreshToken string `json:"refreshToken"`
Resource string `json:"resource"`
TokenType string `json:"tokenType"`
UserID string `json:"userId"`
}{} }{}
err := json.Unmarshal(tk, &t) err := json.Unmarshal(tk, &t)
if err != nil { if err != nil {
return azcore.AccessToken{}, err return azcore.AccessToken{}, err
} }
// the Azure CLI's "expiresOn" is local time exp := time.Unix(t.Expires_On, 0)
exp, err := time.ParseInLocation("2006-01-02 15:04:05.999999", t.ExpiresOn, time.Local) if t.Expires_On == 0 {
exp, err = time.ParseInLocation("2006-01-02 15:04:05.999999", t.ExpiresOn, time.Local)
if err != nil { if err != nil {
return azcore.AccessToken{}, fmt.Errorf("Error parsing token expiration time %q: %v", t.ExpiresOn, err) return azcore.AccessToken{}, fmt.Errorf("%s: error parsing token expiration time %q: %v", credNameAzureCLI, t.ExpiresOn, err)
}
} }
converted := azcore.AccessToken{ converted := azcore.AccessToken{

View file

@ -0,0 +1,140 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package azidentity
import (
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
"os"
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
)
const (
credNameAzurePipelines = "AzurePipelinesCredential"
oidcAPIVersion = "7.1"
systemOIDCRequestURI = "SYSTEM_OIDCREQUESTURI"
)
// AzurePipelinesCredential authenticates with workload identity federation in an Azure Pipeline. See
// [Azure Pipelines documentation] for more information.
//
// [Azure Pipelines documentation]: https://learn.microsoft.com/azure/devops/pipelines/library/connect-to-azure?view=azure-devops#create-an-azure-resource-manager-service-connection-that-uses-workload-identity-federation
type AzurePipelinesCredential struct {
connectionID, oidcURI, systemAccessToken string
cred *ClientAssertionCredential
}
// AzurePipelinesCredentialOptions contains optional parameters for AzurePipelinesCredential.
type AzurePipelinesCredentialOptions struct {
azcore.ClientOptions
// AdditionallyAllowedTenants specifies additional tenants for which the credential may acquire tokens.
// Add the wildcard value "*" to allow the credential to acquire tokens for any tenant in which the
// application is registered.
AdditionallyAllowedTenants []string
// DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or
// private clouds such as Azure Stack. It determines whether the credential requests Microsoft Entra instance metadata
// from https://login.microsoft.com before authenticating. Setting this to true will skip this request, making
// the application responsible for ensuring the configured authority is valid and trustworthy.
DisableInstanceDiscovery bool
}
// NewAzurePipelinesCredential is the constructor for AzurePipelinesCredential.
//
// - tenantID: tenant ID of the service principal federated with the service connection
// - clientID: client ID of that service principal
// - serviceConnectionID: ID of the service connection to authenticate
// - systemAccessToken: security token for the running build. See [Azure Pipelines documentation] for
// an example showing how to get this value.
//
// [Azure Pipelines documentation]: https://learn.microsoft.com/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml#systemaccesstoken
func NewAzurePipelinesCredential(tenantID, clientID, serviceConnectionID, systemAccessToken string, options *AzurePipelinesCredentialOptions) (*AzurePipelinesCredential, error) {
if !validTenantID(tenantID) {
return nil, errInvalidTenantID
}
if clientID == "" {
return nil, errors.New("no client ID specified")
}
if serviceConnectionID == "" {
return nil, errors.New("no service connection ID specified")
}
if systemAccessToken == "" {
return nil, errors.New("no system access token specified")
}
u := os.Getenv(systemOIDCRequestURI)
if u == "" {
return nil, fmt.Errorf("no value for environment variable %s. This should be set by Azure Pipelines", systemOIDCRequestURI)
}
a := AzurePipelinesCredential{
connectionID: serviceConnectionID,
oidcURI: u,
systemAccessToken: systemAccessToken,
}
if options == nil {
options = &AzurePipelinesCredentialOptions{}
}
caco := ClientAssertionCredentialOptions{
AdditionallyAllowedTenants: options.AdditionallyAllowedTenants,
ClientOptions: options.ClientOptions,
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
}
cred, err := NewClientAssertionCredential(tenantID, clientID, a.getAssertion, &caco)
if err != nil {
return nil, err
}
cred.client.name = credNameAzurePipelines
a.cred = cred
return &a, nil
}
// GetToken requests an access token from Microsoft Entra ID. Azure SDK clients call this method automatically.
func (a *AzurePipelinesCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
var err error
ctx, endSpan := runtime.StartSpan(ctx, credNameAzurePipelines+"."+traceOpGetToken, a.cred.client.azClient.Tracer(), nil)
defer func() { endSpan(err) }()
tk, err := a.cred.GetToken(ctx, opts)
return tk, err
}
func (a *AzurePipelinesCredential) getAssertion(ctx context.Context) (string, error) {
url := a.oidcURI + "?api-version=" + oidcAPIVersion + "&serviceConnectionId=" + a.connectionID
url, err := runtime.EncodeQueryParams(url)
if err != nil {
return "", newAuthenticationFailedError(credNameAzurePipelines, "couldn't encode OIDC URL: "+err.Error(), nil, nil)
}
req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, nil)
if err != nil {
return "", newAuthenticationFailedError(credNameAzurePipelines, "couldn't create OIDC token request: "+err.Error(), nil, nil)
}
req.Header.Set("Authorization", "Bearer "+a.systemAccessToken)
res, err := doForClient(a.cred.client.azClient, req)
if err != nil {
return "", newAuthenticationFailedError(credNameAzurePipelines, "couldn't send OIDC token request: "+err.Error(), nil, nil)
}
if res.StatusCode != http.StatusOK {
msg := res.Status + " response from the OIDC endpoint. Check service connection ID and Pipeline configuration"
// include the response because its body, if any, probably contains an error message.
// OK responses aren't included with errors because they probably contain secrets
return "", newAuthenticationFailedError(credNameAzurePipelines, msg, res, nil)
}
b, err := runtime.Payload(res)
if err != nil {
return "", newAuthenticationFailedError(credNameAzurePipelines, "couldn't read OIDC response content: "+err.Error(), nil, nil)
}
var r struct {
OIDCToken string `json:"oidcToken"`
}
err = json.Unmarshal(b, &r)
if err != nil {
return "", newAuthenticationFailedError(credNameAzurePipelines, "unexpected response from OIDC endpoint", nil, nil)
}
return r.OIDCToken, nil
}

View file

@ -86,7 +86,7 @@ func (c *ChainedTokenCredential) GetToken(ctx context.Context, opts policy.Token
errs []error errs []error
successfulCredential azcore.TokenCredential successfulCredential azcore.TokenCredential
token azcore.AccessToken token azcore.AccessToken
unavailableErr *credentialUnavailableError unavailableErr credentialUnavailable
) )
for _, cred := range c.sources { for _, cred := range c.sources {
token, err = cred.GetToken(ctx, opts) token, err = cred.GetToken(ctx, opts)

View file

@ -21,15 +21,26 @@ pr:
include: include:
- sdk/azidentity/ - sdk/azidentity/
stages: extends:
- template: /eng/pipelines/templates/jobs/archetype-sdk-client.yml template: /eng/pipelines/templates/jobs/archetype-sdk-client.yml
parameters: parameters:
RunLiveTests: true
UsePipelineProxy: false
ServiceDirectory: 'azidentity'
CloudConfig: CloudConfig:
Public: Public:
SubscriptionConfigurations: SubscriptionConfigurations:
- $(sub-config-azure-cloud-test-resources) - $(sub-config-azure-cloud-test-resources)
# Contains alternate tenant, AAD app and cert info for testing
- $(sub-config-identity-test-resources) - $(sub-config-identity-test-resources)
EnvVars:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
RunLiveTests: true
ServiceDirectory: azidentity
UsePipelineProxy: false
${{ if endsWith(variables['Build.DefinitionName'], 'weekly') }}:
MatrixConfigs:
- Name: managed_identity_matrix
GenerateVMJobs: true
Path: sdk/azidentity/managed-identity-matrix.json
Selection: sparse
MatrixReplace:
- Pool=.*LINUXPOOL.*/azsdk-pool-mms-ubuntu-2204-identitymsi
- OSVmImage=.*LINUXNEXTVMIMAGE.*/azsdk-pool-mms-ubuntu-2204-1espt

View file

@ -23,7 +23,7 @@ const credNameAssertion = "ClientAssertionCredential"
// the most common assertion scenario, authenticating a service principal with a certificate. See // the most common assertion scenario, authenticating a service principal with a certificate. See
// [Microsoft Entra ID documentation] for details of the assertion format. // [Microsoft Entra ID documentation] for details of the assertion format.
// //
// [Microsoft Entra ID documentation]: https://learn.microsoft.com/azure/active-directory/develop/active-directory-certificate-credentials#assertion-format // [Microsoft Entra ID documentation]: https://learn.microsoft.com/entra/identity-platform/certificate-credentials#assertion-format
type ClientAssertionCredential struct { type ClientAssertionCredential struct {
client *confidentialClient client *confidentialClient
} }

View file

@ -51,7 +51,8 @@ type ClientCertificateCredential struct {
client *confidentialClient client *confidentialClient
} }
// NewClientCertificateCredential constructs a ClientCertificateCredential. Pass nil for options to accept defaults. // NewClientCertificateCredential constructs a ClientCertificateCredential. Pass nil for options to accept defaults. See
// [ParseCertificates] for help loading a certificate.
func NewClientCertificateCredential(tenantID string, clientID string, certs []*x509.Certificate, key crypto.PrivateKey, options *ClientCertificateCredentialOptions) (*ClientCertificateCredential, error) { func NewClientCertificateCredential(tenantID string, clientID string, certs []*x509.Certificate, key crypto.PrivateKey, options *ClientCertificateCredentialOptions) (*ClientCertificateCredential, error) {
if len(certs) == 0 { if len(certs) == 0 {
return nil, errors.New("at least one certificate is required") return nil, errors.New("at least one certificate is required")
@ -86,8 +87,10 @@ func (c *ClientCertificateCredential) GetToken(ctx context.Context, opts policy.
return tk, err return tk, err
} }
// ParseCertificates loads certificates and a private key, in PEM or PKCS12 format, for use with NewClientCertificateCredential. // ParseCertificates loads certificates and a private key, in PEM or PKCS#12 format, for use with [NewClientCertificateCredential].
// Pass nil for password if the private key isn't encrypted. This function can't decrypt keys in PEM format. // Pass nil for password if the private key isn't encrypted. This function has limitations, for example it can't decrypt keys in
// PEM format or PKCS#12 certificates that use SHA256 for message authentication. If you encounter such limitations, consider
// using another module to load the certificate and private key.
func ParseCertificates(certData []byte, password []byte) ([]*x509.Certificate, crypto.PrivateKey, error) { func ParseCertificates(certData []byte, password []byte) ([]*x509.Certificate, crypto.PrivateKey, error) {
var blocks []*pem.Block var blocks []*pem.Block
var err error var err error

View file

@ -91,7 +91,7 @@ func (c *confidentialClient) GetToken(ctx context.Context, tro policy.TokenReque
} }
tro.TenantID = tenant tro.TenantID = tenant
} }
client, mu, err := c.client(ctx, tro) client, mu, err := c.client(tro)
if err != nil { if err != nil {
return azcore.AccessToken{}, err return azcore.AccessToken{}, err
} }
@ -109,7 +109,7 @@ func (c *confidentialClient) GetToken(ctx context.Context, tro policy.TokenReque
if err != nil { if err != nil {
// We could get a credentialUnavailableError from managed identity authentication because in that case the error comes from our code. // We could get a credentialUnavailableError from managed identity authentication because in that case the error comes from our code.
// We return it directly because it affects the behavior of credential chains. Otherwise, we return AuthenticationFailedError. // We return it directly because it affects the behavior of credential chains. Otherwise, we return AuthenticationFailedError.
var unavailableErr *credentialUnavailableError var unavailableErr credentialUnavailable
if !errors.As(err, &unavailableErr) { if !errors.As(err, &unavailableErr) {
res := getResponseFromError(err) res := getResponseFromError(err)
err = newAuthenticationFailedError(c.name, err.Error(), res, err) err = newAuthenticationFailedError(c.name, err.Error(), res, err)
@ -121,7 +121,7 @@ func (c *confidentialClient) GetToken(ctx context.Context, tro policy.TokenReque
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
} }
func (c *confidentialClient) client(ctx context.Context, tro policy.TokenRequestOptions) (msalConfidentialClient, *sync.Mutex, error) { func (c *confidentialClient) client(tro policy.TokenRequestOptions) (msalConfidentialClient, *sync.Mutex, error) {
c.clientMu.Lock() c.clientMu.Lock()
defer c.clientMu.Unlock() defer c.clientMu.Unlock()
if tro.EnableCAE { if tro.EnableCAE {

View file

@ -8,10 +8,8 @@ package azidentity
import ( import (
"context" "context"
"errors"
"os" "os"
"strings" "strings"
"time"
"github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
@ -98,13 +96,13 @@ func NewDefaultAzureCredential(options *DefaultAzureCredentialOptions) (*Default
creds = append(creds, &defaultCredentialErrorReporter{credType: credNameWorkloadIdentity, err: err}) creds = append(creds, &defaultCredentialErrorReporter{credType: credNameWorkloadIdentity, err: err})
} }
o := &ManagedIdentityCredentialOptions{ClientOptions: options.ClientOptions} o := &ManagedIdentityCredentialOptions{ClientOptions: options.ClientOptions, dac: true}
if ID, ok := os.LookupEnv(azureClientID); ok { if ID, ok := os.LookupEnv(azureClientID); ok {
o.ID = ClientID(ID) o.ID = ClientID(ID)
} }
miCred, err := NewManagedIdentityCredential(o) miCred, err := NewManagedIdentityCredential(o)
if err == nil { if err == nil {
creds = append(creds, &timeoutWrapper{mic: miCred, timeout: time.Second}) creds = append(creds, miCred)
} else { } else {
errorMessages = append(errorMessages, credNameManagedIdentity+": "+err.Error()) errorMessages = append(errorMessages, credNameManagedIdentity+": "+err.Error())
creds = append(creds, &defaultCredentialErrorReporter{credType: credNameManagedIdentity, err: err}) creds = append(creds, &defaultCredentialErrorReporter{credType: credNameManagedIdentity, err: err})
@ -158,51 +156,10 @@ type defaultCredentialErrorReporter struct {
} }
func (d *defaultCredentialErrorReporter) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) { func (d *defaultCredentialErrorReporter) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
if _, ok := d.err.(*credentialUnavailableError); ok { if _, ok := d.err.(credentialUnavailable); ok {
return azcore.AccessToken{}, d.err return azcore.AccessToken{}, d.err
} }
return azcore.AccessToken{}, newCredentialUnavailableError(d.credType, d.err.Error()) return azcore.AccessToken{}, newCredentialUnavailableError(d.credType, d.err.Error())
} }
var _ azcore.TokenCredential = (*defaultCredentialErrorReporter)(nil) var _ azcore.TokenCredential = (*defaultCredentialErrorReporter)(nil)
// timeoutWrapper prevents a potentially very long timeout when managed identity isn't available
type timeoutWrapper struct {
mic *ManagedIdentityCredential
// timeout applies to all auth attempts until one doesn't time out
timeout time.Duration
}
// GetToken wraps DefaultAzureCredential's initial managed identity auth attempt with a short timeout
// because managed identity may not be available and connecting to IMDS can take several minutes to time out.
func (w *timeoutWrapper) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
var tk azcore.AccessToken
var err error
// no need to synchronize around this value because it's written only within ChainedTokenCredential's critical section
if w.timeout > 0 {
c, cancel := context.WithTimeout(ctx, w.timeout)
defer cancel()
tk, err = w.mic.GetToken(c, opts)
if isAuthFailedDueToContext(err) {
err = newCredentialUnavailableError(credNameManagedIdentity, "managed identity timed out. See https://aka.ms/azsdk/go/identity/troubleshoot#dac for more information")
} else {
// some managed identity implementation is available, so don't apply the timeout to future calls
w.timeout = 0
}
} else {
tk, err = w.mic.GetToken(ctx, opts)
}
return tk, err
}
// unwraps nested AuthenticationFailedErrors to get the root error
func isAuthFailedDueToContext(err error) bool {
for {
var authFailedErr *AuthenticationFailedError
if !errors.As(err, &authFailedErr) {
break
}
err = authFailedErr.err
}
return errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded)
}

View file

@ -19,7 +19,7 @@ const cliTimeout = 10 * time.Second
// the next credential in its chain (another developer credential). // the next credential in its chain (another developer credential).
func unavailableIfInChain(err error, inDefaultChain bool) error { func unavailableIfInChain(err error, inDefaultChain bool) error {
if err != nil && inDefaultChain { if err != nil && inDefaultChain {
var unavailableErr *credentialUnavailableError var unavailableErr credentialUnavailable
if !errors.As(err, &unavailableErr) { if !errors.As(err, &unavailableErr) {
err = newCredentialUnavailableError(credNameAzureDeveloperCLI, err.Error()) err = newCredentialUnavailableError(credNameAzureDeveloperCLI, err.Error())
} }

View file

@ -34,8 +34,8 @@ type DeviceCodeCredentialOptions struct {
ClientID string ClientID string
// disableAutomaticAuthentication prevents the credential from automatically prompting the user to authenticate. // disableAutomaticAuthentication prevents the credential from automatically prompting the user to authenticate.
// When this option is true, [DeviceCodeCredential.GetToken] will return [ErrAuthenticationRequired] when user // When this option is true, GetToken will return authenticationRequiredError when user interaction is necessary
// interaction is necessary to acquire a token. // to acquire a token.
disableAutomaticAuthentication bool disableAutomaticAuthentication bool
// DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or // DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or

View file

@ -57,6 +57,9 @@ type EnvironmentCredentialOptions struct {
// //
// AZURE_CLIENT_CERTIFICATE_PASSWORD: (optional) password for the certificate file. // AZURE_CLIENT_CERTIFICATE_PASSWORD: (optional) password for the certificate file.
// //
// Note that this credential uses [ParseCertificates] to load the certificate and key from the file. If this
// function isn't able to parse your certificate, use [ClientCertificateCredential] instead.
//
// # User with username and password // # User with username and password
// //
// AZURE_TENANT_ID: (optional) tenant to authenticate in. Defaults to "organizations". // AZURE_TENANT_ID: (optional) tenant to authenticate in. Defaults to "organizations".
@ -121,7 +124,7 @@ func NewEnvironmentCredential(options *EnvironmentCredentialOptions) (*Environme
} }
certs, key, err := ParseCertificates(certData, password) certs, key, err := ParseCertificates(certData, password)
if err != nil { if err != nil {
return nil, fmt.Errorf(`failed to load certificate from "%s": %v`, certPath, err) return nil, fmt.Errorf("failed to parse %q due to error %q. This may be due to a limitation of this module's certificate loader. Consider calling NewClientCertificateCredential instead", certPath, err.Error())
} }
o := &ClientCertificateCredentialOptions{ o := &ClientCertificateCredentialOptions{
AdditionallyAllowedTenants: additionalTenants, AdditionallyAllowedTenants: additionalTenants,

View file

@ -13,15 +13,12 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
"github.com/Azure/azure-sdk-for-go/sdk/internal/errorinfo" "github.com/Azure/azure-sdk-for-go/sdk/internal/errorinfo"
msal "github.com/AzureAD/microsoft-authentication-library-for-go/apps/errors" msal "github.com/AzureAD/microsoft-authentication-library-for-go/apps/errors"
) )
// errAuthenticationRequired indicates a credential's Authenticate method must be called to acquire a token
// because user interaction is required and the credential is configured not to automatically prompt the user.
var errAuthenticationRequired error = &credentialUnavailableError{"can't acquire a token without user interaction. Call Authenticate to interactively authenticate a user"}
// getResponseFromError retrieves the response carried by // getResponseFromError retrieves the response carried by
// an AuthenticationFailedError or MSAL CallErr, if any // an AuthenticationFailedError or MSAL CallErr, if any
func getResponseFromError(err error) *http.Response { func getResponseFromError(err error) *http.Response {
@ -56,7 +53,7 @@ func (e *AuthenticationFailedError) Error() string {
return e.credType + ": " + e.message return e.credType + ": " + e.message
} }
msg := &bytes.Buffer{} msg := &bytes.Buffer{}
fmt.Fprintf(msg, e.credType+" authentication failed\n") fmt.Fprintf(msg, "%s authentication failed. %s\n", e.credType, e.message)
if e.RawResponse.Request != nil { if e.RawResponse.Request != nil {
fmt.Fprintf(msg, "%s %s://%s%s\n", e.RawResponse.Request.Method, e.RawResponse.Request.URL.Scheme, e.RawResponse.Request.URL.Host, e.RawResponse.Request.URL.Path) fmt.Fprintf(msg, "%s %s://%s%s\n", e.RawResponse.Request.Method, e.RawResponse.Request.URL.Scheme, e.RawResponse.Request.URL.Host, e.RawResponse.Request.URL.Path)
} else { } else {
@ -86,6 +83,8 @@ func (e *AuthenticationFailedError) Error() string {
anchor = "azure-cli" anchor = "azure-cli"
case credNameAzureDeveloperCLI: case credNameAzureDeveloperCLI:
anchor = "azd" anchor = "azd"
case credNameAzurePipelines:
anchor = "apc"
case credNameCert: case credNameCert:
anchor = "client-cert" anchor = "client-cert"
case credNameSecret: case credNameSecret:
@ -110,8 +109,34 @@ func (*AuthenticationFailedError) NonRetriable() {
var _ errorinfo.NonRetriable = (*AuthenticationFailedError)(nil) var _ errorinfo.NonRetriable = (*AuthenticationFailedError)(nil)
// credentialUnavailableError indicates a credential can't attempt authentication because it lacks required // authenticationRequiredError indicates a credential's Authenticate method must be called to acquire a token
// data or state // because the credential requires user interaction and is configured not to request it automatically.
type authenticationRequiredError struct {
credentialUnavailableError
// TokenRequestOptions for the required token. Pass this to the credential's Authenticate method.
TokenRequestOptions policy.TokenRequestOptions
}
func newauthenticationRequiredError(credType string, tro policy.TokenRequestOptions) error {
return &authenticationRequiredError{
credentialUnavailableError: credentialUnavailableError{
credType + " can't acquire a token without user interaction. Call Authenticate to authenticate a user interactively",
},
TokenRequestOptions: tro,
}
}
var (
_ credentialUnavailable = (*authenticationRequiredError)(nil)
_ errorinfo.NonRetriable = (*authenticationRequiredError)(nil)
)
type credentialUnavailable interface {
error
credentialUnavailable()
}
type credentialUnavailableError struct { type credentialUnavailableError struct {
message string message string
} }
@ -135,6 +160,11 @@ func (e *credentialUnavailableError) Error() string {
} }
// NonRetriable is a marker method indicating this error should not be retried. It has no implementation. // NonRetriable is a marker method indicating this error should not be retried. It has no implementation.
func (e *credentialUnavailableError) NonRetriable() {} func (*credentialUnavailableError) NonRetriable() {}
var _ errorinfo.NonRetriable = (*credentialUnavailableError)(nil) func (*credentialUnavailableError) credentialUnavailable() {}
var (
_ credentialUnavailable = (*credentialUnavailableError)(nil)
_ errorinfo.NonRetriable = (*credentialUnavailableError)(nil)
)

View file

@ -3,12 +3,20 @@ github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0-beta.1/go.mod h1:3Ug6Qzto9an
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0 h1:fb8kj/Dh4CSwgsOzHeZY4Xh68cFVbzXx+ONXGMY//4w= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0 h1:fb8kj/Dh4CSwgsOzHeZY4Xh68cFVbzXx+ONXGMY//4w=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0/go.mod h1:uReU2sSxZExRPBAg3qKzmAucSi51+SP1OhohieR821Q= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0/go.mod h1:uReU2sSxZExRPBAg3qKzmAucSi51+SP1OhohieR821Q=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2/go.mod h1:yInRyqWXAuaPrgI7p70+lDDgh3mlBohis29jGMISnmc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/keybase/dbus v0.0.0-20220506165403-5aa21ea2c23a/go.mod h1:YPNKjjE7Ubp9dTbnWvsP3HT+hYnY6TfXzubYTBeUxc8=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/montanaflynn/stats v0.7.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/montanaflynn/stats v0.7.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
@ -16,14 +24,19 @@ github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -35,7 +48,13 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View file

@ -33,8 +33,8 @@ type InteractiveBrowserCredentialOptions struct {
ClientID string ClientID string
// disableAutomaticAuthentication prevents the credential from automatically prompting the user to authenticate. // disableAutomaticAuthentication prevents the credential from automatically prompting the user to authenticate.
// When this option is true, [InteractiveBrowserCredential.GetToken] will return [ErrAuthenticationRequired] when // When this option is true, GetToken will return authenticationRequiredError when user interaction is necessary
// user interaction is necessary to acquire a token. // to acquire a token.
disableAutomaticAuthentication bool disableAutomaticAuthentication bool
// DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or // DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or

View file

@ -0,0 +1,17 @@
{
"include": [
{
"Agent": {
"msi_image": {
"ArmTemplateParameters": "@{deployResources = $true}",
"OSVmImage": "env:LINUXNEXTVMIMAGE",
"Pool": "env:LINUXPOOL"
}
},
"GoVersion": [
"1.22.1"
],
"IDENTITY_IMDS_AVAILABLE": "1"
}
]
}

View file

@ -14,13 +14,15 @@ import (
"net/http" "net/http"
"net/url" "net/url"
"os" "os"
"path/filepath"
"runtime"
"strconv" "strconv"
"strings" "strings"
"time" "time"
"github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" azruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming" "github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming"
"github.com/Azure/azure-sdk-for-go/sdk/internal/log" "github.com/Azure/azure-sdk-for-go/sdk/internal/log"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential" "github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential"
@ -44,6 +46,8 @@ const (
serviceFabricAPIVersion = "2019-07-01-preview" serviceFabricAPIVersion = "2019-07-01-preview"
) )
var imdsProbeTimeout = time.Second
type msiType int type msiType int
const ( const (
@ -55,13 +59,28 @@ const (
msiTypeServiceFabric msiTypeServiceFabric
) )
// managedIdentityClient provides the base for authenticating in managed identity environments
// This type includes an runtime.Pipeline and TokenCredentialOptions.
type managedIdentityClient struct { type managedIdentityClient struct {
azClient *azcore.Client azClient *azcore.Client
msiType msiType
endpoint string endpoint string
id ManagedIDKind id ManagedIDKind
msiType msiType
probeIMDS bool
}
// arcKeyDirectory returns the directory expected to contain Azure Arc keys
var arcKeyDirectory = func() (string, error) {
switch runtime.GOOS {
case "linux":
return "/var/opt/azcmagent/tokens", nil
case "windows":
pd := os.Getenv("ProgramData")
if pd == "" {
return "", errors.New("environment variable ProgramData has no value")
}
return filepath.Join(pd, "AzureConnectedMachineAgent", "Tokens"), nil
default:
return "", fmt.Errorf("unsupported OS %q", runtime.GOOS)
}
} }
type wrappedNumber json.Number type wrappedNumber json.Number
@ -88,7 +107,7 @@ func setIMDSRetryOptionDefaults(o *policy.RetryOptions) {
if o.StatusCodes == nil { if o.StatusCodes == nil {
o.StatusCodes = []int{ o.StatusCodes = []int{
// IMDS docs recommend retrying 404, 410, 429 and 5xx // IMDS docs recommend retrying 404, 410, 429 and 5xx
// https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-token#error-handling // https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/how-to-use-vm-token#error-handling
http.StatusNotFound, // 404 http.StatusNotFound, // 404
http.StatusGone, // 410 http.StatusGone, // 410
http.StatusTooManyRequests, // 429 http.StatusTooManyRequests, // 429
@ -147,11 +166,12 @@ func newManagedIdentityClient(options *ManagedIdentityCredentialOptions) (*manag
c.msiType = msiTypeCloudShell c.msiType = msiTypeCloudShell
} }
} else { } else {
c.probeIMDS = options.dac
setIMDSRetryOptionDefaults(&cp.Retry) setIMDSRetryOptionDefaults(&cp.Retry)
} }
client, err := azcore.NewClient(module, version, runtime.PipelineOptions{ client, err := azcore.NewClient(module, version, azruntime.PipelineOptions{
Tracing: runtime.TracingOptions{ Tracing: azruntime.TracingOptions{
Namespace: traceNamespace, Namespace: traceNamespace,
}, },
}, &cp) }, &cp)
@ -180,6 +200,27 @@ func (c *managedIdentityClient) provideToken(ctx context.Context, params confide
// authenticate acquires an access token // authenticate acquires an access token
func (c *managedIdentityClient) authenticate(ctx context.Context, id ManagedIDKind, scopes []string) (azcore.AccessToken, error) { func (c *managedIdentityClient) authenticate(ctx context.Context, id ManagedIDKind, scopes []string) (azcore.AccessToken, error) {
// no need to synchronize around this value because it's true only when DefaultAzureCredential constructed the client,
// and in that case ChainedTokenCredential.GetToken synchronizes goroutines that would execute this block
if c.probeIMDS {
cx, cancel := context.WithTimeout(ctx, imdsProbeTimeout)
defer cancel()
cx = policy.WithRetryOptions(cx, policy.RetryOptions{MaxRetries: -1})
req, err := azruntime.NewRequest(cx, http.MethodGet, c.endpoint)
if err == nil {
_, err = c.azClient.Pipeline().Do(req)
}
if err != nil {
msg := err.Error()
if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
msg = "managed identity timed out. See https://aka.ms/azsdk/go/identity/troubleshoot#dac for more information"
}
return azcore.AccessToken{}, newCredentialUnavailableError(credNameManagedIdentity, msg)
}
// send normal token requests from now on because something responded
c.probeIMDS = false
}
msg, err := c.createAuthRequest(ctx, id, scopes) msg, err := c.createAuthRequest(ctx, id, scopes)
if err != nil { if err != nil {
return azcore.AccessToken{}, err return azcore.AccessToken{}, err
@ -190,7 +231,7 @@ func (c *managedIdentityClient) authenticate(ctx context.Context, id ManagedIDKi
return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, err.Error(), nil, err) return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, err.Error(), nil, err)
} }
if runtime.HasStatusCode(resp, http.StatusOK, http.StatusCreated) { if azruntime.HasStatusCode(resp, http.StatusOK, http.StatusCreated) {
return c.createAccessToken(resp) return c.createAccessToken(resp)
} }
@ -201,15 +242,15 @@ func (c *managedIdentityClient) authenticate(ctx context.Context, id ManagedIDKi
return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, "the requested identity isn't assigned to this resource", resp, nil) return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, "the requested identity isn't assigned to this resource", resp, nil)
} }
msg := "failed to authenticate a system assigned identity" msg := "failed to authenticate a system assigned identity"
if body, err := runtime.Payload(resp); err == nil && len(body) > 0 { if body, err := azruntime.Payload(resp); err == nil && len(body) > 0 {
msg += fmt.Sprintf(". The endpoint responded with %s", body) msg += fmt.Sprintf(". The endpoint responded with %s", body)
} }
return azcore.AccessToken{}, newCredentialUnavailableError(credNameManagedIdentity, msg) return azcore.AccessToken{}, newCredentialUnavailableError(credNameManagedIdentity, msg)
case http.StatusForbidden: case http.StatusForbidden:
// Docker Desktop runs a proxy that responds 403 to IMDS token requests. If we get that response, // Docker Desktop runs a proxy that responds 403 to IMDS token requests. If we get that response,
// we return credentialUnavailableError so credential chains continue to their next credential // we return credentialUnavailableError so credential chains continue to their next credential
body, err := runtime.Payload(resp) body, err := azruntime.Payload(resp)
if err == nil && strings.Contains(string(body), "A socket operation was attempted to an unreachable network") { if err == nil && strings.Contains(string(body), "unreachable") {
return azcore.AccessToken{}, newCredentialUnavailableError(credNameManagedIdentity, fmt.Sprintf("unexpected response %q", string(body))) return azcore.AccessToken{}, newCredentialUnavailableError(credNameManagedIdentity, fmt.Sprintf("unexpected response %q", string(body)))
} }
} }
@ -226,7 +267,7 @@ func (c *managedIdentityClient) createAccessToken(res *http.Response) (azcore.Ac
ExpiresIn wrappedNumber `json:"expires_in,omitempty"` // this field should always return the number of seconds for which a token is valid ExpiresIn wrappedNumber `json:"expires_in,omitempty"` // this field should always return the number of seconds for which a token is valid
ExpiresOn interface{} `json:"expires_on,omitempty"` // the value returned in this field varies between a number and a date string ExpiresOn interface{} `json:"expires_on,omitempty"` // the value returned in this field varies between a number and a date string
}{} }{}
if err := runtime.UnmarshalAsJSON(res, &value); err != nil { if err := azruntime.UnmarshalAsJSON(res, &value); err != nil {
return azcore.AccessToken{}, fmt.Errorf("internal AccessToken: %v", err) return azcore.AccessToken{}, fmt.Errorf("internal AccessToken: %v", err)
} }
if value.ExpiresIn != "" { if value.ExpiresIn != "" {
@ -276,7 +317,7 @@ func (c *managedIdentityClient) createAuthRequest(ctx context.Context, id Manage
} }
func (c *managedIdentityClient) createIMDSAuthRequest(ctx context.Context, id ManagedIDKind, scopes []string) (*policy.Request, error) { func (c *managedIdentityClient) createIMDSAuthRequest(ctx context.Context, id ManagedIDKind, scopes []string) (*policy.Request, error) {
request, err := runtime.NewRequest(ctx, http.MethodGet, c.endpoint) request, err := azruntime.NewRequest(ctx, http.MethodGet, c.endpoint)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -296,7 +337,7 @@ func (c *managedIdentityClient) createIMDSAuthRequest(ctx context.Context, id Ma
} }
func (c *managedIdentityClient) createAppServiceAuthRequest(ctx context.Context, id ManagedIDKind, scopes []string) (*policy.Request, error) { func (c *managedIdentityClient) createAppServiceAuthRequest(ctx context.Context, id ManagedIDKind, scopes []string) (*policy.Request, error) {
request, err := runtime.NewRequest(ctx, http.MethodGet, c.endpoint) request, err := azruntime.NewRequest(ctx, http.MethodGet, c.endpoint)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -316,7 +357,7 @@ func (c *managedIdentityClient) createAppServiceAuthRequest(ctx context.Context,
} }
func (c *managedIdentityClient) createAzureMLAuthRequest(ctx context.Context, id ManagedIDKind, scopes []string) (*policy.Request, error) { func (c *managedIdentityClient) createAzureMLAuthRequest(ctx context.Context, id ManagedIDKind, scopes []string) (*policy.Request, error) {
request, err := runtime.NewRequest(ctx, http.MethodGet, c.endpoint) request, err := azruntime.NewRequest(ctx, http.MethodGet, c.endpoint)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -339,7 +380,7 @@ func (c *managedIdentityClient) createAzureMLAuthRequest(ctx context.Context, id
} }
func (c *managedIdentityClient) createServiceFabricAuthRequest(ctx context.Context, id ManagedIDKind, scopes []string) (*policy.Request, error) { func (c *managedIdentityClient) createServiceFabricAuthRequest(ctx context.Context, id ManagedIDKind, scopes []string) (*policy.Request, error) {
request, err := runtime.NewRequest(ctx, http.MethodGet, c.endpoint) request, err := azruntime.NewRequest(ctx, http.MethodGet, c.endpoint)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -362,7 +403,7 @@ func (c *managedIdentityClient) createServiceFabricAuthRequest(ctx context.Conte
func (c *managedIdentityClient) getAzureArcSecretKey(ctx context.Context, resources []string) (string, error) { func (c *managedIdentityClient) getAzureArcSecretKey(ctx context.Context, resources []string) (string, error) {
// create the request to retreive the secret key challenge provided by the HIMDS service // create the request to retreive the secret key challenge provided by the HIMDS service
request, err := runtime.NewRequest(ctx, http.MethodGet, c.endpoint) request, err := azruntime.NewRequest(ctx, http.MethodGet, c.endpoint)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -384,22 +425,36 @@ func (c *managedIdentityClient) getAzureArcSecretKey(ctx context.Context, resour
} }
header := response.Header.Get("WWW-Authenticate") header := response.Header.Get("WWW-Authenticate")
if len(header) == 0 { if len(header) == 0 {
return "", errors.New("did not receive a value from WWW-Authenticate header") return "", newAuthenticationFailedError(credNameManagedIdentity, "HIMDS response has no WWW-Authenticate header", nil, nil)
} }
// the WWW-Authenticate header is expected in the following format: Basic realm=/some/file/path.key // the WWW-Authenticate header is expected in the following format: Basic realm=/some/file/path.key
pos := strings.LastIndex(header, "=") _, p, found := strings.Cut(header, "=")
if pos == -1 { if !found {
return "", fmt.Errorf("did not receive a correct value from WWW-Authenticate header: %s", header) return "", newAuthenticationFailedError(credNameManagedIdentity, "unexpected WWW-Authenticate header from HIMDS: "+header, nil, nil)
} }
key, err := os.ReadFile(header[pos+1:]) expected, err := arcKeyDirectory()
if err != nil { if err != nil {
return "", fmt.Errorf("could not read file (%s) contents: %v", header[pos+1:], err) return "", err
}
if filepath.Dir(p) != expected || !strings.HasSuffix(p, ".key") {
return "", newAuthenticationFailedError(credNameManagedIdentity, "unexpected file path from HIMDS service: "+p, nil, nil)
}
f, err := os.Stat(p)
if err != nil {
return "", newAuthenticationFailedError(credNameManagedIdentity, fmt.Sprintf("could not stat %q: %v", p, err), nil, nil)
}
if s := f.Size(); s > 4096 {
return "", newAuthenticationFailedError(credNameManagedIdentity, fmt.Sprintf("key is too large (%d bytes)", s), nil, nil)
}
key, err := os.ReadFile(p)
if err != nil {
return "", newAuthenticationFailedError(credNameManagedIdentity, fmt.Sprintf("could not read %q: %v", p, err), nil, nil)
} }
return string(key), nil return string(key), nil
} }
func (c *managedIdentityClient) createAzureArcAuthRequest(ctx context.Context, id ManagedIDKind, resources []string, key string) (*policy.Request, error) { func (c *managedIdentityClient) createAzureArcAuthRequest(ctx context.Context, id ManagedIDKind, resources []string, key string) (*policy.Request, error) {
request, err := runtime.NewRequest(ctx, http.MethodGet, c.endpoint) request, err := azruntime.NewRequest(ctx, http.MethodGet, c.endpoint)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -421,7 +476,7 @@ func (c *managedIdentityClient) createAzureArcAuthRequest(ctx context.Context, i
} }
func (c *managedIdentityClient) createCloudShellAuthRequest(ctx context.Context, id ManagedIDKind, scopes []string) (*policy.Request, error) { func (c *managedIdentityClient) createCloudShellAuthRequest(ctx context.Context, id ManagedIDKind, scopes []string) (*policy.Request, error) {
request, err := runtime.NewRequest(ctx, http.MethodPost, c.endpoint) request, err := azruntime.NewRequest(ctx, http.MethodPost, c.endpoint)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -64,12 +64,19 @@ type ManagedIdentityCredentialOptions struct {
// instead of the hosting environment's default. The value may be the identity's client ID or resource ID, but note that // instead of the hosting environment's default. The value may be the identity's client ID or resource ID, but note that
// some platforms don't accept resource IDs. // some platforms don't accept resource IDs.
ID ManagedIDKind ID ManagedIDKind
// dac indicates whether the credential is part of DefaultAzureCredential. When true, and the environment doesn't have
// configuration for a specific managed identity API, the credential tries to determine whether IMDS is available before
// sending its first token request. It does this by sending a malformed request with a short timeout. Any response to that
// request is taken to mean IMDS is available, in which case the credential will send ordinary token requests thereafter
// with no special timeout. The purpose of this behavior is to prevent a very long timeout when IMDS isn't available.
dac bool
} }
// ManagedIdentityCredential authenticates an Azure managed identity in any hosting environment supporting managed identities. // ManagedIdentityCredential authenticates an Azure managed identity in any hosting environment supporting managed identities.
// This credential authenticates a system-assigned identity by default. Use ManagedIdentityCredentialOptions.ID to specify a // This credential authenticates a system-assigned identity by default. Use ManagedIdentityCredentialOptions.ID to specify a
// user-assigned identity. See Microsoft Entra ID documentation for more information about managed identities: // user-assigned identity. See Microsoft Entra ID documentation for more information about managed identities:
// https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview // https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/overview
type ManagedIdentityCredential struct { type ManagedIdentityCredential struct {
client *confidentialClient client *confidentialClient
mic *managedIdentityClient mic *managedIdentityClient

View file

@ -10,6 +10,7 @@ import (
"context" "context"
"crypto" "crypto"
"crypto/x509" "crypto/x509"
"errors"
"github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
@ -24,7 +25,7 @@ const credNameOBO = "OnBehalfOfCredential"
// is not an interactive authentication flow, an application using it must have admin consent for any delegated // is not an interactive authentication flow, an application using it must have admin consent for any delegated
// permissions before requesting tokens for them. See [Microsoft Entra ID documentation] for more details. // permissions before requesting tokens for them. See [Microsoft Entra ID documentation] for more details.
// //
// [Microsoft Entra ID documentation]: https://learn.microsoft.com/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow // [Microsoft Entra ID documentation]: https://learn.microsoft.com/entra/identity-platform/v2-oauth2-on-behalf-of-flow
type OnBehalfOfCredential struct { type OnBehalfOfCredential struct {
client *confidentialClient client *confidentialClient
} }
@ -60,6 +61,19 @@ func NewOnBehalfOfCredentialWithCertificate(tenantID, clientID, userAssertion st
return newOnBehalfOfCredential(tenantID, clientID, userAssertion, cred, options) return newOnBehalfOfCredential(tenantID, clientID, userAssertion, cred, options)
} }
// NewOnBehalfOfCredentialWithClientAssertions constructs an OnBehalfOfCredential that authenticates with client assertions.
// userAssertion is the user's access token for the application. The getAssertion function should return client assertions
// that authenticate the application to Microsoft Entra ID, such as federated credentials.
func NewOnBehalfOfCredentialWithClientAssertions(tenantID, clientID, userAssertion string, getAssertion func(context.Context) (string, error), options *OnBehalfOfCredentialOptions) (*OnBehalfOfCredential, error) {
if getAssertion == nil {
return nil, errors.New("getAssertion can't be nil. It must be a function that returns client assertions")
}
cred := confidential.NewCredFromAssertionCallback(func(ctx context.Context, _ confidential.AssertionRequestOptions) (string, error) {
return getAssertion(ctx)
})
return newOnBehalfOfCredential(tenantID, clientID, userAssertion, cred, options)
}
// NewOnBehalfOfCredentialWithSecret constructs an OnBehalfOfCredential that authenticates with a client secret. // NewOnBehalfOfCredentialWithSecret constructs an OnBehalfOfCredential that authenticates with a client secret.
func NewOnBehalfOfCredentialWithSecret(tenantID, clientID, userAssertion, clientSecret string, options *OnBehalfOfCredentialOptions) (*OnBehalfOfCredential, error) { func NewOnBehalfOfCredentialWithSecret(tenantID, clientID, userAssertion, clientSecret string, options *OnBehalfOfCredentialOptions) (*OnBehalfOfCredential, error) {
cred, err := confidential.NewCredFromSecret(clientSecret) cred, err := confidential.NewCredFromSecret(clientSecret)

View file

@ -152,7 +152,7 @@ func (p *publicClient) GetToken(ctx context.Context, tro policy.TokenRequestOpti
return p.token(ar, err) return p.token(ar, err)
} }
if p.opts.DisableAutomaticAuthentication { if p.opts.DisableAutomaticAuthentication {
return azcore.AccessToken{}, errAuthenticationRequired return azcore.AccessToken{}, newauthenticationRequiredError(p.name, tro)
} }
at, err := p.reqToken(ctx, client, tro) at, err := p.reqToken(ctx, client, tro)
if err == nil { if err == nil {

View file

@ -0,0 +1,112 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
# IMPORTANT: Do not invoke this file directly. Please instead run eng/common/TestResources/New-TestResources.ps1 from the repository root.
param (
[hashtable] $AdditionalParameters = @{},
[hashtable] $DeploymentOutputs
)
$ErrorActionPreference = 'Stop'
$PSNativeCommandUseErrorActionPreference = $true
if ($CI) {
if (!$AdditionalParameters['deployResources']) {
Write-Host "Skipping post-provisioning script because resources weren't deployed"
return
}
az login --service-principal -u $DeploymentOutputs['AZIDENTITY_CLIENT_ID'] -p $DeploymentOutputs['AZIDENTITY_CLIENT_SECRET'] --tenant $DeploymentOutputs['AZIDENTITY_TENANT_ID']
az account set --subscription $DeploymentOutputs['AZIDENTITY_SUBSCRIPTION_ID']
}
Write-Host "Building container"
$image = "$($DeploymentOutputs['AZIDENTITY_ACR_LOGIN_SERVER'])/azidentity-managed-id-test"
Set-Content -Path "$PSScriptRoot/Dockerfile" -Value @"
FROM mcr.microsoft.com/oss/go/microsoft/golang:latest as builder
ENV GOARCH=amd64 GOWORK=off
COPY . /azidentity
WORKDIR /azidentity/testdata/managed-id-test
RUN go mod tidy
RUN go build -o /build/managed-id-test .
RUN GOOS=windows go build -o /build/managed-id-test.exe .
FROM mcr.microsoft.com/mirror/docker/library/alpine:3.16
RUN apk add gcompat
COPY --from=builder /build/* .
RUN chmod +x managed-id-test
CMD ["./managed-id-test"]
"@
# build from sdk/azidentity because we need that dir in the context (because the test app uses local azidentity)
docker build -t $image "$PSScriptRoot"
az acr login -n $DeploymentOutputs['AZIDENTITY_ACR_NAME']
docker push $image
$rg = $DeploymentOutputs['AZIDENTITY_RESOURCE_GROUP']
# ACI is easier to provision here than in the bicep file because the image isn't available before now
Write-Host "Deploying Azure Container Instance"
$aciName = "azidentity-test"
az container create -g $rg -n $aciName --image $image `
--acr-identity $($DeploymentOutputs['AZIDENTITY_USER_ASSIGNED_IDENTITY']) `
--assign-identity [system] $($DeploymentOutputs['AZIDENTITY_USER_ASSIGNED_IDENTITY']) `
--role "Storage Blob Data Reader" `
--scope $($DeploymentOutputs['AZIDENTITY_STORAGE_ID']) `
-e AZIDENTITY_STORAGE_NAME=$($DeploymentOutputs['AZIDENTITY_STORAGE_NAME']) `
AZIDENTITY_STORAGE_NAME_USER_ASSIGNED=$($DeploymentOutputs['AZIDENTITY_STORAGE_NAME_USER_ASSIGNED']) `
AZIDENTITY_USER_ASSIGNED_IDENTITY=$($DeploymentOutputs['AZIDENTITY_USER_ASSIGNED_IDENTITY']) `
FUNCTIONS_CUSTOMHANDLER_PORT=80
Write-Host "##vso[task.setvariable variable=AZIDENTITY_ACI_NAME;]$aciName"
# Azure Functions deployment: copy the Windows binary from the Docker image, deploy it in a zip
Write-Host "Deploying to Azure Functions"
$container = docker create $image
docker cp ${container}:managed-id-test.exe "$PSScriptRoot/testdata/managed-id-test/"
docker rm -v $container
Compress-Archive -Path "$PSScriptRoot/testdata/managed-id-test/*" -DestinationPath func.zip -Force
az functionapp deploy -g $rg -n $DeploymentOutputs['AZIDENTITY_FUNCTION_NAME'] --src-path func.zip --type zip
Write-Host "Creating federated identity"
$aksName = $DeploymentOutputs['AZIDENTITY_AKS_NAME']
$idName = $DeploymentOutputs['AZIDENTITY_USER_ASSIGNED_IDENTITY_NAME']
$issuer = az aks show -g $rg -n $aksName --query "oidcIssuerProfile.issuerUrl" -otsv
$podName = "azidentity-test"
$serviceAccountName = "workload-identity-sa"
az identity federated-credential create -g $rg --identity-name $idName --issuer $issuer --name $idName --subject system:serviceaccount:default:$serviceAccountName
Write-Host "Deploying to AKS"
az aks get-credentials -g $rg -n $aksName
az aks update --attach-acr $DeploymentOutputs['AZIDENTITY_ACR_NAME'] -g $rg -n $aksName
Set-Content -Path "$PSScriptRoot/k8s.yaml" -Value @"
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
azure.workload.identity/client-id: $($DeploymentOutputs['AZIDENTITY_USER_ASSIGNED_IDENTITY_CLIENT_ID'])
name: $serviceAccountName
namespace: default
---
apiVersion: v1
kind: Pod
metadata:
name: $podName
namespace: default
labels:
app: $podName
azure.workload.identity/use: "true"
spec:
serviceAccountName: $serviceAccountName
containers:
- name: $podName
image: $image
env:
- name: AZIDENTITY_STORAGE_NAME
value: $($DeploymentOutputs['AZIDENTITY_STORAGE_NAME_USER_ASSIGNED'])
- name: AZIDENTITY_USE_WORKLOAD_IDENTITY
value: "true"
- name: FUNCTIONS_CUSTOMHANDLER_PORT
value: "80"
nodeSelector:
kubernetes.io/os: linux
"@
kubectl apply -f "$PSScriptRoot/k8s.yaml"
Write-Host "##vso[task.setvariable variable=AZIDENTITY_POD_NAME;]$podName"

View file

@ -1,36 +1,44 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
# IMPORTANT: Do not invoke this file directly. Please instead run eng/common/TestResources/New-TestResources.ps1 from the repository root.
[CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')]
param ( param (
[hashtable] $AdditionalParameters = @{},
# Captures any arguments from eng/New-TestResources.ps1 not declared here (no parameter errors). # Captures any arguments from eng/New-TestResources.ps1 not declared here (no parameter errors).
[Parameter(ValueFromRemainingArguments = $true)] [Parameter(ValueFromRemainingArguments = $true)]
$RemainingArguments $RemainingArguments
) )
if (-not (Test-Path "$PSScriptRoot/sshkey.pub")) {
ssh-keygen -t rsa -b 4096 -f "$PSScriptRoot/sshkey" -N '' -C ''
}
$templateFileParameters['sshPubKey'] = Get-Content "$PSScriptRoot/sshkey.pub"
if (!$CI) { if (!$CI) {
# TODO: Remove this once auto-cloud config downloads are supported locally # TODO: Remove this once auto-cloud config downloads are supported locally
Write-Host "Skipping cert setup in local testing mode" Write-Host "Skipping cert setup in local testing mode"
return return
} }
if ($EnvironmentVariables -eq $null -or $EnvironmentVariables.Count -eq 0) { if ($null -eq $EnvironmentVariables -or $EnvironmentVariables.Count -eq 0) {
throw "EnvironmentVariables must be set in the calling script New-TestResources.ps1" throw "EnvironmentVariables must be set in the calling script New-TestResources.ps1"
} }
$tmp = $env:TEMP ? $env:TEMP : [System.IO.Path]::GetTempPath() $tmp = $env:TEMP ? $env:TEMP : [System.IO.Path]::GetTempPath()
$pfxPath = Join-Path $tmp "test.pfx" $pfxPath = Join-Path $tmp "test.pfx"
$pemPath = Join-Path $tmp "test.pem" $pemPath = Join-Path $tmp "test.pem"
$sniPath = Join-Path $tmp "testsni.pfx"
Write-Host "Creating identity test files: $pfxPath $pemPath $sniPath" Write-Host "Creating identity test files: $pfxPath $pemPath"
[System.Convert]::FromBase64String($EnvironmentVariables['PFX_CONTENTS']) | Set-Content -Path $pfxPath -AsByteStream [System.Convert]::FromBase64String($EnvironmentVariables['PFX_CONTENTS']) | Set-Content -Path $pfxPath -AsByteStream
Set-Content -Path $pemPath -Value $EnvironmentVariables['PEM_CONTENTS'] Set-Content -Path $pemPath -Value $EnvironmentVariables['PEM_CONTENTS']
[System.Convert]::FromBase64String($EnvironmentVariables['SNI_CONTENTS']) | Set-Content -Path $sniPath -AsByteStream
# Set for pipeline # Set for pipeline
Write-Host "##vso[task.setvariable variable=IDENTITY_SP_CERT_PFX;]$pfxPath" Write-Host "##vso[task.setvariable variable=IDENTITY_SP_CERT_PFX;]$pfxPath"
Write-Host "##vso[task.setvariable variable=IDENTITY_SP_CERT_PEM;]$pemPath" Write-Host "##vso[task.setvariable variable=IDENTITY_SP_CERT_PEM;]$pemPath"
Write-Host "##vso[task.setvariable variable=IDENTITY_SP_CERT_SNI;]$sniPath"
# Set for local # Set for local
$env:IDENTITY_SP_CERT_PFX = $pfxPath $env:IDENTITY_SP_CERT_PFX = $pfxPath
$env:IDENTITY_SP_CERT_PEM = $pemPath $env:IDENTITY_SP_CERT_PEM = $pemPath
$env:IDENTITY_SP_CERT_SNI = $sniPath

View file

@ -1 +1,219 @@
param baseName string // Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
@description('Kubernetes cluster admin user name.')
param adminUser string = 'azureuser'
@minLength(6)
@maxLength(23)
@description('The base resource name.')
param baseName string = resourceGroup().name
@description('Whether to deploy resources. When set to false, this file deploys nothing.')
param deployResources bool = false
param sshPubKey string = ''
@description('The location of the resource. By default, this is the same as the resource group.')
param location string = resourceGroup().location
// https://learn.microsoft.com/azure/role-based-access-control/built-in-roles
var acrPull = subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')
var blobReader = subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1')
resource sa 'Microsoft.Storage/storageAccounts@2021-08-01' = if (deployResources) {
kind: 'StorageV2'
location: location
name: 'sa${uniqueString(baseName)}'
properties: {
accessTier: 'Hot'
}
sku: {
name: 'Standard_LRS'
}
}
resource saUserAssigned 'Microsoft.Storage/storageAccounts@2021-08-01' = if (deployResources) {
kind: 'StorageV2'
location: location
name: 'sa2${uniqueString(baseName)}'
properties: {
accessTier: 'Hot'
}
sku: {
name: 'Standard_LRS'
}
}
resource usermgdid 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = if (deployResources) {
location: location
name: baseName
}
resource acrPullContainerInstance 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (deployResources) {
name: guid(resourceGroup().id, acrPull, 'containerInstance')
properties: {
principalId: deployResources ? usermgdid.properties.principalId : ''
principalType: 'ServicePrincipal'
roleDefinitionId: acrPull
}
scope: containerRegistry
}
resource blobRoleUserAssigned 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (deployResources) {
scope: saUserAssigned
name: guid(resourceGroup().id, blobReader, usermgdid.id)
properties: {
principalId: deployResources ? usermgdid.properties.principalId : ''
principalType: 'ServicePrincipal'
roleDefinitionId: blobReader
}
}
resource blobRoleFunc 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (deployResources) {
name: guid(resourceGroup().id, blobReader, 'azfunc')
properties: {
principalId: deployResources ? azfunc.identity.principalId : ''
roleDefinitionId: blobReader
principalType: 'ServicePrincipal'
}
scope: sa
}
resource containerRegistry 'Microsoft.ContainerRegistry/registries@2023-01-01-preview' = if (deployResources) {
location: location
name: uniqueString(resourceGroup().id)
properties: {
adminUserEnabled: true
}
sku: {
name: 'Basic'
}
}
resource farm 'Microsoft.Web/serverfarms@2021-03-01' = if (deployResources) {
kind: 'app'
location: location
name: '${baseName}_asp'
properties: {}
sku: {
capacity: 1
family: 'B'
name: 'B1'
size: 'B1'
tier: 'Basic'
}
}
resource azfunc 'Microsoft.Web/sites@2021-03-01' = if (deployResources) {
identity: {
type: 'SystemAssigned, UserAssigned'
userAssignedIdentities: {
'${deployResources ? usermgdid.id : ''}': {}
}
}
kind: 'functionapp'
location: location
name: '${baseName}func'
properties: {
enabled: true
httpsOnly: true
keyVaultReferenceIdentity: 'SystemAssigned'
serverFarmId: farm.id
siteConfig: {
alwaysOn: true
appSettings: [
{
name: 'AZIDENTITY_STORAGE_NAME'
value: deployResources ? sa.name : null
}
{
name: 'AZIDENTITY_STORAGE_NAME_USER_ASSIGNED'
value: deployResources ? saUserAssigned.name : null
}
{
name: 'AZIDENTITY_USER_ASSIGNED_IDENTITY'
value: deployResources ? usermgdid.id : null
}
{
name: 'AzureWebJobsStorage'
value: 'DefaultEndpointsProtocol=https;AccountName=${deployResources ? sa.name : ''};EndpointSuffix=${deployResources ? environment().suffixes.storage : ''};AccountKey=${deployResources ? sa.listKeys().keys[0].value : ''}'
}
{
name: 'FUNCTIONS_EXTENSION_VERSION'
value: '~4'
}
{
name: 'FUNCTIONS_WORKER_RUNTIME'
value: 'custom'
}
{
name: 'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING'
value: 'DefaultEndpointsProtocol=https;AccountName=${deployResources ? sa.name : ''};EndpointSuffix=${deployResources ? environment().suffixes.storage : ''};AccountKey=${deployResources ? sa.listKeys().keys[0].value : ''}'
}
{
name: 'WEBSITE_CONTENTSHARE'
value: toLower('${baseName}-func')
}
]
http20Enabled: true
minTlsVersion: '1.2'
}
}
}
resource aks 'Microsoft.ContainerService/managedClusters@2023-06-01' = if (deployResources) {
name: baseName
location: location
identity: {
type: 'SystemAssigned'
}
properties: {
agentPoolProfiles: [
{
count: 1
enableAutoScaling: false
kubeletDiskType: 'OS'
mode: 'System'
name: 'agentpool'
osDiskSizeGB: 128
osDiskType: 'Managed'
osSKU: 'Ubuntu'
osType: 'Linux'
type: 'VirtualMachineScaleSets'
vmSize: 'Standard_D2s_v3'
}
]
dnsPrefix: 'identitytest'
enableRBAC: true
linuxProfile: {
adminUsername: adminUser
ssh: {
publicKeys: [
{
keyData: sshPubKey
}
]
}
}
oidcIssuerProfile: {
enabled: true
}
securityProfile: {
workloadIdentity: {
enabled: true
}
}
}
}
output AZIDENTITY_ACR_LOGIN_SERVER string = deployResources ? containerRegistry.properties.loginServer : ''
output AZIDENTITY_ACR_NAME string = deployResources ? containerRegistry.name : ''
output AZIDENTITY_AKS_NAME string = deployResources ? aks.name : ''
output AZIDENTITY_FUNCTION_NAME string = deployResources ? azfunc.name : ''
output AZIDENTITY_STORAGE_ID string = deployResources ? sa.id : ''
output AZIDENTITY_STORAGE_NAME string = deployResources ? sa.name : ''
output AZIDENTITY_STORAGE_NAME_USER_ASSIGNED string = deployResources ? saUserAssigned.name : ''
output AZIDENTITY_USER_ASSIGNED_IDENTITY string = deployResources ? usermgdid.id : ''
output AZIDENTITY_USER_ASSIGNED_IDENTITY_CLIENT_ID string = deployResources ? usermgdid.properties.clientId : ''
output AZIDENTITY_USER_ASSIGNED_IDENTITY_NAME string = deployResources ? usermgdid.name : ''

View file

@ -14,5 +14,5 @@ const (
module = "github.com/Azure/azure-sdk-for-go/sdk/" + component module = "github.com/Azure/azure-sdk-for-go/sdk/" + component
// Version is the semantic version (see http://semver.org) of this module. // Version is the semantic version (see http://semver.org) of this module.
version = "v1.5.2" version = "v1.7.0"
) )

View file

@ -0,0 +1,18 @@
package aws
// AccountIDEndpointMode controls how a resolved AWS account ID is handled for endpoint routing.
type AccountIDEndpointMode string
const (
// AccountIDEndpointModeUnset indicates the AWS account ID will not be used for endpoint routing
AccountIDEndpointModeUnset AccountIDEndpointMode = ""
// AccountIDEndpointModePreferred indicates the AWS account ID will be used for endpoint routing if present
AccountIDEndpointModePreferred = "preferred"
// AccountIDEndpointModeRequired indicates an error will be returned if the AWS account ID is not resolved from identity
AccountIDEndpointModeRequired = "required"
// AccountIDEndpointModeDisabled indicates the AWS account ID will be ignored during endpoint routing
AccountIDEndpointModeDisabled = "disabled"
)

View file

@ -162,6 +162,9 @@ type Config struct {
// This variable is sourced from environment variable AWS_REQUEST_MIN_COMPRESSION_SIZE_BYTES or // This variable is sourced from environment variable AWS_REQUEST_MIN_COMPRESSION_SIZE_BYTES or
// the shared config profile attribute request_min_compression_size_bytes // the shared config profile attribute request_min_compression_size_bytes
RequestMinCompressSizeBytes int64 RequestMinCompressSizeBytes int64
// Controls how a resolved AWS account ID is handled for endpoint routing.
AccountIDEndpointMode AccountIDEndpointMode
} }
// NewConfig returns a new Config pointer that can be chained with builder // NewConfig returns a new Config pointer that can be chained with builder

View file

@ -90,6 +90,9 @@ type Credentials struct {
// The time the credentials will expire at. Should be ignored if CanExpire // The time the credentials will expire at. Should be ignored if CanExpire
// is false. // is false.
Expires time.Time Expires time.Time
// The ID of the account for the credentials.
AccountID string
} }
// Expired returns if the credentials have expired. // Expired returns if the credentials have expired.

View file

@ -3,4 +3,4 @@
package aws package aws
// goModuleVersion is the tagged release for this module // goModuleVersion is the tagged release for this module
const goModuleVersion = "1.27.1" const goModuleVersion = "1.30.0"

View file

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"os" "os"
"runtime" "runtime"
"sort"
"strings" "strings"
"github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/aws"
@ -30,6 +31,7 @@ const (
FrameworkMetadata FrameworkMetadata
AdditionalMetadata AdditionalMetadata
ApplicationIdentifier ApplicationIdentifier
FeatureMetadata2
) )
func (k SDKAgentKeyType) string() string { func (k SDKAgentKeyType) string() string {
@ -50,6 +52,8 @@ func (k SDKAgentKeyType) string() string {
return "lib" return "lib"
case ApplicationIdentifier: case ApplicationIdentifier:
return "app" return "app"
case FeatureMetadata2:
return "m"
case AdditionalMetadata: case AdditionalMetadata:
fallthrough fallthrough
default: default:
@ -64,9 +68,29 @@ var validChars = map[rune]bool{
'-': true, '.': true, '^': true, '_': true, '`': true, '|': true, '~': true, '-': true, '.': true, '^': true, '_': true, '`': true, '|': true, '~': true,
} }
// UserAgentFeature enumerates tracked SDK features.
type UserAgentFeature string
// Enumerates UserAgentFeature.
const (
UserAgentFeatureResourceModel UserAgentFeature = "A" // n/a (we don't generate separate resource types)
UserAgentFeatureWaiter = "B"
UserAgentFeaturePaginator = "C"
UserAgentFeatureRetryModeLegacy = "D" // n/a (equivalent to standard)
UserAgentFeatureRetryModeStandard = "E"
UserAgentFeatureRetryModeAdaptive = "F"
UserAgentFeatureS3Transfer = "G"
UserAgentFeatureS3CryptoV1N = "H" // n/a (crypto client is external)
UserAgentFeatureS3CryptoV2 = "I" // n/a
UserAgentFeatureS3ExpressBucket = "J"
UserAgentFeatureS3AccessGrants = "K" // not yet implemented
UserAgentFeatureGZIPRequestCompression = "L"
)
// RequestUserAgent is a build middleware that set the User-Agent for the request. // RequestUserAgent is a build middleware that set the User-Agent for the request.
type RequestUserAgent struct { type RequestUserAgent struct {
sdkAgent, userAgent *smithyhttp.UserAgentBuilder sdkAgent, userAgent *smithyhttp.UserAgentBuilder
features map[UserAgentFeature]struct{}
} }
// NewRequestUserAgent returns a new requestUserAgent which will set the User-Agent and X-Amz-User-Agent for the // NewRequestUserAgent returns a new requestUserAgent which will set the User-Agent and X-Amz-User-Agent for the
@ -87,6 +111,7 @@ func NewRequestUserAgent() *RequestUserAgent {
r := &RequestUserAgent{ r := &RequestUserAgent{
sdkAgent: sdkAgent, sdkAgent: sdkAgent,
userAgent: userAgent, userAgent: userAgent,
features: map[UserAgentFeature]struct{}{},
} }
addSDKMetadata(r) addSDKMetadata(r)
@ -191,6 +216,12 @@ func (u *RequestUserAgent) AddUserAgentKeyValue(key, value string) {
u.userAgent.AddKeyValue(strings.Map(rules, key), strings.Map(rules, value)) u.userAgent.AddKeyValue(strings.Map(rules, key), strings.Map(rules, value))
} }
// AddUserAgentFeature adds the feature ID to the tracking list to be emitted
// in the final User-Agent string.
func (u *RequestUserAgent) AddUserAgentFeature(feature UserAgentFeature) {
u.features[feature] = struct{}{}
}
// AddSDKAgentKey adds the component identified by name to the User-Agent string. // AddSDKAgentKey adds the component identified by name to the User-Agent string.
func (u *RequestUserAgent) AddSDKAgentKey(keyType SDKAgentKeyType, key string) { func (u *RequestUserAgent) AddSDKAgentKey(keyType SDKAgentKeyType, key string) {
// TODO: should target sdkAgent // TODO: should target sdkAgent
@ -227,6 +258,9 @@ func (u *RequestUserAgent) HandleBuild(ctx context.Context, in middleware.BuildI
func (u *RequestUserAgent) addHTTPUserAgent(request *smithyhttp.Request) { func (u *RequestUserAgent) addHTTPUserAgent(request *smithyhttp.Request) {
const userAgent = "User-Agent" const userAgent = "User-Agent"
updateHTTPHeader(request, userAgent, u.userAgent.Build()) updateHTTPHeader(request, userAgent, u.userAgent.Build())
if len(u.features) > 0 {
updateHTTPHeader(request, userAgent, buildFeatureMetrics(u.features))
}
} }
func (u *RequestUserAgent) addHTTPSDKAgent(request *smithyhttp.Request) { func (u *RequestUserAgent) addHTTPSDKAgent(request *smithyhttp.Request) {
@ -259,3 +293,13 @@ func rules(r rune) rune {
return '-' return '-'
} }
} }
func buildFeatureMetrics(features map[UserAgentFeature]struct{}) string {
fs := make([]string, 0, len(features))
for f := range features {
fs = append(fs, string(f))
}
sort.Strings(fs)
return fmt.Sprintf("%s/%s", FeatureMetadata2.string(), strings.Join(fs, ","))
}

View file

@ -2,12 +2,15 @@ package retry
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"github.com/aws/aws-sdk-go-v2/aws/middleware/private/metrics"
"strconv" "strconv"
"strings" "strings"
"time" "time"
"github.com/aws/aws-sdk-go-v2/aws/middleware/private/metrics"
internalcontext "github.com/aws/aws-sdk-go-v2/internal/context"
"github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/aws"
awsmiddle "github.com/aws/aws-sdk-go-v2/aws/middleware" awsmiddle "github.com/aws/aws-sdk-go-v2/aws/middleware"
"github.com/aws/aws-sdk-go-v2/internal/sdk" "github.com/aws/aws-sdk-go-v2/internal/sdk"
@ -39,6 +42,10 @@ type Attempt struct {
requestCloner RequestCloner requestCloner RequestCloner
} }
// define the threshold at which we will consider certain kind of errors to be probably
// caused by clock skew
const skewThreshold = 4 * time.Minute
// NewAttemptMiddleware returns a new Attempt retry middleware. // NewAttemptMiddleware returns a new Attempt retry middleware.
func NewAttemptMiddleware(retryer aws.Retryer, requestCloner RequestCloner, optFns ...func(*Attempt)) *Attempt { func NewAttemptMiddleware(retryer aws.Retryer, requestCloner RequestCloner, optFns ...func(*Attempt)) *Attempt {
m := &Attempt{ m := &Attempt{
@ -86,6 +93,9 @@ func (r *Attempt) HandleFinalize(ctx context.Context, in smithymiddle.FinalizeIn
AttemptClockSkew: attemptClockSkew, AttemptClockSkew: attemptClockSkew,
}) })
// Setting clock skew to be used on other context (like signing)
ctx = internalcontext.SetAttemptSkewContext(ctx, attemptClockSkew)
var attemptResult AttemptResult var attemptResult AttemptResult
out, attemptResult, releaseRetryToken, err = r.handleAttempt(attemptCtx, attemptInput, releaseRetryToken, next) out, attemptResult, releaseRetryToken, err = r.handleAttempt(attemptCtx, attemptInput, releaseRetryToken, next)
attemptClockSkew, _ = awsmiddle.GetAttemptSkew(attemptResult.ResponseMetadata) attemptClockSkew, _ = awsmiddle.GetAttemptSkew(attemptResult.ResponseMetadata)
@ -185,6 +195,8 @@ func (r *Attempt) handleAttempt(
return out, attemptResult, nopRelease, err return out, attemptResult, nopRelease, err
} }
err = wrapAsClockSkew(ctx, err)
//------------------------------ //------------------------------
// Is Retryable and Should Retry // Is Retryable and Should Retry
//------------------------------ //------------------------------
@ -247,6 +259,37 @@ func (r *Attempt) handleAttempt(
return out, attemptResult, releaseRetryToken, err return out, attemptResult, releaseRetryToken, err
} }
// errors that, if detected when we know there's a clock skew,
// can be retried and have a high chance of success
var possibleSkewCodes = map[string]struct{}{
"InvalidSignatureException": {},
"SignatureDoesNotMatch": {},
"AuthFailure": {},
}
var definiteSkewCodes = map[string]struct{}{
"RequestExpired": {},
"RequestInTheFuture": {},
"RequestTimeTooSkewed": {},
}
// wrapAsClockSkew checks if this error could be related to a clock skew
// error and if so, wrap the error.
func wrapAsClockSkew(ctx context.Context, err error) error {
var v interface{ ErrorCode() string }
if !errors.As(err, &v) {
return err
}
if _, ok := definiteSkewCodes[v.ErrorCode()]; ok {
return &retryableClockSkewError{Err: err}
}
_, isPossibleSkewCode := possibleSkewCodes[v.ErrorCode()]
if skew := internalcontext.GetAttemptSkewContext(ctx); skew > skewThreshold && isPossibleSkewCode {
return &retryableClockSkewError{Err: err}
}
return err
}
// MetricsHeader attaches SDK request metric header for retries to the transport // MetricsHeader attaches SDK request metric header for retries to the transport
type MetricsHeader struct{} type MetricsHeader struct{}

View file

@ -2,6 +2,7 @@ package retry
import ( import (
"errors" "errors"
"fmt"
"net" "net"
"net/url" "net/url"
"strings" "strings"
@ -199,3 +200,23 @@ func (r RetryableErrorCode) IsErrorRetryable(err error) aws.Ternary {
return aws.TrueTernary return aws.TrueTernary
} }
// retryableClockSkewError marks errors that can be caused by clock skew
// (difference between server time and client time).
// This is returned when there's certain confidence that adjusting the client time
// could allow a retry to succeed
type retryableClockSkewError struct{ Err error }
func (e *retryableClockSkewError) Error() string {
return fmt.Sprintf("Probable clock skew error: %v", e.Err)
}
// Unwrap returns the wrapped error.
func (e *retryableClockSkewError) Unwrap() error {
return e.Err
}
// RetryableError allows the retryer to retry this request
func (e *retryableClockSkewError) RetryableError() bool {
return true
}

View file

@ -1,3 +1,19 @@
# v1.27.21 (2024-06-19)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.27.20 (2024-06-18)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.27.19 (2024-06-17)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.27.18 (2024-06-07)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.27.17 (2024-06-03) # v1.27.17 (2024-06-03)
* **Documentation**: Add deprecation docs to global endpoint resolution interfaces. These APIs were previously deprecated with the introduction of service-specific endpoint resolution (EndpointResolverV2 and BaseEndpoint on service client options). * **Documentation**: Add deprecation docs to global endpoint resolution interfaces. These APIs were previously deprecated with the introduction of service-specific endpoint resolution (EndpointResolverV2 and BaseEndpoint on service client options).

View file

@ -80,6 +80,9 @@ var defaultAWSConfigResolvers = []awsConfigResolver{
// Sets the RequestMinCompressSizeBytes if present in env var or shared config profile // Sets the RequestMinCompressSizeBytes if present in env var or shared config profile
resolveRequestMinCompressSizeBytes, resolveRequestMinCompressSizeBytes,
// Sets the AccountIDEndpointMode if present in env var or shared config profile
resolveAccountIDEndpointMode,
} }
// A Config represents a generic configuration value or set of values. This type // A Config represents a generic configuration value or set of values. This type

View file

@ -80,6 +80,9 @@ const (
awsRequestMinCompressionSizeBytes = "AWS_REQUEST_MIN_COMPRESSION_SIZE_BYTES" awsRequestMinCompressionSizeBytes = "AWS_REQUEST_MIN_COMPRESSION_SIZE_BYTES"
awsS3DisableExpressSessionAuthEnv = "AWS_S3_DISABLE_EXPRESS_SESSION_AUTH" awsS3DisableExpressSessionAuthEnv = "AWS_S3_DISABLE_EXPRESS_SESSION_AUTH"
awsAccountIDEnv = "AWS_ACCOUNT_ID"
awsAccountIDEndpointModeEnv = "AWS_ACCOUNT_ID_ENDPOINT_MODE"
) )
var ( var (
@ -290,6 +293,9 @@ type EnvConfig struct {
// will only bypass the modified endpoint routing and signing behaviors // will only bypass the modified endpoint routing and signing behaviors
// associated with the feature. // associated with the feature.
S3DisableExpressAuth *bool S3DisableExpressAuth *bool
// Indicates whether account ID will be required/ignored in endpoint2.0 routing
AccountIDEndpointMode aws.AccountIDEndpointMode
} }
// loadEnvConfig reads configuration values from the OS's environment variables. // loadEnvConfig reads configuration values from the OS's environment variables.
@ -309,6 +315,7 @@ func NewEnvConfig() (EnvConfig, error) {
setStringFromEnvVal(&creds.AccessKeyID, credAccessEnvKeys) setStringFromEnvVal(&creds.AccessKeyID, credAccessEnvKeys)
setStringFromEnvVal(&creds.SecretAccessKey, credSecretEnvKeys) setStringFromEnvVal(&creds.SecretAccessKey, credSecretEnvKeys)
if creds.HasKeys() { if creds.HasKeys() {
creds.AccountID = os.Getenv(awsAccountIDEnv)
creds.SessionToken = os.Getenv(awsSessionTokenEnvVar) creds.SessionToken = os.Getenv(awsSessionTokenEnvVar)
cfg.Credentials = creds cfg.Credentials = creds
} }
@ -389,6 +396,10 @@ func NewEnvConfig() (EnvConfig, error) {
return cfg, err return cfg, err
} }
if err := setAIDEndPointModeFromEnvVal(&cfg.AccountIDEndpointMode, []string{awsAccountIDEndpointModeEnv}); err != nil {
return cfg, err
}
return cfg, nil return cfg, nil
} }
@ -417,6 +428,10 @@ func (c EnvConfig) getRequestMinCompressSizeBytes(context.Context) (int64, bool,
return *c.RequestMinCompressSizeBytes, true, nil return *c.RequestMinCompressSizeBytes, true, nil
} }
func (c EnvConfig) getAccountIDEndpointMode(context.Context) (aws.AccountIDEndpointMode, bool, error) {
return c.AccountIDEndpointMode, len(c.AccountIDEndpointMode) > 0, nil
}
// GetRetryMaxAttempts returns the value of AWS_MAX_ATTEMPTS if was specified, // GetRetryMaxAttempts returns the value of AWS_MAX_ATTEMPTS if was specified,
// and not 0. // and not 0.
func (c EnvConfig) GetRetryMaxAttempts(ctx context.Context) (int, bool, error) { func (c EnvConfig) GetRetryMaxAttempts(ctx context.Context) (int, bool, error) {
@ -491,6 +506,28 @@ func setEC2IMDSEndpointMode(mode *imds.EndpointModeState, keys []string) error {
return nil return nil
} }
func setAIDEndPointModeFromEnvVal(m *aws.AccountIDEndpointMode, keys []string) error {
for _, k := range keys {
value := os.Getenv(k)
if len(value) == 0 {
continue
}
switch value {
case "preferred":
*m = aws.AccountIDEndpointModePreferred
case "required":
*m = aws.AccountIDEndpointModeRequired
case "disabled":
*m = aws.AccountIDEndpointModeDisabled
default:
return fmt.Errorf("invalid value for environment variable, %s=%s, must be preferred/required/disabled", k, value)
}
break
}
return nil
}
// GetRegion returns the AWS Region if set in the environment. Returns an empty // GetRegion returns the AWS Region if set in the environment. Returns an empty
// string if not set. // string if not set.
func (c EnvConfig) getRegion(ctx context.Context) (string, bool, error) { func (c EnvConfig) getRegion(ctx context.Context) (string, bool, error) {

View file

@ -3,4 +3,4 @@
package config package config
// goModuleVersion is the tagged release for this module // goModuleVersion is the tagged release for this module
const goModuleVersion = "1.27.17" const goModuleVersion = "1.27.21"

View file

@ -215,6 +215,8 @@ type LoadOptions struct {
// Whether S3 Express auth is disabled. // Whether S3 Express auth is disabled.
S3DisableExpressAuth *bool S3DisableExpressAuth *bool
AccountIDEndpointMode aws.AccountIDEndpointMode
} }
func (o LoadOptions) getDefaultsMode(ctx context.Context) (aws.DefaultsMode, bool, error) { func (o LoadOptions) getDefaultsMode(ctx context.Context) (aws.DefaultsMode, bool, error) {
@ -278,6 +280,10 @@ func (o LoadOptions) getRequestMinCompressSizeBytes(ctx context.Context) (int64,
return *o.RequestMinCompressSizeBytes, true, nil return *o.RequestMinCompressSizeBytes, true, nil
} }
func (o LoadOptions) getAccountIDEndpointMode(ctx context.Context) (aws.AccountIDEndpointMode, bool, error) {
return o.AccountIDEndpointMode, len(o.AccountIDEndpointMode) > 0, nil
}
// WithRegion is a helper function to construct functional options // WithRegion is a helper function to construct functional options
// that sets Region on config's LoadOptions. Setting the region to // that sets Region on config's LoadOptions. Setting the region to
// an empty string, will result in the region value being ignored. // an empty string, will result in the region value being ignored.
@ -323,6 +329,17 @@ func WithRequestMinCompressSizeBytes(RequestMinCompressSizeBytes *int64) LoadOpt
} }
} }
// WithAccountIDEndpointMode is a helper function to construct functional options
// that sets AccountIDEndpointMode on config's LoadOptions
func WithAccountIDEndpointMode(m aws.AccountIDEndpointMode) LoadOptionsFunc {
return func(o *LoadOptions) error {
if m != "" {
o.AccountIDEndpointMode = m
}
return nil
}
}
// getDefaultRegion returns DefaultRegion from config's LoadOptions // getDefaultRegion returns DefaultRegion from config's LoadOptions
func (o LoadOptions) getDefaultRegion(ctx context.Context) (string, bool, error) { func (o LoadOptions) getDefaultRegion(ctx context.Context) (string, bool, error) {
if len(o.DefaultRegion) == 0 { if len(o.DefaultRegion) == 0 {

View file

@ -225,6 +225,23 @@ func getRequestMinCompressSizeBytes(ctx context.Context, configs configs) (value
return return
} }
// accountIDEndpointModeProvider provides access to the AccountIDEndpointMode
type accountIDEndpointModeProvider interface {
getAccountIDEndpointMode(context.Context) (aws.AccountIDEndpointMode, bool, error)
}
func getAccountIDEndpointMode(ctx context.Context, configs configs) (value aws.AccountIDEndpointMode, found bool, err error) {
for _, cfg := range configs {
if p, ok := cfg.(accountIDEndpointModeProvider); ok {
value, found, err = p.getAccountIDEndpointMode(ctx)
if err != nil || found {
break
}
}
}
return
}
// ec2IMDSRegionProvider provides access to the ec2 imds region // ec2IMDSRegionProvider provides access to the ec2 imds region
// configuration value // configuration value
type ec2IMDSRegionProvider interface { type ec2IMDSRegionProvider interface {

View file

@ -166,6 +166,22 @@ func resolveRequestMinCompressSizeBytes(ctx context.Context, cfg *aws.Config, co
return nil return nil
} }
// resolveAccountIDEndpointMode extracts the AccountIDEndpointMode from the configs slice's
// SharedConfig or EnvConfig
func resolveAccountIDEndpointMode(ctx context.Context, cfg *aws.Config, configs configs) error {
m, found, err := getAccountIDEndpointMode(ctx, configs)
if err != nil {
return err
}
if !found {
m = aws.AccountIDEndpointModePreferred
}
cfg.AccountIDEndpointMode = m
return nil
}
// resolveDefaultRegion extracts the first instance of a default region and sets `aws.Config.Region` to the default // resolveDefaultRegion extracts the first instance of a default region and sets `aws.Config.Region` to the default
// region if region had not been resolved from other sources. // region if region had not been resolved from other sources.
func resolveDefaultRegion(ctx context.Context, cfg *aws.Config, configs configs) error { func resolveDefaultRegion(ctx context.Context, cfg *aws.Config, configs configs) error {

View file

@ -115,6 +115,9 @@ const (
requestMinCompressionSizeBytes = "request_min_compression_size_bytes" requestMinCompressionSizeBytes = "request_min_compression_size_bytes"
s3DisableExpressSessionAuthKey = "s3_disable_express_session_auth" s3DisableExpressSessionAuthKey = "s3_disable_express_session_auth"
accountIDKey = "aws_account_id"
accountIDEndpointMode = "account_id_endpoint_mode"
) )
// defaultSharedConfigProfile allows for swapping the default profile for testing // defaultSharedConfigProfile allows for swapping the default profile for testing
@ -341,6 +344,8 @@ type SharedConfig struct {
// will only bypass the modified endpoint routing and signing behaviors // will only bypass the modified endpoint routing and signing behaviors
// associated with the feature. // associated with the feature.
S3DisableExpressAuth *bool S3DisableExpressAuth *bool
AccountIDEndpointMode aws.AccountIDEndpointMode
} }
func (c SharedConfig) getDefaultsMode(ctx context.Context) (value aws.DefaultsMode, ok bool, err error) { func (c SharedConfig) getDefaultsMode(ctx context.Context) (value aws.DefaultsMode, ok bool, err error) {
@ -1124,12 +1129,17 @@ func (c *SharedConfig) setFromIniSection(profile string, section ini.Section) er
return fmt.Errorf("failed to load %s from shared config, %w", requestMinCompressionSizeBytes, err) return fmt.Errorf("failed to load %s from shared config, %w", requestMinCompressionSizeBytes, err)
} }
if err := updateAIDEndpointMode(&c.AccountIDEndpointMode, section, accountIDEndpointMode); err != nil {
return fmt.Errorf("failed to load %s from shared config, %w", accountIDEndpointMode, err)
}
// Shared Credentials // Shared Credentials
creds := aws.Credentials{ creds := aws.Credentials{
AccessKeyID: section.String(accessKeyIDKey), AccessKeyID: section.String(accessKeyIDKey),
SecretAccessKey: section.String(secretAccessKey), SecretAccessKey: section.String(secretAccessKey),
SessionToken: section.String(sessionTokenKey), SessionToken: section.String(sessionTokenKey),
Source: fmt.Sprintf("SharedConfigCredentials: %s", section.SourceFile[accessKeyIDKey]), Source: fmt.Sprintf("SharedConfigCredentials: %s", section.SourceFile[accessKeyIDKey]),
AccountID: section.String(accountIDKey),
} }
if creds.HasKeys() { if creds.HasKeys() {
@ -1177,6 +1187,26 @@ func updateDisableRequestCompression(disable **bool, sec ini.Section, key string
return nil return nil
} }
func updateAIDEndpointMode(m *aws.AccountIDEndpointMode, sec ini.Section, key string) error {
if !sec.Has(key) {
return nil
}
v := sec.String(key)
switch v {
case "preferred":
*m = aws.AccountIDEndpointModePreferred
case "required":
*m = aws.AccountIDEndpointModeRequired
case "disabled":
*m = aws.AccountIDEndpointModeDisabled
default:
return fmt.Errorf("invalid value for shared config profile field, %s=%s, must be preferred/required/disabled", key, v)
}
return nil
}
func (c SharedConfig) getRequestMinCompressSizeBytes(ctx context.Context) (int64, bool, error) { func (c SharedConfig) getRequestMinCompressSizeBytes(ctx context.Context) (int64, bool, error) {
if c.RequestMinCompressSizeBytes == nil { if c.RequestMinCompressSizeBytes == nil {
return 0, false, nil return 0, false, nil
@ -1191,6 +1221,10 @@ func (c SharedConfig) getDisableRequestCompression(ctx context.Context) (bool, b
return *c.DisableRequestCompression, true, nil return *c.DisableRequestCompression, true, nil
} }
func (c SharedConfig) getAccountIDEndpointMode(ctx context.Context) (aws.AccountIDEndpointMode, bool, error) {
return c.AccountIDEndpointMode, len(c.AccountIDEndpointMode) > 0, nil
}
func updateDefaultsMode(mode *aws.DefaultsMode, section ini.Section, key string) error { func updateDefaultsMode(mode *aws.DefaultsMode, section ini.Section, key string) error {
if !section.Has(key) { if !section.Has(key) {
return nil return nil

View file

@ -1,3 +1,19 @@
# v1.17.21 (2024-06-19)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.17.20 (2024-06-18)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.17.19 (2024-06-17)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.17.18 (2024-06-07)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.17.17 (2024-06-03) # v1.17.17 (2024-06-03)
* **Dependency Update**: Updated to the latest SDK module versions * **Dependency Update**: Updated to the latest SDK module versions

View file

@ -128,6 +128,7 @@ type GetCredentialsOutput struct {
AccessKeyID string AccessKeyID string
SecretAccessKey string SecretAccessKey string
Token string Token string
AccountID string
} }
// EndpointError is an error returned from the endpoint service // EndpointError is an error returned from the endpoint service

View file

@ -152,6 +152,7 @@ func (p *Provider) Retrieve(ctx context.Context) (aws.Credentials, error) {
SecretAccessKey: resp.SecretAccessKey, SecretAccessKey: resp.SecretAccessKey,
SessionToken: resp.Token, SessionToken: resp.Token,
Source: ProviderName, Source: ProviderName,
AccountID: resp.AccountID,
} }
if resp.Expiration != nil { if resp.Expiration != nil {

View file

@ -3,4 +3,4 @@
package credentials package credentials
// goModuleVersion is the tagged release for this module // goModuleVersion is the tagged release for this module
const goModuleVersion = "1.17.17" const goModuleVersion = "1.17.21"

View file

@ -167,6 +167,9 @@ type CredentialProcessResponse struct {
// The date on which the current credentials expire. // The date on which the current credentials expire.
Expiration *time.Time Expiration *time.Time
// The ID of the account for credentials
AccountID string `json:"AccountId"`
} }
// Retrieve executes the credential process command and returns the // Retrieve executes the credential process command and returns the
@ -208,6 +211,7 @@ func (p *Provider) Retrieve(ctx context.Context) (aws.Credentials, error) {
AccessKeyID: resp.AccessKeyID, AccessKeyID: resp.AccessKeyID,
SecretAccessKey: resp.SecretAccessKey, SecretAccessKey: resp.SecretAccessKey,
SessionToken: resp.SessionToken, SessionToken: resp.SessionToken,
AccountID: resp.AccountID,
} }
// Handle expiration // Handle expiration

View file

@ -129,6 +129,7 @@ func (p *Provider) Retrieve(ctx context.Context) (aws.Credentials, error) {
CanExpire: true, CanExpire: true,
Expires: time.Unix(0, output.RoleCredentials.Expiration*int64(time.Millisecond)).UTC(), Expires: time.Unix(0, output.RoleCredentials.Expiration*int64(time.Millisecond)).UTC(),
Source: ProviderName, Source: ProviderName,
AccountID: p.options.AccountID,
}, nil }, nil
} }

View file

@ -308,6 +308,11 @@ func (p *AssumeRoleProvider) Retrieve(ctx context.Context) (aws.Credentials, err
return aws.Credentials{Source: ProviderName}, err return aws.Credentials{Source: ProviderName}, err
} }
var accountID string
if resp.AssumedRoleUser != nil {
accountID = getAccountID(resp.AssumedRoleUser)
}
return aws.Credentials{ return aws.Credentials{
AccessKeyID: *resp.Credentials.AccessKeyId, AccessKeyID: *resp.Credentials.AccessKeyId,
SecretAccessKey: *resp.Credentials.SecretAccessKey, SecretAccessKey: *resp.Credentials.SecretAccessKey,
@ -316,5 +321,6 @@ func (p *AssumeRoleProvider) Retrieve(ctx context.Context) (aws.Credentials, err
CanExpire: true, CanExpire: true,
Expires: *resp.Credentials.Expiration, Expires: *resp.Credentials.Expiration,
AccountID: accountID,
}, nil }, nil
} }

View file

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"strconv" "strconv"
"strings"
"time" "time"
"github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/aws"
@ -135,6 +136,11 @@ func (p *WebIdentityRoleProvider) Retrieve(ctx context.Context) (aws.Credentials
return aws.Credentials{}, fmt.Errorf("failed to retrieve credentials, %w", err) return aws.Credentials{}, fmt.Errorf("failed to retrieve credentials, %w", err)
} }
var accountID string
if resp.AssumedRoleUser != nil {
accountID = getAccountID(resp.AssumedRoleUser)
}
// InvalidIdentityToken error is a temporary error that can occur // InvalidIdentityToken error is a temporary error that can occur
// when assuming an Role with a JWT web identity token. // when assuming an Role with a JWT web identity token.
@ -145,6 +151,19 @@ func (p *WebIdentityRoleProvider) Retrieve(ctx context.Context) (aws.Credentials
Source: WebIdentityProviderName, Source: WebIdentityProviderName,
CanExpire: true, CanExpire: true,
Expires: *resp.Credentials.Expiration, Expires: *resp.Credentials.Expiration,
AccountID: accountID,
} }
return value, nil return value, nil
} }
// extract accountID from arn with format "arn:partition:service:region:account-id:[resource-section]"
func getAccountID(u *types.AssumedRoleUser) string {
if u.Arn == nil {
return ""
}
parts := strings.Split(*u.Arn, ":")
if len(parts) < 5 {
return ""
}
return parts[4]
}

View file

@ -1,3 +1,19 @@
# v1.16.8 (2024-06-19)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.16.7 (2024-06-18)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.16.6 (2024-06-17)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.16.5 (2024-06-07)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.16.4 (2024-06-03) # v1.16.4 (2024-06-03)
* **Dependency Update**: Updated to the latest SDK module versions * **Dependency Update**: Updated to the latest SDK module versions

View file

@ -3,4 +3,4 @@
package imds package imds
// goModuleVersion is the tagged release for this module // goModuleVersion is the tagged release for this module
const goModuleVersion = "1.16.4" const goModuleVersion = "1.16.8"

View file

@ -1,3 +1,20 @@
# v1.17.1 (2024-06-19)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.17.0 (2024-06-18)
* **Feature**: Track usage of various AWS SDK features in user-agent string.
* **Dependency Update**: Updated to the latest SDK module versions
# v1.16.25 (2024-06-17)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.16.24 (2024-06-07)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.16.23 (2024-06-05) # v1.16.23 (2024-06-05)
* **Dependency Update**: Updated to the latest SDK module versions * **Dependency Update**: Updated to the latest SDK module versions

View file

@ -183,7 +183,10 @@ func (d Downloader) Download(ctx context.Context, w io.WriterAt, input *s3.GetOb
// Copy ClientOptions // Copy ClientOptions
clientOptions := make([]func(*s3.Options), 0, len(impl.cfg.ClientOptions)+1) clientOptions := make([]func(*s3.Options), 0, len(impl.cfg.ClientOptions)+1)
clientOptions = append(clientOptions, func(o *s3.Options) { clientOptions = append(clientOptions, func(o *s3.Options) {
o.APIOptions = append(o.APIOptions, middleware.AddSDKAgentKey(middleware.FeatureMetadata, userAgentKey)) o.APIOptions = append(o.APIOptions,
middleware.AddSDKAgentKey(middleware.FeatureMetadata, userAgentKey),
addFeatureUserAgent, // yes, there are two of these
)
}) })
clientOptions = append(clientOptions, impl.cfg.ClientOptions...) clientOptions = append(clientOptions, impl.cfg.ClientOptions...)
impl.cfg.ClientOptions = clientOptions impl.cfg.ClientOptions = clientOptions

View file

@ -3,4 +3,4 @@
package manager package manager
// goModuleVersion is the tagged release for this module // goModuleVersion is the tagged release for this module
const goModuleVersion = "1.16.23" const goModuleVersion = "1.17.1"

View file

@ -311,6 +311,7 @@ func (u Uploader) Upload(ctx context.Context, input *s3.PutObjectInput, opts ...
clientOptions = append(clientOptions, func(o *s3.Options) { clientOptions = append(clientOptions, func(o *s3.Options) {
o.APIOptions = append(o.APIOptions, o.APIOptions = append(o.APIOptions,
middleware.AddSDKAgentKey(middleware.FeatureMetadata, userAgentKey), middleware.AddSDKAgentKey(middleware.FeatureMetadata, userAgentKey),
addFeatureUserAgent, // yes, there are two of these
func(s *smithymiddleware.Stack) error { func(s *smithymiddleware.Stack) error {
return s.Finalize.Insert(&setS3ExpressDefaultChecksum{}, "ResolveEndpointV2", smithymiddleware.After) return s.Finalize.Insert(&setS3ExpressDefaultChecksum{}, "ResolveEndpointV2", smithymiddleware.After)
}, },
@ -853,3 +854,31 @@ func (*setS3ExpressDefaultChecksum) HandleFinalize(
return next.HandleFinalize(ctx, in) return next.HandleFinalize(ctx, in)
} }
func addFeatureUserAgent(stack *smithymiddleware.Stack) error {
ua, err := getOrAddRequestUserAgent(stack)
if err != nil {
return err
}
ua.AddUserAgentFeature(middleware.UserAgentFeatureS3Transfer)
return nil
}
func getOrAddRequestUserAgent(stack *smithymiddleware.Stack) (*middleware.RequestUserAgent, error) {
id := (*middleware.RequestUserAgent)(nil).ID()
mw, ok := stack.Build.Get(id)
if !ok {
mw = middleware.NewRequestUserAgent()
if err := stack.Build.Add(mw, smithymiddleware.After); err != nil {
return nil, err
}
}
ua, ok := mw.(*middleware.RequestUserAgent)
if !ok {
return nil, fmt.Errorf("%T for %s middleware did not match expected type", mw, id)
}
return ua, nil
}

View file

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4" v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4"
internalcontext "github.com/aws/aws-sdk-go-v2/internal/context"
"github.com/aws/aws-sdk-go-v2/internal/sdk" "github.com/aws/aws-sdk-go-v2/internal/sdk"
"github.com/aws/smithy-go" "github.com/aws/smithy-go"
"github.com/aws/smithy-go/auth" "github.com/aws/smithy-go/auth"
@ -39,7 +40,10 @@ func (v *V4SignerAdapter) SignRequest(ctx context.Context, r *smithyhttp.Request
} }
hash := v4.GetPayloadHash(ctx) hash := v4.GetPayloadHash(ctx)
err := v.Signer.SignHTTP(ctx, ca.Credentials, r.Request, hash, name, region, sdk.NowTime(), func(o *v4.SignerOptions) { signingTime := sdk.NowTime()
skew := internalcontext.GetAttemptSkewContext(ctx)
signingTime = signingTime.Add(skew)
err := v.Signer.SignHTTP(ctx, ca.Credentials, r.Request, hash, name, region, signingTime, func(o *v4.SignerOptions) {
o.DisableURIPathEscaping, _ = smithyhttp.GetDisableDoubleEncoding(&props) o.DisableURIPathEscaping, _ = smithyhttp.GetDisableDoubleEncoding(&props)
o.Logger = v.Logger o.Logger = v.Logger

View file

@ -1,3 +1,19 @@
# v1.3.12 (2024-06-19)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.3.11 (2024-06-18)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.3.10 (2024-06-17)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.3.9 (2024-06-07)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.3.8 (2024-06-03) # v1.3.8 (2024-06-03)
* **Dependency Update**: Updated to the latest SDK module versions * **Dependency Update**: Updated to the latest SDK module versions

View file

@ -3,4 +3,4 @@
package configsources package configsources
// goModuleVersion is the tagged release for this module // goModuleVersion is the tagged release for this module
const goModuleVersion = "1.3.8" const goModuleVersion = "1.3.12"

View file

@ -2,12 +2,14 @@ package context
import ( import (
"context" "context"
"time"
"github.com/aws/smithy-go/middleware" "github.com/aws/smithy-go/middleware"
) )
type s3BackendKey struct{} type s3BackendKey struct{}
type checksumInputAlgorithmKey struct{} type checksumInputAlgorithmKey struct{}
type clockSkew struct{}
const ( const (
// S3BackendS3Express identifies the S3Express backend // S3BackendS3Express identifies the S3Express backend
@ -37,3 +39,14 @@ func GetChecksumInputAlgorithm(ctx context.Context) string {
v, _ := middleware.GetStackValue(ctx, checksumInputAlgorithmKey{}).(string) v, _ := middleware.GetStackValue(ctx, checksumInputAlgorithmKey{}).(string)
return v return v
} }
// SetAttemptSkewContext sets the clock skew value on the context
func SetAttemptSkewContext(ctx context.Context, v time.Duration) context.Context {
return middleware.WithStackValue(ctx, clockSkew{}, v)
}
// GetAttemptSkewContext gets the clock skew value from the context
func GetAttemptSkewContext(ctx context.Context) time.Duration {
x, _ := middleware.GetStackValue(ctx, clockSkew{}).(time.Duration)
return x
}

View file

@ -17,6 +17,7 @@ type PartitionConfig struct {
DualStackDnsSuffix string `json:"dualStackDnsSuffix"` DualStackDnsSuffix string `json:"dualStackDnsSuffix"`
SupportsFIPS bool `json:"supportsFIPS"` SupportsFIPS bool `json:"supportsFIPS"`
SupportsDualStack bool `json:"supportsDualStack"` SupportsDualStack bool `json:"supportsDualStack"`
ImplicitGlobalRegion string `json:"implicitGlobalRegion"`
} }
type RegionOverrides struct { type RegionOverrides struct {

View file

@ -18,6 +18,7 @@ var partitions = []Partition{
DualStackDnsSuffix: "api.aws", DualStackDnsSuffix: "api.aws",
SupportsFIPS: true, SupportsFIPS: true,
SupportsDualStack: true, SupportsDualStack: true,
ImplicitGlobalRegion: "us-east-1",
}, },
Regions: map[string]RegionOverrides{ Regions: map[string]RegionOverrides{
"af-south-1": { "af-south-1": {
@ -111,6 +112,13 @@ var partitions = []Partition{
SupportsFIPS: nil, SupportsFIPS: nil,
SupportsDualStack: nil, SupportsDualStack: nil,
}, },
"ca-west-1": {
Name: nil,
DnsSuffix: nil,
DualStackDnsSuffix: nil,
SupportsFIPS: nil,
SupportsDualStack: nil,
},
"eu-central-1": { "eu-central-1": {
Name: nil, Name: nil,
DnsSuffix: nil, DnsSuffix: nil,
@ -234,6 +242,7 @@ var partitions = []Partition{
DualStackDnsSuffix: "api.amazonwebservices.com.cn", DualStackDnsSuffix: "api.amazonwebservices.com.cn",
SupportsFIPS: true, SupportsFIPS: true,
SupportsDualStack: true, SupportsDualStack: true,
ImplicitGlobalRegion: "cn-northwest-1",
}, },
Regions: map[string]RegionOverrides{ Regions: map[string]RegionOverrides{
"aws-cn-global": { "aws-cn-global": {
@ -268,6 +277,7 @@ var partitions = []Partition{
DualStackDnsSuffix: "api.aws", DualStackDnsSuffix: "api.aws",
SupportsFIPS: true, SupportsFIPS: true,
SupportsDualStack: true, SupportsDualStack: true,
ImplicitGlobalRegion: "us-gov-west-1",
}, },
Regions: map[string]RegionOverrides{ Regions: map[string]RegionOverrides{
"aws-us-gov-global": { "aws-us-gov-global": {
@ -302,6 +312,7 @@ var partitions = []Partition{
DualStackDnsSuffix: "c2s.ic.gov", DualStackDnsSuffix: "c2s.ic.gov",
SupportsFIPS: true, SupportsFIPS: true,
SupportsDualStack: false, SupportsDualStack: false,
ImplicitGlobalRegion: "us-iso-east-1",
}, },
Regions: map[string]RegionOverrides{ Regions: map[string]RegionOverrides{
"aws-iso-global": { "aws-iso-global": {
@ -336,6 +347,7 @@ var partitions = []Partition{
DualStackDnsSuffix: "sc2s.sgov.gov", DualStackDnsSuffix: "sc2s.sgov.gov",
SupportsFIPS: true, SupportsFIPS: true,
SupportsDualStack: false, SupportsDualStack: false,
ImplicitGlobalRegion: "us-isob-east-1",
}, },
Regions: map[string]RegionOverrides{ Regions: map[string]RegionOverrides{
"aws-iso-b-global": { "aws-iso-b-global": {
@ -363,8 +375,17 @@ var partitions = []Partition{
DualStackDnsSuffix: "cloud.adc-e.uk", DualStackDnsSuffix: "cloud.adc-e.uk",
SupportsFIPS: true, SupportsFIPS: true,
SupportsDualStack: false, SupportsDualStack: false,
ImplicitGlobalRegion: "eu-isoe-west-1",
},
Regions: map[string]RegionOverrides{
"eu-isoe-west-1": {
Name: nil,
DnsSuffix: nil,
DualStackDnsSuffix: nil,
SupportsFIPS: nil,
SupportsDualStack: nil,
},
}, },
Regions: map[string]RegionOverrides{},
}, },
{ {
ID: "aws-iso-f", ID: "aws-iso-f",
@ -375,6 +396,7 @@ var partitions = []Partition{
DualStackDnsSuffix: "csp.hci.ic.gov", DualStackDnsSuffix: "csp.hci.ic.gov",
SupportsFIPS: true, SupportsFIPS: true,
SupportsDualStack: false, SupportsDualStack: false,
ImplicitGlobalRegion: "us-isof-south-1",
}, },
Regions: map[string]RegionOverrides{}, Regions: map[string]RegionOverrides{},
}, },

View file

@ -1,3 +1,19 @@
# v2.6.12 (2024-06-19)
* **Dependency Update**: Updated to the latest SDK module versions
# v2.6.11 (2024-06-18)
* **Dependency Update**: Updated to the latest SDK module versions
# v2.6.10 (2024-06-17)
* **Dependency Update**: Updated to the latest SDK module versions
# v2.6.9 (2024-06-07)
* **Dependency Update**: Updated to the latest SDK module versions
# v2.6.8 (2024-06-03) # v2.6.8 (2024-06-03)
* **Dependency Update**: Updated to the latest SDK module versions * **Dependency Update**: Updated to the latest SDK module versions

View file

@ -3,4 +3,4 @@
package endpoints package endpoints
// goModuleVersion is the tagged release for this module // goModuleVersion is the tagged release for this module
const goModuleVersion = "2.6.8" const goModuleVersion = "2.6.12"

View file

@ -0,0 +1,42 @@
package middleware
import (
"context"
"sync/atomic"
"time"
internalcontext "github.com/aws/aws-sdk-go-v2/internal/context"
"github.com/aws/smithy-go/middleware"
)
// AddTimeOffsetMiddleware sets a value representing clock skew on the request context.
// This can be read by other operations (such as signing) to correct the date value they send
// on the request
type AddTimeOffsetMiddleware struct {
Offset *atomic.Int64
}
// ID the identifier for AddTimeOffsetMiddleware
func (m *AddTimeOffsetMiddleware) ID() string { return "AddTimeOffsetMiddleware" }
// HandleBuild sets a value for attemptSkew on the request context if one is set on the client.
func (m AddTimeOffsetMiddleware) HandleBuild(ctx context.Context, in middleware.BuildInput, next middleware.BuildHandler) (
out middleware.BuildOutput, metadata middleware.Metadata, err error,
) {
if m.Offset != nil {
offset := time.Duration(m.Offset.Load())
ctx = internalcontext.SetAttemptSkewContext(ctx, offset)
}
return next.HandleBuild(ctx, in)
}
// HandleDeserialize gets the clock skew context from the context, and if set, sets it on the pointer
// held by AddTimeOffsetMiddleware
func (m *AddTimeOffsetMiddleware) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) (
out middleware.DeserializeOutput, metadata middleware.Metadata, err error,
) {
if v := internalcontext.GetAttemptSkewContext(ctx); v != 0 {
m.Offset.Store(v.Nanoseconds())
}
return next.HandleDeserialize(ctx, in)
}

View file

@ -1,3 +1,19 @@
# v1.3.12 (2024-06-19)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.3.11 (2024-06-18)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.3.10 (2024-06-17)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.3.9 (2024-06-07)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.3.8 (2024-06-03) # v1.3.8 (2024-06-03)
* **Dependency Update**: Updated to the latest SDK module versions * **Dependency Update**: Updated to the latest SDK module versions

View file

@ -3,4 +3,4 @@
package v4a package v4a
// goModuleVersion is the tagged release for this module // goModuleVersion is the tagged release for this module
const goModuleVersion = "1.3.8" const goModuleVersion = "1.3.12"

View file

@ -5,6 +5,8 @@ import (
"fmt" "fmt"
"time" "time"
internalcontext "github.com/aws/aws-sdk-go-v2/internal/context"
v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4" v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4"
"github.com/aws/aws-sdk-go-v2/internal/sdk" "github.com/aws/aws-sdk-go-v2/internal/sdk"
"github.com/aws/smithy-go" "github.com/aws/smithy-go"
@ -72,7 +74,11 @@ func (v *SignerAdapter) SignRequest(ctx context.Context, r *smithyhttp.Request,
} }
hash := v4.GetPayloadHash(ctx) hash := v4.GetPayloadHash(ctx)
err := v.Signer.SignHTTP(ctx, ca.Credentials, r.Request, hash, name, regions, sdk.NowTime(), func(o *SignerOptions) { signingTime := sdk.NowTime()
if skew := internalcontext.GetAttemptSkewContext(ctx); skew != 0 {
signingTime.Add(skew)
}
err := v.Signer.SignHTTP(ctx, ca.Credentials, r.Request, hash, name, regions, signingTime, func(o *SignerOptions) {
o.DisableURIPathEscaping, _ = smithyhttp.GetDisableDoubleEncoding(&props) o.DisableURIPathEscaping, _ = smithyhttp.GetDisableDoubleEncoding(&props)
o.Logger = v.Logger o.Logger = v.Logger

View file

@ -1,3 +1,19 @@
# v1.3.14 (2024-06-19)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.3.13 (2024-06-18)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.3.12 (2024-06-17)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.3.11 (2024-06-07)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.3.10 (2024-06-03) # v1.3.10 (2024-06-03)
* **Dependency Update**: Updated to the latest SDK module versions * **Dependency Update**: Updated to the latest SDK module versions

View file

@ -3,4 +3,4 @@
package checksum package checksum
// goModuleVersion is the tagged release for this module // goModuleVersion is the tagged release for this module
const goModuleVersion = "1.3.10" const goModuleVersion = "1.3.14"

View file

@ -1,3 +1,19 @@
# v1.11.14 (2024-06-19)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.11.13 (2024-06-18)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.11.12 (2024-06-17)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.11.11 (2024-06-07)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.11.10 (2024-06-03) # v1.11.10 (2024-06-03)
* **Dependency Update**: Updated to the latest SDK module versions * **Dependency Update**: Updated to the latest SDK module versions

View file

@ -3,4 +3,4 @@
package presignedurl package presignedurl
// goModuleVersion is the tagged release for this module // goModuleVersion is the tagged release for this module
const goModuleVersion = "1.11.10" const goModuleVersion = "1.11.14"

View file

@ -1,3 +1,19 @@
# v1.17.12 (2024-06-19)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.17.11 (2024-06-18)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.17.10 (2024-06-17)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.17.9 (2024-06-07)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.17.8 (2024-06-03) # v1.17.8 (2024-06-03)
* **Dependency Update**: Updated to the latest SDK module versions * **Dependency Update**: Updated to the latest SDK module versions

View file

@ -3,4 +3,4 @@
package s3shared package s3shared
// goModuleVersion is the tagged release for this module // goModuleVersion is the tagged release for this module
const goModuleVersion = "1.17.8" const goModuleVersion = "1.17.12"

View file

@ -1,3 +1,21 @@
# v1.56.1 (2024-06-19)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.56.0 (2024-06-18)
* **Feature**: Track usage of various AWS SDK features in user-agent string.
* **Dependency Update**: Updated to the latest SDK module versions
# v1.55.2 (2024-06-17)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.55.1 (2024-06-07)
* **Bug Fix**: Add clock skew correction on all service clients
* **Dependency Update**: Updated to the latest SDK module versions
# v1.55.0 (2024-06-05) # v1.55.0 (2024-06-05)
* **Feature**: Added new params copySource and key to copyObject API for supporting S3 Access Grants plugin. These changes will not change any of the existing S3 API functionality. * **Feature**: Added new params copySource and key to copyObject API for supporting S3 Access Grants plugin. These changes will not change any of the existing S3 API functionality.

View file

@ -14,6 +14,7 @@ import (
internalauth "github.com/aws/aws-sdk-go-v2/internal/auth" internalauth "github.com/aws/aws-sdk-go-v2/internal/auth"
internalauthsmithy "github.com/aws/aws-sdk-go-v2/internal/auth/smithy" internalauthsmithy "github.com/aws/aws-sdk-go-v2/internal/auth/smithy"
internalConfig "github.com/aws/aws-sdk-go-v2/internal/configsources" internalConfig "github.com/aws/aws-sdk-go-v2/internal/configsources"
internalmiddleware "github.com/aws/aws-sdk-go-v2/internal/middleware"
"github.com/aws/aws-sdk-go-v2/internal/v4a" "github.com/aws/aws-sdk-go-v2/internal/v4a"
acceptencodingcust "github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding" acceptencodingcust "github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding"
internalChecksum "github.com/aws/aws-sdk-go-v2/service/internal/checksum" internalChecksum "github.com/aws/aws-sdk-go-v2/service/internal/checksum"
@ -22,12 +23,14 @@ import (
s3sharedconfig "github.com/aws/aws-sdk-go-v2/service/internal/s3shared/config" s3sharedconfig "github.com/aws/aws-sdk-go-v2/service/internal/s3shared/config"
s3cust "github.com/aws/aws-sdk-go-v2/service/s3/internal/customizations" s3cust "github.com/aws/aws-sdk-go-v2/service/s3/internal/customizations"
smithy "github.com/aws/smithy-go" smithy "github.com/aws/smithy-go"
smithyauth "github.com/aws/smithy-go/auth"
smithydocument "github.com/aws/smithy-go/document" smithydocument "github.com/aws/smithy-go/document"
"github.com/aws/smithy-go/logging" "github.com/aws/smithy-go/logging"
"github.com/aws/smithy-go/middleware" "github.com/aws/smithy-go/middleware"
smithyhttp "github.com/aws/smithy-go/transport/http" smithyhttp "github.com/aws/smithy-go/transport/http"
"net" "net"
"net/http" "net/http"
"sync/atomic"
"time" "time"
) )
@ -38,6 +41,9 @@ const ServiceAPIVersion = "2006-03-01"
// Storage Service. // Storage Service.
type Client struct { type Client struct {
options Options options Options
// Difference between the time reported by the server and the client
timeOffset *atomic.Int64
} }
// New returns an initialized Client based on the functional options. Provide // New returns an initialized Client based on the functional options. Provide
@ -82,6 +88,8 @@ func New(options Options, optFns ...func(*Options)) *Client {
finalizeExpressCredentials(&options, client) finalizeExpressCredentials(&options, client)
initializeTimeOffsetResolver(client)
return client return client
} }
@ -268,6 +276,7 @@ func NewFromConfig(cfg aws.Config, optFns ...func(*Options)) *Client {
Logger: cfg.Logger, Logger: cfg.Logger,
ClientLogMode: cfg.ClientLogMode, ClientLogMode: cfg.ClientLogMode,
AppID: cfg.AppID, AppID: cfg.AppID,
AccountIDEndpointMode: cfg.AccountIDEndpointMode,
} }
resolveAWSRetryerProvider(cfg, &opts) resolveAWSRetryerProvider(cfg, &opts)
resolveAWSRetryMaxAttempts(cfg, &opts) resolveAWSRetryMaxAttempts(cfg, &opts)
@ -475,6 +484,30 @@ func addContentSHA256Header(stack *middleware.Stack) error {
return stack.Finalize.Insert(&v4.ContentSHA256Header{}, (*v4.ComputePayloadSHA256)(nil).ID(), middleware.After) return stack.Finalize.Insert(&v4.ContentSHA256Header{}, (*v4.ComputePayloadSHA256)(nil).ID(), middleware.After)
} }
func addIsWaiterUserAgent(o *Options) {
o.APIOptions = append(o.APIOptions, func(stack *middleware.Stack) error {
ua, err := getOrAddRequestUserAgent(stack)
if err != nil {
return err
}
ua.AddUserAgentFeature(awsmiddleware.UserAgentFeatureWaiter)
return nil
})
}
func addIsPaginatorUserAgent(o *Options) {
o.APIOptions = append(o.APIOptions, func(stack *middleware.Stack) error {
ua, err := getOrAddRequestUserAgent(stack)
if err != nil {
return err
}
ua.AddUserAgentFeature(awsmiddleware.UserAgentFeaturePaginator)
return nil
})
}
func addRetry(stack *middleware.Stack, o Options) error { func addRetry(stack *middleware.Stack, o Options) error {
attempt := retry.NewAttemptMiddleware(o.Retryer, smithyhttp.RequestCloner, func(m *retry.Attempt) { attempt := retry.NewAttemptMiddleware(o.Retryer, smithyhttp.RequestCloner, func(m *retry.Attempt) {
m.LogAttempts = o.ClientLogMode.IsRetries() m.LogAttempts = o.ClientLogMode.IsRetries()
@ -548,6 +581,18 @@ func resolveUseFIPSEndpoint(cfg aws.Config, o *Options) error {
return nil return nil
} }
func resolveAccountID(identity smithyauth.Identity, mode aws.AccountIDEndpointMode) *string {
if mode == aws.AccountIDEndpointModeDisabled {
return nil
}
if ca, ok := identity.(*internalauthsmithy.CredentialsAdapter); ok && ca.Credentials.AccountID != "" {
return aws.String(ca.Credentials.AccountID)
}
return nil
}
type httpSignerV4a interface { type httpSignerV4a interface {
SignHTTP(ctx context.Context, credentials v4a.Credentials, r *http.Request, payloadHash, SignHTTP(ctx context.Context, credentials v4a.Credentials, r *http.Request, payloadHash,
service string, regionSet []string, signingTime time.Time, service string, regionSet []string, signingTime time.Time,
@ -568,6 +613,51 @@ func newDefaultV4aSigner(o Options) *v4a.Signer {
}) })
} }
func addTimeOffsetBuild(stack *middleware.Stack, c *Client) error {
mw := internalmiddleware.AddTimeOffsetMiddleware{Offset: c.timeOffset}
if err := stack.Build.Add(&mw, middleware.After); err != nil {
return err
}
return stack.Deserialize.Insert(&mw, "RecordResponseTiming", middleware.Before)
}
func initializeTimeOffsetResolver(c *Client) {
c.timeOffset = new(atomic.Int64)
}
func checkAccountID(identity smithyauth.Identity, mode aws.AccountIDEndpointMode) error {
switch mode {
case aws.AccountIDEndpointModeUnset:
case aws.AccountIDEndpointModePreferred:
case aws.AccountIDEndpointModeDisabled:
case aws.AccountIDEndpointModeRequired:
if ca, ok := identity.(*internalauthsmithy.CredentialsAdapter); !ok {
return fmt.Errorf("accountID is required but not set")
} else if ca.Credentials.AccountID == "" {
return fmt.Errorf("accountID is required but not set")
}
// default check in case invalid mode is configured through request config
default:
return fmt.Errorf("invalid accountID endpoint mode %s, must be preferred/required/disabled", mode)
}
return nil
}
func addUserAgentRetryMode(stack *middleware.Stack, options Options) error {
ua, err := getOrAddRequestUserAgent(stack)
if err != nil {
return err
}
switch options.Retryer.(type) {
case *retry.Standard:
ua.AddUserAgentFeature(awsmiddleware.UserAgentFeatureRetryModeStandard)
case *retry.AdaptiveMode:
ua.AddUserAgentFeature(awsmiddleware.UserAgentFeatureRetryModeAdaptive)
}
return nil
}
func addMetadataRetrieverMiddleware(stack *middleware.Stack) error { func addMetadataRetrieverMiddleware(stack *middleware.Stack) error {
return s3shared.AddMetadataRetrieverMiddleware(stack) return s3shared.AddMetadataRetrieverMiddleware(stack)
} }

View file

@ -233,6 +233,15 @@ func (c *Client) addOperationAbortMultipartUploadMiddlewares(stack *middleware.S
if err = addPutBucketContextMiddleware(stack); err != nil { if err = addPutBucketContextMiddleware(stack); err != nil {
return err return err
} }
if err = addTimeOffsetBuild(stack, c); err != nil {
return err
}
if err = addUserAgentRetryMode(stack, options); err != nil {
return err
}
if err = addIsExpressUserAgent(stack); err != nil {
return err
}
if err = addOpAbortMultipartUploadValidationMiddleware(stack); err != nil { if err = addOpAbortMultipartUploadValidationMiddleware(stack); err != nil {
return err return err
} }

View file

@ -455,6 +455,15 @@ func (c *Client) addOperationCompleteMultipartUploadMiddlewares(stack *middlewar
if err = addPutBucketContextMiddleware(stack); err != nil { if err = addPutBucketContextMiddleware(stack); err != nil {
return err return err
} }
if err = addTimeOffsetBuild(stack, c); err != nil {
return err
}
if err = addUserAgentRetryMode(stack, options); err != nil {
return err
}
if err = addIsExpressUserAgent(stack); err != nil {
return err
}
if err = addOpCompleteMultipartUploadValidationMiddleware(stack); err != nil { if err = addOpCompleteMultipartUploadValidationMiddleware(stack); err != nil {
return err return err
} }

Some files were not shown because too many files have changed in this diff Show more