diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 460bfa7d..9aa904da 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -15,12 +15,12 @@ jobs: cancel-in-progress: true runs-on: actuated-8cpu-12gb steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: fetch-depth: 1 - name: Install Go - uses: actions/setup-go@v6 + uses: actions/setup-go@v7 with: - go-version: 1.25.x + go-version: 1.27.x - name: Make run: make all diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index e9e36ed0..119fa21e 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -9,18 +9,18 @@ jobs: publish: runs-on: actuated-8cpu-12gb steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: fetch-depth: 1 - name: Install Go - uses: actions/setup-go@v6 + uses: actions/setup-go@v7 with: - go-version: 1.25.x + go-version: 1.27.x - name: Make run: make all - name: Upload release binaries - uses: alexellis/upload-assets@0.4.1 + uses: alexellis/upload-assets@0.5.0 env: GITHUB_TOKEN: ${{ github.token }} with: diff --git a/go.mod b/go.mod index bef442a4..17280f8e 100644 --- a/go.mod +++ b/go.mod @@ -1,15 +1,15 @@ module github.com/inlets/inletsctl -go 1.25.0 +go 1.27.0 require ( github.com/alexellis/go-execute/v2 v2.2.1 github.com/golang/mock v1.6.0 github.com/inlets/cloud-provision v0.7.2 - github.com/linode/linodego v1.67.0 + github.com/linode/linodego v1.69.1 github.com/morikuni/aec v1.1.0 github.com/pkg/errors v0.9.1 - github.com/sethvargo/go-password v0.3.1 + github.com/sethvargo/go-password v0.4.0 github.com/spf13/cobra v1.10.2 github.com/spf13/pflag v1.0.10 ) @@ -17,64 +17,64 @@ require ( // replace github.com/inlets/cloud-provision => ../cloud-provision require ( - cloud.google.com/go/auth v0.20.0 // indirect - cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect - cloud.google.com/go/compute/metadata v0.9.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.12.0 // indirect + cloud.google.com/go/auth v0.24.1 // indirect + cloud.google.com/go/auth/oauth2adapt v0.3.0 // indirect + cloud.google.com/go/compute/metadata v0.10.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.23.3 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.15.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.13.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute v1.0.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork v1.1.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v1.7.1 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.10.1 // indirect github.com/aws/aws-sdk-go v1.55.8 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/digitalocean/godo v1.184.0 // indirect - github.com/dimchansky/utfbom v1.1.1 // indirect + github.com/digitalocean/godo v1.231.0 // indirect + github.com/dimchansky/utfbom v1.2.0 // indirect github.com/dirien/ovh-go-sdk v0.2.0 // indirect - github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/go-logr/logr v1.4.3 // indirect + github.com/felixge/httpsnoop v1.1.0 // indirect + github.com/go-logr/logr v1.4.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-resty/resty/v2 v2.17.2 // indirect github.com/golang-jwt/jwt/v5 v5.3.1 // indirect github.com/google/go-querystring v1.2.0 // indirect - github.com/google/s2a-go v0.1.9 // indirect + github.com/google/s2a-go v0.1.11 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.3.14 // indirect - github.com/googleapis/gax-go/v2 v2.21.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.24 // indirect + github.com/googleapis/gax-go/v2 v2.27.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-retryablehttp v0.7.8 // indirect github.com/hetznercloud/hcloud-go v1.59.2 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/klauspost/compress v1.18.5 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/ovh/go-ovh v1.9.0 // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect - github.com/prometheus/client_golang v1.23.2 // indirect - github.com/prometheus/client_model v0.6.2 // indirect - github.com/prometheus/common v0.67.5 // indirect - github.com/prometheus/procfs v0.20.1 // indirect - github.com/scaleway/scaleway-sdk-go v1.0.0-beta.36 // indirect + github.com/prometheus/client_golang v1.25.0 // indirect + github.com/prometheus/client_model v0.6.3 // indirect + github.com/prometheus/common v0.72.1 // indirect + github.com/prometheus/procfs v0.22.0 // indirect + github.com/scaleway/scaleway-sdk-go v1.39.0 // indirect github.com/vultr/govultr/v2 v2.17.2 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 // indirect - go.opentelemetry.io/otel v1.43.0 // indirect - go.opentelemetry.io/otel/metric v1.43.0 // indirect - go.opentelemetry.io/otel/trace v1.43.0 // indirect - go.yaml.in/yaml/v2 v2.4.4 // indirect - golang.org/x/crypto v0.49.0 // indirect - golang.org/x/net v0.52.0 // indirect - golang.org/x/oauth2 v0.36.0 // indirect - golang.org/x/sys v0.43.0 // indirect - golang.org/x/text v0.35.0 // indirect - golang.org/x/time v0.15.0 // indirect - google.golang.org/api v0.275.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d // indirect - google.golang.org/grpc v1.80.0 // indirect - google.golang.org/protobuf v1.36.11 // indirect - gopkg.in/ini.v1 v1.67.1 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0 // indirect + go.opentelemetry.io/otel v1.47.0 // indirect + go.opentelemetry.io/otel/log v1.47.0 // indirect + go.opentelemetry.io/otel/metric v1.47.0 // indirect + go.opentelemetry.io/otel/trace v1.47.0 // indirect + golang.org/x/crypto v0.58.0 // indirect + golang.org/x/net v0.61.0 // indirect + golang.org/x/oauth2 v0.37.0 // indirect + golang.org/x/sync v0.24.0 // indirect + golang.org/x/sys v0.49.0 // indirect + golang.org/x/text v0.43.0 // indirect + golang.org/x/time v0.16.0 // indirect + google.golang.org/api v0.307.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20261019180522-ce908d29299b // indirect + google.golang.org/grpc v1.84.0 // indirect + google.golang.org/protobuf v1.36.12 // indirect + gopkg.in/ini.v1 v1.67.3 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/go.sum b/go.sum index 338bb036..f9642c51 100644 --- a/go.sum +++ b/go.sum @@ -1,30 +1,17 @@ -cloud.google.com/go/auth v0.14.0 h1:A5C4dKV/Spdvxcl0ggWwWEzzP7AZMJSEIgrkngwhGYM= -cloud.google.com/go/auth v0.14.0/go.mod h1:CYsoRL1PdiDuqeQpZE0bP2pnPrGqFcOkI0nldEQis+A= -cloud.google.com/go/auth v0.20.0 h1:kXTssoVb4azsVDoUiF8KvxAqrsQcQtB53DcSgta74CA= -cloud.google.com/go/auth v0.20.0/go.mod h1:942/yi/itH1SsmpyrbnTMDgGfdy2BUqIKyd0cyYLc5Q= -cloud.google.com/go/auth/oauth2adapt v0.2.7 h1:/Lc7xODdqcEw8IrZ9SvwnlLX6j9FHQM74z6cBk9Rw6M= -cloud.google.com/go/auth/oauth2adapt v0.2.7/go.mod h1:NTbTTzfvPl1Y3V1nPpOgl2w6d/FjO7NNUQaWSox6ZMc= -cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= -cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= -cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= -cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= -cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= -cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 h1:g0EZJwz7xkXQiZAI5xi9f3WWFYBlX1CPTrR+NDToRkQ= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0/go.mod h1:XCW7KnZet0Opnr7HccfUw1PLc4CjHqpcaxW8DHklNkQ= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0 h1:fou+2+WFTib47nS+nz/ozhEBnvU96bKHy6LjRsY4E28= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0/go.mod h1:t76Ruy8AHvUAC8GfMWJMa0ElSbuIcO03NLpynfbgsPA= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.1 h1:1mvYtZfWQAnwNah/C+Z+Jb9rQH95LPE2vlmMuWAHJk8= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.1/go.mod h1:75I/mXtme1JyWFtz8GocPHVFyH421IBoZErnO16dd0k= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 h1:Hk5QBxZQC1jb2Fwj6mpzme37xbCDdNTxU7O9eb5+LB4= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1/go.mod h1:IYus9qsFobWIc2YVwe/WPjcnyCkPKtnHAqUYeebc8z0= -github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.1 h1:Bk5uOhSAenHyR5P61D/NzeQCv+4fEVV8mOkJ82NqpWw= -github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.1/go.mod h1:QZ4pw3or1WPmRBxf0cHd1tknzrT54WPBOQoGutCPvSU= -github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.12.0 h1:fhqpLE3UEXi9lPaBRpQ6XuRW0nU7hgg4zlmZZa+a9q4= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.12.0/go.mod h1:7dCRMLwisfRH3dBupKeNCioWYUZ4SS09Z14H+7i8ZoY= +cloud.google.com/go/auth v0.24.1 h1:NTmd2iJb4DsGIav0KiqFMYI88nMshA2wnFMBatRmoCs= +cloud.google.com/go/auth v0.24.1/go.mod h1:1dmBXa9xfBvBr39ZnDUDkaaA91ccq9CcqENDgJA4d7c= +cloud.google.com/go/auth/oauth2adapt v0.3.0 h1:FY8oSZpCYoUNv6QxVODuMjQz4IlSOVeiQtZ08vLPz88= +cloud.google.com/go/auth/oauth2adapt v0.3.0/go.mod h1:7+2uCm7++XFO+/lN06c2HXpDXb/NMNn2/UwyBPbTnkk= +cloud.google.com/go/compute/metadata v0.10.0 h1:pyKMUQSwchgkIBBJGdILqQbs/BNJXqwSA7Ej6LAvvtY= +cloud.google.com/go/compute/metadata v0.10.0/go.mod h1:rGFHRrIif570kSibjFTMbt6/4/tzgJWFGI/HVol4GIk= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.23.3 h1:qgnWTiWs1G7AqcKZegFvkJD1bmXJcaDU3uC0ELSgZ5U= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.23.3/go.mod h1:XtxD48QPInqoj+GMlcRlXHEYsoOxFnP6w2JgIZ9rDS4= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.15.0 h1:w3gDUJlJ0BfBsHH02DCBDwbkmMSXJqBj6nBOCo9iocY= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.15.0/go.mod h1:7scl8mG/IFLVjJ9ef/ltdND2T1z0CkgVSaQoUxLvmeU= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.4.0 h1:xFaZZ+IubdftrDHnGGwZ6QvQ3KHTtWl2MCK+GMt2vxs= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.4.0/go.mod h1:mCBhUhlMjLLJKr5aqw2TNS/VqJOie8MzWq3DAMJeKso= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.13.0 h1:Terj1CMW4+NY5CpWjSRkqLoxh2DkYDdv/FH2z0897Uc= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.13.0/go.mod h1:7Ut2Qw9vcwpLW5Q4MBy43uSxXS7tK2yjs94OJ6j5thE= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute v1.0.0 h1:/Di3vB4sNeQ+7A8efjUVENvyB945Wruvstucqp7ZArg= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute v1.0.0/go.mod h1:gM3K25LQlsET3QR+4V74zxCsFAy0r6xMNN9n80SZn+4= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.0.0 h1:lMW1lD/17LUA5z1XTURo7LcVG2ICBPlyMHjIUrcFZNQ= @@ -39,136 +26,96 @@ github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1. github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0/go.mod h1:5kakwfW5CjC9KK+Q4wjXAg+ShuIm2mBMua0ZFj2C8PE= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= -github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2 h1:kYRSnvJju5gYVyhkij+RTJ/VR6QIUaCfWeaFm2ycsjQ= -github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= -github.com/AzureAD/microsoft-authentication-library-for-go v1.7.1 h1:edShSHV3DV90+kt+CMaEXEzR9QF7wFrPJxVGz2blMIU= -github.com/AzureAD/microsoft-authentication-library-for-go v1.7.1/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk= +github.com/AzureAD/microsoft-authentication-library-for-go v1.10.1 h1:0O6j18nQDoIff6/mtosT5LNU2WehEwp+LqfX6699oqY= +github.com/AzureAD/microsoft-authentication-library-for-go v1.10.1/go.mod h1:xdYAf5bjkOpsd3auA8riiJW4vneBubt9caavL7626jQ= github.com/alexellis/go-execute/v2 v2.2.1 h1:4Ye3jiCKQarstODOEmqDSRCqxMHLkC92Bhse743RdOI= github.com/alexellis/go-execute/v2 v2.2.1/go.mod h1:FMdRnUTiFAmYXcv23txrp3VYZfLo24nMpiIneWgKHTQ= -github.com/aws/aws-sdk-go v1.55.6 h1:cSg4pvZ3m8dgYcgqB97MrcdjUmZ1BeMYKUxMMB89IPk= -github.com/aws/aws-sdk-go v1.55.6/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= github.com/aws/aws-sdk-go v1.55.8 h1:JRmEUbU52aJQZ2AjX4q4Wu7t4uZjOu71uyNmaWlUkJQ= github.com/aws/aws-sdk-go v1.55.8/go.mod h1:ZkViS9AqA6otK+JBBNH2++sx1sgxrPKcSzPPvQkUtXk= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= -github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/digitalocean/godo v1.134.0 h1:dT7aQR9jxNOQEZwzP+tAYcxlj5szFZScC33+PAYGQVM= -github.com/digitalocean/godo v1.134.0/go.mod h1:PU8JB6I1XYkQIdHFop8lLAY9ojp6M0XcU0TWaQSxbrc= -github.com/digitalocean/godo v1.184.0 h1:2B2CQhxftlf3xa24Nrzn5CBQlaQjyaWqi3XbbnJlG3w= -github.com/digitalocean/godo v1.184.0/go.mod h1:xQsWpVCCbkDrWisHA72hPzPlnC+4W5w/McZY5ij9uvU= -github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= -github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= +github.com/digitalocean/godo v1.231.0 h1:fnwYt5a5IiBLHIc1xL6jHmGNaPpJ9sK5uw+HYZxpHC4= +github.com/digitalocean/godo v1.231.0/go.mod h1:xQsWpVCCbkDrWisHA72hPzPlnC+4W5w/McZY5ij9uvU= +github.com/dimchansky/utfbom v1.2.0 h1:ikiGYT9Wa8zleQ0xrlAWC9Ar9LNInSWRodJ5MkHB3d4= +github.com/dimchansky/utfbom v1.2.0/go.mod h1:kJPs9PFVyF/LnFVVGz+XXvouv0KxympBxr0pSwv0KQU= github.com/dirien/ovh-go-sdk v0.2.0 h1:hIL39yxXnUNEUw1gn3g2cA9QKj2cHdbbowAyq8tHug4= github.com/dirien/ovh-go-sdk v0.2.0/go.mod h1:kz6dmFoAym8NbdVTdGRzQuTGfRNoMrSuevxvxxBPVjA= -github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= -github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.1.0 h1:3YtUj32ZZkqZtt3sZZsClsymw/QDuVfpNhoA31zeORc= +github.com/felixge/httpsnoop v1.1.0/go.mod h1:Zqxgdd+1Rkcz8euOqdr7lqgCRJztwr5hp9vDSi5UZCE= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= -github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8= +github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-resty/resty/v2 v2.16.3 h1:zacNT7lt4b8M/io2Ahj6yPypL7bqx9n1iprfQuodV+E= -github.com/go-resty/resty/v2 v2.16.3/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA= github.com/go-resty/resty/v2 v2.17.2 h1:FQW5oHYcIlkCNrMD2lloGScxcHJ0gkjshV3qcQAyHQk= github.com/go-resty/resty/v2 v2.17.2/go.mod h1:kCKZ3wWmwJaNc7S29BRtUhJwy7iqmn+2mLtQrOyQlVA= -github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= -github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= -github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= -github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= -github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY= github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= -github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-querystring v1.2.0 h1:yhqkPbu2/OH+V9BfpCVPZkNmUXhb2gBxJArfhIxNtP0= github.com/google/go-querystring v1.2.0/go.mod h1:8IFJqpSRITyJ8QhQ13bmbeMBDfmeEJZD5A0egEOmkqU= -github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= -github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= +github.com/google/s2a-go v0.1.11 h1:7v1V1TraNGP63WptsAkNqr2w8jgm4vM6A6qx6Lsw9iM= +github.com/google/s2a-go v0.1.11/go.mod h1:pz4tyvwXvJLLbyrkh6FW1eS2zPUXMaTmyNhYtyP2tNw= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= -github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= -github.com/googleapis/enterprise-certificate-proxy v0.3.14 h1:yh8ncqsbUY4shRD5dA6RlzjJaT4hi3kII+zYw8wmLb8= -github.com/googleapis/enterprise-certificate-proxy v0.3.14/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg= -github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q= -github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA= -github.com/googleapis/gax-go/v2 v2.21.0 h1:h45NjjzEO3faG9Lg/cFrBh2PgegVVgzqKzuZl/wMbiI= -github.com/googleapis/gax-go/v2 v2.21.0/go.mod h1:But/NJU6TnZsrLai/xBAQLLz+Hc7fHZJt/hsCz3Fih4= +github.com/googleapis/enterprise-certificate-proxy v0.3.24 h1:G9iCJIY+AYVmUskKdjX8FVy7sG+nbzjOQ41cvlmhcvg= +github.com/googleapis/enterprise-certificate-proxy v0.3.24/go.mod h1:hEjCmnoakQzv5ImLUp6alkY7XgLlNoAxwTXmhHHNIsI= +github.com/googleapis/gax-go/v2 v2.27.0 h1:qe2iQOUzxb3fd6x6ewpIEixPQhJ+0Ihc/RRZhKA/2g0= +github.com/googleapis/gax-go/v2 v2.27.0/go.mod h1:RofiqDw3ehcG4L0H1zO3D2Itpwd3/uS/7wdmbNDF1DE= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= -github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= -github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48= github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw= github.com/hetznercloud/hcloud-go v1.59.2 h1:NkCPwYiPv85FnOV3IW9/gxfW61TPIUSwyPHRSLwCkHA= github.com/hetznercloud/hcloud-go v1.59.2/go.mod h1:oTebZCjd+osj75jlI76Z+zjN1sTxmMiQ1MWoO8aRl1c= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/inlets/cloud-provision v0.7.1 h1:+D4lAjw4u4nmrDt/K3OLau3dvVVXFWvgewdCSNLXqKI= -github.com/inlets/cloud-provision v0.7.1/go.mod h1:oQlBTv7QX0p2eMMus4CWmE0QV3AVuJSS7s+YaUko55g= github.com/inlets/cloud-provision v0.7.2 h1:vbCZO2bKLODRkVwJn1KA7p8UWbq7rFIBZUQNwN50GPg= github.com/inlets/cloud-provision v0.7.2/go.mod h1:rBNfe1tODfOfK5aTWlg46x9a1LXmzQH4tqXkbk0uLd4= -github.com/jarcoal/httpmock v1.3.1 h1:iUx3whfZWVf3jT01hQTO/Eo5sAYtB2/rqaUuOtpInww= -github.com/jarcoal/httpmock v1.3.1/go.mod h1:3yb8rc4BI7TCBhFY8ng0gjuLKJNquuDNiPaZjnENuYg= github.com/jarcoal/httpmock v1.4.1 h1:0Ju+VCFuARfFlhVXFc2HxlcQkfB+Xq12/EotHko+x2A= +github.com/jarcoal/httpmock v1.4.1/go.mod h1:ftW1xULwo+j0R0JJkJIIi7UKigZUXCLLanykgjwBXL0= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 h1:IsMZxCuZqKuao2vNdfD82fjjgPLfyHLpR41Z88viRWs= -github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeWNIJaW+O5xpRQbPp0Ybqu1vJd/pm7s2F473HRrkw= github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRtuthU= -github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= -github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= -github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= -github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXwkPPMeUgOK1k= +github.com/klauspost/compress v1.20.1 h1:T7kKElXUMXrUJ2E9QhQhxFtcK5rPyLdsGZvdbLMPdiQ= +github.com/klauspost/compress v1.20.1/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 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/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/linode/linodego v1.46.0 h1:+uOG4SD2MIrhbrLrvOD5HrbdLN3D19Wgn3MgdUNQjeU= -github.com/linode/linodego v1.46.0/go.mod h1:vyklQRzZUWhFVBZdYx4dcYJU/gG9yKB9VUcUs6ub0Lk= -github.com/linode/linodego v1.67.0 h1:pomhFuuCCJI4N6emtB9027h1yXHY2/MIT0hwHEFwvq4= -github.com/linode/linodego v1.67.0/go.mod h1:+9mbdu0P3WMRCl0QbVfiFavR+Iel7TCRDJk3nInyx14= +github.com/linode/linodego v1.69.1 h1:f45N2MHR/oece2/ktTTCYmrlfse4//k3NgwcF5zbGZ0= +github.com/linode/linodego v1.69.1/go.mod h1:Fha0NYsQSx5VZK1HQNJY/z/dIxxkFp+vb5veawbmAUw= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/maxatome/go-testdeep v1.12.0 h1:Ql7Go8Tg0C1D/uMMX59LAoYK7LffeJQ6X2T04nTH68g= github.com/maxatome/go-testdeep v1.12.0/go.mod h1:lPZc/HAcJMP92l7yI6TRz1aZN5URwUBUAfUNvrclaNM= -github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= -github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/morikuni/aec v1.1.0 h1:vBBl0pUnvi/Je71dsRrhMBtreIqNMYErSAbEeb8jrXQ= github.com/morikuni/aec v1.1.0/go.mod h1:xDRgiq/iw5l+zkao76YTKzKttOp2cwPEne25HDkJnBw= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/ovh/go-ovh v1.6.0 h1:ixLOwxQdzYDx296sXcgS35TOPEahJkpjMGtzPadCjQI= -github.com/ovh/go-ovh v1.6.0/go.mod h1:cTVDnl94z4tl8pP1uZ/8jlVxntjSIf09bNcQ5TJSC7c= github.com/ovh/go-ovh v1.9.0 h1:6K8VoL3BYjVV3In9tPJUdT7qMx9h0GExN9EXx1r2kKE= github.com/ovh/go-ovh v1.9.0/go.mod h1:cTVDnl94z4tl8pP1uZ/8jlVxntjSIf09bNcQ5TJSC7c= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= @@ -177,45 +124,23 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= -github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= -github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= -github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= -github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= -github.com/prometheus/common v0.61.0 h1:3gv/GThfX0cV2lpO7gkTUwZru38mxevy90Bj8YFSRQQ= -github.com/prometheus/common v0.61.0/go.mod h1:zr29OCN/2BsJRaFwG8QOBr41D6kkchKbpeNH7pAjb/s= -github.com/prometheus/common v0.67.3 h1:shd26MlnwTw5jksTDhC7rTQIteBxy+ZZDr3t7F2xN2Q= -github.com/prometheus/common v0.67.3/go.mod h1:gP0fq6YjjNCLssJCQp0yk4M8W6ikLURwkdd/YKtTbyI= -github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= -github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= -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.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws= -github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw= -github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc= -github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo= -github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E= -github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw= -github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= -github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/prometheus/client_golang v1.25.0 h1:cDtW1TcFsMi1RJc8khwCKB4VhzwV04aKqbYtNOXuiK0= +github.com/prometheus/client_golang v1.25.0/go.mod h1:j2X/4/kaQHLPnmyEU8zjmkndo1T317VpCIQEml8LTKk= +github.com/prometheus/client_model v0.6.3 h1:O0jaTVAYNxTHYInEPFJt5I3+sN8zqBtVMPTB1qyxiEo= +github.com/prometheus/client_model v0.6.3/go.mod h1:gpN5P9S7Rr6Yr92PiQ+Ixvhf6JZEkF1dnxsYL2aPBEM= +github.com/prometheus/common v0.72.1 h1:ZAiQed/nk8IIcsdzb2TlJu23NEUDyDLQ9TXTN2WRK6Y= +github.com/prometheus/common v0.72.1/go.mod h1:1IoBY4IRaJnhs2ESjNzjilP1cJ/P8pimGoomq7zRXrA= +github.com/prometheus/procfs v0.22.0 h1:6q9+/JL9IKAPbCmBrv9n5O5Ty3NKnciV5X7YGw0oics= +github.com/prometheus/procfs v0.22.0/go.mod h1:CvmFr/GVhIjIvWJZW3tgkODBQMRIf0EyWMQLHCHab58= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30 h1:yoKAVkEVwAqbGbR8n87rHQ1dulL25rKloGadb3vm770= -github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30/go.mod h1:sH0u6fq6x4R5M7WxkoQFY/o7UaiItec0o1LinLCJNq8= -github.com/scaleway/scaleway-sdk-go v1.0.0-beta.36 h1:ObX9hZmK+VmijreZO/8x9pQ8/P/ToHD/bdSb4Eg4tUo= -github.com/scaleway/scaleway-sdk-go v1.0.0-beta.36/go.mod h1:LEsDu4BubxK7/cWhtlQWfuxwL4rf/2UEpxXz1o1EMtM= -github.com/sethvargo/go-password v0.3.1 h1:WqrLTjo7X6AcVYfC6R7GtSyuUQR9hGyAj/f1PYQZCJU= -github.com/sethvargo/go-password v0.3.1/go.mod h1:rXofC1zT54N7R8K/h1WDUdkf9BOx5OptoxrMBcrXzvs= -github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= -github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= -github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s= -github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0= +github.com/scaleway/scaleway-sdk-go v1.39.0 h1:HCoThqjNYqx+tFcI+JadoqdRN5UBHmC4Ee9lgqEqglw= +github.com/scaleway/scaleway-sdk-go v1.39.0/go.mod h1:ly2TNjJyW0SouDBZcQb2aNgqJYqI5t3BZF/UzBKFZ8o= +github.com/sethvargo/go-password v0.4.0 h1:eSidVKQw5C7CmTDAtH3RipBTSjdU1ZRxQaynD2GWLVU= +github.com/sethvargo/go-password v0.4.0/go.mod h1:PO3nYHwUpcHPR0F9woy7a4abZPvzRuqJr0GaeIYTm3k= github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= @@ -226,136 +151,97 @@ github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/ 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.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE= +github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg= github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs= github.com/vultr/govultr/v2 v2.17.2/go.mod h1:ZFOKGWmgjytfyjeyAdhQlSWwTjh2ig+X49cAp50dzXI= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= -go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo= -go.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw= -go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I= -go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= -go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= -go.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5WtEnklQ= -go.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M= -go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= -go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= -go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= -go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= -go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= -go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= -go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= -go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= -go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s= -go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck= -go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= -go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= -go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= -go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0 h1:LxwW/9ctSCv+QkE/cLR7M91ZIkXNMqJtEMi1vCw9U8s= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0/go.mod h1:tOsftB4SslBwwErVEPaenU2RpThXWPIU8DoJHEC4dyw= +go.opentelemetry.io/otel v1.47.0 h1:j7ALJ/zgkS7Z6aeJW09p8VC9804bC+PpeTfCD4XPnOM= +go.opentelemetry.io/otel v1.47.0/go.mod h1:8wS9O2qfXrYrzp6hIF/HOYJJf/wIhFPhR2xLuP+iXQU= +go.opentelemetry.io/otel/log v1.47.0 h1:cOTS1CcLbSQeZKanGJ+0JpF/+t4PELi3O3bbl2lqCcI= +go.opentelemetry.io/otel/log v1.47.0/go.mod h1:9byitSQ5pLC6PpqwGXjqdMKya6ZTswHRZh2vvXT33nw= +go.opentelemetry.io/otel/metric v1.47.0 h1:4PptaldXx3Eat1XjMZ68pPJEs5wrhlemctZE9a3UdWY= +go.opentelemetry.io/otel/metric v1.47.0/go.mod h1:ADGSXxRrXM6bjbvLo535EstVFlPpPYZm4LBKixjDHwU= +go.opentelemetry.io/otel/sdk v1.47.0 h1:zWXEr4j2lFefG87TU6Yg8a7ngfohIKFZHKp0Hf5hC6I= +go.opentelemetry.io/otel/sdk v1.47.0/go.mod h1:VUc24kiOeoGsxG8G9ULx3fWKvB7jMhnGE8Oi607lgR0= +go.opentelemetry.io/otel/sdk/metric v1.47.0 h1:lfISg2j93VT6yqdk9OfUaZmw/GfcZqCCV3jdXtsPnKw= +go.opentelemetry.io/otel/sdk/metric v1.47.0/go.mod h1:ypLp+mW1Nt2x+Szt3b5/i1syodyts49lMOwxpDI3VGw= +go.opentelemetry.io/otel/trace v1.47.0 h1:JOjX/Oci8K94QHddo+bbfya/Ai/nf6/dt9ZfrFNWSrM= +go.opentelemetry.io/otel/trace v1.47.0/go.mod h1:jNaSLa2PZEYFG6fRjJABAu+bw4FS08uDmPg28lTghu0= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= +go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= +go.yaml.in/yaml/v4 v4.0.0-rc.6 h1:1h7H1ohdUh93/FyE4YaDa1Zh64K6VVbjF4K6WUxMtH4= +go.yaml.in/yaml/v4 v4.0.0-rc.6/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= -golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= -golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= -golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= -golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= -golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= +golang.org/x/crypto v0.58.0 h1:COkYLr4k7nDI4r6QtMML2AfzeIswWHAJthLS6K/M/54= +golang.org/x/crypto v0.58.0/go.mod h1:Xh+kl5A+M0gMiWDytH2Hhr5Z7WbNCpv/eB/EFgfSk+w= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= -golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= -golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= -golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= -golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0= -golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw= -golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70= -golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= -golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo= -golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= -golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= -golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= +golang.org/x/net v0.61.0 h1:RR+6j/BTBCrggOLugxa+66R8FvoN6MHlzDlZIbN9YFw= +golang.org/x/net v0.61.0/go.mod h1:WgDCOTH8iwtB66T4/GfI94AHo/hhdb7Hah9NDseQfiI= +golang.org/x/oauth2 v0.37.0 h1:JUlcxA8oAtauLfiH8FX2/FkAWHAdi0QtGCGc+hofE98= +golang.org/x/oauth2 v0.37.0/go.mod h1:IxwZNxUULJmpBFf9K/9NTMSIfZZuvuTy1gGxhigP/58= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.24.0 h1:iqiDrGoDgyuvAKrhLQthUEzU/R378N78gXbBjxed7oA= +golang.org/x/sync v0.24.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= -golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= -golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/sys v0.49.0 h1:XbzkgYJHdqh/8m2Uu0W/dQv8nktxx4BFHp1M0gROTXA= +golang.org/x/sys v0.49.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= -golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= -golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= -golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= -golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= -golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= -golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= -golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= -golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= +golang.org/x/text v0.43.0 h1:1QivrlhwAsnMOcqgOdl9my7s9OyZl8O5/UGUTJVXoWc= +golang.org/x/text v0.43.0/go.mod h1:hbSIYA/amXcRXTFSZqh8tWHEoqRvvbKPJ2uz/KU+a+s= +golang.org/x/time v0.16.0 h1:vMb6ptszcQMkcwiRTAuNNU50gom6++Q/6gY2hDM6VDE= +golang.org/x/time v0.16.0/go.mod h1:rVKOqvZeKvrDKTQiAHJ7wmwP0RzleSphoEA9RcdLA0s= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.217.0 h1:GYrUtD289o4zl1AhiTZL0jvQGa2RDLyC+kX1N/lfGOU= -google.golang.org/api v0.217.0/go.mod h1:qMc2E8cBAbQlRypBTBWHklNJlaZZJBwDv81B1Iu8oSI= -google.golang.org/api v0.275.0 h1:vfY5d9vFVJeWEZT65QDd9hbndr7FyZ2+6mIzGAh71NI= -google.golang.org/api v0.275.0/go.mod h1:Fnag/EWUPIcJXuIkP1pjoTgS5vdxlk3eeemL7Do6bvw= -google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 h1:CkkIfIt50+lT6NHAVoRYEyAvQGFM7xEwXUUywFvEb3Q= -google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08= -google.golang.org/genproto/googleapis/api v0.0.0-20260319201613-d00831a3d3e7 h1:41r6JMbpzBMen0R/4TZeeAmGXSJC7DftGINUodzTkPI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d h1:wT2n40TBqFY6wiwazVK9/iTWbsQrgk5ZfCSVFLO9LQA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= -google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= -google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= -google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= -google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= -google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= +google.golang.org/api v0.307.0 h1:KJJv1V/cOeCUrgKFippAhSg98QlR2IZFqubQKf7gQdg= +google.golang.org/api v0.307.0/go.mod h1:4XMH+b/ZEfuTbK7FnrFRY9c4xfFHVflGTKuy/i5wUmE= +google.golang.org/genproto v0.0.0-20261012220534-4341edf3f941 h1:CXq2XEi5aEyLjjPZIwqrmQH8ZY4ctUwK7uyAx3mjX/U= +google.golang.org/genproto v0.0.0-20261012220534-4341edf3f941/go.mod h1:3gK0ehnhP0V7/x3ypGoLyT3d0n6TSi/EcsphIjHrcz4= +google.golang.org/genproto/googleapis/api v0.0.0-20261012220534-4341edf3f941 h1:DS/w3N8rsfrwxwgGSj6WhMsPo7aNQGmDx74J81zd0NQ= +google.golang.org/genproto/googleapis/api v0.0.0-20261012220534-4341edf3f941/go.mod h1:AuGAdi9KnXss7xbLxIKhCvk+Ro/SxpET/iS45DNYN+M= +google.golang.org/genproto/googleapis/rpc v0.0.0-20261019180522-ce908d29299b h1:6WNWHZk91dp4gZ25642OALkuG1UVNZbwENJD19DnB8k= +google.golang.org/genproto/googleapis/rpc v0.0.0-20261019180522-ce908d29299b/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc= +google.golang.org/grpc v1.84.0 h1:soMyaPJ8pAak5PIQ0DGBUir0XRo2fRoMqhNWMLlLxO0= +google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0= +google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc= +google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= -gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.67.1 h1:tVBILHy0R6e4wkYOn3XmiITt/hEVH4TFMYvAX2Ytz6k= -gopkg.in/ini.v1 v1.67.1/go.mod h1:x/cyOwCgZqOkJoDIJ3c1KNHMo10+nLGAhh+kn3Zizss= +gopkg.in/dnaeon/go-vcr.v4 v4.0.7 h1:Mq/RF+mq3QwtEunJSsoTbYPt3elSAmdJhAxrEaqr88I= +gopkg.in/dnaeon/go-vcr.v4 v4.0.7/go.mod h1:cRwV/njsN/D8qNJu4NAXWswz6b4OUh3rMIu4SObbLBg= +gopkg.in/ini.v1 v1.67.3 h1:iM9Lhz5MRSGhHVGGwCuzG9KO8PoirCXj/m/qTmOJJQw= +gopkg.in/ini.v1 v1.67.3/go.mod h1:x/cyOwCgZqOkJoDIJ3c1KNHMo10+nLGAhh+kn3Zizss= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/vendor/cloud.google.com/go/auth/CHANGES.md b/vendor/cloud.google.com/go/auth/CHANGES.md index 2c1f6ff8..df93da32 100644 --- a/vendor/cloud.google.com/go/auth/CHANGES.md +++ b/vendor/cloud.google.com/go/auth/CHANGES.md @@ -1,5 +1,73 @@ # Changes +## [0.24.1](https://github.com/googleapis/google-cloud-go/compare/auth/v0.24.0...auth/v0.24.1) (2026-10-08) + + +### Bug Fixes + +* **auth:** Return empty tls.Certificate on secureconnect helper failure ([#20632](https://github.com/googleapis/google-cloud-go/issues/20632)) ([1cdb61a](https://github.com/googleapis/google-cloud-go/commit/1cdb61a25ffb7ac5d0c859191d485621c4f7aed7)), refs [#20593](https://github.com/googleapis/google-cloud-go/issues/20593) + +## [0.24.0](https://github.com/googleapis/google-cloud-go/compare/auth/v0.23.3...auth/v0.24.0) (2026-09-23) + + +### Features + +* **all:** Update supported go versions ([#20520](https://github.com/googleapis/google-cloud-go/issues/20520)) ([90413d3](https://github.com/googleapis/google-cloud-go/commit/90413d3e9d381ef4b92e3c496d98b023c5b2d8cc)) + + +### Bug Fixes + +* **auth:** Honor DisableAsyncRefresh and EarlyTokenRefresh consistently ([#20564](https://github.com/googleapis/google-cloud-go/issues/20564)) ([39f0ea5](https://github.com/googleapis/google-cloud-go/commit/39f0ea51dcbcae2bef1e8c900bdf2e675a19199c)), refs [#20563](https://github.com/googleapis/google-cloud-go/issues/20563) + +## [0.23.3](https://github.com/googleapis/google-cloud-go/compare/auth/v0.23.2...auth/v0.23.3) (2026-09-17) + + +### Bug Fixes + +* Handle secureconnect helper failures gracefully ([c2794c6](https://github.com/googleapis/google-cloud-go/commit/c2794c6bdf267278489af42591f3c3549ae8fcba)) +* Handle secureconnect helper failures gracefully ([#20443](https://github.com/googleapis/google-cloud-go/issues/20443)) ([c2794c6](https://github.com/googleapis/google-cloud-go/commit/c2794c6bdf267278489af42591f3c3549ae8fcba)) + +## [0.23.2](https://github.com/googleapis/google-cloud-go/compare/auth/v0.23.1...auth/v0.23.2) (2026-08-20) + + +### Bug Fixes + +* **auth:** Eliminate timing race conditions in grpctransport otel tests ([#20175](https://github.com/googleapis/google-cloud-go/issues/20175)) ([#20382](https://github.com/googleapis/google-cloud-go/issues/20382)) ([637505e](https://github.com/googleapis/google-cloud-go/commit/637505e5d5f090eec020604c3702b6ace11dcd38)) + +## [0.23.1](https://github.com/googleapis/google-cloud-go/compare/auth/v0.23.0...auth/v0.23.1) (2026-08-13) + + +### Bug Fixes + +* **auth:** Fix OpenTelemetry test flake in grpctransport ([#20191](https://github.com/googleapis/google-cloud-go/issues/20191)) ([e43ce28](https://github.com/googleapis/google-cloud-go/commit/e43ce28d01ea80970e6373e1c4540cb470cdc4a6)) + +## [0.23.0](https://github.com/googleapis/google-cloud-go/compare/auth/v0.22.0...auth/v0.23.0) (2026-08-07) + + +### Features + +* X509 workload identity ecp support ([#20138](https://github.com/googleapis/google-cloud-go/issues/20138)) ([5fa474a](https://github.com/googleapis/google-cloud-go/commit/5fa474a10a3863a1bb34ecb27540e8a574d7a736)) + +## [0.22.0](https://github.com/googleapis/google-cloud-go/compare/auth/v0.21.0...auth/v0.22.0) (2026-07-13) + + +### Features + +* **auth:** Populate http.response.status_code in http transport ([#20053](https://github.com/googleapis/google-cloud-go/issues/20053)) ([bff5d7c](https://github.com/googleapis/google-cloud-go/commit/bff5d7c9bc7f8ea8c0059f7d8e2d4294ba92c5bc)) + +## [0.21.0](https://github.com/googleapis/google-cloud-go/compare/auth/v0.20.0...auth/v0.21.0) (2026-07-07) + + +### Features + +* **auth:** Implement updated design for regional access boundary ([#13417](https://github.com/googleapis/google-cloud-go/issues/13417)) ([fadb6c7](https://github.com/googleapis/google-cloud-go/commit/fadb6c764dbe869fca736d9f0446b5010f21d2f2)) + + +### Bug Fixes + +* **auth:** Avoid double impersonation in idtoken and clarify docs ([#14474](https://github.com/googleapis/google-cloud-go/issues/14474)) ([995bfc3](https://github.com/googleapis/google-cloud-go/commit/995bfc36199ba6ae1c88803c71f39a0b19fc8c0f)), closes [#11105](https://github.com/googleapis/google-cloud-go/issues/11105) +* **auth:** Correct go min version ([#20094](https://github.com/googleapis/google-cloud-go/issues/20094)) ([6bb4358](https://github.com/googleapis/google-cloud-go/commit/6bb4358dca69b803e52eb2af882fa5afc24d54e2)) + ## [0.20.0](https://github.com/googleapis/google-cloud-go/releases/tag/auth%2Fv0.20.0) (2026-04-06) ## [0.19.0](https://github.com/googleapis/google-cloud-go/releases/tag/auth%2Fv0.19.0) (2026-03-23) diff --git a/vendor/cloud.google.com/go/auth/auth.go b/vendor/cloud.google.com/go/auth/auth.go index c6d80158..fd6a11dd 100644 --- a/vendor/cloud.google.com/go/auth/auth.go +++ b/vendor/cloud.google.com/go/auth/auth.go @@ -386,7 +386,7 @@ func (c *cachedTokenProvider) tokenBlocking(ctx context.Context) (*Token, error) c.mu.Lock() defer c.mu.Unlock() c.isRefreshErr = false - if c.cachedToken.IsValid() || (!c.autoRefresh && !c.cachedToken.isEmpty()) { + if c.cachedToken.isValidWithEarlyExpiry(c.expireEarly) || (!c.autoRefresh && !c.cachedToken.isEmpty()) { return c.cachedToken, nil } t, err := c.tp.Token(ctx) diff --git a/vendor/cloud.google.com/go/auth/credentials/detect.go b/vendor/cloud.google.com/go/auth/credentials/detect.go index c9d7600e..f79cca4d 100644 --- a/vendor/cloud.google.com/go/auth/credentials/detect.go +++ b/vendor/cloud.google.com/go/auth/credentials/detect.go @@ -27,7 +27,7 @@ import ( "cloud.google.com/go/auth" "cloud.google.com/go/auth/internal" "cloud.google.com/go/auth/internal/credsfile" - "cloud.google.com/go/auth/internal/trustboundary" + "cloud.google.com/go/auth/internal/regionalaccessboundary" "cloud.google.com/go/compute/metadata" "github.com/googleapis/gax-go/v2/internallog" ) @@ -138,11 +138,15 @@ func OnGCE() bool { // Google APIs can compromise the security of your systems and data. For // more information, refer to [Validate credential configurations from // external sources](https://cloud.google.com/docs/authentication/external/externally-sourced-credentials). +// +// Note: If the detected credential configuration file contains a +// `service_account_impersonation_url` field, the returned credentials will +// yield tokens that are already impersonated to that target service account. func DetectDefault(opts *DetectOptions) (*auth.Credentials, error) { if err := opts.validate(); err != nil { return nil, err } - trustBoundaryEnabled, err := trustboundary.IsEnabled() + regionalAccessBoundaryEnabled, err := regionalaccessboundary.IsEnabled() if err != nil { return nil, err } @@ -175,12 +179,12 @@ func DetectDefault(opts *DetectOptions) (*auth.Credentials, error) { } tp := computeTokenProvider(opts, metadataClient) - if trustBoundaryEnabled { - gceConfigProvider := trustboundary.NewGCEConfigProvider(gceUniverseDomainProvider) + if regionalAccessBoundaryEnabled { + gceConfigProvider := regionalaccessboundary.NewGCEConfigProvider(gceUniverseDomainProvider) var err error - tp, err = trustboundary.NewProvider(opts.client(), gceConfigProvider, opts.logger(), tp) + tp, err = regionalaccessboundary.NewProvider(opts.client(), gceConfigProvider, opts.logger(), tp) if err != nil { - return nil, fmt.Errorf("credentials: failed to initialize GCE trust boundary provider: %w", err) + return nil, fmt.Errorf("credentials: failed to initialize GCE Regional Access Boundary provider: %w", err) } } @@ -454,16 +458,17 @@ func clientCredConfigFromJSON(b []byte, opts *DetectOptions) *auth.Options3LO { } } return &auth.Options3LO{ - ClientID: c.ClientID, - ClientSecret: c.ClientSecret, - RedirectURL: c.RedirectURIs[0], - Scopes: opts.scopes(), - AuthURL: c.AuthURI, - TokenURL: c.TokenURI, - Client: opts.client(), - Logger: opts.logger(), - EarlyTokenExpiry: opts.EarlyTokenRefresh, - AuthHandlerOpts: handleOpts, + ClientID: c.ClientID, + ClientSecret: c.ClientSecret, + RedirectURL: c.RedirectURIs[0], + Scopes: opts.scopes(), + AuthURL: c.AuthURI, + TokenURL: c.TokenURI, + Client: opts.client(), + Logger: opts.logger(), + EarlyTokenExpiry: opts.EarlyTokenRefresh, + DisableAsyncRefresh: opts.DisableAsyncRefresh, + AuthHandlerOpts: handleOpts, // TODO(codyoss): refactor this out. We need to add in auto-detection // for this use case. AuthStyle: auth.StyleInParams, diff --git a/vendor/cloud.google.com/go/auth/credentials/filetypes.go b/vendor/cloud.google.com/go/auth/credentials/filetypes.go index f3737a5e..59932fc6 100644 --- a/vendor/cloud.google.com/go/auth/credentials/filetypes.go +++ b/vendor/cloud.google.com/go/auth/credentials/filetypes.go @@ -25,7 +25,7 @@ import ( "cloud.google.com/go/auth/credentials/internal/impersonate" internalauth "cloud.google.com/go/auth/internal" "cloud.google.com/go/auth/internal/credsfile" - "cloud.google.com/go/auth/internal/trustboundary" + "cloud.google.com/go/auth/internal/regionalaccessboundary" ) const cloudPlatformScope = "https://www.googleapis.com/auth/cloud-platform" @@ -109,7 +109,8 @@ func fileCredentials(b []byte, opts *DetectOptions) (*auth.Credentials, error) { } return auth.NewCredentials(&auth.CredentialsOptions{ TokenProvider: auth.NewCachedTokenProvider(tp, &auth.CachedTokenProviderOptions{ - ExpireEarly: opts.EarlyTokenRefresh, + ExpireEarly: opts.EarlyTokenRefresh, + DisableAsyncRefresh: opts.DisableAsyncRefresh, }), JSON: b, ProjectIDProvider: internalauth.StaticCredentialsProperty(projectID), @@ -159,29 +160,30 @@ func handleServiceAccount(f *credsfile.ServiceAccountFile, opts *DetectOptions) return nil, err } - trustBoundaryEnabled, err := trustboundary.IsEnabled() + regionalAccessBoundaryEnabled, err := regionalaccessboundary.IsEnabled() if err != nil { return nil, err } - if !trustBoundaryEnabled { + if !regionalAccessBoundaryEnabled { return tp, nil } - saConfig := trustboundary.NewServiceAccountConfigProvider(opts2LO.Email, opts2LO.UniverseDomain) - return trustboundary.NewProvider(opts.client(), saConfig, opts.logger(), tp) + saConfig := regionalaccessboundary.NewServiceAccountConfigProvider(opts2LO.Email, opts2LO.UniverseDomain) + return regionalaccessboundary.NewProvider(opts.client(), saConfig, opts.logger(), tp) } func handleUserCredential(f *credsfile.UserCredentialsFile, opts *DetectOptions) (auth.TokenProvider, error) { opts3LO := &auth.Options3LO{ - ClientID: f.ClientID, - ClientSecret: f.ClientSecret, - Scopes: opts.scopes(), - AuthURL: googleAuthURL, - TokenURL: opts.tokenURL(), - AuthStyle: auth.StyleInParams, - EarlyTokenExpiry: opts.EarlyTokenRefresh, - RefreshToken: f.RefreshToken, - Client: opts.client(), - Logger: opts.logger(), + ClientID: f.ClientID, + ClientSecret: f.ClientSecret, + Scopes: opts.scopes(), + AuthURL: googleAuthURL, + TokenURL: opts.tokenURL(), + AuthStyle: auth.StyleInParams, + EarlyTokenExpiry: opts.EarlyTokenRefresh, + DisableAsyncRefresh: opts.DisableAsyncRefresh, + RefreshToken: f.RefreshToken, + Client: opts.client(), + Logger: opts.logger(), } return auth.New3LOTokenProvider(opts3LO) } @@ -199,6 +201,8 @@ func handleExternalAccount(f *credsfile.ExternalAccountFile, opts *DetectOptions QuotaProjectID: f.QuotaProjectID, Scopes: opts.scopes(), WorkforcePoolUserProject: f.WorkforcePoolUserProject, + EarlyTokenRefresh: opts.EarlyTokenRefresh, + DisableAsyncRefresh: opts.DisableAsyncRefresh, Client: opts.client(), Logger: opts.logger(), IsDefaultClient: opts.Client == nil, @@ -210,67 +214,69 @@ func handleExternalAccount(f *credsfile.ExternalAccountFile, opts *DetectOptions if err != nil { return nil, err } - trustBoundaryEnabled, err := trustboundary.IsEnabled() + regionalAccessBoundaryEnabled, err := regionalaccessboundary.IsEnabled() if err != nil { return nil, err } - if !trustBoundaryEnabled { + if !regionalAccessBoundaryEnabled { return tp, nil } ud := resolveUniverseDomain(opts.UniverseDomain, f.UniverseDomain) - var configProvider trustboundary.ConfigProvider + var configProvider regionalaccessboundary.ConfigProvider if f.ServiceAccountImpersonationURL == "" { // No impersonation, this is a direct external account credential. - // The trust boundary is based on the workload/workforce pool. + // The Regional Access Boundary is based on the workload/workforce pool. var err error - configProvider, err = trustboundary.NewExternalAccountConfigProvider(f.Audience, ud) + configProvider, err = regionalaccessboundary.NewExternalAccountConfigProvider(f.Audience, ud) if err != nil { return nil, err } } else { - // Impersonation is used. The trust boundary is based on the target service account. + // Impersonation is used. The Regional Access Boundary is based on the target service account. targetSAEmail, err := impersonate.ExtractServiceAccountEmail(f.ServiceAccountImpersonationURL) if err != nil { - return nil, fmt.Errorf("credentials: could not extract target service account email for trust boundary: %w", err) + return nil, fmt.Errorf("credentials: could not extract target service account email for Regional Access Boundary: %w", err) } - configProvider = trustboundary.NewServiceAccountConfigProvider(targetSAEmail, ud) + configProvider = regionalaccessboundary.NewServiceAccountConfigProvider(targetSAEmail, ud) } - return trustboundary.NewProvider(opts.client(), configProvider, opts.logger(), tp) + return regionalaccessboundary.NewProvider(opts.client(), configProvider, opts.logger(), tp) } func handleExternalAccountAuthorizedUser(f *credsfile.ExternalAccountAuthorizedUserFile, opts *DetectOptions) (auth.TokenProvider, error) { externalOpts := &externalaccountuser.Options{ - Audience: f.Audience, - RefreshToken: f.RefreshToken, - TokenURL: f.TokenURL, - TokenInfoURL: f.TokenInfoURL, - ClientID: f.ClientID, - ClientSecret: f.ClientSecret, - Scopes: opts.scopes(), - Client: opts.client(), - Logger: opts.logger(), + Audience: f.Audience, + RefreshToken: f.RefreshToken, + TokenURL: f.TokenURL, + TokenInfoURL: f.TokenInfoURL, + ClientID: f.ClientID, + ClientSecret: f.ClientSecret, + Scopes: opts.scopes(), + EarlyTokenRefresh: opts.EarlyTokenRefresh, + DisableAsyncRefresh: opts.DisableAsyncRefresh, + Client: opts.client(), + Logger: opts.logger(), } tp, err := externalaccountuser.NewTokenProvider(externalOpts) if err != nil { return nil, err } - trustBoundaryEnabled, err := trustboundary.IsEnabled() + regionalAccessBoundaryEnabled, err := regionalaccessboundary.IsEnabled() if err != nil { return nil, err } - if !trustBoundaryEnabled { + if !regionalAccessBoundaryEnabled { return tp, nil } ud := resolveUniverseDomain(opts.UniverseDomain, f.UniverseDomain) - configProvider, err := trustboundary.NewExternalAccountConfigProvider(f.Audience, ud) + configProvider, err := regionalaccessboundary.NewExternalAccountConfigProvider(f.Audience, ud) if err != nil { return nil, err } - return trustboundary.NewProvider(opts.client(), configProvider, opts.logger(), tp) + return regionalaccessboundary.NewProvider(opts.client(), configProvider, opts.logger(), tp) } func handleImpersonatedServiceAccount(f *credsfile.ImpersonatedServiceAccountFile, opts *DetectOptions) (auth.TokenProvider, error) { @@ -306,19 +312,19 @@ func handleImpersonatedServiceAccount(f *credsfile.ImpersonatedServiceAccountFil if err != nil { return nil, err } - trustBoundaryEnabled, err := trustboundary.IsEnabled() + regionalAccessBoundaryEnabled, err := regionalaccessboundary.IsEnabled() if err != nil { return nil, err } - if !trustBoundaryEnabled { + if !regionalAccessBoundaryEnabled { return tp, nil } targetSAEmail, err := impersonate.ExtractServiceAccountEmail(f.ServiceAccountImpersonationURL) if err != nil { - return nil, fmt.Errorf("credentials: could not extract target service account email for trust boundary: %w", err) + return nil, fmt.Errorf("credentials: could not extract target service account email for Regional Access Boundary: %w", err) } - targetSAConfig := trustboundary.NewServiceAccountConfigProvider(targetSAEmail, ud) - return trustboundary.NewProvider(opts.client(), targetSAConfig, opts.logger(), tp) + targetSAConfig := regionalaccessboundary.NewServiceAccountConfigProvider(targetSAEmail, ud) + return regionalaccessboundary.NewProvider(opts.client(), targetSAConfig, opts.logger(), tp) } func handleGDCHServiceAccount(f *credsfile.GDCHServiceAccountFile, opts *DetectOptions) (auth.TokenProvider, error) { return gdch.NewTokenProvider(f, &gdch.Options{ diff --git a/vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/externalaccount.go b/vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/externalaccount.go index f4f49f17..ae38487f 100644 --- a/vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/externalaccount.go +++ b/vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/externalaccount.go @@ -100,6 +100,13 @@ type Options struct { // for AWS credentials. One of SubjectTokenProvider, // AWSSecurityCredentialProvider or CredentialSource must be provided. Optional. AwsSecurityCredentialsProvider AwsSecurityCredentialsProvider + // EarlyTokenRefresh configures how early before a token expires that it + // should be refreshed. If unset, the default value is 3 minutes and 45 + // seconds. Optional. + EarlyTokenRefresh time.Duration + // DisableAsyncRefresh configures a synchronous workflow that refreshes + // stale tokens while blocking. The default is false. Optional. + DisableAsyncRefresh bool // Client for token request. Client *http.Client // IsDefaultClient marks whether the client passed in is a default client that can be overriden. @@ -249,8 +256,12 @@ func NewTokenProvider(opts *Options) (auth.TokenProvider, error) { logger: logger, } + cacheOpts := &auth.CachedTokenProviderOptions{ + ExpireEarly: opts.EarlyTokenRefresh, + DisableAsyncRefresh: opts.DisableAsyncRefresh, + } if opts.ServiceAccountImpersonationURL == "" { - return auth.NewCachedTokenProvider(tp, nil), nil + return auth.NewCachedTokenProvider(tp, cacheOpts), nil } scopes := make([]string, len(opts.Scopes)) @@ -261,14 +272,14 @@ func NewTokenProvider(opts *Options) (auth.TokenProvider, error) { Client: client, URL: opts.ServiceAccountImpersonationURL, Scopes: scopes, - Tp: auth.NewCachedTokenProvider(tp, nil), + Tp: auth.NewCachedTokenProvider(tp, cacheOpts), TokenLifetimeSeconds: opts.ServiceAccountImpersonationLifetimeSeconds, Logger: logger, }) if err != nil { return nil, err } - return auth.NewCachedTokenProvider(imp, nil), nil + return auth.NewCachedTokenProvider(imp, cacheOpts), nil } type subjectTokenProvider interface { diff --git a/vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/x509_provider.go b/vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/x509_provider.go index d86ca593..d67f45f4 100644 --- a/vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/x509_provider.go +++ b/vendor/cloud.google.com/go/auth/credentials/internal/externalaccount/x509_provider.go @@ -30,6 +30,7 @@ import ( "time" "cloud.google.com/go/auth/internal/transport/cert" + "github.com/googleapis/enterprise-certificate-proxy/client" ) // x509Provider implements the subjectTokenProvider type for x509 workload @@ -57,13 +58,13 @@ func (xp *x509Provider) providerType() string { // reads the certificate file, and parses the certificate data. func loadLeafCertificate(configFilePath string) (*x509.Certificate, error) { // Get the path to the certificate file from the configuration file. - path, err := cert.GetCertificatePath(configFilePath) + path, err := cert.GetFileBasedCertificatePath(configFilePath) if err != nil { - return nil, fmt.Errorf("failed to get certificate path from config file: %w", err) + return nil, fmt.Errorf("credentials: failed to get certificate path from config file: %w", err) } leafCertBytes, err := os.ReadFile(path) if err != nil { - return nil, fmt.Errorf("failed to read leaf certificate file: %w", err) + return nil, fmt.Errorf("credentials: failed to read leaf certificate file: %w", err) } // Parse the certificate bytes. return parseCertificate(leafCertBytes) @@ -78,20 +79,20 @@ func encodeCert(cert *x509.Certificate) string { // parseCertificate parses a PEM-encoded certificate from the given byte slice. func parseCertificate(certData []byte) (*x509.Certificate, error) { if len(certData) == 0 { - return nil, errors.New("invalid certificate data: empty input") + return nil, errors.New("credentials: invalid certificate data: empty input") } // Decode the PEM-encoded data. block, _ := pem.Decode(certData) if block == nil { - return nil, errors.New("invalid PEM-encoded certificate data: no PEM block found") + return nil, errors.New("credentials: invalid PEM-encoded certificate data: no PEM block found") } if block.Type != "CERTIFICATE" { - return nil, fmt.Errorf("invalid PEM-encoded certificate data: expected CERTIFICATE block type, got %s", block.Type) + return nil, fmt.Errorf("credentials: invalid PEM-encoded certificate data: expected CERTIFICATE block type, got %s", block.Type) } // Parse the DER-encoded certificate. certificate, err := x509.ParseCertificate(block.Bytes) if err != nil { - return nil, fmt.Errorf("failed to parse certificate: %w", err) + return nil, fmt.Errorf("credentials: failed to parse certificate: %w", err) } return certificate, nil } @@ -110,9 +111,9 @@ func readTrustChain(trustChainPath string) ([]*x509.Certificate, error) { trustChainData, err := os.ReadFile(trustChainPath) if err != nil { if errors.Is(err, fs.ErrNotExist) { - return nil, fmt.Errorf("trust chain file not found: %w", err) + return nil, fmt.Errorf("credentials: trust chain file not found: %w", err) } - return nil, fmt.Errorf("failed to read trust chain file: %w", err) + return nil, fmt.Errorf("credentials: failed to read trust chain file: %w", err) } // Split the file content into PEM certificate blocks. @@ -130,7 +131,7 @@ func readTrustChain(trustChainPath string) ([]*x509.Certificate, error) { // Parse the certificate data. cert, err := parseCertificate([]byte(certData)) if err != nil { - return nil, fmt.Errorf("error parsing certificate from trust chain file: %w", err) + return nil, fmt.Errorf("credentials: error parsing certificate from trust chain file: %w", err) } // Append the certificate to the trust chain. @@ -141,6 +142,35 @@ func readTrustChain(trustChainPath string) ([]*x509.Certificate, error) { return certificateTrustChain, nil } +func (xp *x509Provider) ecpSubjectToken(configFilePath string) (string, error) { + key, err := client.Cred(configFilePath) + if err != nil { + return "", fmt.Errorf("credentials: failed to initialize ECP client: %w", err) + } + defer key.Close() + + rawChain := key.CertificateChain() + if len(rawChain) == 0 { + return "", errors.New("credentials: ECP returned an empty certificate chain") + } + + certChain := make([]string, 0, len(rawChain)) + for _, derBytes := range rawChain { + cert, err := x509.ParseCertificate(derBytes) + if err != nil { + return "", fmt.Errorf("credentials: failed to parse certificate from ECP chain: %w", err) + } + certChain = append(certChain, encodeCert(cert)) + } + + jsonChain, err := json.Marshal(certChain) + if err != nil { + return "", fmt.Errorf("credentials: failed to format certificate data: %w", err) + } + + return string(jsonChain), nil +} + // subjectToken retrieves the X.509 subject token. It loads the leaf // certificate and, if a trust chain path is configured, the trust chain // certificates. It then constructs a JSON array containing the base64-encoded @@ -148,16 +178,24 @@ func readTrustChain(trustChainPath string) ([]*x509.Certificate, error) { // The leaf certificate must be at the top of the trust chain file. This JSON // array is used as the subject token for mTLS authentication. func (xp *x509Provider) subjectToken(context.Context) (string, error) { + configFilePath := cert.GetConfigFilePath(xp.ConfigFilePath) + + // First check if it's ECP based cert config + if cert.IsECPConfig(configFilePath) { + return xp.ecpSubjectToken(configFilePath) + } + + // It's not ECP, do the normal file based cert config way. // Load the leaf certificate. - leafCert, err := loadLeafCertificate(xp.ConfigFilePath) + leafCert, err := loadLeafCertificate(configFilePath) if err != nil { - return "", fmt.Errorf("failed to load leaf certificate: %w", err) + return "", fmt.Errorf("credentials: failed to load leaf certificate: %w", err) } // Read the trust chain. trustChain, err := readTrustChain(xp.TrustChainPath) if err != nil { - return "", fmt.Errorf("failed to read trust chain: %w", err) + return "", fmt.Errorf("credentials: failed to read trust chain: %w", err) } // Initialize the certificate chain with the leaf certificate. @@ -178,7 +216,7 @@ func (xp *x509Provider) subjectToken(context.Context) (string, error) { // Return an error if the current certificate is the same as the leaf certificate. if encoded == certChain[0] { - return "", errors.New("the leaf certificate must be at the top of the trust chain file") + return "", errors.New("credentials: the leaf certificate must be at the top of the trust chain file") } // Add the current certificate to the chain. @@ -189,7 +227,7 @@ func (xp *x509Provider) subjectToken(context.Context) (string, error) { // Convert the certificate chain to a JSON array of base64-encoded strings. jsonChain, err := json.Marshal(certChain) if err != nil { - return "", fmt.Errorf("failed to format certificate data: %w", err) + return "", fmt.Errorf("credentials: failed to format certificate data: %w", err) } // Return the JSON-formatted certificate chain. diff --git a/vendor/cloud.google.com/go/auth/credentials/internal/externalaccountuser/externalaccountuser.go b/vendor/cloud.google.com/go/auth/credentials/internal/externalaccountuser/externalaccountuser.go index ae39206e..e4a34b1e 100644 --- a/vendor/cloud.google.com/go/auth/credentials/internal/externalaccountuser/externalaccountuser.go +++ b/vendor/cloud.google.com/go/auth/credentials/internal/externalaccountuser/externalaccountuser.go @@ -51,6 +51,14 @@ type Options struct { // Scopes contains the desired scopes for the returned access token. Scopes []string + // EarlyTokenRefresh configures how early before a token expires that it + // should be refreshed. If unset, the default value is 3 minutes and 45 + // seconds. Optional. + EarlyTokenRefresh time.Duration + // DisableAsyncRefresh configures a synchronous workflow that refreshes + // stale tokens while blocking. The default is false. Optional. + DisableAsyncRefresh bool + // Client for token request. Client *http.Client // Logger for logging. @@ -71,7 +79,10 @@ func NewTokenProvider(opts *Options) (auth.TokenProvider, error) { tp := &tokenProvider{ o: opts, } - return auth.NewCachedTokenProvider(tp, nil), nil + return auth.NewCachedTokenProvider(tp, &auth.CachedTokenProviderOptions{ + ExpireEarly: opts.EarlyTokenRefresh, + DisableAsyncRefresh: opts.DisableAsyncRefresh, + }), nil } type tokenProvider struct { diff --git a/vendor/cloud.google.com/go/auth/httptransport/transport.go b/vendor/cloud.google.com/go/auth/httptransport/transport.go index 87b3fef2..be1945a9 100644 --- a/vendor/cloud.google.com/go/auth/httptransport/transport.go +++ b/vendor/cloud.google.com/go/auth/httptransport/transport.go @@ -284,6 +284,11 @@ func (t *otelAttributeTransport) RoundTrip(req *http.Request) (*http.Response, e } resp, err := t.base.RoundTrip(req) + if gax.IsFeatureEnabled("METRICS") { + if data != nil && resp != nil { + data.SetHTTPStatusCode(resp.StatusCode) + } + } var logger *slog.Logger if gax.IsFeatureEnabled("LOGGING") { diff --git a/vendor/cloud.google.com/go/auth/internal/internal.go b/vendor/cloud.google.com/go/auth/internal/internal.go index 48e9bd9e..d79e0ffb 100644 --- a/vendor/cloud.google.com/go/auth/internal/internal.go +++ b/vendor/cloud.google.com/go/auth/internal/internal.go @@ -48,11 +48,8 @@ const ( // Universe domain is the default service domain for a given Cloud universe. DefaultUniverseDomain = "googleapis.com" - // TrustBoundaryNoOp is a constant indicating no trust boundary is enforced. - TrustBoundaryNoOp = "0x0" - - // TrustBoundaryDataKey is the key used to store trust boundary data in a token's metadata. - TrustBoundaryDataKey = "google.auth.trust_boundary_data" + // RegionalAccessBoundaryDataKey is the key used to store regional access boundary data in a token's metadata. + RegionalAccessBoundaryDataKey = "google.auth.regional_access_boundary_data" ) type clonableTransport interface { @@ -231,55 +228,35 @@ func FormatIAMServiceAccountResource(name string) string { return fmt.Sprintf("projects/-/serviceAccounts/%s", name) } -// TrustBoundaryData represents the trust boundary data associated with a token. +// RegionalAccessBoundaryData represents the regional access boundary data associated with a token. // It contains information about the regions or environments where the token is valid. -type TrustBoundaryData struct { +type RegionalAccessBoundaryData struct { // Locations is the list of locations that the token is allowed to be used in. Locations []string // EncodedLocations represents the locations in an encoded format. EncodedLocations string } -// NewTrustBoundaryData returns a new TrustBoundaryData with the specified locations and encoded locations. -func NewTrustBoundaryData(locations []string, encodedLocations string) *TrustBoundaryData { +// NewRegionalAccessBoundaryData returns a new RegionalAccessBoundaryData with the specified locations and encoded locations. +func NewRegionalAccessBoundaryData(locations []string, encodedLocations string) *RegionalAccessBoundaryData { // Ensure consistency by treating a nil slice as an empty slice. if locations == nil { locations = []string{} } locationsCopy := make([]string, len(locations)) copy(locationsCopy, locations) - return &TrustBoundaryData{ + return &RegionalAccessBoundaryData{ Locations: locationsCopy, EncodedLocations: encodedLocations, } } -// NewNoOpTrustBoundaryData returns a new TrustBoundaryData with no restrictions. -func NewNoOpTrustBoundaryData() *TrustBoundaryData { - return &TrustBoundaryData{ - Locations: []string{}, - EncodedLocations: TrustBoundaryNoOp, - } -} - -// TrustBoundaryHeader returns the value for the x-allowed-locations header and a bool -// indicating if the header should be set. The return values are structured to -// handle three distinct states required by the backend: -// 1. Header not set: (value="", present=false) -> data is empty. -// 2. Header set to an empty string: (value="", present=true) -> data is a no-op. -// 3. Header set to a value: (value="...", present=true) -> data has locations. -func (t TrustBoundaryData) TrustBoundaryHeader() (value string, present bool) { +// RegionalAccessBoundaryHeader returns the value for the x-allowed-locations header and a bool +// indicating if the header should be set. If EncodedLocations is empty, the header +// should not be present. Otherwise, it should be present with the value of EncodedLocations. +func (t RegionalAccessBoundaryData) RegionalAccessBoundaryHeader() (value string, present bool) { if t.EncodedLocations == "" { - // If the data is empty, the header should not be present. return "", false } - - // If data is not empty, the header should always be present. - present = true - value = "" - if t.EncodedLocations != TrustBoundaryNoOp { - value = t.EncodedLocations - } - // For a no-op, the backend requires an empty string. - return value, present + return t.EncodedLocations, true } diff --git a/vendor/cloud.google.com/go/auth/internal/trustboundary/external_accounts_config_providers.go b/vendor/cloud.google.com/go/auth/internal/regionalaccessboundary/external_accounts_config_providers.go similarity index 60% rename from vendor/cloud.google.com/go/auth/internal/trustboundary/external_accounts_config_providers.go rename to vendor/cloud.google.com/go/auth/internal/regionalaccessboundary/external_accounts_config_providers.go index 8fa5600b..2c118901 100644 --- a/vendor/cloud.google.com/go/auth/internal/trustboundary/external_accounts_config_providers.go +++ b/vendor/cloud.google.com/go/auth/internal/regionalaccessboundary/external_accounts_config_providers.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package trustboundary +package regionalaccessboundary import ( "context" @@ -21,13 +21,13 @@ import ( ) const ( - workloadAllowedLocationsEndpoint = "https://iamcredentials.%s/v1/projects/%s/locations/global/workloadIdentityPools/%s/allowedLocations" - workforceAllowedLocationsEndpoint = "https://iamcredentials.%s/v1/locations/global/workforcePools/%s/allowedLocations" + workloadAllowedLocationsEndpoint = "https://iamcredentials.googleapis.com/v1/projects/%s/locations/global/workloadIdentityPools/%s/allowedLocations" + workforceAllowedLocationsEndpoint = "https://iamcredentials.googleapis.com/v1/locations/global/workforcePools/%s/allowedLocations" ) var ( - workforceAudiencePattern = regexp.MustCompile(`//iam\.([^/]+)/locations/global/workforcePools/([^/]+)`) - workloadAudiencePattern = regexp.MustCompile(`//iam\.([^/]+)/projects/([^/]+)/locations/global/workloadIdentityPools/([^/]+)`) + workforceAudiencePattern = regexp.MustCompile(`^//iam\.([^/]+)/locations/([^/]+)/workforcePools/([^/]+)/providers/[^/]+$`) + workloadAudiencePattern = regexp.MustCompile(`^//iam\.([^/]+)/projects/([^/]+)/locations/([^/]+)/workloadIdentityPools/([^/]+)/providers/[^/]+$`) ) // NewExternalAccountConfigProvider creates a new ConfigProvider for external accounts. @@ -36,19 +36,19 @@ func NewExternalAccountConfigProvider(audience, inputUniverseDomain string) (Con var isWorkload bool matches := workloadAudiencePattern.FindStringSubmatch(audience) - if len(matches) == 4 { // Expecting full match, domain, projectNumber, poolID + if len(matches) == 5 { // Expecting full match, domain, projectNumber, location, poolID audienceDomain = matches[1] projectNumber = matches[2] - poolID = matches[3] + poolID = matches[4] isWorkload = true } else { matches = workforceAudiencePattern.FindStringSubmatch(audience) - if len(matches) == 3 { // Expecting full match, domain, poolID + if len(matches) == 4 { // Expecting full match, domain, location, poolID audienceDomain = matches[1] - poolID = matches[2] + poolID = matches[3] isWorkload = false } else { - return nil, fmt.Errorf("trustboundary: unknown audience format: %q", audience) + return nil, fmt.Errorf("regionalaccessboundary: unknown audience format: %q", audience) } } @@ -56,7 +56,7 @@ func NewExternalAccountConfigProvider(audience, inputUniverseDomain string) (Con if effectiveUniverseDomain == "" { effectiveUniverseDomain = audienceDomain } else if audienceDomain != "" && effectiveUniverseDomain != audienceDomain { - return nil, fmt.Errorf("trustboundary: provided universe domain (%q) does not match domain in audience (%q)", inputUniverseDomain, audienceDomain) + return nil, fmt.Errorf("regionalaccessboundary: provided universe domain (%q) does not match domain in audience (%q)", inputUniverseDomain, audienceDomain) } if isWorkload { @@ -77,8 +77,8 @@ type workforcePoolConfigProvider struct { universeDomain string } -func (p *workforcePoolConfigProvider) GetTrustBoundaryEndpoint(ctx context.Context) (string, error) { - return fmt.Sprintf(workforceAllowedLocationsEndpoint, p.universeDomain, p.poolID), nil +func (p *workforcePoolConfigProvider) GetRegionalAccessBoundaryEndpoint(ctx context.Context) (string, error) { + return fmt.Sprintf(workforceAllowedLocationsEndpoint, p.poolID), nil } func (p *workforcePoolConfigProvider) GetUniverseDomain(ctx context.Context) (string, error) { @@ -91,8 +91,8 @@ type workloadIdentityPoolConfigProvider struct { universeDomain string } -func (p *workloadIdentityPoolConfigProvider) GetTrustBoundaryEndpoint(ctx context.Context) (string, error) { - return fmt.Sprintf(workloadAllowedLocationsEndpoint, p.universeDomain, p.projectNumber, p.poolID), nil +func (p *workloadIdentityPoolConfigProvider) GetRegionalAccessBoundaryEndpoint(ctx context.Context) (string, error) { + return fmt.Sprintf(workloadAllowedLocationsEndpoint, p.projectNumber, p.poolID), nil } func (p *workloadIdentityPoolConfigProvider) GetUniverseDomain(ctx context.Context) (string, error) { diff --git a/vendor/cloud.google.com/go/auth/internal/regionalaccessboundary/regional_access_boundary.go b/vendor/cloud.google.com/go/auth/internal/regionalaccessboundary/regional_access_boundary.go new file mode 100644 index 00000000..a94d25ee --- /dev/null +++ b/vendor/cloud.google.com/go/auth/internal/regionalaccessboundary/regional_access_boundary.go @@ -0,0 +1,503 @@ +// Copyright 2026 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. + +package regionalaccessboundary + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "io" + "log/slog" + "maps" + "math/rand" + "net" + "net/http" + "net/url" + "os" + "strings" + "sync" + "time" + + "cloud.google.com/go/auth" + "cloud.google.com/go/auth/internal" + "cloud.google.com/go/auth/internal/retry" + "github.com/googleapis/gax-go/v2/internallog" +) + +// ProviderKey is the key to fetch the DataProvider from Token Metadata. +const ProviderKey = "regionalaccessboundary.ProviderKey" + +const ( + // serviceAccountAllowedLocationsEndpoint is the URL for fetching allowed locations for a given service account email. + serviceAccountAllowedLocationsEndpoint = "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/%s/allowedLocations" + + // cacheTTL is the duration cached RAB data remains valid before hard expiry. + cacheTTL = 6 * time.Hour + // cacheSoftExpiry is the threshold before hard expiry where a background refresh is triggered. + cacheSoftExpiry = 1 * time.Hour + // baseCooldownDuration is the initial delay after a failed background fetch. + baseCooldownDuration = 15 * time.Minute +) + +var ( + // retryOptions configures the retry behavior for Regional Access Boundary lookups. + retryOptions = &retry.Options{ + Initial: 1 * time.Second, + Max: 60 * time.Second, + Multiplier: 2.0, + MaxAttempts: 6, + } +) + +// isEnabled wraps isRegionalAccessBoundaryEnabled with sync.OnceValues to ensure it's +// called only once. +var isEnabled = sync.OnceValues(isRegionalAccessBoundaryEnabled) + +// IsEnabled returns if the Regional Access Boundary feature is enabled and an error if +// the configuration is invalid. The underlying check is performed only once. +func IsEnabled() (bool, error) { + return isEnabled() +} + +// isRegionalAccessBoundaryEnabled checks if the Regional Access Boundary feature +// is enabled via the GOOGLE_AUTH_TRUST_BOUNDARY_ENABLED environment variable. +// +// If the environment variable is not set or empty, it is considered false. +// +// The environment variable is interpreted as a boolean with the following +// (case-insensitive) rules: +// - "true", "1" are considered true. +// - All other values (including "false", "0", or invalid strings) are considered false. +func isRegionalAccessBoundaryEnabled() (bool, error) { + val := strings.ToLower(os.Getenv("GOOGLE_AUTH_TRUST_BOUNDARY_ENABLED")) + return val == "true" || val == "1", nil +} + +// ConfigProvider provides specific configuration for Regional Access Boundary lookups. +type ConfigProvider interface { + // GetRegionalAccessBoundaryEndpoint returns the endpoint URL for the Regional Access Boundary lookup. + GetRegionalAccessBoundaryEndpoint(ctx context.Context) (url string, err error) + // GetUniverseDomain returns the universe domain associated with the credential. + // It may return an error if the universe domain cannot be determined. + GetUniverseDomain(ctx context.Context) (string, error) +} + +// AllowedLocationsResponse is the structure of the response from the Regional Access Boundary API. +type AllowedLocationsResponse struct { + // Locations is the list of allowed locations. + Locations []string `json:"locations"` + // EncodedLocations is the encoded representation of the allowed locations. + EncodedLocations string `json:"encodedLocations"` +} + +// fetchRegionalAccessBoundaryData fetches the Regional Access Boundary data from the API. +func fetchRegionalAccessBoundaryData(ctx context.Context, client *http.Client, url string, token *auth.Token, logger *slog.Logger) (*internal.RegionalAccessBoundaryData, error) { + if logger == nil { + logger = slog.New(slog.NewTextHandler(io.Discard, nil)) + } + if client == nil { + return nil, errors.New("regionalaccessboundary: HTTP client is required") + } + + if url == "" { + return nil, errors.New("regionalaccessboundary: URL cannot be empty") + } + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) + if err != nil { + return nil, fmt.Errorf("regionalaccessboundary: failed to create Regional Access Boundary request: %w", err) + } + + if token == nil || token.Value == "" { + return nil, errors.New("regionalaccessboundary: access token required for lookup API authentication") + } + typ := token.Type + if typ == "" { + typ = internal.TokenTypeBearer + } + req.Header.Set("Authorization", typ+" "+token.Value) + logger.DebugContext(ctx, "Regional Access Boundary request", "request", internallog.HTTPRequest(req, nil)) + + retryer := retry.NewWithOptions(retryOptions) + startTime := time.Now() + var response *http.Response + for { + response, err = client.Do(req) + + var statusCode int + if response != nil { + statusCode = response.StatusCode + } + pause, shouldRetry := retryer.Retry(statusCode, err) + + // Enforce a maximum 1 minute retry window for specific server errors. + if shouldRetry && (statusCode == 500 || statusCode == 502 || statusCode == 503 || statusCode == 504) { + if time.Since(startTime)+pause > 1*time.Minute { + shouldRetry = false + } + } + + if !shouldRetry { + break + } + + if response != nil { + // Drain and close the body to reuse the connection + io.Copy(io.Discard, response.Body) + response.Body.Close() + } + + if err := retry.Sleep(ctx, pause); err != nil { + return nil, err + } + } + + if err != nil { + return nil, fmt.Errorf("regionalaccessboundary: failed to fetch Regional Access Boundary: %w", err) + } + defer response.Body.Close() + + body, err := io.ReadAll(response.Body) + if err != nil { + return nil, fmt.Errorf("regionalaccessboundary: failed to read Regional Access Boundary response: %w", err) + } + + logger.DebugContext(ctx, "Regional Access Boundary response", "response", internallog.HTTPResponse(response, body)) + + if response.StatusCode != http.StatusOK { + return nil, fmt.Errorf("regionalaccessboundary: Regional Access Boundary request failed with status: %s, body: %s", response.Status, string(body)) + } + + apiResponse := AllowedLocationsResponse{} + if err := json.Unmarshal(body, &apiResponse); err != nil { + return nil, fmt.Errorf("regionalaccessboundary: failed to unmarshal Regional Access Boundary response: %w", err) + } + + if apiResponse.EncodedLocations == "" { + return nil, errors.New("regionalaccessboundary: invalid API response: encodedLocations is empty") + } + + return internal.NewRegionalAccessBoundaryData(apiResponse.Locations, apiResponse.EncodedLocations), nil +} + +// DataProvider fetches and caches Regional Access Boundary Data. +// It implements the auth.TokenProvider interface and uses a ConfigProvider +// to get type-specific details for the lookup. +type DataProvider struct { + client *http.Client + configProvider ConfigProvider + logger *slog.Logger + base auth.TokenProvider + + mu sync.RWMutex + data *internal.RegionalAccessBoundaryData + dataExpiry time.Time + isFetching bool + cooldownExpiry time.Time + cooldownDuration time.Duration // tracks the current cooldown duration for exponential backoff +} + +// NewProvider wraps the provided base [auth.TokenProvider] and returns a new +// provider that fetches and caches the Regional Access Boundary data. It uses +// the provided HTTP client and configProvider. +func NewProvider(client *http.Client, configProvider ConfigProvider, logger *slog.Logger, base auth.TokenProvider) (*DataProvider, error) { + if client == nil { + return nil, errors.New("regionalaccessboundary: HTTP client cannot be nil for DataProvider") + } + if configProvider == nil { + return nil, errors.New("regionalaccessboundary: ConfigProvider cannot be nil for DataProvider") + } + p := &DataProvider{ + client: client, + configProvider: configProvider, + logger: internallog.New(logger), + base: base, + cooldownDuration: 15 * time.Minute, + } + return p, nil +} + +// Token retrieves a token from the base provider and injects the DataProvider +// instance into its metadata. +func (p *DataProvider) Token(ctx context.Context) (*auth.Token, error) { + token, err := p.base.Token(ctx) + if err != nil { + return nil, err + } + + // Clone the token and its metadata to avoid mutating shared/cached state. + newToken := *token + newToken.Metadata = maps.Clone(token.Metadata) + if newToken.Metadata == nil { + newToken.Metadata = make(map[string]interface{}) + } + newToken.Metadata[ProviderKey] = p + + return &newToken, nil +} + +// GetHeaderValue immediately returns a valid header if it's cached, or kicks off a background fetch +// if it is unpopulated or expired. +func (p *DataProvider) GetHeaderValue(ctx context.Context, reqURL string, accessToken *auth.Token) string { + if !strings.Contains(reqURL, "://") { + reqURL = "https://" + reqURL + } + if u, err := url.Parse(reqURL); err == nil { + host := u.Host + if host == "" && strings.HasPrefix(u.Path, "/") { + host = strings.TrimPrefix(u.Path, "/") + } + if h, _, err := net.SplitHostPort(host); err == nil { + host = h + } + // Skip lookup for regional endpoints. + if host == "rep.googleapis.com" || strings.HasSuffix(host, ".rep.googleapis.com") || + host == "rep.sandbox.googleapis.com" || strings.HasSuffix(host, ".rep.sandbox.googleapis.com") { + return "" + } + // Skip lookup for IAM and STS endpoints as they do not require RAB headers. + if host == "iam.googleapis.com" || host == "iamcredentials.googleapis.com" || + host == "sts.googleapis.com" { + return "" + } + } + + // Skip lookup for non-default universe domains. + uniDomain, err := p.configProvider.GetUniverseDomain(ctx) + if err != nil { + p.logger.WarnContext(ctx, "regionalaccessboundary: error getting universe domain", "error", err) + return "" + } + if uniDomain != "" && uniDomain != internal.DefaultUniverseDomain { + return "" + } + + // Return the cached data if present and not expired. + p.mu.RLock() + data := p.data + dataExpiry := p.dataExpiry + p.mu.RUnlock() + + now := time.Now() + if data != nil && now.Before(dataExpiry) { + val, _ := data.RegionalAccessBoundaryHeader() + + // Soft Expiry: if the cached data is within the soft expiration window, + // initiate a non-blocking background refresh to proactively fetch new data + // while continuing to serve the current valid cache block. + if now.After(dataExpiry.Add(-cacheSoftExpiry)) { + p.mu.Lock() + if !p.isFetching && now.After(p.cooldownExpiry) { + p.isFetching = true + go p.fetchAsync(context.Background(), accessToken) + } + p.mu.Unlock() + } + + return val + } + + p.mu.Lock() + defer p.mu.Unlock() + + // Skip lookup if in cooldown or another process is already fetching. + if p.isFetching || time.Now().Before(p.cooldownExpiry) { + return "" + } + + // Start async RAB lookup and return empty header. + p.isFetching = true + go p.fetchAsync(context.Background(), accessToken) + return "" +} + +// fetchAsync performs the background lookup for Regional Access Boundary data. +// It updates the provider's state based on the result (success or failure). +func (p *DataProvider) fetchAsync(ctx context.Context, accessToken *auth.Token) { + defer func() { + p.mu.Lock() + p.isFetching = false + p.mu.Unlock() + }() + + url, err := p.configProvider.GetRegionalAccessBoundaryEndpoint(ctx) + if err != nil { + p.logger.WarnContext(ctx, "regionalaccessboundary: error getting the lookup endpoint", "error", err) + p.handleFetchFailure(ctx) + return + } + + newData, fetchErr := fetchRegionalAccessBoundaryData(ctx, p.client, url, accessToken, p.logger) + + if fetchErr != nil { + p.logger.WarnContext(ctx, "regionalaccessboundary: async fetch failed", "error", fetchErr) + p.handleFetchFailure(ctx) + return + } + + p.handleFetchSuccess(newData) +} + +// handleFetchSuccess updates the cache with new data and clears any existing cooldown. +func (p *DataProvider) handleFetchSuccess(newData *internal.RegionalAccessBoundaryData) { + p.mu.Lock() + defer p.mu.Unlock() + p.data = newData + p.dataExpiry = time.Now().Add(cacheTTL) + p.cooldownExpiry = time.Time{} + p.cooldownDuration = baseCooldownDuration +} + +// handleFetchFailure triggers the cooldown period using exponential backoff. +func (p *DataProvider) handleFetchFailure(ctx context.Context) { + p.mu.Lock() + defer p.mu.Unlock() + + // Add random bounded jitter (between half of the base and the full base) to prevent thundering herds + jitter := p.cooldownDuration/2 + time.Duration(rand.Int63n(int64(p.cooldownDuration/2))) + p.cooldownExpiry = time.Now().Add(jitter) + + // Exponential backoff for the NEXT attempt, up to cacheTTL max (6 hours) + nextCooldown := p.cooldownDuration * 2 + if nextCooldown > cacheTTL { + nextCooldown = cacheTTL + } + p.cooldownDuration = nextCooldown +} + +// serviceAccountConfig holds configuration for SA Regional Access Boundary lookups. +// It implements the ConfigProvider interface. +type serviceAccountConfig struct { + ServiceAccountEmail string + UniverseDomain string +} + +// NewServiceAccountConfigProvider creates a new config for service accounts. +func NewServiceAccountConfigProvider(saEmail, universeDomain string) ConfigProvider { + return &serviceAccountConfig{ + ServiceAccountEmail: saEmail, + UniverseDomain: universeDomain, + } +} + +// GetRegionalAccessBoundaryEndpoint returns the formatted URL for fetching allowed locations +// for the configured service account. +func (sac *serviceAccountConfig) GetRegionalAccessBoundaryEndpoint(ctx context.Context) (url string, err error) { + if sac.ServiceAccountEmail == "" { + return "", errors.New("regionalaccessboundary: service account email cannot be empty for config") + } + return fmt.Sprintf(serviceAccountAllowedLocationsEndpoint, sac.ServiceAccountEmail), nil +} + +// GetUniverseDomain returns the configured universe domain, defaulting to +// [internal.DefaultUniverseDomain] if not explicitly set. +func (sac *serviceAccountConfig) GetUniverseDomain(ctx context.Context) (string, error) { + if sac.UniverseDomain == "" { + return internal.DefaultUniverseDomain, nil + } + return sac.UniverseDomain, nil +} + +// GCEConfigProvider implements ConfigProvider for GCE environments. +// It lazily fetches and caches the necessary metadata (service account email, universe domain) +type GCEConfigProvider struct { + // universeDomainProvider provides the universe domain and underlying metadata client. + universeDomainProvider *internal.ComputeUniverseDomainProvider + + // Caching for service account email + saMu sync.Mutex + saEmail string + + // Caching for universe domain + udOnce sync.Once + ud string + udErr error +} + +// NewGCEConfigProvider creates a new GCEConfigProvider +// which uses the provided gceUDP to interact with the GCE metadata server. +func NewGCEConfigProvider(gceUDP *internal.ComputeUniverseDomainProvider) *GCEConfigProvider { + // The validity of gceUDP and its internal MetadataClient will be checked + // within the GetRegionalAccessBoundaryEndpoint and GetUniverseDomain methods. + return &GCEConfigProvider{ + universeDomainProvider: gceUDP, + } +} + +func (g *GCEConfigProvider) fetchSA(ctx context.Context) (string, error) { + if g.universeDomainProvider == nil || g.universeDomainProvider.MetadataClient == nil { + return "", errors.New("regionalaccessboundary: GCEConfigProvider not properly initialized (missing ComputeUniverseDomainProvider or MetadataClient)") + } + mdClient := g.universeDomainProvider.MetadataClient + saEmail, err := mdClient.EmailWithContext(ctx, "default") + if err != nil { + return "", fmt.Errorf("regionalaccessboundary: GCE config: failed to get service account email: %w", err) + } + return saEmail, nil +} + +func (g *GCEConfigProvider) fetchUD(ctx context.Context) { + if g.universeDomainProvider == nil || g.universeDomainProvider.MetadataClient == nil { + g.udErr = errors.New("regionalaccessboundary: GCEConfigProvider not properly initialized (missing ComputeUniverseDomainProvider or MetadataClient)") + return + } + ud, err := g.universeDomainProvider.GetProperty(ctx) + if err != nil { + g.udErr = fmt.Errorf("regionalaccessboundary: GCE config: failed to get universe domain: %w", err) + return + } + if ud == "" { + ud = internal.DefaultUniverseDomain + } + g.ud = ud +} + +// GetRegionalAccessBoundaryEndpoint constructs the Regional Access Boundary lookup URL for a GCE environment. +// It uses cached service account email after the first call. +func (g *GCEConfigProvider) GetRegionalAccessBoundaryEndpoint(ctx context.Context) (string, error) { + // Check if we already have a cached service account email. + g.saMu.Lock() + if g.saEmail != "" { + email := g.saEmail + g.saMu.Unlock() + return fmt.Sprintf(serviceAccountAllowedLocationsEndpoint, email), nil + } + g.saMu.Unlock() + + // Fetch the email from the metadata server. We do not hold the lock + // during this I/O operation to avoid blocking other goroutines. + email, err := g.fetchSA(ctx) + if err != nil { + return "", err + } + + // Cache the successful result. + g.saMu.Lock() + g.saEmail = email + g.saMu.Unlock() + + return fmt.Sprintf(serviceAccountAllowedLocationsEndpoint, email), nil +} + +// GetUniverseDomain retrieves the universe domain from the GCE metadata server. +// It uses a cached value after the first call. +func (g *GCEConfigProvider) GetUniverseDomain(ctx context.Context) (string, error) { + g.udOnce.Do(func() { g.fetchUD(ctx) }) + if g.udErr != nil { + return "", g.udErr + } + return g.ud, nil +} diff --git a/vendor/cloud.google.com/go/auth/internal/retry/retry.go b/vendor/cloud.google.com/go/auth/internal/retry/retry.go index 276cc4a3..7cbd06a7 100644 --- a/vendor/cloud.google.com/go/auth/internal/retry/retry.go +++ b/vendor/cloud.google.com/go/auth/internal/retry/retry.go @@ -22,10 +22,6 @@ import ( "time" ) -const ( - maxRetryAttempts = 5 -) - var ( syscallRetryable = func(error) bool { return false } ) @@ -61,21 +57,69 @@ func Sleep(ctx context.Context, d time.Duration) error { // New returns a new Retryer with the default backoff strategy. func New() *Retryer { - return &Retryer{bo: &defaultBackoff{ - cur: 100 * time.Millisecond, - max: 30 * time.Second, - mul: 2, - }} + return NewWithOptions(&Options{ + Initial: 100 * time.Millisecond, + Max: 30 * time.Second, + Multiplier: 2, + MaxAttempts: 5, + }) +} + +// Options defines the configuration for the Retryer. +type Options struct { + // Initial is the initial backoff duration. + Initial time.Duration + // Max is the maximum backoff duration for a single retry attempt. + // It does not limit the total time of all retries. + Max time.Duration + // Multiplier is the factor by which the backoff duration is multiplied after each attempt. + Multiplier float64 + // MaxAttempts is the maximum number of attempts before giving up. + MaxAttempts int +} + +// NewWithOptions returns a new Retryer with the specified backoff strategy. +// If any option is not set (zero value), it defaults to the values used in New(). +func NewWithOptions(opts *Options) *Retryer { + initial := opts.Initial + if initial <= 0 { + initial = 100 * time.Millisecond + } + + max := opts.Max + if max <= 0 { + max = 30 * time.Second + } + + multiplier := opts.Multiplier + if multiplier < 1.0 { + multiplier = 2.0 + } + + maxAttempts := opts.MaxAttempts + if maxAttempts <= 0 { + maxAttempts = 5 + } + + return &Retryer{ + bo: &defaultBackoff{ + cur: initial, + max: max, + mul: multiplier, + }, + maxAttempts: maxAttempts, + } } type backoff interface { Pause() time.Duration } -// Retryer is a retryer for HTTP requests. +// Retryer handles retry logic for HTTP requests using a configurable backoff strategy. type Retryer struct { - bo backoff - attempts int + bo backoff + attempts int + maxAttempts int } // Retry determines if a request should be retried. @@ -87,7 +131,7 @@ func (r *Retryer) Retry(status int, err error) (time.Duration, bool) { if !retryOk { return 0, false } - if r.attempts == maxRetryAttempts { + if r.attempts == r.maxAttempts { return 0, false } r.attempts++ diff --git a/vendor/cloud.google.com/go/auth/internal/retry/retry_linux.go b/vendor/cloud.google.com/go/auth/internal/retry/retry_linux.go new file mode 100644 index 00000000..8f0a78c5 --- /dev/null +++ b/vendor/cloud.google.com/go/auth/internal/retry/retry_linux.go @@ -0,0 +1,31 @@ +// Copyright 2026 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. + +//go:build linux +// +build linux + +package retry + +import ( + "errors" + "syscall" +) + +func init() { + // Initialize syscallRetryable to return true on transient socket-level + // errors. These errors are specific to Linux. + syscallRetryable = func(err error) bool { + return errors.Is(err, syscall.ECONNRESET) || errors.Is(err, syscall.ECONNREFUSED) + } +} diff --git a/vendor/cloud.google.com/go/auth/internal/transport/cba.go b/vendor/cloud.google.com/go/auth/internal/transport/cba.go index 14bca966..ebce7db5 100644 --- a/vendor/cloud.google.com/go/auth/internal/transport/cba.go +++ b/vendor/cloud.google.com/go/auth/internal/transport/cba.go @@ -65,15 +65,16 @@ const ( // transport packages in order to avoid cyclic deps. It correlates 1:1 with // fields on httptransport.Options and grpctransport.Options. type Options struct { - Endpoint string - DefaultEndpointTemplate string - DefaultMTLSEndpoint string - ClientCertProvider cert.Provider - Client *http.Client - UniverseDomain string - EnableDirectPath bool - EnableDirectPathXds bool - Logger *slog.Logger + Endpoint string + DefaultEndpointTemplate string + DefaultMTLSEndpoint string + ClientCertProvider cert.Provider + Client *http.Client + UniverseDomain string + EnableDirectPath bool + EnableDirectPathXds bool + EnableDirectPathXdsOverInterconnect bool + Logger *slog.Logger } // getUniverseDomain returns the default service domain for a given Cloud diff --git a/vendor/cloud.google.com/go/auth/internal/transport/cert/secureconnect_cert.go b/vendor/cloud.google.com/go/auth/internal/transport/cert/secureconnect_cert.go index 738cb216..ecb2448b 100644 --- a/vendor/cloud.google.com/go/auth/internal/transport/cert/secureconnect_cert.go +++ b/vendor/cloud.google.com/go/auth/internal/transport/cert/secureconnect_cert.go @@ -76,9 +76,17 @@ func NewSecureConnectProvider(configFilePath string) (Provider, error) { if err := validateMetadata(metadata); err != nil { return nil, fmt.Errorf("cert: invalid config in %q: %w", configFilePath, err) } - return (&secureConnectSource{ + source := &secureConnectSource{ metadata: metadata, - }).getClientCertificate, nil + } + _, err = source.getClientCertificate(nil) + if errors.Is(err, errSourceUnavailable) { + return nil, errSourceUnavailable + } + if err != nil { + return nil, err + } + return source.getClientCertificate, nil } func validateMetadata(metadata secureConnectMetadata) error { @@ -101,7 +109,10 @@ func (s *secureConnectSource) getClientCertificate(info *tls.CertificateRequestI command := s.metadata.Cmd data, err := exec.Command(command[0], command[1:]...).Output() if err != nil { - return nil, err + // Return errSourceUnavailable so the probe in NewSecureConnectProvider + // can recognize the source as unavailable, and so crypto/tls aborts + // the handshake with a clear error if it fails at runtime. + return nil, fmt.Errorf("%w: %v", errSourceUnavailable, err) } cert, err := tls.X509KeyPair(data, data) if err != nil { diff --git a/vendor/cloud.google.com/go/auth/internal/transport/cert/workload_cert.go b/vendor/cloud.google.com/go/auth/internal/transport/cert/workload_cert.go index b2a3be23..ddb0c380 100644 --- a/vendor/cloud.google.com/go/auth/internal/transport/cert/workload_cert.go +++ b/vendor/cloud.google.com/go/auth/internal/transport/cert/workload_cert.go @@ -37,11 +37,21 @@ type certificateConfig struct { CertConfigs certConfigs `json:"cert_configs"` } -// getconfigFilePath determines the path to the certificate configuration file. +type certConfigInfo struct { + certPath string // path to the certificate file + keyPath string // path to the private key file + useECP bool // whether to use Enterprise Certificate Proxy +} + +// GetConfigFilePath determines the path to the certificate configuration file. // It first checks for the presence of an environment variable that specifies // the file path. If the environment variable is not set, it falls back to -// a default configuration file path. -func getconfigFilePath() string { +// a default configuration file path. If a non-empty configFilePath is provided, +// it is returned. +func GetConfigFilePath(configFilePath string) string { + if configFilePath != "" { + return configFilePath + } envFilePath := util.GetConfigFilePathFromEnv() if envFilePath != "" { return envFilePath @@ -50,21 +60,32 @@ func getconfigFilePath() string { } -// GetCertificatePath retrieves the certificate file path from the provided +// GetFileBasedCertificatePath retrieves the certificate file path from the provided // configuration file. If the configFilePath is empty, it attempts to load // the configuration from a well-known gcloud location. // This function is exposed to allow other packages, such as the // externalaccount package, to retrieve the certificate path without needing // to load the entire certificate configuration. -func GetCertificatePath(configFilePath string) (string, error) { - if configFilePath == "" { - configFilePath = getconfigFilePath() - } - certFile, _, err := getCertAndKeyFiles(configFilePath) +func GetFileBasedCertificatePath(configFilePath string) (string, error) { + configFilePath = GetConfigFilePath(configFilePath) + info, err := parseCertConfig(configFilePath) if err != nil { return "", err } - return certFile, nil + if info.useECP { + return "", errors.New("enterprise certificate proxy is enabled, certificate path is not available") + } + return info.certPath, nil +} + +// IsECPConfig checks if the given configuration is an ECP certificate configuration. +func IsECPConfig(configFilePath string) bool { + configFilePath = GetConfigFilePath(configFilePath) + info, err := parseCertConfig(configFilePath) + if err != nil { + return false + } + return info.useECP } // NewWorkloadX509CertProvider creates a certificate source @@ -76,17 +97,19 @@ func GetCertificatePath(configFilePath string) (string, error) { // If configFilePath is empty, the client will attempt to load the config from // a well-known gcloud location. func NewWorkloadX509CertProvider(configFilePath string) (Provider, error) { - if configFilePath == "" { - configFilePath = getconfigFilePath() - } - certFile, keyFile, err := getCertAndKeyFiles(configFilePath) + configFilePath = GetConfigFilePath(configFilePath) + info, err := parseCertConfig(configFilePath) if err != nil { return nil, err } + if info.useECP { + return NewEnterpriseCertificateProxyProvider(configFilePath) + } + source := &workloadSource{ - CertPath: certFile, - KeyPath: keyFile, + CertPath: info.certPath, + KeyPath: info.keyPath, } return source.getClientCertificate, nil } @@ -101,38 +124,60 @@ func (s *workloadSource) getClientCertificate(info *tls.CertificateRequestInfo) return &cert, nil } -// getCertAndKeyFiles attempts to read the provided config file and return the certificate and private -// key file paths. -func getCertAndKeyFiles(configFilePath string) (string, string, error) { +// parseCertConfig attempts to read the provided config file and return the certificate, private +// key file paths, and a boolean indicating whether to use ECP inside a certConfigInfo struct. +func parseCertConfig(configFilePath string) (certConfigInfo, error) { jsonFile, err := os.Open(configFilePath) if err != nil { - return "", "", errSourceUnavailable + return certConfigInfo{}, errSourceUnavailable } + defer jsonFile.Close() byteValue, err := io.ReadAll(jsonFile) if err != nil { - return "", "", err + return certConfigInfo{}, err } var config certificateConfig if err := json.Unmarshal(byteValue, &config); err != nil { - return "", "", err + return certConfigInfo{}, err } if config.CertConfigs.Workload == nil { - return "", "", errSourceUnavailable + // If 'workload' field is absent, it is an ECP config. + // Validate that the config file is a valid ECP file. + var rawMap map[string]any + if err := json.Unmarshal(byteValue, &rawMap); err != nil { + return certConfigInfo{}, err + } + certConfigs, ok := rawMap["cert_configs"].(map[string]any) + if !ok { + return certConfigInfo{}, errSourceUnavailable + } + hasECPSection := false + for _, section := range []string{"pkcs11", "windows_store", "macos_keychain"} { + if _, exists := certConfigs[section]; exists { + hasECPSection = true + break + } + } + _, hasLibs := rawMap["libs"] + if !hasECPSection || !hasLibs { + return certConfigInfo{}, errSourceUnavailable + } + return certConfigInfo{useECP: true}, nil } certFile := config.CertConfigs.Workload.CertPath keyFile := config.CertConfigs.Workload.KeyPath if certFile == "" { - return "", "", errors.New("certificate configuration is missing the certificate file location") + return certConfigInfo{}, errors.New("certificate configuration is missing the certificate file location") } if keyFile == "" { - return "", "", errors.New("certificate configuration is missing the key file location") + return certConfigInfo{}, errors.New("certificate configuration is missing the key file location") } - return certFile, keyFile, nil + return certConfigInfo{certPath: certFile, keyPath: keyFile}, nil } diff --git a/vendor/cloud.google.com/go/auth/internal/transport/headers/headers.go b/vendor/cloud.google.com/go/auth/internal/transport/headers/headers.go index 5483a763..01c06e27 100644 --- a/vendor/cloud.google.com/go/auth/internal/transport/headers/headers.go +++ b/vendor/cloud.google.com/go/auth/internal/transport/headers/headers.go @@ -15,14 +15,20 @@ package headers import ( + "context" "net/http" "cloud.google.com/go/auth" "cloud.google.com/go/auth/internal" + "cloud.google.com/go/auth/internal/regionalaccessboundary" ) -// SetAuthHeader uses the provided token to set the Authorization and trust -// boundary headers on a request. If the token.Type is empty, the type is +type regionalAccessBoundaryProvider interface { + GetHeaderValue(ctx context.Context, reqURL string, token *auth.Token) string +} + +// SetAuthHeader uses the provided token to set the Authorization and regional +// access boundary headers on a request. If the token.Type is empty, the type is // assumed to be Bearer. func SetAuthHeader(token *auth.Token, req *http.Request) { typ := token.Type @@ -31,31 +37,26 @@ func SetAuthHeader(token *auth.Token, req *http.Request) { } req.Header.Set("Authorization", typ+" "+token.Value) - if headerVal, setHeader := getTrustBoundaryHeader(token); setHeader { - req.Header.Set("x-allowed-locations", headerVal) + if provider, ok := token.Metadata[regionalaccessboundary.ProviderKey].(regionalAccessBoundaryProvider); ok { + if headerVal := provider.GetHeaderValue(req.Context(), req.URL.String(), token); headerVal != "" { + req.Header.Set("x-allowed-locations", headerVal) + } } } -// SetAuthMetadata uses the provided token to set the Authorization and trust -// boundary metadata. If the token.Type is empty, the type is assumed to be +// SetAuthMetadata uses the provided token to set the Authorization and regional +// access boundary metadata. If the token.Type is empty, the type is assumed to be // Bearer. -func SetAuthMetadata(token *auth.Token, m map[string]string) { +func SetAuthMetadata(ctx context.Context, token *auth.Token, reqURL string, m map[string]string) { typ := token.Type if typ == "" { typ = internal.TokenTypeBearer } m["authorization"] = typ + " " + token.Value - if headerVal, setHeader := getTrustBoundaryHeader(token); setHeader { - m["x-allowed-locations"] = headerVal - } -} - -func getTrustBoundaryHeader(token *auth.Token) (val string, present bool) { - if data, ok := token.Metadata[internal.TrustBoundaryDataKey]; ok { - if tbd, ok := data.(internal.TrustBoundaryData); ok { - return tbd.TrustBoundaryHeader() + if provider, ok := token.Metadata[regionalaccessboundary.ProviderKey].(regionalAccessBoundaryProvider); ok { + if headerVal := provider.GetHeaderValue(ctx, reqURL, token); headerVal != "" { + m["x-allowed-locations"] = headerVal } } - return "", false } diff --git a/vendor/cloud.google.com/go/auth/internal/transport/s2a.go b/vendor/cloud.google.com/go/auth/internal/transport/s2a.go index a6330995..7e74590d 100644 --- a/vendor/cloud.google.com/go/auth/internal/transport/s2a.go +++ b/vendor/cloud.google.com/go/auth/internal/transport/s2a.go @@ -126,7 +126,7 @@ func shouldUseS2A(clientCertSource cert.Provider, opts *Options) bool { return false } // If directPath is enabled, skip S2A. - return !opts.EnableDirectPath && !opts.EnableDirectPathXds + return !opts.EnableDirectPath && !opts.EnableDirectPathXds && !opts.EnableDirectPathXdsOverInterconnect } func isGoogleS2AEnabled() bool { diff --git a/vendor/cloud.google.com/go/auth/internal/transport/transport.go b/vendor/cloud.google.com/go/auth/internal/transport/transport.go index fb0a8a1e..c4f4c26b 100644 --- a/vendor/cloud.google.com/go/auth/internal/transport/transport.go +++ b/vendor/cloud.google.com/go/auth/internal/transport/transport.go @@ -67,15 +67,16 @@ func CloneDetectOptions(oldDo *credentials.DetectOptions) *credentials.DetectOpt } newDo := &credentials.DetectOptions{ // Simple types - TokenBindingType: oldDo.TokenBindingType, - Audience: oldDo.Audience, - Subject: oldDo.Subject, - EarlyTokenRefresh: oldDo.EarlyTokenRefresh, - TokenURL: oldDo.TokenURL, - STSAudience: oldDo.STSAudience, - CredentialsFile: oldDo.CredentialsFile, - UseSelfSignedJWT: oldDo.UseSelfSignedJWT, - UniverseDomain: oldDo.UniverseDomain, + TokenBindingType: oldDo.TokenBindingType, + Audience: oldDo.Audience, + Subject: oldDo.Subject, + EarlyTokenRefresh: oldDo.EarlyTokenRefresh, + DisableAsyncRefresh: oldDo.DisableAsyncRefresh, + TokenURL: oldDo.TokenURL, + STSAudience: oldDo.STSAudience, + CredentialsFile: oldDo.CredentialsFile, + UseSelfSignedJWT: oldDo.UseSelfSignedJWT, + UniverseDomain: oldDo.UniverseDomain, // These fields are pointer types that we just want to use exactly as // the user set, copy the ref diff --git a/vendor/cloud.google.com/go/auth/internal/trustboundary/trust_boundary.go b/vendor/cloud.google.com/go/auth/internal/trustboundary/trust_boundary.go deleted file mode 100644 index bf898fff..00000000 --- a/vendor/cloud.google.com/go/auth/internal/trustboundary/trust_boundary.go +++ /dev/null @@ -1,392 +0,0 @@ -// Copyright 2025 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. - -package trustboundary - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "io" - "log/slog" - "net/http" - "os" - "strings" - "sync" - - "cloud.google.com/go/auth" - "cloud.google.com/go/auth/internal" - "cloud.google.com/go/auth/internal/retry" - "cloud.google.com/go/auth/internal/transport/headers" - "github.com/googleapis/gax-go/v2/internallog" -) - -const ( - // serviceAccountAllowedLocationsEndpoint is the URL for fetching allowed locations for a given service account email. - serviceAccountAllowedLocationsEndpoint = "https://iamcredentials.%s/v1/projects/-/serviceAccounts/%s/allowedLocations" -) - -// isEnabled wraps isTrustBoundaryEnabled with sync.OnceValues to ensure it's -// called only once. -var isEnabled = sync.OnceValues(isTrustBoundaryEnabled) - -// IsEnabled returns if the trust boundary feature is enabled and an error if -// the configuration is invalid. The underlying check is performed only once. -func IsEnabled() (bool, error) { - return isEnabled() -} - -// isTrustBoundaryEnabled checks if the trust boundary feature is enabled via -// GOOGLE_AUTH_TRUST_BOUNDARY_ENABLED environment variable. -// -// If the environment variable is not set, it is considered false. -// -// The environment variable is interpreted as a boolean with the following -// (case-insensitive) rules: -// - "true", "1" are considered true. -// - "false", "0" are considered false. -// -// Any other values will return an error. -func isTrustBoundaryEnabled() (bool, error) { - const envVar = "GOOGLE_AUTH_TRUST_BOUNDARY_ENABLED" - val, ok := os.LookupEnv(envVar) - if !ok { - return false, nil - } - val = strings.ToLower(val) - switch val { - case "true", "1": - return true, nil - case "false", "0": - return false, nil - default: - return false, fmt.Errorf(`invalid value for %s: %q. Must be one of "true", "false", "1", or "0"`, envVar, val) - } -} - -// ConfigProvider provides specific configuration for trust boundary lookups. -type ConfigProvider interface { - // GetTrustBoundaryEndpoint returns the endpoint URL for the trust boundary lookup. - GetTrustBoundaryEndpoint(ctx context.Context) (url string, err error) - // GetUniverseDomain returns the universe domain associated with the credential. - // It may return an error if the universe domain cannot be determined. - GetUniverseDomain(ctx context.Context) (string, error) -} - -// AllowedLocationsResponse is the structure of the response from the Trust Boundary API. -type AllowedLocationsResponse struct { - // Locations is the list of allowed locations. - Locations []string `json:"locations"` - // EncodedLocations is the encoded representation of the allowed locations. - EncodedLocations string `json:"encodedLocations"` -} - -// fetchTrustBoundaryData fetches the trust boundary data from the API. -func fetchTrustBoundaryData(ctx context.Context, client *http.Client, url string, token *auth.Token, logger *slog.Logger) (*internal.TrustBoundaryData, error) { - if logger == nil { - logger = slog.New(slog.NewTextHandler(io.Discard, nil)) - } - if client == nil { - return nil, errors.New("trustboundary: HTTP client is required") - } - - if url == "" { - return nil, errors.New("trustboundary: URL cannot be empty") - } - - req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) - if err != nil { - return nil, fmt.Errorf("trustboundary: failed to create trust boundary request: %w", err) - } - - if token == nil || token.Value == "" { - return nil, errors.New("trustboundary: access token required for lookup API authentication") - } - headers.SetAuthHeader(token, req) - logger.DebugContext(ctx, "trust boundary request", "request", internallog.HTTPRequest(req, nil)) - - retryer := retry.New() - var response *http.Response - for { - response, err = client.Do(req) - - var statusCode int - if response != nil { - statusCode = response.StatusCode - } - pause, shouldRetry := retryer.Retry(statusCode, err) - - if !shouldRetry { - break - } - - if response != nil { - // Drain and close the body to reuse the connection - io.Copy(io.Discard, response.Body) - response.Body.Close() - } - - if err := retry.Sleep(ctx, pause); err != nil { - return nil, err - } - } - - if err != nil { - return nil, fmt.Errorf("trustboundary: failed to fetch trust boundary: %w", err) - } - defer response.Body.Close() - - body, err := io.ReadAll(response.Body) - if err != nil { - return nil, fmt.Errorf("trustboundary: failed to read trust boundary response: %w", err) - } - - logger.DebugContext(ctx, "trust boundary response", "response", internallog.HTTPResponse(response, body)) - - if response.StatusCode != http.StatusOK { - return nil, fmt.Errorf("trustboundary: trust boundary request failed with status: %s, body: %s", response.Status, string(body)) - } - - apiResponse := AllowedLocationsResponse{} - if err := json.Unmarshal(body, &apiResponse); err != nil { - return nil, fmt.Errorf("trustboundary: failed to unmarshal trust boundary response: %w", err) - } - - if apiResponse.EncodedLocations == "" { - return nil, errors.New("trustboundary: invalid API response: encodedLocations is empty") - } - - return internal.NewTrustBoundaryData(apiResponse.Locations, apiResponse.EncodedLocations), nil -} - -// serviceAccountConfig holds configuration for SA trust boundary lookups. -// It implements the ConfigProvider interface. -type serviceAccountConfig struct { - ServiceAccountEmail string - UniverseDomain string -} - -// NewServiceAccountConfigProvider creates a new config for service accounts. -func NewServiceAccountConfigProvider(saEmail, universeDomain string) ConfigProvider { - return &serviceAccountConfig{ - ServiceAccountEmail: saEmail, - UniverseDomain: universeDomain, - } -} - -// GetTrustBoundaryEndpoint returns the formatted URL for fetching allowed locations -// for the configured service account and universe domain. -func (sac *serviceAccountConfig) GetTrustBoundaryEndpoint(ctx context.Context) (url string, err error) { - if sac.ServiceAccountEmail == "" { - return "", errors.New("trustboundary: service account email cannot be empty for config") - } - ud := sac.UniverseDomain - if ud == "" { - ud = internal.DefaultUniverseDomain - } - return fmt.Sprintf(serviceAccountAllowedLocationsEndpoint, ud, sac.ServiceAccountEmail), nil -} - -// GetUniverseDomain returns the configured universe domain, defaulting to -// [internal.DefaultUniverseDomain] if not explicitly set. -func (sac *serviceAccountConfig) GetUniverseDomain(ctx context.Context) (string, error) { - if sac.UniverseDomain == "" { - return internal.DefaultUniverseDomain, nil - } - return sac.UniverseDomain, nil -} - -// DataProvider fetches and caches trust boundary Data. -// It implements the DataProvider interface and uses a ConfigProvider -// to get type-specific details for the lookup. -type DataProvider struct { - client *http.Client - configProvider ConfigProvider - data *internal.TrustBoundaryData - logger *slog.Logger - base auth.TokenProvider -} - -// NewProvider wraps the provided base [auth.TokenProvider] to create a new -// provider that injects tokens with trust boundary data. It uses the provided -// HTTP client and configProvider to fetch the data and attach it to the token's -// metadata. -func NewProvider(client *http.Client, configProvider ConfigProvider, logger *slog.Logger, base auth.TokenProvider) (*DataProvider, error) { - if client == nil { - return nil, errors.New("trustboundary: HTTP client cannot be nil for DataProvider") - } - if configProvider == nil { - return nil, errors.New("trustboundary: ConfigProvider cannot be nil for DataProvider") - } - p := &DataProvider{ - client: client, - configProvider: configProvider, - logger: internallog.New(logger), - base: base, - } - return p, nil -} - -// Token retrieves a token from the base provider and injects it with trust -// boundary data. -func (p *DataProvider) Token(ctx context.Context) (*auth.Token, error) { - // Get the original token. - token, err := p.base.Token(ctx) - if err != nil { - return nil, err - } - - tbData, err := p.GetTrustBoundaryData(ctx, token) - if err != nil { - return nil, fmt.Errorf("trustboundary: error fetching the trust boundary data: %w", err) - } - if tbData != nil { - if token.Metadata == nil { - token.Metadata = make(map[string]interface{}) - } - token.Metadata[internal.TrustBoundaryDataKey] = *tbData - } - return token, nil -} - -// GetTrustBoundaryData retrieves the trust boundary data. -// It first checks the universe domain: if it's non-default, a NoOp is returned. -// Otherwise, it checks a local cache. If the data is not cached as NoOp, -// it fetches new data from the endpoint provided by its ConfigProvider, -// using the given accessToken for authentication. Results are cached. -// If fetching fails, it returns previously cached data if available, otherwise the fetch error. -func (p *DataProvider) GetTrustBoundaryData(ctx context.Context, token *auth.Token) (*internal.TrustBoundaryData, error) { - // Check the universe domain. - uniDomain, err := p.configProvider.GetUniverseDomain(ctx) - if err != nil { - return nil, fmt.Errorf("trustboundary: error getting universe domain: %w", err) - } - if uniDomain != "" && uniDomain != internal.DefaultUniverseDomain { - if p.data == nil || p.data.EncodedLocations != internal.TrustBoundaryNoOp { - p.data = internal.NewNoOpTrustBoundaryData() - } - return p.data, nil - } - - // Check cache for a no-op result from a previous API call. - cachedData := p.data - if cachedData != nil && cachedData.EncodedLocations == internal.TrustBoundaryNoOp { - return cachedData, nil - } - - // Get the endpoint - url, err := p.configProvider.GetTrustBoundaryEndpoint(ctx) - if err != nil { - return nil, fmt.Errorf("trustboundary: error getting the lookup endpoint: %w", err) - } - - // Proceed to fetch new data. - newData, fetchErr := fetchTrustBoundaryData(ctx, p.client, url, token, p.logger) - - if fetchErr != nil { - // Fetch failed. Fallback to cachedData if available. - if cachedData != nil { - return cachedData, nil // Successful fallback - } - // No cache to fallback to. - return nil, fmt.Errorf("trustboundary: failed to fetch trust boundary data for endpoint %s and no cache available: %w", url, fetchErr) - } - - // Fetch successful. Update cache. - p.data = newData - return newData, nil -} - -// GCEConfigProvider implements ConfigProvider for GCE environments. -// It lazily fetches and caches the necessary metadata (service account email, universe domain) -// from the GCE metadata server. -type GCEConfigProvider struct { - // universeDomainProvider provides the universe domain and underlying metadata client. - universeDomainProvider *internal.ComputeUniverseDomainProvider - - // Caching for service account email - saOnce sync.Once - saEmail string - saEmailErr error - - // Caching for universe domain - udOnce sync.Once - ud string - udErr error -} - -// NewGCEConfigProvider creates a new GCEConfigProvider -// which uses the provided gceUDP to interact with the GCE metadata server. -func NewGCEConfigProvider(gceUDP *internal.ComputeUniverseDomainProvider) *GCEConfigProvider { - // The validity of gceUDP and its internal MetadataClient will be checked - // within the GetTrustBoundaryEndpoint and GetUniverseDomain methods. - return &GCEConfigProvider{ - universeDomainProvider: gceUDP, - } -} - -func (g *GCEConfigProvider) fetchSA(ctx context.Context) { - if g.universeDomainProvider == nil || g.universeDomainProvider.MetadataClient == nil { - g.saEmailErr = errors.New("trustboundary: GCEConfigProvider not properly initialized (missing ComputeUniverseDomainProvider or MetadataClient)") - return - } - mdClient := g.universeDomainProvider.MetadataClient - saEmail, err := mdClient.EmailWithContext(ctx, "default") - if err != nil { - g.saEmailErr = fmt.Errorf("trustboundary: GCE config: failed to get service account email: %w", err) - return - } - g.saEmail = saEmail -} - -func (g *GCEConfigProvider) fetchUD(ctx context.Context) { - if g.universeDomainProvider == nil || g.universeDomainProvider.MetadataClient == nil { - g.udErr = errors.New("trustboundary: GCEConfigProvider not properly initialized (missing ComputeUniverseDomainProvider or MetadataClient)") - return - } - ud, err := g.universeDomainProvider.GetProperty(ctx) - if err != nil { - g.udErr = fmt.Errorf("trustboundary: GCE config: failed to get universe domain: %w", err) - return - } - if ud == "" { - ud = internal.DefaultUniverseDomain - } - g.ud = ud -} - -// GetTrustBoundaryEndpoint constructs the trust boundary lookup URL for a GCE environment. -// It uses cached metadata (service account email, universe domain) after the first call. -func (g *GCEConfigProvider) GetTrustBoundaryEndpoint(ctx context.Context) (string, error) { - g.saOnce.Do(func() { g.fetchSA(ctx) }) - if g.saEmailErr != nil { - return "", g.saEmailErr - } - g.udOnce.Do(func() { g.fetchUD(ctx) }) - if g.udErr != nil { - return "", g.udErr - } - return fmt.Sprintf(serviceAccountAllowedLocationsEndpoint, g.ud, g.saEmail), nil -} - -// GetUniverseDomain retrieves the universe domain from the GCE metadata server. -// It uses a cached value after the first call. -func (g *GCEConfigProvider) GetUniverseDomain(ctx context.Context) (string, error) { - g.udOnce.Do(func() { g.fetchUD(ctx) }) - if g.udErr != nil { - return "", g.udErr - } - return g.ud, nil -} diff --git a/vendor/cloud.google.com/go/auth/internal/version.go b/vendor/cloud.google.com/go/auth/internal/version.go index d627069b..39e24f21 100644 --- a/vendor/cloud.google.com/go/auth/internal/version.go +++ b/vendor/cloud.google.com/go/auth/internal/version.go @@ -17,4 +17,4 @@ package internal // Version is the current tagged release of the library. -const Version = "0.20.0" +const Version = "0.24.1" diff --git a/vendor/cloud.google.com/go/auth/oauth2adapt/CHANGES.md b/vendor/cloud.google.com/go/auth/oauth2adapt/CHANGES.md index 42716752..4332fc2a 100644 --- a/vendor/cloud.google.com/go/auth/oauth2adapt/CHANGES.md +++ b/vendor/cloud.google.com/go/auth/oauth2adapt/CHANGES.md @@ -1,4 +1,11 @@ -# Changelog +# Changes + +## [0.3.0](https://github.com/googleapis/google-cloud-go/compare/auth/oauth2adapt/v0.2.8...auth/oauth2adapt/v0.3.0) (2026-09-23) + + +### Features + +* **all:** Update supported go versions ([#20520](https://github.com/googleapis/google-cloud-go/issues/20520)) ([90413d3](https://github.com/googleapis/google-cloud-go/commit/90413d3e9d381ef4b92e3c496d98b023c5b2d8cc)) ## [0.2.8](https://github.com/googleapis/google-cloud-go/compare/auth/oauth2adapt/v0.2.7...auth/oauth2adapt/v0.2.8) (2025-03-17) diff --git a/vendor/cloud.google.com/go/auth/threelegged.go b/vendor/cloud.google.com/go/auth/threelegged.go index 07804dc1..9a9d0265 100644 --- a/vendor/cloud.google.com/go/auth/threelegged.go +++ b/vendor/cloud.google.com/go/auth/threelegged.go @@ -67,6 +67,9 @@ type Options3LO struct { // refreshed. If not set the default value is 3 minutes and 45 seconds. // Optional. EarlyTokenExpiry time.Duration + // DisableAsyncRefresh configures a synchronous workflow that refreshes + // stale tokens while blocking. The default is false. Optional. + DisableAsyncRefresh bool // AuthHandlerOpts provides a set of options for doing a // 3-legged OAuth2 flow with a custom [AuthorizationHandler]. Optional. @@ -192,7 +195,8 @@ func New3LOTokenProvider(opts *Options3LO) (TokenProvider, error) { return new3LOTokenProviderWithAuthHandler(opts), nil } return NewCachedTokenProvider(&tokenProvider3LO{opts: opts, refreshToken: opts.RefreshToken, client: opts.client()}, &CachedTokenProviderOptions{ - ExpireEarly: opts.EarlyTokenExpiry, + ExpireEarly: opts.EarlyTokenExpiry, + DisableAsyncRefresh: opts.DisableAsyncRefresh, }), nil } @@ -211,7 +215,8 @@ type AuthorizationHandlerOptions struct { func new3LOTokenProviderWithAuthHandler(opts *Options3LO) TokenProvider { return NewCachedTokenProvider(&tokenProviderWithHandler{opts: opts, state: opts.AuthHandlerOpts.State}, &CachedTokenProviderOptions{ - ExpireEarly: opts.EarlyTokenExpiry, + ExpireEarly: opts.EarlyTokenExpiry, + DisableAsyncRefresh: opts.DisableAsyncRefresh, }) } diff --git a/vendor/cloud.google.com/go/compute/metadata/.repo-metadata.json b/vendor/cloud.google.com/go/compute/metadata/.repo-metadata.json new file mode 100644 index 00000000..d64bf6cc --- /dev/null +++ b/vendor/cloud.google.com/go/compute/metadata/.repo-metadata.json @@ -0,0 +1,10 @@ +{ + "api_shortname": "compute-metadata", + "client_documentation": "https://cloud.google.com/go/docs/reference/cloud.google.com/go/compute/latest/metadata", + "client_library_type": "manual", + "description": "Service Metadata API", + "distribution_name": "cloud.google.com/go/compute/metadata", + "language": "go", + "library_type": "CORE", + "release_level": "stable" +} \ No newline at end of file diff --git a/vendor/cloud.google.com/go/compute/metadata/CHANGES.md b/vendor/cloud.google.com/go/compute/metadata/CHANGES.md index e384683c..f03d5cd3 100644 --- a/vendor/cloud.google.com/go/compute/metadata/CHANGES.md +++ b/vendor/cloud.google.com/go/compute/metadata/CHANGES.md @@ -1,5 +1,19 @@ # Changes +## [0.10.0](https://github.com/googleapis/google-cloud-go/compare/compute/metadata/v0.9.1...compute/metadata/v0.10.0) (2026-09-23) + + +### Features + +* **all:** Update supported go versions ([#20520](https://github.com/googleapis/google-cloud-go/issues/20520)) ([90413d3](https://github.com/googleapis/google-cloud-go/commit/90413d3e9d381ef4b92e3c496d98b023c5b2d8cc)) + +## [0.9.1](https://github.com/googleapis/google-cloud-go/compare/compute/metadata/v0.9.0...compute/metadata/v0.9.1) (2026-09-17) + + +### Bug Fixes + +* **compute/metadata:** Timeout initial metadata subscriber GET request ([#20488](https://github.com/googleapis/google-cloud-go/issues/20488)) ([f06f6b3](https://github.com/googleapis/google-cloud-go/commit/f06f6b35e4b7ae8b48a3f9d1715229fe81cb2ebd)), refs [#20487](https://github.com/googleapis/google-cloud-go/issues/20487) + ## [0.9.0](https://github.com/googleapis/google-cloud-go/compare/compute/metadata/v0.8.4...compute/metadata/v0.9.0) (2025-09-24) diff --git a/vendor/cloud.google.com/go/compute/metadata/metadata.go b/vendor/cloud.google.com/go/compute/metadata/metadata.go index 6bd18916..918231e3 100644 --- a/vendor/cloud.google.com/go/compute/metadata/metadata.go +++ b/vendor/cloud.google.com/go/compute/metadata/metadata.go @@ -889,7 +889,9 @@ func (c *Client) SubscribeWithContext(ctx context.Context, suffix string, fn fun const failedSubscribeSleep = time.Second * 5 // First check to see if the metadata value exists at all. - val, lastETag, err := c.getETagWithSubClient(ctx, suffix, true) + initCtx, cancel := context.WithTimeout(ctx, 5*time.Second) + val, lastETag, err := c.getETagWithSubClient(initCtx, suffix, true) + cancel() if err != nil { return err } diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md index fa477145..8cda72f5 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md @@ -1,5 +1,61 @@ # Release History +## 1.23.3 (2026-10-06) + +### Bugs Fixed + +* Fixed `arm.ResourceID.Location` being empty when the `locations` segment uses different casing. + +### Other Changes + +* Added `azure-deprecating` to the default set of allowed (non-redacted) response headers for logging. +* Replaced internal default HTTP client with the one from `sdk/internal`. + +## 1.23.2 (2026-09-28) + +### Bugs Fixed + +* Fixed unmarshalling `datetime.RFC7231` to use a fixed `GMT` zone. + +## 1.23.1 (2026-08-27) + +### Other Changes + +* Upgraded dependencies. + +## 1.23.0 (2026-08-11) + +### Features Added + +* Helper method `runtime.NewRequestForNextLink` for creating requests for pageable operations that uses a next link. It handles absolute and relative next links. + +### Bugs Fixed + +* Fixed an issue where `runtime.Pager[T].More` could return `true` indefinitely after `NextPage` failed to retrieve the first page, causing `for pager.More()` loops to spin. After a page fetch returns an error the `Pager` now enters a terminal state: `More` returns `false` and subsequent `NextPage` calls return the same error without invoking the fetcher again. + +## 1.22.0 (2026-06-04) + +### Features Added + +* Added type `datetime.RFC7231` for date/time values in RFC 1123 format with a fixed GMT timezone. + +### Other Changes + +* Upgraded dependencies. + +## 1.21.1 (2026-04-16) + +### Bugs Fixed + +* Fixed an issue in `ResponseError.Error()` where the request URL path was being logged unescaped. +* Redact query parameters when logging errors. +* For `runtime.JoinPaths`, don't add a slash between root and paths when `paths` starts with `?` (query string). + +### Other Changes + +* Upgraded to Go 1.25.0. +* Upgraded dependencies. + ## 1.21.0 (2026-01-12) ### Features Added diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/internal/resource/resource_identifier.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/internal/resource/resource_identifier.go index c602e77d..4b4aa1fb 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/internal/resource/resource_identifier.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/internal/resource/resource_identifier.go @@ -141,7 +141,7 @@ func (id *ResourceID) init(parent *ResourceID, resourceType ResourceType, name s id.SubscriptionID = name } - if resourceType.lastType() == locationsKey { + if strings.EqualFold(resourceType.lastType(), locationsKey) { id.Location = name } diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/ci.yml b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/ci.yml index b81b6210..5807f6b6 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/ci.yml +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/ci.yml @@ -3,7 +3,6 @@ trigger: branches: include: - main - - feature/* - hotfix/* - release/* paths: diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/doc.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/doc.go index 4862a9f6..299ed5e3 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/doc.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/doc.go @@ -190,7 +190,10 @@ and determining if there are more pages to fetch. No IO calls are made until th pager := widgetClient.NewListWidgetsPager(nil) for pager.More() { page, err := pager.NextPage(context.TODO()) - // handle err + if err != nil { + // process error + break + } for _, widget := range page.Values { // process widget } diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/request.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/request.go index 4bf72263..2df0c7a9 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/request.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/request.go @@ -11,8 +11,11 @@ import ( "fmt" "io" "net/http" + "net/url" + "path" "reflect" "strconv" + "strings" "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared" ) @@ -119,6 +122,26 @@ func NewRequest(ctx context.Context, httpMethod string, endpoint string) (*Reque return &Request{req: req, values: opValues{}}, nil } +// NewRequestForNextLink creates a new policy.Request with the specified input. +// This helper is for use in paged operations that use the "next link" pattern. +// - endpoint is the service endpoint (e.g. https://contoso.com) +// - nextLink the absolute or relative URL to the next page of items +// +// When nextLink is an absolute URL, its value is used to create the request to the next page. +// If nextLink is a relative URL, it will be joined with the specified endpoint. +// +// Exported as runtime.NewRequestForNextLink(). +func NewRequestForNextLink(ctx context.Context, httpMethod, endpoint, nextLink string) (*Request, error) { + nextLink, err := EncodeQueryParams(nextLink, true) + if err != nil { + return nil, err + } + if !hasScheme(nextLink) { + nextLink = JoinPaths(endpoint, nextLink) + } + return NewRequest(ctx, httpMethod, nextLink) +} + // Body returns the original body specified when the Request was created. func (req *Request) Body() io.ReadSeekCloser { return req.body @@ -257,3 +280,89 @@ func SetBody(req *Request, body io.ReadSeekCloser, contentType string, clobberCo } return nil } + +// JoinPaths concatenates multiple URL path segments into one path, +// inserting path separation characters as required. JoinPaths will preserve +// query parameters in the root path. +// Exported as runtime.JoinPaths +func JoinPaths(root string, paths ...string) string { + if len(paths) == 0 { + return root + } + + qps := "" + if strings.Contains(root, "?") { + splitPath := strings.Split(root, "?") + root, qps = splitPath[0], splitPath[1] + } + + p := path.Join(paths...) + // path.Join will remove any trailing slashes. + // if one was provided, preserve it. + if strings.HasSuffix(paths[len(paths)-1], "/") && !strings.HasSuffix(p, "/") { + p += "/" + } + + if qps != "" { + if strings.Contains(p, "?") { + p = p + "&" + qps + } else { + p = p + "?" + qps + } + } + + if strings.HasSuffix(root, "/") && strings.HasPrefix(p, "/") { + root = root[:len(root)-1] + } else if !strings.HasSuffix(root, "/") && !strings.HasPrefix(p, "/") && !strings.HasPrefix(p, "?") { + p = "/" + p + } + return root + p +} + +// EncodeQueryParams will parse and encode any query parameters in the specified URL. +// Any semicolons will automatically be escaped. +// When encodeSpaces is true all spaces that were form-encoded to + are replaced with %20. +// Exported as runtime.EncodeQueryParams +func EncodeQueryParams(u string, encodeSpaces bool) (string, error) { + before, after, found := strings.Cut(u, "?") + if !found { + return u, nil + } + // starting in Go 1.17, url.ParseQuery will reject semicolons in query params. + // so, we must escape them first. note that this assumes that semicolons aren't + // being used as query param separators which is per the current RFC. + // for more info: + // https://github.com/golang/go/issues/25192 + // https://github.com/golang/go/issues/50034 + qp, err := url.ParseQuery(strings.ReplaceAll(after, ";", "%3B")) + if err != nil { + return "", err + } + encoded := qp.Encode() + if encodeSpaces { + encoded = strings.ReplaceAll(encoded, "+", "%20") + } + return before + "?" + encoded, nil +} + +// hasScheme reports whether s begins with a URI scheme, i.e. is an absolute URI. +// Per RFC 3986: scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) ":". +// This avoids the allocations of url.Parse when we only need to know if the URI is absolute. +func hasScheme(s string) bool { + for i := 0; i < len(s); i++ { + c := s[i] + switch { + case c >= 'a' && c <= 'z', c >= 'A' && c <= 'Z': + // always valid + case c == ':': + return i > 0 + case i == 0: + return false + case c >= '0' && c <= '9', c == '+', c == '-', c == '.': + // valid after the first character + default: + return false + } + } + return false +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/response_error.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/response_error.go index ef0635bb..8246b6a5 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/response_error.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/response_error.go @@ -131,7 +131,7 @@ func (e *ResponseError) Error() string { msg := &bytes.Buffer{} if e.RawResponse != 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.EscapedPath()) } else { fmt.Fprintln(msg, "Request information not available") } diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go index 213202e3..bfbea747 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go @@ -37,5 +37,5 @@ const ( Module = "azcore" // Version is the semantic version (see http://semver.org) of this module. - Version = "v1.21.0" + Version = "v1.23.3" ) diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pager.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pager.go index 743513be..a05b0c34 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pager.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pager.go @@ -35,6 +35,9 @@ type Pager[T any] struct { handler PagingHandler[T] tracer tracing.Tracer firstPage bool + // fetchErr is set when Fetcher returns an error, placing the Pager in a + // terminal state so that More returns false. + fetchErr error } // NewPager creates an instance of Pager using the specified PagingHandler. @@ -48,7 +51,16 @@ func NewPager[T any](handler PagingHandler[T]) *Pager[T] { } // More returns true if there are more pages to retrieve. +// +// If a prior call to [Pager.NextPage] returned an error while fetching a page, +// the Pager enters a terminal state and More returns false so that a for loop +// over the pager terminates instead of retrying indefinitely. func (p *Pager[T]) More() bool { + // a failed fetch puts the Pager in a terminal state; there are no more pages + // to retrieve regardless of whether it was the first or a subsequent page. + if p.fetchErr != nil { + return false + } if p.current != nil { return p.handler.More(*p.current) } @@ -56,7 +68,17 @@ func (p *Pager[T]) More() bool { } // NextPage advances the pager to the next page. +// +// If fetching the page returns an error, the Pager enters a terminal state: +// [Pager.More] returns false and every subsequent call to NextPage returns the +// same error without invoking the fetcher again. func (p *Pager[T]) NextPage(ctx context.Context) (T, error) { + if p.fetchErr != nil { + // a prior fetch failed; the Pager is in a terminal state. return the + // stored error rather than re-invoking the fetcher, which may not be + // safe to retry (e.g. stateful handlers that latch into a done state). + return *new(T), p.fetchErr + } if p.current != nil { if p.firstPage { // we get here if it's an LRO-pager, we already have the first page @@ -76,6 +98,7 @@ func (p *Pager[T]) NextPage(ctx context.Context) (T, error) { resp, err := p.handler.Fetcher(ctx, p.current) if err != nil { + p.fetchErr = err return *new(T), err } p.current = &resp diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pipeline.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pipeline.go index 3d95fe30..b93c9c36 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pipeline.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pipeline.go @@ -6,6 +6,7 @@ package runtime import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported" "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + azt "github.com/Azure/azure-sdk-for-go/sdk/internal/transport" ) // PipelineOptions contains Pipeline options for SDK developers @@ -85,7 +86,7 @@ func NewPipeline(module, version string, plOpts PipelineOptions, options *policy policies = append(policies, exported.PolicyFunc(bodyDownloadPolicy)) transport := cp.Transport if transport == nil { - transport = defaultHTTPClient + transport = azt.DefaultHTTPClient } return exported.NewPipeline(transport, policies...) } diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_bearer_token.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_bearer_token.go index 547e5a32..f204a19c 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_bearer_token.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_bearer_token.go @@ -182,7 +182,7 @@ func (b *BearerTokenPolicy) handleChallenge(req *policy.Request, res *http.Respo func checkHTTPSForAuth(req *policy.Request, allowHTTP bool) error { if strings.ToLower(req.Raw().URL.Scheme) != "https" && !allowHTTP { - return errorinfo.NonRetriableError(errors.New("authenticated requests are not permitted for non TLS protected (https) endpoints")) + return errorinfo.NonRetriableError(errors.New("authorized requests are not permitted for non-TLS protected (https) endpoints")) } return nil } diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_http_trace.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_http_trace.go index ddf9ede0..7017d5e1 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_http_trace.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_http_trace.go @@ -5,10 +5,8 @@ package runtime import ( "context" - "errors" "fmt" "net/http" - "net/url" "strings" "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported" @@ -73,14 +71,7 @@ func (h *httpTracePolicy) Do(req *policy.Request) (resp *http.Response, err erro span.SetAttributes(tracing.Attribute{Key: attrAZServiceReqID, Value: reqID}) } } else if err != nil { - var urlErr *url.Error - if errors.As(err, &urlErr) { - // calling *url.Error.Error() will include the unsanitized URL - // which we don't want. in addition, we already have the HTTP verb - // and sanitized URL in the trace so we aren't losing any info - err = urlErr.Err - } - span.SetStatus(tracing.SpanStatusError, err.Error()) + span.SetStatus(tracing.SpanStatusError, getSanitizedURLString(err.Error(), req.Raw().URL, h.allowedQP)) } span.End() }() diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_logging.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_logging.go index dd59fbc9..61ba383a 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_logging.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_logging.go @@ -34,6 +34,7 @@ func NewLogPolicy(o *policy.LogOptions) policy.Policy { // construct default hash set of allowed headers allowedHeaders := map[string]struct{}{ "accept": {}, + "azure-deprecating": {}, "cache-control": {}, "connection": {}, "content-length": {}, @@ -158,6 +159,27 @@ func getSanitizedURL(u url.URL, allowedQueryParams map[string]struct{}) string { return u.String() } +// getSanitizedURLString returns s with the query params of u redacted. +// if s doesn't contain u, then s is returned unchanged. +func getSanitizedURLString(s string, u *url.URL, allowedQueryParams map[string]struct{}) string { + if u.RawQuery == "" { + // the URL doesn't have any query params, so nothing to redact + return s + } + + urlIndex := strings.Index(strings.ToLower(s), strings.ToLower(u.String())) + if urlIndex < 0 { + // the URL isn't in the string, so nothing to redact + return s + } + + // replace the unsanitized URL in the error message with the sanitized version + sanitizedURL := getSanitizedURL(*u, allowedQueryParams) + s = s[:urlIndex] + sanitizedURL + s[urlIndex+len(u.String()):] + + return s +} + // writeRequestWithResponse appends a formatted HTTP request into a Buffer. If request and/or err are // not nil, then these are also written into the Buffer. func (p *logPolicy) writeRequestWithResponse(b *bytes.Buffer, req *policy.Request, resp *http.Response, err error) { @@ -171,7 +193,7 @@ func (p *logPolicy) writeRequestWithResponse(b *bytes.Buffer, req *policy.Reques } if err != nil { fmt.Fprintln(b, " --------------------------------------------------------------------------------") - fmt.Fprint(b, " ERROR:\n"+err.Error()+"\n") + fmt.Fprint(b, " ERROR:\n"+getSanitizedURLString(err.Error(), req.Raw().URL, p.allowedQP)+"\n") } } diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_retry.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_retry.go index 696e1d9f..50c86791 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_retry.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_retry.go @@ -115,7 +115,8 @@ func (p *retryPolicy) Do(req *policy.Request) (resp *http.Response, err error) { // do this outside the for loop so defers don't accumulate. rwbody = &retryableRequestBody{body: req.Body()} defer func() { - // TODO: https://github.com/Azure/azure-sdk-for-go/issues/25649 + // Match net/http behavior: after a request has produced either a response + // or a transport error, request body close errors are not surfaced to callers. _ = rwbody.realClose() }() } diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/request.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/request.go index df7826b7..20ec6511 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/request.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/request.go @@ -14,8 +14,6 @@ import ( "mime/multipart" "net/http" "net/textproto" - "net/url" - "path" "strings" "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported" @@ -43,6 +41,17 @@ func NewRequest(ctx context.Context, httpMethod string, endpoint string) (*polic return exported.NewRequest(ctx, httpMethod, endpoint) } +// NewRequestForNextLink creates a new policy.Request with the specified input. +// This helper is for use in paged operations that use the "next link" pattern. +// - endpoint is the service endpoint (e.g. https://contoso.com) +// - nextLink the absolute or relative URL to the next page of items +// +// When nextLink is an absolute URL, its value is used to create the request to the next page. +// If nextLink is a relative URL, it will be joined with the specified endpoint. +func NewRequestForNextLink(ctx context.Context, httpMethod, endpoint, nextLink string) (*policy.Request, error) { + return exported.NewRequestForNextLink(ctx, httpMethod, endpoint, nextLink) +} + // NewRequestFromRequest creates a new policy.Request with an existing *http.Request func NewRequestFromRequest(req *http.Request) (*policy.Request, error) { return exported.NewRequestFromRequest(req) @@ -51,54 +60,14 @@ func NewRequestFromRequest(req *http.Request) (*policy.Request, error) { // EncodeQueryParams will parse and encode any query parameters in the specified URL. // Any semicolons will automatically be escaped. func EncodeQueryParams(u string) (string, error) { - before, after, found := strings.Cut(u, "?") - if !found { - return u, nil - } - // starting in Go 1.17, url.ParseQuery will reject semicolons in query params. - // so, we must escape them first. note that this assumes that semicolons aren't - // being used as query param separators which is per the current RFC. - // for more info: - // https://github.com/golang/go/issues/25192 - // https://github.com/golang/go/issues/50034 - qp, err := url.ParseQuery(strings.ReplaceAll(after, ";", "%3B")) - if err != nil { - return "", err - } - return before + "?" + qp.Encode(), nil + return exported.EncodeQueryParams(u, false) } // JoinPaths concatenates multiple URL path segments into one path, // inserting path separation characters as required. JoinPaths will preserve // query parameters in the root path func JoinPaths(root string, paths ...string) string { - if len(paths) == 0 { - return root - } - - qps := "" - if strings.Contains(root, "?") { - splitPath := strings.Split(root, "?") - root, qps = splitPath[0], splitPath[1] - } - - p := path.Join(paths...) - // path.Join will remove any trailing slashes. - // if one was provided, preserve it. - if strings.HasSuffix(paths[len(paths)-1], "/") && !strings.HasSuffix(p, "/") { - p += "/" - } - - if qps != "" { - p = p + "?" + qps - } - - if strings.HasSuffix(root, "/") && strings.HasPrefix(p, "/") { - root = root[:len(root)-1] - } else if !strings.HasSuffix(root, "/") && !strings.HasPrefix(p, "/") { - p = "/" + p - } - return root + p + return exported.JoinPaths(root, paths...) } // EncodeByteArray will base-64 encode the byte slice v. diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/BREAKING_CHANGES.md b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/BREAKING_CHANGES.md index 567e6975..a7551e49 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/BREAKING_CHANGES.md +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/BREAKING_CHANGES.md @@ -1,11 +1,22 @@ # Breaking Changes +## v1.15.0 + +### Service Fabric transport requirements + +`ManagedIdentityCredential` now requires a transport that supports the Service Fabric endpoint's +certificate pinning. Applications with a custom `ClientOptions.Transport` must provide an +`*http.Client` whose Transport is `nil` or a standard `*http.Transport` without custom TLS dialing +or verification callbacks. Unsupported transports cause credential construction to fail. +Leave `ClientOptions.Transport` `nil` to use the default transport. The credential derives the +pinned client without modifying a caller-supplied client and rejects redirects. + ## v1.8.0 ### New errors from `NewManagedIdentityCredential` in some environments `NewManagedIdentityCredential` now returns an error when `ManagedIdentityCredentialOptions.ID` is set in a hosting environment whose managed identity API doesn't support user-assigned identities. `ManagedIdentityCredential.GetToken()` formerly logged a warning in these cases. Returning an error instead prevents the credential authenticating an unexpected identity. The affected hosting environments are: - * Azure Arc + * Azure Arc (user-assigned identities are supported starting in v1.15.0 when the agent supports them) * Azure ML (when a resource or object ID is specified; client IDs are supported) * Cloud Shell * Service Fabric diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md index 4a6349e1..ce7aff7e 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md @@ -1,11 +1,87 @@ # Release History +## 1.15.0 (2026-10-14) + +### Features Added + +- `ManagedIdentityCredential` and `DefaultAzureCredential` support user-assigned managed identities + on Azure Arc when the agent supports them +- `WorkloadIdentityCredential` supports identity binding mode via `WorkloadIdentityCredentialOptions.EnableAzureProxy` + +### Bugs Fixed + +- `ManagedIdentityCredential` verifies the Service Fabric endpoint's certificate against + `IDENTITY_SERVER_THUMBPRINT` and rejects redirects + +### Other Changes + +- On Service Fabric, a custom `ClientOptions.Transport` must be an `*http.Client` with a `nil` + Transport or a standard `*http.Transport` without custom TLS dialing or verification callbacks. + Unsupported transports now cause credential construction to fail +- Upgraded dependencies + +## 1.14.1 (2026-08-27) + +### Other Changes + +- Upgraded dependencies + +## 1.14.0 (2026-06-15) + +### Breaking Changes + +> These changes affect only code written against a beta version such as v1.14.0-beta.3 +- Removed `WorkloadIdentityCredentialOptions.EnableAzureProxy`. + It will return in v1.15.0-beta.1 + +### Bugs Fixed + +- `AzureDeveloperCLICredential` improved reporting of error messages returned from `azd` + +### Other Changes + +- Returned `azidentity` errors include links to the troubleshooting guide when appropriate +- This module now requires a minimum Go version of 1.25 +- Upgraded dependencies + +## 1.14.0-beta.3 (2026-02-10) + +### Breaking Changes + +> These changes affect only code written against a beta version such as v1.14.0-beta.2 +- Renamed `WorkloadIdentityCredentialOptions.EnableAzureTokenProxy` to `EnableAzureProxy` + +### Other Changes + +- Removed extraneous JSON from `AzureDeveloperCLICredential` errors + +## 1.14.0-beta.2 (2025-11-10) + +### Breaking Changes + +> These changes affect only code written against a beta version such as v1.13.0-beta.1 +- `WorkloadIdentityCredential` identity binding mode is disabled by default. To enable it, set + `WorkloadIdentityCredentialOptions.EnableAzureTokenProxy` to `true` +- Removed identity binding mode support from `DefaultAzureCredential`. To use this feature, use + `WorkloadIdentityCredential` directly instead and set + `WorkloadIdentityCredentialOptions.EnableAzureTokenProxy` to `true` + +### Bugs Fixed + +- `AzureCLICredential` quoted arguments incorrectly on Windows + ## 1.13.1 (2025-11-10) ### Bugs Fixed - `AzureCLICredential` quoted arguments incorrectly on Windows +## 1.14.0-beta.1 (2025-10-07) + +### Features Added + +- Restored the `WorkloadIdentityCredential` identity binding mode support removed in v1.13.0 + ## 1.13.0 (2025-10-07) ### Features Added diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/README.md b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/README.md index 127c25b7..2abfccfa 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/README.md +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/README.md @@ -68,6 +68,25 @@ in any hosting environment which supports managed identities, such as (this list * [Azure Service Fabric](https://learn.microsoft.com/azure/service-fabric/concepts-managed-identity) * [Azure Virtual Machines](https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/how-to-use-vm-token) +### Azure Arc user-assigned identities + +On Azure Arc, `ManagedIdentityCredential` supports selecting a user-assigned identity by client, +object, or resource ID through `ManagedIdentityCredentialOptions.ID`. `DefaultAzureCredential` +supports selecting one by client ID through the `AZURE_CLIENT_ID` environment variable. +The Azure Arc agent must support user-assigned +identities and confirm the requested identity in its token response. Otherwise, token acquisition +fails rather than authenticating the machine's system-assigned identity. + +### Service Fabric transport requirements + +On Service Fabric, `ManagedIdentityCredential` pins the endpoint certificate to +`IDENTITY_SERVER_THUMBPRINT` and rejects redirects. Leave `ClientOptions.Transport` `nil` to use +the default transport. A custom transport must be an `*http.Client` whose `Transport` is `nil` or +an `*http.Transport` without custom TLS dialing or verification callbacks. The credential derives +the pinned client without modifying the caller's client. Unsupported transports cause credential +construction to fail. See the [troubleshooting guide](https://aka.ms/azsdk/go/identity/troubleshoot#azure-service-fabric-managed-identity) +for configuration errors. + ## Examples - [Authenticate with DefaultAzureCredential](#authenticate-with-defaultazurecredential "Authenticate with DefaultAzureCredential") @@ -244,5 +263,3 @@ additional questions or comments. [ctc_overview]: https://aka.ms/azsdk/go/identity/credential-chains#chainedtokencredential-overview [dac_overview]: https://aka.ms/azsdk/go/identity/credential-chains#defaultazurecredential-overview - - diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md index 517006a4..82c2ba7b 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md @@ -20,6 +20,8 @@ This troubleshooting guide covers failure investigation techniques, common error - [Troubleshoot ManagedIdentityCredential authentication issues](#troubleshoot-managedidentitycredential-authentication-issues) - [Azure App Service and Azure Functions managed identity](#azure-app-service-and-azure-functions-managed-identity) - [Azure Virtual Machine managed identity](#azure-virtual-machine-managed-identity) + - [Azure Arc managed identity](#azure-arc-managed-identity) + - [Azure Service Fabric managed identity](#azure-service-fabric-managed-identity) - [Troubleshoot WorkloadIdentityCredential authentication issues](#troubleshoot-workloadidentitycredential-authentication-issues) - [Get additional help](#get-additional-help) @@ -83,7 +85,7 @@ azlog.SetEvents(azidentity.EventAuthentication) | Error |Description| Mitigation | |---|---|---| -|"DefaultAzureCredential failed to acquire a token"|No credential in the `DefaultAzureCredential` chain provided a token|