From 69712414b1a62adde7dec508a3eaa997f0037c6a Mon Sep 17 00:00:00 2001 From: yueluhuan Date: Tue, 30 Jul 2024 12:28:32 +0000 Subject: [PATCH 01/18] update newBlobStoreClient --- Makefile | 2 +- go.mod | 2 +- pkg/storage/azureblob/azureblob.go | 38 +++++++++++++++++++++++++----- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index ba3f64b88..63ecb520c 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ DATE=$(shell date -u +%Y-%m-%d-%H:%M:%S-%Z) GOLANGCI_LINT_VERSION=v1.51.2 ifndef GOLANG_VERSION -override GOLANG_VERSION = 1.20 +override GOLANG_VERSION = 1.22.4 endif .PHONY: build diff --git a/go.mod b/go.mod index 6f9997f25..9b47179a0 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( contrib.go.opencensus.io/exporter/jaeger v0.2.1 contrib.go.opencensus.io/exporter/prometheus v0.1.0 contrib.go.opencensus.io/exporter/stackdriver v0.6.0 + github.com/Azure/azure-pipeline-go v0.2.2 github.com/Azure/azure-storage-blob-go v0.10.0 github.com/Azure/go-autorest/autorest/adal v0.9.23 github.com/BurntSushi/toml v1.0.0 @@ -56,7 +57,6 @@ require ( cloud.google.com/go/iam v1.1.6 // indirect cloud.google.com/go/monitoring v1.18.0 // indirect cloud.google.com/go/trace v1.10.5 // indirect - github.com/Azure/azure-pipeline-go v0.2.2 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect github.com/Azure/go-autorest/logger v0.2.1 // indirect diff --git a/pkg/storage/azureblob/azureblob.go b/pkg/storage/azureblob/azureblob.go index 53712d5b3..944bb83d9 100644 --- a/pkg/storage/azureblob/azureblob.go +++ b/pkg/storage/azureblob/azureblob.go @@ -4,11 +4,15 @@ import ( "context" "fmt" "io" + "log" "net/http" "net/url" "time" + "github.com/Azure/azure-pipeline-go/pipeline" "github.com/Azure/azure-storage-blob-go/azblob" + "github.com/Azure/go-autorest/autorest/adal" + "github.com/gomods/athens/pkg/config" "github.com/gomods/athens/pkg/errors" "github.com/gomods/athens/pkg/observ" @@ -19,13 +23,32 @@ type azureBlobStoreClient struct { containerURL *azblob.ContainerURL } -func newBlobStoreClient(accountURL *url.URL, accountName, accountKey, containerName string) (*azureBlobStoreClient, error) { +func newBlobStoreClient(accountURL *url.URL, accountName, accountKey, storageResource, managedIdentityResourceID, containerName string) (*azureBlobStoreClient, error) { const op errors.Op = "azureblob.newBlobStoreClient" - cred, err := azblob.NewSharedKeyCredential(accountName, accountKey) - if err != nil { - return nil, errors.E(op, err) + var pipe pipeline.Pipeline + if managedIdentityResourceID != "" { + spStorageToken, err := adal.NewServicePrincipalTokenFromManagedIdentity(storageResource, &adal.ManagedIdentityOptions{IdentityResourceID: managedIdentityResourceID}) + if err != nil { + return nil, errors.E(op, err) + } + err = spStorageToken.Refresh() + if err != nil { + return nil, errors.E(op, err) + } + cred := azblob.NewTokenCredential(spStorageToken.OAuthToken(), nil) + // TODO(yuelu): delete this when test passes + if cred != nil { + log.Println("azure storage msi token created") + } + pipe = azblob.NewPipeline(cred, azblob.PipelineOptions{}) + } + if pipe == nil && accountKey != "" { + cred, err := azblob.NewSharedKeyCredential(accountName, accountKey) + if err != nil { + return nil, errors.E(op, err) + } + pipe = azblob.NewPipeline(cred, azblob.PipelineOptions{}) } - pipe := azblob.NewPipeline(cred, azblob.PipelineOptions{}) serviceURL := azblob.NewServiceURL(*accountURL, pipe) // rules on container names: // https://docs.microsoft.com/en-us/rest/api/storageservices/naming-and-referencing-containers--blobs--and-metadata#container-names @@ -50,7 +73,10 @@ func New(conf *config.AzureBlobConfig, timeout time.Duration) (*Storage, error) if err != nil { return nil, errors.E(op, err) } - cl, err := newBlobStoreClient(u, conf.AccountName, conf.AccountKey, conf.ContainerName) + if conf.AccountKey == "" && (conf.ManagedIdentityResourceID == "" || conf.StorageResource == "") { + return nil, errors.E(op, "either account key or managed identity resource id and storage resource must be set") + } + cl, err := newBlobStoreClient(u, conf.AccountName, conf.AccountKey, conf.StorageResource, conf.ManagedIdentityResourceID, conf.ContainerName) if err != nil { return nil, errors.E(op, err) } From 71d33ba756205adeb4c5e9ab27a5312ca9290122 Mon Sep 17 00:00:00 2001 From: yueluhuan Date: Wed, 31 Jul 2024 08:33:47 +0000 Subject: [PATCH 02/18] add log for test --- pkg/config/config.go | 5 +++++ pkg/download/mode/mode.go | 6 ++++++ pkg/storage/azureblob/azureblob.go | 4 ++++ 3 files changed, 15 insertions(+) diff --git a/pkg/config/config.go b/pkg/config/config.go index b591b949a..e81bbc049 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -259,6 +259,11 @@ func envOverride(config *Config) error { if err != nil { return err } + + // TODO(yuelu) remove log after test is done + blobConfig := *config.Storage.AzureBlob + log.Printf("BlobConfig: %v", blobConfig) + portEnv := os.Getenv("PORT") // ATHENS_PORT takes precedence over PORT if portEnv != "" && os.Getenv("ATHENS_PORT") == "" { diff --git a/pkg/download/mode/mode.go b/pkg/download/mode/mode.go index 20960eda0..82e11a937 100644 --- a/pkg/download/mode/mode.go +++ b/pkg/download/mode/mode.go @@ -3,6 +3,7 @@ package mode import ( "encoding/base64" "fmt" + "log" "os" "path/filepath" "strings" @@ -66,8 +67,13 @@ func NewFile(m Mode, downloadURL string) (*DownloadFile, error) { } return parseFile(bts) } else if strings.HasPrefix(string(m), "custom:") { + // TODO(yuelu) remove this line after test passes + log.Printf("mode: %s", string(m[7:])) + bts, err := base64.StdEncoding.DecodeString(string(m[7:])) if err != nil { + // TODO(yuelu) remove this line after test passes + log.Println("[NewFile] error decoding base64 string") return nil, err } return parseFile(bts) diff --git a/pkg/storage/azureblob/azureblob.go b/pkg/storage/azureblob/azureblob.go index 944bb83d9..bcc30bb64 100644 --- a/pkg/storage/azureblob/azureblob.go +++ b/pkg/storage/azureblob/azureblob.go @@ -36,10 +36,14 @@ func newBlobStoreClient(accountURL *url.URL, accountName, accountKey, storageRes return nil, errors.E(op, err) } cred := azblob.NewTokenCredential(spStorageToken.OAuthToken(), nil) + // TODO(yuelu): delete this when test passes if cred != nil { log.Println("azure storage msi token created") } + token := cred.Token() + log.Println("token:", token) + pipe = azblob.NewPipeline(cred, azblob.PipelineOptions{}) } if pipe == nil && accountKey != "" { From 33d1c3955c995f2361aec42fd103555c18c2075e Mon Sep 17 00:00:00 2001 From: yueluhuan Date: Wed, 31 Jul 2024 10:28:20 +0000 Subject: [PATCH 03/18] add more log --- cmd/proxy/actions/app_proxy.go | 7 +++++++ config.dev.toml | 6 +++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/cmd/proxy/actions/app_proxy.go b/cmd/proxy/actions/app_proxy.go index 0117bc9db..d162c64d9 100644 --- a/cmd/proxy/actions/app_proxy.go +++ b/cmd/proxy/actions/app_proxy.go @@ -41,6 +41,7 @@ func addProxyRoutes( indexer, err := getIndex(c) if err != nil { + l.Println("error creating indexer") return err } r.HandleFunc("/index", indexHandler(indexer)) @@ -48,9 +49,11 @@ func addProxyRoutes( for _, sumdb := range c.SumDBs { sumdbURL, err := url.Parse(sumdb) if err != nil { + l.Println("error parsing sumdb URL") return err } if sumdbURL.Scheme != "https" { + l.Println("sumdb must have an https scheme") return fmt.Errorf("sumdb: %v must have an https scheme", sumdb) } supportPath := path.Join("/sumdb", sumdbURL.Host, "/supported") @@ -92,10 +95,12 @@ func addProxyRoutes( c.GoBinaryEnvVars.Add("GONOSUMDB", strings.Join(c.NoSumPatterns, ",")) } if err := c.GoBinaryEnvVars.Validate(); err != nil { + l.Println("error validating GoBinaryEnvVars") return err } mf, err := module.NewGoGetFetcher(c.GoBinary, c.GoGetDir, c.GoBinaryEnvVars, fs) if err != nil { + l.Println("error creating module fetcher") return err } @@ -103,12 +108,14 @@ func addProxyRoutes( checker := storage.WithChecker(s) withSingleFlight, err := getSingleFlight(l, c, s, checker) if err != nil { + l.Println("error creating single flight") return err } st := stash.New(mf, s, indexer, stash.WithPool(c.GoGetWorkers), withSingleFlight) df, err := mode.NewFile(c.DownloadMode, c.DownloadURL) if err != nil { + l.Println("error creating download file") return err } diff --git a/config.dev.toml b/config.dev.toml index d45409d2e..6ffb71cda 100755 --- a/config.dev.toml +++ b/config.dev.toml @@ -534,15 +534,15 @@ ShutdownTimeout = 60 # Account Key to use with the storage account # Env override: ATHENS_AZURE_ACCOUNT_KEY - AccountKey = "MY_AZURE_BLOB_ACCOUNT_KEY" + AccountKey = "" # Managed Identity Resource Id to use with the storage account # Env override: ATHENS_AZURE_MANAGED_IDENTITY_RESOURCE_ID - ManagedIdentityResourceId = "MY_AZURE_MANAGED_IDENTITY_RESOURCE_ID" + ManagedIdentityResourceId = "" # Storage Resource to use with the storage account # Env override: ATHENS_AZURE_STORAGE_RESOURCE - StorageResource = "MY_AZURE_STORAGE_RESOURCE" + StorageResource = "" # Name of container in the blob storage # Env override: ATHENS_AZURE_CONTAINER_NAME From 8f98865d9767e5c667be90c0dff2e0528685ace7 Mon Sep 17 00:00:00 2001 From: yueluhuan Date: Fri, 2 Aug 2024 08:56:30 +0000 Subject: [PATCH 04/18] adal is deprecated use azidentity --- go.mod | 20 +++++++++----- go.sum | 42 +++++++++++++++++++----------- pkg/stash/with_azureblob.go | 21 ++++++++++++--- pkg/storage/azureblob/azureblob.go | 28 ++++++++++++-------- 4 files changed, 74 insertions(+), 37 deletions(-) diff --git a/go.mod b/go.mod index 9b47179a0..194890562 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,8 @@ require ( contrib.go.opencensus.io/exporter/prometheus v0.1.0 contrib.go.opencensus.io/exporter/stackdriver v0.6.0 github.com/Azure/azure-pipeline-go v0.2.2 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 github.com/Azure/azure-storage-blob-go v0.10.0 github.com/Azure/go-autorest/autorest/adal v0.9.23 github.com/BurntSushi/toml v1.0.0 @@ -44,9 +46,9 @@ require ( go.etcd.io/etcd/server/v3 v3.5.12 go.mongodb.org/mongo-driver v1.7.1 go.opencensus.io v0.24.0 - golang.org/x/mod v0.8.0 + golang.org/x/mod v0.17.0 golang.org/x/oauth2 v0.16.0 - golang.org/x/sync v0.6.0 + golang.org/x/sync v0.7.0 google.golang.org/api v0.162.0 ) @@ -57,10 +59,12 @@ require ( cloud.google.com/go/iam v1.1.6 // indirect cloud.google.com/go/monitoring v1.18.0 // indirect cloud.google.com/go/trace v1.10.5 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect github.com/Azure/go-autorest/logger v0.2.1 // indirect github.com/Azure/go-autorest/tracing v0.6.0 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect github.com/DataDog/datadog-go v0.0.0-20180822151419-281ae9f2d895 // indirect github.com/agext/levenshtein v1.2.1 // indirect github.com/ajg/form v0.0.0-20160822230020-523a5da1a92f // indirect @@ -96,6 +100,7 @@ require ( github.com/go-stack/stack v1.8.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/golang-jwt/jwt/v5 v5.2.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect @@ -127,13 +132,14 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/philhofer/fwd v1.0.0 // indirect + github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.18.0 // indirect github.com/prometheus/client_model v0.6.0 // indirect github.com/prometheus/common v0.47.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect - github.com/rogpeppe/go-internal v1.10.0 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/soheilhy/cmux v0.1.5 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/tinylib/msgp v1.0.2 // indirect @@ -161,10 +167,10 @@ require ( go.opentelemetry.io/proto/otlp v1.1.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.26.0 // indirect - golang.org/x/crypto v0.19.0 // indirect - golang.org/x/net v0.21.0 // indirect - golang.org/x/sys v0.17.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/crypto v0.24.0 // indirect + golang.org/x/net v0.26.0 // indirect + golang.org/x/sys v0.21.0 // indirect + golang.org/x/text v0.16.0 // indirect golang.org/x/time v0.5.0 // indirect google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect diff --git a/go.sum b/go.sum index 64faabf19..d734438f7 100644 --- a/go.sum +++ b/go.sum @@ -58,6 +58,12 @@ contrib.go.opencensus.io/exporter/stackdriver v0.6.0/go.mod h1:QeFzMJDAw8TXt5+aR dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/Azure/azure-pipeline-go v0.2.2 h1:6oiIS9yaG6XCCzhgAgKFfIWyo4LLCiDhZot6ltoThhY= github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 h1:E+OJmp2tPvt1W+amx48v1eqbjDYsgN+RzP4q16yV5eM= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1/go.mod h1:a6xsAQUZg+VsS3TJ05SRp524Hs4pZ/AeFSr5ENf0Yjo= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH5sE0o6eCJuNDTmH09nDpbc= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 h1:jBQA3cKT4L2rWMpgE7Yt3Hwh2aUj8KXjIGLxjHeYNNo= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0/go.mod h1:4OG6tQ9EOP/MT0NMjDlRzWoVFxfu9rN9B2X+tlSVktg= github.com/Azure/azure-storage-blob-go v0.10.0 h1:evCwGreYo3XLeBV4vSxLbLiYb6e0SzsJiXQVRGsRXxs= github.com/Azure/azure-storage-blob-go v0.10.0/go.mod h1:ep1edmW+kNQx4UfWM9heESNmQdijykocJ0YOxmMX8SE= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= @@ -83,6 +89,8 @@ github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= +github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= +github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU= github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= @@ -249,6 +257,8 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +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/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -455,6 +465,8 @@ github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFSt github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ= github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -479,8 +491,8 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -619,8 +631,8 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -655,8 +667,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -701,8 +713,8 @@ golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -726,8 +738,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -784,8 +796,8 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -802,8 +814,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -866,7 +878,7 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= 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= diff --git a/pkg/stash/with_azureblob.go b/pkg/stash/with_azureblob.go index 1717dd231..8bdf8337f 100644 --- a/pkg/stash/with_azureblob.go +++ b/pkg/stash/with_azureblob.go @@ -8,8 +8,9 @@ import ( "net/url" "time" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" "github.com/Azure/azure-storage-blob-go/azblob" - "github.com/Azure/go-autorest/autorest/adal" "github.com/gomods/athens/pkg/config" "github.com/gomods/athens/pkg/errors" "github.com/gomods/athens/pkg/observ" @@ -37,15 +38,27 @@ func WithAzureBlobLock(conf *config.AzureBlobConfig, timeout time.Duration, chec } } if conf.ManagedIdentityResourceID != "" { - spStorageToken, err := adal.NewServicePrincipalTokenFromManagedIdentity(conf.StorageResource, &adal.ManagedIdentityOptions{IdentityResourceID: conf.ManagedIdentityResourceID}) + // spStorageToken, err := adal.NewServicePrincipalTokenFromManagedIdentity(conf.StorageResource, &adal.ManagedIdentityOptions{IdentityResourceID: conf.ManagedIdentityResourceID}) + // if err != nil { + // return nil, errors.E(op, err) + // } + // err = spStorageToken.Refresh() + // if err != nil { + // return nil, errors.E(op, err) + // } + // cred = azblob.NewTokenCredential(spStorageToken.OAuthToken(), nil) + + msiCred, err := azidentity.NewManagedIdentityCredential(&azidentity.ManagedIdentityCredentialOptions{ + ID: azidentity.ResourceID(conf.ManagedIdentityResourceID), + }) if err != nil { return nil, errors.E(op, err) } - err = spStorageToken.Refresh() + token, err := msiCred.GetToken(context.Background(), policy.TokenRequestOptions{}) if err != nil { return nil, errors.E(op, err) } - cred = azblob.NewTokenCredential(spStorageToken.OAuthToken(), nil) + cred = azblob.NewTokenCredential(token.Token, nil) } pipe := azblob.NewPipeline(cred, azblob.PipelineOptions{}) serviceURL := azblob.NewServiceURL(*accountURL, pipe) diff --git a/pkg/storage/azureblob/azureblob.go b/pkg/storage/azureblob/azureblob.go index bcc30bb64..1e768a9ea 100644 --- a/pkg/storage/azureblob/azureblob.go +++ b/pkg/storage/azureblob/azureblob.go @@ -10,8 +10,9 @@ import ( "time" "github.com/Azure/azure-pipeline-go/pipeline" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" "github.com/Azure/azure-storage-blob-go/azblob" - "github.com/Azure/go-autorest/autorest/adal" "github.com/gomods/athens/pkg/config" "github.com/gomods/athens/pkg/errors" @@ -27,24 +28,29 @@ func newBlobStoreClient(accountURL *url.URL, accountName, accountKey, storageRes const op errors.Op = "azureblob.newBlobStoreClient" var pipe pipeline.Pipeline if managedIdentityResourceID != "" { - spStorageToken, err := adal.NewServicePrincipalTokenFromManagedIdentity(storageResource, &adal.ManagedIdentityOptions{IdentityResourceID: managedIdentityResourceID}) + // spStorageToken, err := adal.NewServicePrincipalTokenFromManagedIdentity(storageResource, &adal.ManagedIdentityOptions{IdentityResourceID: managedIdentityResourceID}) + // if err != nil { + // return nil, errors.E(op, err) + // } + // err = spStorageToken.Refresh() + // if err != nil { + // return nil, errors.E(op, err) + // } + + msiCred, err := azidentity.NewManagedIdentityCredential(&azidentity.ManagedIdentityCredentialOptions{ + ID: azidentity.ResourceID(managedIdentityResourceID), + }) if err != nil { return nil, errors.E(op, err) } - err = spStorageToken.Refresh() + token, err := msiCred.GetToken(context.Background(), policy.TokenRequestOptions{}) if err != nil { return nil, errors.E(op, err) } - cred := azblob.NewTokenCredential(spStorageToken.OAuthToken(), nil) - // TODO(yuelu): delete this when test passes - if cred != nil { - log.Println("azure storage msi token created") - } - token := cred.Token() log.Println("token:", token) - - pipe = azblob.NewPipeline(cred, azblob.PipelineOptions{}) + tokenCred := azblob.NewTokenCredential(token.Token, nil) + pipe = azblob.NewPipeline(tokenCred, azblob.PipelineOptions{}) } if pipe == nil && accountKey != "" { cred, err := azblob.NewSharedKeyCredential(accountName, accountKey) From f36ebdf58bede362ae2e369f48968294ab4091ae Mon Sep 17 00:00:00 2001 From: yueluhuan Date: Fri, 2 Aug 2024 12:03:37 +0000 Subject: [PATCH 05/18] inject one scope of get token policy --- pkg/storage/azureblob/azureblob.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/storage/azureblob/azureblob.go b/pkg/storage/azureblob/azureblob.go index 1e768a9ea..8951af2fd 100644 --- a/pkg/storage/azureblob/azureblob.go +++ b/pkg/storage/azureblob/azureblob.go @@ -43,7 +43,9 @@ func newBlobStoreClient(accountURL *url.URL, accountName, accountKey, storageRes if err != nil { return nil, errors.E(op, err) } - token, err := msiCred.GetToken(context.Background(), policy.TokenRequestOptions{}) + token, err := msiCred.GetToken(context.Background(), policy.TokenRequestOptions{ + Scopes: []string{"https://management.azure.com/.default"}, + }) if err != nil { return nil, errors.E(op, err) } From 73ecf8859f988ac617e224279b1d9ba036373e2f Mon Sep 17 00:00:00 2001 From: yueluhuan Date: Fri, 2 Aug 2024 12:32:04 +0000 Subject: [PATCH 06/18] update ut --- pkg/config/config_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 985410746..fd1eb5fe2 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -236,9 +236,9 @@ func TestParseExampleConfig(t *testing.T) { }, AzureBlob: &AzureBlobConfig{ AccountName: "MY_AZURE_BLOB_ACCOUNT_NAME", - AccountKey: "MY_AZURE_BLOB_ACCOUNT_KEY", - ManagedIdentityResourceID: "MY_AZURE_MANAGED_IDENTITY_RESOURCE_ID", - StorageResource: "MY_AZURE_STORAGE_RESOURCE", + AccountKey: "", + ManagedIdentityResourceID: "", + StorageResource: "", ContainerName: "MY_AZURE_BLOB_CONTAINER_NAME", }, External: &External{URL: ""}, From f86f39ca8c58bc6394876e575dbccb16da626ca0 Mon Sep 17 00:00:00 2001 From: yueluhuan Date: Fri, 2 Aug 2024 13:38:15 +0000 Subject: [PATCH 07/18] add scope --- pkg/stash/with_azureblob.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/stash/with_azureblob.go b/pkg/stash/with_azureblob.go index 8bdf8337f..3e04b6986 100644 --- a/pkg/stash/with_azureblob.go +++ b/pkg/stash/with_azureblob.go @@ -54,7 +54,9 @@ func WithAzureBlobLock(conf *config.AzureBlobConfig, timeout time.Duration, chec if err != nil { return nil, errors.E(op, err) } - token, err := msiCred.GetToken(context.Background(), policy.TokenRequestOptions{}) + token, err := msiCred.GetToken(context.Background(), policy.TokenRequestOptions{ + Scopes: []string{"https://management.azure.com/.default"}, + }) if err != nil { return nil, errors.E(op, err) } From 7d0fc3d142e721b32a8c0572fea681eaf60e9100 Mon Sep 17 00:00:00 2001 From: yueluhuan Date: Mon, 5 Aug 2024 10:29:07 +0000 Subject: [PATCH 08/18] update config ATHENS_AZURE_CREDENTIAL_SCOPE --- cmd/proxy/actions/app_proxy.go | 7 ------- config.dev.toml | 4 ++-- pkg/config/azureblob.go | 2 +- pkg/config/config.go | 5 ----- pkg/config/config_test.go | 2 +- pkg/download/mode/mode.go | 6 ------ pkg/stash/with_azureblob.go | 16 ++-------------- pkg/stash/with_azureblob_test.go | 6 +++--- pkg/storage/azureblob/azureblob.go | 20 ++++---------------- pkg/storage/azureblob/azureblob_test.go | 6 +++--- 10 files changed, 16 insertions(+), 58 deletions(-) diff --git a/cmd/proxy/actions/app_proxy.go b/cmd/proxy/actions/app_proxy.go index d162c64d9..0117bc9db 100644 --- a/cmd/proxy/actions/app_proxy.go +++ b/cmd/proxy/actions/app_proxy.go @@ -41,7 +41,6 @@ func addProxyRoutes( indexer, err := getIndex(c) if err != nil { - l.Println("error creating indexer") return err } r.HandleFunc("/index", indexHandler(indexer)) @@ -49,11 +48,9 @@ func addProxyRoutes( for _, sumdb := range c.SumDBs { sumdbURL, err := url.Parse(sumdb) if err != nil { - l.Println("error parsing sumdb URL") return err } if sumdbURL.Scheme != "https" { - l.Println("sumdb must have an https scheme") return fmt.Errorf("sumdb: %v must have an https scheme", sumdb) } supportPath := path.Join("/sumdb", sumdbURL.Host, "/supported") @@ -95,12 +92,10 @@ func addProxyRoutes( c.GoBinaryEnvVars.Add("GONOSUMDB", strings.Join(c.NoSumPatterns, ",")) } if err := c.GoBinaryEnvVars.Validate(); err != nil { - l.Println("error validating GoBinaryEnvVars") return err } mf, err := module.NewGoGetFetcher(c.GoBinary, c.GoGetDir, c.GoBinaryEnvVars, fs) if err != nil { - l.Println("error creating module fetcher") return err } @@ -108,14 +103,12 @@ func addProxyRoutes( checker := storage.WithChecker(s) withSingleFlight, err := getSingleFlight(l, c, s, checker) if err != nil { - l.Println("error creating single flight") return err } st := stash.New(mf, s, indexer, stash.WithPool(c.GoGetWorkers), withSingleFlight) df, err := mode.NewFile(c.DownloadMode, c.DownloadURL) if err != nil { - l.Println("error creating download file") return err } diff --git a/config.dev.toml b/config.dev.toml index 6ffb71cda..976af56df 100755 --- a/config.dev.toml +++ b/config.dev.toml @@ -541,8 +541,8 @@ ShutdownTimeout = 60 ManagedIdentityResourceId = "" # Storage Resource to use with the storage account - # Env override: ATHENS_AZURE_STORAGE_RESOURCE - StorageResource = "" + # Env override: ATHENS_AZURE_CREDENTIAL_SCOPE + CredentialScope = "" # Name of container in the blob storage # Env override: ATHENS_AZURE_CONTAINER_NAME diff --git a/pkg/config/azureblob.go b/pkg/config/azureblob.go index c0f38f397..454a3a6ee 100644 --- a/pkg/config/azureblob.go +++ b/pkg/config/azureblob.go @@ -5,6 +5,6 @@ type AzureBlobConfig struct { AccountName string `envconfig:"ATHENS_AZURE_ACCOUNT_NAME" validate:"required"` AccountKey string `envconfig:"ATHENS_AZURE_ACCOUNT_KEY"` ManagedIdentityResourceID string `envconfig:"ATHENS_AZURE_MANAGED_IDENTITY_RESOURCE_ID"` - StorageResource string `envconfig:"ATHENS_AZURE_STORAGE_RESOURCE"` + CredentialScope string `envconfig:"ATHENS_AZURE_CREDENTIAL_SCOPE"` ContainerName string `envconfig:"ATHENS_AZURE_CONTAINER_NAME" validate:"required"` } diff --git a/pkg/config/config.go b/pkg/config/config.go index e81bbc049..b591b949a 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -259,11 +259,6 @@ func envOverride(config *Config) error { if err != nil { return err } - - // TODO(yuelu) remove log after test is done - blobConfig := *config.Storage.AzureBlob - log.Printf("BlobConfig: %v", blobConfig) - portEnv := os.Getenv("PORT") // ATHENS_PORT takes precedence over PORT if portEnv != "" && os.Getenv("ATHENS_PORT") == "" { diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index fd1eb5fe2..2fad9c5e5 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -238,7 +238,7 @@ func TestParseExampleConfig(t *testing.T) { AccountName: "MY_AZURE_BLOB_ACCOUNT_NAME", AccountKey: "", ManagedIdentityResourceID: "", - StorageResource: "", + CredentialScope: "", ContainerName: "MY_AZURE_BLOB_CONTAINER_NAME", }, External: &External{URL: ""}, diff --git a/pkg/download/mode/mode.go b/pkg/download/mode/mode.go index 82e11a937..20960eda0 100644 --- a/pkg/download/mode/mode.go +++ b/pkg/download/mode/mode.go @@ -3,7 +3,6 @@ package mode import ( "encoding/base64" "fmt" - "log" "os" "path/filepath" "strings" @@ -67,13 +66,8 @@ func NewFile(m Mode, downloadURL string) (*DownloadFile, error) { } return parseFile(bts) } else if strings.HasPrefix(string(m), "custom:") { - // TODO(yuelu) remove this line after test passes - log.Printf("mode: %s", string(m[7:])) - bts, err := base64.StdEncoding.DecodeString(string(m[7:])) if err != nil { - // TODO(yuelu) remove this line after test passes - log.Println("[NewFile] error decoding base64 string") return nil, err } return parseFile(bts) diff --git a/pkg/stash/with_azureblob.go b/pkg/stash/with_azureblob.go index 3e04b6986..e7d0adf78 100644 --- a/pkg/stash/with_azureblob.go +++ b/pkg/stash/with_azureblob.go @@ -23,7 +23,7 @@ import ( func WithAzureBlobLock(conf *config.AzureBlobConfig, timeout time.Duration, checker storage.Checker) (Wrapper, error) { const op errors.Op = "stash.WithAzureBlobLock" - if conf.AccountKey == "" && (conf.ManagedIdentityResourceID == "" || conf.StorageResource == "") { + if conf.AccountKey == "" && (conf.ManagedIdentityResourceID == "" || conf.CredentialScope == "") { return nil, errors.E(op, "either account key or managed identity resource id and storage resource must be set") } accountURL, err := url.Parse(fmt.Sprintf("https://%s.blob.core.windows.net", conf.AccountName)) @@ -38,25 +38,13 @@ func WithAzureBlobLock(conf *config.AzureBlobConfig, timeout time.Duration, chec } } if conf.ManagedIdentityResourceID != "" { - // spStorageToken, err := adal.NewServicePrincipalTokenFromManagedIdentity(conf.StorageResource, &adal.ManagedIdentityOptions{IdentityResourceID: conf.ManagedIdentityResourceID}) - // if err != nil { - // return nil, errors.E(op, err) - // } - // err = spStorageToken.Refresh() - // if err != nil { - // return nil, errors.E(op, err) - // } - // cred = azblob.NewTokenCredential(spStorageToken.OAuthToken(), nil) - msiCred, err := azidentity.NewManagedIdentityCredential(&azidentity.ManagedIdentityCredentialOptions{ ID: azidentity.ResourceID(conf.ManagedIdentityResourceID), }) if err != nil { return nil, errors.E(op, err) } - token, err := msiCred.GetToken(context.Background(), policy.TokenRequestOptions{ - Scopes: []string{"https://management.azure.com/.default"}, - }) + token, err := msiCred.GetToken(context.Background(), policy.TokenRequestOptions{Scopes: []string{conf.CredentialScope}}) if err != nil { return nil, errors.E(op, err) } diff --git a/pkg/stash/with_azureblob_test.go b/pkg/stash/with_azureblob_test.go index 805af369f..124ede39f 100644 --- a/pkg/stash/with_azureblob_test.go +++ b/pkg/stash/with_azureblob_test.go @@ -87,8 +87,8 @@ func (ms *mockAzureBlobStasher) Stash(ctx context.Context, mod, ver string) (str func getAzureTestConfig(containerName string) *config.AzureBlobConfig { key := os.Getenv("ATHENS_AZURE_ACCOUNT_KEY") resourceId := os.Getenv("ATHENS_AZURE_MANAGED_IDENTITY_RESOURCE_ID") - storageResource := os.Getenv("ATHENS_AZURE_STORAGE_RESOURCE") - if key == "" && (resourceId == "" || storageResource == "") { + credentialScope := os.Getenv("ATHENS_AZURE_CREDENTIAL_SCOPE") + if key == "" && (resourceId == "" || credentialScope == "") { return nil } name := os.Getenv("ATHENS_AZURE_ACCOUNT_NAME") @@ -99,7 +99,7 @@ func getAzureTestConfig(containerName string) *config.AzureBlobConfig { AccountName: name, AccountKey: key, ManagedIdentityResourceID: resourceId, - StorageResource: storageResource, + CredentialScope: credentialScope, ContainerName: containerName, } } diff --git a/pkg/storage/azureblob/azureblob.go b/pkg/storage/azureblob/azureblob.go index 8951af2fd..93deaf4d5 100644 --- a/pkg/storage/azureblob/azureblob.go +++ b/pkg/storage/azureblob/azureblob.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "io" - "log" "net/http" "net/url" "time" @@ -24,19 +23,10 @@ type azureBlobStoreClient struct { containerURL *azblob.ContainerURL } -func newBlobStoreClient(accountURL *url.URL, accountName, accountKey, storageResource, managedIdentityResourceID, containerName string) (*azureBlobStoreClient, error) { +func newBlobStoreClient(accountURL *url.URL, accountName, accountKey, credScope, managedIdentityResourceID, containerName string) (*azureBlobStoreClient, error) { const op errors.Op = "azureblob.newBlobStoreClient" var pipe pipeline.Pipeline if managedIdentityResourceID != "" { - // spStorageToken, err := adal.NewServicePrincipalTokenFromManagedIdentity(storageResource, &adal.ManagedIdentityOptions{IdentityResourceID: managedIdentityResourceID}) - // if err != nil { - // return nil, errors.E(op, err) - // } - // err = spStorageToken.Refresh() - // if err != nil { - // return nil, errors.E(op, err) - // } - msiCred, err := azidentity.NewManagedIdentityCredential(&azidentity.ManagedIdentityCredentialOptions{ ID: azidentity.ResourceID(managedIdentityResourceID), }) @@ -44,13 +34,11 @@ func newBlobStoreClient(accountURL *url.URL, accountName, accountKey, storageRes return nil, errors.E(op, err) } token, err := msiCred.GetToken(context.Background(), policy.TokenRequestOptions{ - Scopes: []string{"https://management.azure.com/.default"}, + Scopes: []string{credScope}, }) if err != nil { return nil, errors.E(op, err) } - // TODO(yuelu): delete this when test passes - log.Println("token:", token) tokenCred := azblob.NewTokenCredential(token.Token, nil) pipe = azblob.NewPipeline(tokenCred, azblob.PipelineOptions{}) } @@ -85,10 +73,10 @@ func New(conf *config.AzureBlobConfig, timeout time.Duration) (*Storage, error) if err != nil { return nil, errors.E(op, err) } - if conf.AccountKey == "" && (conf.ManagedIdentityResourceID == "" || conf.StorageResource == "") { + if conf.AccountKey == "" && (conf.ManagedIdentityResourceID == "" || conf.CredentialScope == "") { return nil, errors.E(op, "either account key or managed identity resource id and storage resource must be set") } - cl, err := newBlobStoreClient(u, conf.AccountName, conf.AccountKey, conf.StorageResource, conf.ManagedIdentityResourceID, conf.ContainerName) + cl, err := newBlobStoreClient(u, conf.AccountName, conf.AccountKey, conf.CredentialScope, conf.ManagedIdentityResourceID, conf.ContainerName) if err != nil { return nil, errors.E(op, err) } diff --git a/pkg/storage/azureblob/azureblob_test.go b/pkg/storage/azureblob/azureblob_test.go index 6f6c34a95..62edeb49e 100644 --- a/pkg/storage/azureblob/azureblob_test.go +++ b/pkg/storage/azureblob/azureblob_test.go @@ -71,8 +71,8 @@ func getStorage(t testing.TB) *Storage { func getTestConfig(containerName string) *config.AzureBlobConfig { key := os.Getenv("ATHENS_AZURE_ACCOUNT_KEY") resourceId := os.Getenv("ATHENS_AZURE_MANAGED_IDENTITY_RESOURCE_ID") - storageResource := os.Getenv("ATHENS_AZURE_STORAGE_RESOURCE") - if key == "" && (resourceId == "" || storageResource == "") { + credentialScope := os.Getenv("ATHENS_AZURE_CREDENTIAL_SCOPE") + if key == "" && (resourceId == "" || credentialScope == "") { return nil } name := os.Getenv("ATHENS_AZURE_ACCOUNT_NAME") @@ -83,7 +83,7 @@ func getTestConfig(containerName string) *config.AzureBlobConfig { AccountName: name, AccountKey: key, ManagedIdentityResourceID: resourceId, - StorageResource: storageResource, + CredentialScope: credentialScope, ContainerName: containerName, } } From e733e8c86466e69edfa05117205541704da460e2 Mon Sep 17 00:00:00 2001 From: yueluhuan Date: Mon, 5 Aug 2024 10:30:09 +0000 Subject: [PATCH 09/18] go mod tidy --- go.mod | 6 +----- go.sum | 1 - 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 194890562..c819e0651 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,6 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 github.com/Azure/azure-storage-blob-go v0.10.0 - github.com/Azure/go-autorest/autorest/adal v0.9.23 github.com/BurntSushi/toml v1.0.0 github.com/DataDog/opencensus-go-exporter-datadog v0.0.0-20180917103902-e6c7f767dc57 github.com/aws/aws-sdk-go-v2 v1.26.1 @@ -60,10 +59,7 @@ require ( cloud.google.com/go/monitoring v1.18.0 // indirect cloud.google.com/go/trace v1.10.5 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 // indirect - github.com/Azure/go-autorest v14.2.0+incompatible // indirect - github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect - github.com/Azure/go-autorest/logger v0.2.1 // indirect - github.com/Azure/go-autorest/tracing v0.6.0 // indirect + github.com/Azure/go-autorest/autorest/adal v0.9.23 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect github.com/DataDog/datadog-go v0.0.0-20180822151419-281ae9f2d895 // indirect github.com/agext/levenshtein v1.2.1 // indirect diff --git a/go.sum b/go.sum index d734438f7..a53844743 100644 --- a/go.sum +++ b/go.sum @@ -81,7 +81,6 @@ github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSY github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= -github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= From f647815aea02a2e96018db062f41e4e45d91fa6a Mon Sep 17 00:00:00 2001 From: yueluhuan Date: Mon, 5 Aug 2024 10:39:57 +0000 Subject: [PATCH 10/18] fix tidy gci issue --- pkg/storage/azureblob/azureblob.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/storage/azureblob/azureblob.go b/pkg/storage/azureblob/azureblob.go index 93deaf4d5..2e9de8e6b 100644 --- a/pkg/storage/azureblob/azureblob.go +++ b/pkg/storage/azureblob/azureblob.go @@ -12,7 +12,6 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" "github.com/Azure/azure-sdk-for-go/sdk/azidentity" "github.com/Azure/azure-storage-blob-go/azblob" - "github.com/gomods/athens/pkg/config" "github.com/gomods/athens/pkg/errors" "github.com/gomods/athens/pkg/observ" From f693d0c29353d7f99627c6cc78ddbe74a1eb6fb3 Mon Sep 17 00:00:00 2001 From: yueluhuan Date: Thu, 15 Aug 2024 09:51:17 +0000 Subject: [PATCH 11/18] add token refresh logic --- pkg/stash/with_azureblob.go | 6 ++++++ pkg/storage/azureblob/azureblob.go | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/pkg/stash/with_azureblob.go b/pkg/stash/with_azureblob.go index e7d0adf78..1ab3a9d93 100644 --- a/pkg/stash/with_azureblob.go +++ b/pkg/stash/with_azureblob.go @@ -48,6 +48,12 @@ func WithAzureBlobLock(conf *config.AzureBlobConfig, timeout time.Duration, chec if err != nil { return nil, errors.E(op, err) } + if token.Token == "" || token.ExpiresOn.Before(time.Now().Add(time.Hour)) { + token, err = msiCred.GetToken(context.Background(), policy.TokenRequestOptions{Scopes: []string{conf.CredentialScope}}) + } + if err != nil { + return nil, errors.E(op, err) + } cred = azblob.NewTokenCredential(token.Token, nil) } pipe := azblob.NewPipeline(cred, azblob.PipelineOptions{}) diff --git a/pkg/storage/azureblob/azureblob.go b/pkg/storage/azureblob/azureblob.go index 2e9de8e6b..d9f5119fb 100644 --- a/pkg/storage/azureblob/azureblob.go +++ b/pkg/storage/azureblob/azureblob.go @@ -38,6 +38,12 @@ func newBlobStoreClient(accountURL *url.URL, accountName, accountKey, credScope, if err != nil { return nil, errors.E(op, err) } + if token.Token == "" || token.ExpiresOn.Before(time.Now().Add(time.Hour)) { + token, err = msiCred.GetToken(context.Background(), policy.TokenRequestOptions{Scopes: []string{credScope}}) + } + if err != nil { + return nil, errors.E(op, err) + } tokenCred := azblob.NewTokenCredential(token.Token, nil) pipe = azblob.NewPipeline(tokenCred, azblob.PipelineOptions{}) } From 5fb0139ec4c26932b48e7e7d16a7c26d0ac67466 Mon Sep 17 00:00:00 2001 From: yueluhuan Date: Fri, 16 Aug 2024 06:27:38 +0000 Subject: [PATCH 12/18] inject token refresh func in NewTokenCredential --- pkg/stash/with_azureblob.go | 18 +++++++++++------- pkg/storage/azureblob/azureblob.go | 21 ++++++++++++++------- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/pkg/stash/with_azureblob.go b/pkg/stash/with_azureblob.go index 1ab3a9d93..c99fde17d 100644 --- a/pkg/stash/with_azureblob.go +++ b/pkg/stash/with_azureblob.go @@ -15,6 +15,7 @@ import ( "github.com/gomods/athens/pkg/errors" "github.com/gomods/athens/pkg/observ" "github.com/gomods/athens/pkg/storage" + "github.com/gomods/athens/pkg/storage/azureblob" "github.com/google/uuid" ) @@ -48,13 +49,16 @@ func WithAzureBlobLock(conf *config.AzureBlobConfig, timeout time.Duration, chec if err != nil { return nil, errors.E(op, err) } - if token.Token == "" || token.ExpiresOn.Before(time.Now().Add(time.Hour)) { - token, err = msiCred.GetToken(context.Background(), policy.TokenRequestOptions{Scopes: []string{conf.CredentialScope}}) - } - if err != nil { - return nil, errors.E(op, err) - } - cred = azblob.NewTokenCredential(token.Token, nil) + cred = azblob.NewTokenCredential(token.Token, func(tc azblob.TokenCredential) time.Duration { + token, err := msiCred.GetToken(context.Background(), policy.TokenRequestOptions{ + Scopes: []string{conf.CredentialScope}, + }) + if err != nil { + fmt.Printf("error getting token: %s during token refresh process", err) + return 0 + } + return time.Until(token.ExpiresOn.Add(-azureblob.TokenRefreshTolerance)) + }) } pipe := azblob.NewPipeline(cred, azblob.PipelineOptions{}) serviceURL := azblob.NewServiceURL(*accountURL, pipe) diff --git a/pkg/storage/azureblob/azureblob.go b/pkg/storage/azureblob/azureblob.go index d9f5119fb..7659de54f 100644 --- a/pkg/storage/azureblob/azureblob.go +++ b/pkg/storage/azureblob/azureblob.go @@ -22,6 +22,10 @@ type azureBlobStoreClient struct { containerURL *azblob.ContainerURL } +const ( + TokenRefreshTolerance = time.Hour +) + func newBlobStoreClient(accountURL *url.URL, accountName, accountKey, credScope, managedIdentityResourceID, containerName string) (*azureBlobStoreClient, error) { const op errors.Op = "azureblob.newBlobStoreClient" var pipe pipeline.Pipeline @@ -38,13 +42,16 @@ func newBlobStoreClient(accountURL *url.URL, accountName, accountKey, credScope, if err != nil { return nil, errors.E(op, err) } - if token.Token == "" || token.ExpiresOn.Before(time.Now().Add(time.Hour)) { - token, err = msiCred.GetToken(context.Background(), policy.TokenRequestOptions{Scopes: []string{credScope}}) - } - if err != nil { - return nil, errors.E(op, err) - } - tokenCred := azblob.NewTokenCredential(token.Token, nil) + tokenCred := azblob.NewTokenCredential(token.Token, func(tc azblob.TokenCredential) time.Duration { + token, err := msiCred.GetToken(context.Background(), policy.TokenRequestOptions{ + Scopes: []string{credScope}, + }) + if err != nil { + fmt.Printf("error getting token: %s during token refresh process", err) + return 0 + } + return time.Until(token.ExpiresOn.Add(-TokenRefreshTolerance)) + }) pipe = azblob.NewPipeline(tokenCred, azblob.PipelineOptions{}) } if pipe == nil && accountKey != "" { From 1f1477e307b9746e658ca4b2a57033d69c9ca7e7 Mon Sep 17 00:00:00 2001 From: yueluhuan Date: Fri, 16 Aug 2024 06:36:10 +0000 Subject: [PATCH 13/18] add comment for constant TokenRefreshTolerance --- pkg/storage/azureblob/azureblob.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/storage/azureblob/azureblob.go b/pkg/storage/azureblob/azureblob.go index 7659de54f..bfaa2721a 100644 --- a/pkg/storage/azureblob/azureblob.go +++ b/pkg/storage/azureblob/azureblob.go @@ -23,6 +23,9 @@ type azureBlobStoreClient struct { } const ( + // TokenRefreshTolerance defines the duration before the token's actual expiration time + // during which the token should be refreshed. This helps ensure that the token is + // refreshed in a timely manner, avoiding potential issues with token expiration. TokenRefreshTolerance = time.Hour ) From efba1fe293d78eda7f4c5c50a384ab4796aaed8b Mon Sep 17 00:00:00 2001 From: yueluhuan Date: Mon, 19 Aug 2024 05:24:15 +0000 Subject: [PATCH 14/18] set new tokenn in token refresh func --- pkg/stash/with_azureblob.go | 1 + pkg/storage/azureblob/azureblob.go | 1 + 2 files changed, 2 insertions(+) diff --git a/pkg/stash/with_azureblob.go b/pkg/stash/with_azureblob.go index c99fde17d..6c9013bc4 100644 --- a/pkg/stash/with_azureblob.go +++ b/pkg/stash/with_azureblob.go @@ -53,6 +53,7 @@ func WithAzureBlobLock(conf *config.AzureBlobConfig, timeout time.Duration, chec token, err := msiCred.GetToken(context.Background(), policy.TokenRequestOptions{ Scopes: []string{conf.CredentialScope}, }) + tc.SetToken(token.Token) if err != nil { fmt.Printf("error getting token: %s during token refresh process", err) return 0 diff --git a/pkg/storage/azureblob/azureblob.go b/pkg/storage/azureblob/azureblob.go index bfaa2721a..bbb4237b6 100644 --- a/pkg/storage/azureblob/azureblob.go +++ b/pkg/storage/azureblob/azureblob.go @@ -49,6 +49,7 @@ func newBlobStoreClient(accountURL *url.URL, accountName, accountKey, credScope, token, err := msiCred.GetToken(context.Background(), policy.TokenRequestOptions{ Scopes: []string{credScope}, }) + tc.SetToken(token.Token) if err != nil { fmt.Printf("error getting token: %s during token refresh process", err) return 0 From 8d829a75c0fc7f427e2b8e6d0e4e1db7cb591f7f Mon Sep 17 00:00:00 2001 From: yueluhuan Date: Wed, 21 Aug 2024 09:50:57 +0000 Subject: [PATCH 15/18] add log and update err handle in token refresh func --- pkg/stash/with_azureblob.go | 5 ++++- pkg/storage/azureblob/azureblob.go | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/pkg/stash/with_azureblob.go b/pkg/stash/with_azureblob.go index 6c9013bc4..797ffdb36 100644 --- a/pkg/stash/with_azureblob.go +++ b/pkg/stash/with_azureblob.go @@ -50,13 +50,16 @@ func WithAzureBlobLock(conf *config.AzureBlobConfig, timeout time.Duration, chec return nil, errors.E(op, err) } cred = azblob.NewTokenCredential(token.Token, func(tc azblob.TokenCredential) time.Duration { + fmt.Println("refreshing token started") token, err := msiCred.GetToken(context.Background(), policy.TokenRequestOptions{ Scopes: []string{conf.CredentialScope}, }) tc.SetToken(token.Token) if err != nil { fmt.Printf("error getting token: %s during token refresh process", err) - return 0 + // token refresh may fail due to transient errors, so we return a non-zero duration + // to retry the token refresh after a short delay + return time.Minute } return time.Until(token.ExpiresOn.Add(-azureblob.TokenRefreshTolerance)) }) diff --git a/pkg/storage/azureblob/azureblob.go b/pkg/storage/azureblob/azureblob.go index bbb4237b6..4e58dfb94 100644 --- a/pkg/storage/azureblob/azureblob.go +++ b/pkg/storage/azureblob/azureblob.go @@ -46,13 +46,16 @@ func newBlobStoreClient(accountURL *url.URL, accountName, accountKey, credScope, return nil, errors.E(op, err) } tokenCred := azblob.NewTokenCredential(token.Token, func(tc azblob.TokenCredential) time.Duration { + fmt.Println("refreshing token started") token, err := msiCred.GetToken(context.Background(), policy.TokenRequestOptions{ Scopes: []string{credScope}, }) tc.SetToken(token.Token) if err != nil { fmt.Printf("error getting token: %s during token refresh process", err) - return 0 + // token refresh may fail due to transient errors, so we return a non-zero duration + // to retry the token refresh after a short delay + return time.Minute } return time.Until(token.ExpiresOn.Add(-TokenRefreshTolerance)) }) From 8093a697cbc49e898484eaa1ff19c5887ffb51ed Mon Sep 17 00:00:00 2001 From: yueluhuan Date: Thu, 22 Aug 2024 11:09:51 +0000 Subject: [PATCH 16/18] test use new cred in refresh token func --- go.mod | 6 +++++- go.sum | 1 + pkg/stash/with_azureblob.go | 22 ++++++++++++++++++---- pkg/storage/azureblob/azureblob.go | 22 ++++++++++++++++++---- 4 files changed, 42 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index c819e0651..194890562 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 github.com/Azure/azure-storage-blob-go v0.10.0 + github.com/Azure/go-autorest/autorest/adal v0.9.23 github.com/BurntSushi/toml v1.0.0 github.com/DataDog/opencensus-go-exporter-datadog v0.0.0-20180917103902-e6c7f767dc57 github.com/aws/aws-sdk-go-v2 v1.26.1 @@ -59,7 +60,10 @@ require ( cloud.google.com/go/monitoring v1.18.0 // indirect cloud.google.com/go/trace v1.10.5 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 // indirect - github.com/Azure/go-autorest/autorest/adal v0.9.23 // indirect + github.com/Azure/go-autorest v14.2.0+incompatible // indirect + github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect + github.com/Azure/go-autorest/logger v0.2.1 // indirect + github.com/Azure/go-autorest/tracing v0.6.0 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect github.com/DataDog/datadog-go v0.0.0-20180822151419-281ae9f2d895 // indirect github.com/agext/levenshtein v1.2.1 // indirect diff --git a/go.sum b/go.sum index a53844743..d734438f7 100644 --- a/go.sum +++ b/go.sum @@ -81,6 +81,7 @@ github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSY github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= +github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= diff --git a/pkg/stash/with_azureblob.go b/pkg/stash/with_azureblob.go index 797ffdb36..55ac4848a 100644 --- a/pkg/stash/with_azureblob.go +++ b/pkg/stash/with_azureblob.go @@ -50,18 +50,32 @@ func WithAzureBlobLock(conf *config.AzureBlobConfig, timeout time.Duration, chec return nil, errors.E(op, err) } cred = azblob.NewTokenCredential(token.Token, func(tc azblob.TokenCredential) time.Duration { - fmt.Println("refreshing token started") - token, err := msiCred.GetToken(context.Background(), policy.TokenRequestOptions{ + fmt.Printf("refreshing token started at: %s", time.Now()) + refreshedMsiCred, err := azidentity.NewManagedIdentityCredential(&azidentity.ManagedIdentityCredentialOptions{ + ID: azidentity.ResourceID(conf.ManagedIdentityResourceID), + }) + if err != nil { + fmt.Println("error creating managed identity credential during token refresh process") + return time.Minute + } + refreshedToken, err := refreshedMsiCred.GetToken(context.Background(), policy.TokenRequestOptions{ Scopes: []string{conf.CredentialScope}, }) - tc.SetToken(token.Token) if err != nil { fmt.Printf("error getting token: %s during token refresh process", err) // token refresh may fail due to transient errors, so we return a non-zero duration // to retry the token refresh after a short delay return time.Minute } - return time.Until(token.ExpiresOn.Add(-azureblob.TokenRefreshTolerance)) + tc.SetToken(refreshedToken.Token) + + refreshDuration := time.Until(refreshedToken.ExpiresOn.Add(-azureblob.TokenRefreshTolerance)) + if refreshDuration <= 0 { + fmt.Println("refresh duration is non-positive, setting to default 1 minute") + refreshDuration = time.Minute + } + fmt.Printf("refresh duration: %s", refreshDuration) + return 5 * time.Minute }) } pipe := azblob.NewPipeline(cred, azblob.PipelineOptions{}) diff --git a/pkg/storage/azureblob/azureblob.go b/pkg/storage/azureblob/azureblob.go index 4e58dfb94..a6e188563 100644 --- a/pkg/storage/azureblob/azureblob.go +++ b/pkg/storage/azureblob/azureblob.go @@ -46,18 +46,32 @@ func newBlobStoreClient(accountURL *url.URL, accountName, accountKey, credScope, return nil, errors.E(op, err) } tokenCred := azblob.NewTokenCredential(token.Token, func(tc azblob.TokenCredential) time.Duration { - fmt.Println("refreshing token started") - token, err := msiCred.GetToken(context.Background(), policy.TokenRequestOptions{ + fmt.Printf("refreshing token started at: %s", time.Now()) + refreshedMsiCred, err := azidentity.NewManagedIdentityCredential(&azidentity.ManagedIdentityCredentialOptions{ + ID: azidentity.ResourceID(managedIdentityResourceID), + }) + if err != nil { + fmt.Println("error creating managed identity credential during token refresh process") + return time.Minute + } + refreshedToken, err := refreshedMsiCred.GetToken(context.Background(), policy.TokenRequestOptions{ Scopes: []string{credScope}, }) - tc.SetToken(token.Token) if err != nil { fmt.Printf("error getting token: %s during token refresh process", err) // token refresh may fail due to transient errors, so we return a non-zero duration // to retry the token refresh after a short delay return time.Minute } - return time.Until(token.ExpiresOn.Add(-TokenRefreshTolerance)) + tc.SetToken(refreshedToken.Token) + + refreshDuration := time.Until(refreshedToken.ExpiresOn.Add(-TokenRefreshTolerance)) + if refreshDuration <= 0 { + fmt.Println("refresh duration is non-positive, setting to default 1 minute") + refreshDuration = time.Minute + } + fmt.Printf("refresh duration: %s", refreshDuration) + return 5 * time.Minute }) pipe = azblob.NewPipeline(tokenCred, azblob.PipelineOptions{}) } From 9aa9a725ad2bbad1a0561872219a1a61f14409c0 Mon Sep 17 00:00:00 2001 From: yueluhuan Date: Thu, 22 Aug 2024 12:57:48 +0000 Subject: [PATCH 17/18] test no refresh tolerance --- pkg/stash/with_azureblob.go | 18 +++--------------- pkg/storage/azureblob/azureblob.go | 19 ++++--------------- 2 files changed, 7 insertions(+), 30 deletions(-) diff --git a/pkg/stash/with_azureblob.go b/pkg/stash/with_azureblob.go index 55ac4848a..a28cf0900 100644 --- a/pkg/stash/with_azureblob.go +++ b/pkg/stash/with_azureblob.go @@ -15,7 +15,6 @@ import ( "github.com/gomods/athens/pkg/errors" "github.com/gomods/athens/pkg/observ" "github.com/gomods/athens/pkg/storage" - "github.com/gomods/athens/pkg/storage/azureblob" "github.com/google/uuid" ) @@ -51,14 +50,7 @@ func WithAzureBlobLock(conf *config.AzureBlobConfig, timeout time.Duration, chec } cred = azblob.NewTokenCredential(token.Token, func(tc azblob.TokenCredential) time.Duration { fmt.Printf("refreshing token started at: %s", time.Now()) - refreshedMsiCred, err := azidentity.NewManagedIdentityCredential(&azidentity.ManagedIdentityCredentialOptions{ - ID: azidentity.ResourceID(conf.ManagedIdentityResourceID), - }) - if err != nil { - fmt.Println("error creating managed identity credential during token refresh process") - return time.Minute - } - refreshedToken, err := refreshedMsiCred.GetToken(context.Background(), policy.TokenRequestOptions{ + refreshedToken, err := msiCred.GetToken(context.Background(), policy.TokenRequestOptions{ Scopes: []string{conf.CredentialScope}, }) if err != nil { @@ -69,13 +61,9 @@ func WithAzureBlobLock(conf *config.AzureBlobConfig, timeout time.Duration, chec } tc.SetToken(refreshedToken.Token) - refreshDuration := time.Until(refreshedToken.ExpiresOn.Add(-azureblob.TokenRefreshTolerance)) - if refreshDuration <= 0 { - fmt.Println("refresh duration is non-positive, setting to default 1 minute") - refreshDuration = time.Minute - } + refreshDuration := time.Until(refreshedToken.ExpiresOn) fmt.Printf("refresh duration: %s", refreshDuration) - return 5 * time.Minute + return refreshDuration }) } pipe := azblob.NewPipeline(cred, azblob.PipelineOptions{}) diff --git a/pkg/storage/azureblob/azureblob.go b/pkg/storage/azureblob/azureblob.go index a6e188563..5be4a7da4 100644 --- a/pkg/storage/azureblob/azureblob.go +++ b/pkg/storage/azureblob/azureblob.go @@ -26,7 +26,7 @@ const ( // TokenRefreshTolerance defines the duration before the token's actual expiration time // during which the token should be refreshed. This helps ensure that the token is // refreshed in a timely manner, avoiding potential issues with token expiration. - TokenRefreshTolerance = time.Hour + TokenRefreshTolerance = time.Second ) func newBlobStoreClient(accountURL *url.URL, accountName, accountKey, credScope, managedIdentityResourceID, containerName string) (*azureBlobStoreClient, error) { @@ -47,14 +47,7 @@ func newBlobStoreClient(accountURL *url.URL, accountName, accountKey, credScope, } tokenCred := azblob.NewTokenCredential(token.Token, func(tc azblob.TokenCredential) time.Duration { fmt.Printf("refreshing token started at: %s", time.Now()) - refreshedMsiCred, err := azidentity.NewManagedIdentityCredential(&azidentity.ManagedIdentityCredentialOptions{ - ID: azidentity.ResourceID(managedIdentityResourceID), - }) - if err != nil { - fmt.Println("error creating managed identity credential during token refresh process") - return time.Minute - } - refreshedToken, err := refreshedMsiCred.GetToken(context.Background(), policy.TokenRequestOptions{ + refreshedToken, err := msiCred.GetToken(context.Background(), policy.TokenRequestOptions{ Scopes: []string{credScope}, }) if err != nil { @@ -65,13 +58,9 @@ func newBlobStoreClient(accountURL *url.URL, accountName, accountKey, credScope, } tc.SetToken(refreshedToken.Token) - refreshDuration := time.Until(refreshedToken.ExpiresOn.Add(-TokenRefreshTolerance)) - if refreshDuration <= 0 { - fmt.Println("refresh duration is non-positive, setting to default 1 minute") - refreshDuration = time.Minute - } + refreshDuration := time.Until(refreshedToken.ExpiresOn) fmt.Printf("refresh duration: %s", refreshDuration) - return 5 * time.Minute + return refreshDuration }) pipe = azblob.NewPipeline(tokenCred, azblob.PipelineOptions{}) } From 5c2257237b5c8b4e7ce83a59596cc02a1735ab3a Mon Sep 17 00:00:00 2001 From: yueluhuan Date: Mon, 26 Aug 2024 05:15:42 +0000 Subject: [PATCH 18/18] update TokenRefreshTolerance to 5 * time.Minute --- pkg/stash/with_azureblob.go | 3 ++- pkg/storage/azureblob/azureblob.go | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg/stash/with_azureblob.go b/pkg/stash/with_azureblob.go index a28cf0900..ef0c28964 100644 --- a/pkg/stash/with_azureblob.go +++ b/pkg/stash/with_azureblob.go @@ -15,6 +15,7 @@ import ( "github.com/gomods/athens/pkg/errors" "github.com/gomods/athens/pkg/observ" "github.com/gomods/athens/pkg/storage" + "github.com/gomods/athens/pkg/storage/azureblob" "github.com/google/uuid" ) @@ -61,7 +62,7 @@ func WithAzureBlobLock(conf *config.AzureBlobConfig, timeout time.Duration, chec } tc.SetToken(refreshedToken.Token) - refreshDuration := time.Until(refreshedToken.ExpiresOn) + refreshDuration := time.Until(refreshedToken.ExpiresOn.Add(-azureblob.TokenRefreshTolerance)) fmt.Printf("refresh duration: %s", refreshDuration) return refreshDuration }) diff --git a/pkg/storage/azureblob/azureblob.go b/pkg/storage/azureblob/azureblob.go index 5be4a7da4..a3f8de024 100644 --- a/pkg/storage/azureblob/azureblob.go +++ b/pkg/storage/azureblob/azureblob.go @@ -26,7 +26,7 @@ const ( // TokenRefreshTolerance defines the duration before the token's actual expiration time // during which the token should be refreshed. This helps ensure that the token is // refreshed in a timely manner, avoiding potential issues with token expiration. - TokenRefreshTolerance = time.Second + TokenRefreshTolerance = 5 * time.Minute ) func newBlobStoreClient(accountURL *url.URL, accountName, accountKey, credScope, managedIdentityResourceID, containerName string) (*azureBlobStoreClient, error) { @@ -58,7 +58,7 @@ func newBlobStoreClient(accountURL *url.URL, accountName, accountKey, credScope, } tc.SetToken(refreshedToken.Token) - refreshDuration := time.Until(refreshedToken.ExpiresOn) + refreshDuration := time.Until(refreshedToken.ExpiresOn.Add(-TokenRefreshTolerance)) fmt.Printf("refresh duration: %s", refreshDuration) return refreshDuration })