diff --git a/tfstate/lookup.go b/tfstate/lookup.go index a8875ae..fb7ff52 100644 --- a/tfstate/lookup.go +++ b/tfstate/lookup.go @@ -171,18 +171,6 @@ func ReadURL(ctx context.Context, loc string) (*TFState, error) { case "s3": key := strings.TrimPrefix(u.Path, "/") src, err = readS3(ctx, u.Host, key, s3Option{}) - case "gs": - key := strings.TrimPrefix(u.Path, "/") - src, err = readGCS(ctx, u.Host, key, "", os.Getenv("GOOGLE_ENCRYPTION_KEY")) - case "azurerm": - split := strings.SplitN(u.Path, "/", 4) - - if len(split) < 4 { - err = fmt.Errorf("invalid azurerm url: %s", u.String()) - break - } - - src, err = readAzureRM(ctx, u.Host, split[1], split[2], split[3], azureRMOption{subscriptionID: u.User.Username()}) case "file": src, err = os.Open(u.Path) case "remote": diff --git a/tfstate/remote.go b/tfstate/remote.go index 01ea307..49da2af 100644 --- a/tfstate/remote.go +++ b/tfstate/remote.go @@ -29,10 +29,6 @@ func strpe(v interface{}) *string { func readRemoteState(ctx context.Context, b *backend, ws string) (io.ReadCloser, error) { switch b.Type { - case "gcs": - return readGCSState(ctx, b.Config, ws) - case "azurerm": - return readAzureRMState(ctx, b.Config, ws) case "s3": return readS3State(ctx, b.Config, ws) case "remote": diff --git a/tfstate/remote_azurerm.go b/tfstate/remote_azurerm.go deleted file mode 100644 index cd820ca..0000000 --- a/tfstate/remote_azurerm.go +++ /dev/null @@ -1,159 +0,0 @@ -package tfstate - -import ( - "context" - "fmt" - "io" - "os" - - "github.com/Azure/azure-sdk-for-go/sdk/azidentity" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob" - "github.com/Azure/go-autorest/autorest/azure/cli" - - "github.com/pkg/errors" -) - -type azureRMOption struct { - accessKey string - useAzureAdAuth string - subscriptionID string -} - -func readAzureRMState(ctx context.Context, config map[string]interface{}, ws string) (io.ReadCloser, error) { - accountName, containerName, key := *strp(config["storage_account_name"]), *strpe(config["container_name"]), *strpe(config["key"]) - resourceGroupName := *strp(config["resource_group_name"]) - if ws != defaultWorkspace { - if prefix := strp(config["workspace_key_prefix"]); prefix != nil { - key = key + *prefix + ws - } else { - key = key + defaultWorkspeceKeyPrefix + ws - } - } - opt := azureRMOption{ - accessKey: *strpe(config["access_key"]), - useAzureAdAuth: *strpe(config["use_azuread_auth"]), - subscriptionID: *strpe(config["subscription_id"]), - } - return readAzureRM(ctx, resourceGroupName, accountName, containerName, key, opt) -} - -func readAzureRM(ctx context.Context, resourceGroupName string, accountName string, containerName string, key string, opt azureRMOption) (io.ReadCloser, error) { - serviceUrl := fmt.Sprintf("https://%s.blob.core.windows.net/", accountName) - - var client *azblob.Client - - if opt.useAzureAdAuth == "true" || os.Getenv("ARM_USE_AZUREAD") == "true" { - cred, err := getDefaultAzureCredential() - if err != nil { - return nil, err - } - - client, err = azblob.NewClient(serviceUrl, cred, nil) - if err != nil { - return nil, errors.Wrap(err, "failed to setup client") - } - } else { - // get blob access key - var accountKey string - for _, gen := range []func() (string, error){ - func() (string, error) { return opt.accessKey, nil }, - func() (string, error) { return os.Getenv("AZURE_STORAGE_ACCESS_KEY"), nil }, - func() (string, error) { return getDefaultAzureAccessKey(ctx, resourceGroupName, accountName, opt) }, - } { - key, err := gen() - if err != nil { - return nil, err - } else if key != "" { - accountKey = key - break - } - } - if accountKey == "" { - return nil, errors.New("Blob access key not found in ENV, terraform config and can't be fetched from current Azure Profile") - } - - // Authenticate - credential, err := azblob.NewSharedKeyCredential(accountName, accountKey) - if err != nil { - return nil, errors.Wrap(err, "failed to create credential") - } - - client, err = azblob.NewClientWithSharedKeyCredential(serviceUrl, credential, nil) - if err != nil { - return nil, errors.Wrap(err, "failed to setup client") - } - } - - blobDownloadResponse, err := client.DownloadStream(ctx, containerName, key, nil) - if err != nil { - return nil, errors.Wrap(err, "failed to download blob") - } - - r := blobDownloadResponse.Body - return r, nil -} - -func getDefaultAzureSubscription() (string, error) { - if value, ok := os.LookupEnv("AZURE_SUBSCRIPTION_ID"); ok { - return value, nil - } - - profilePath, _ := cli.ProfilePath() - profile, err := cli.LoadProfile(profilePath) - if err != nil { - return "", errors.Wrap(err, "failed to load profile") - } - subscriptionID := "" - for _, x := range profile.Subscriptions { - if !x.IsDefault { - continue - } - subscriptionID = x.ID - } - return subscriptionID, nil -} - -func getDefaultAzureAccessKey(ctx context.Context, resourceGroupName string, accountName string, opt azureRMOption) (string, error) { - cred, err := getDefaultAzureCredential() - if err != nil { - return "", err - } - - subscriptionID, err := getAzureSubscription(opt) - if err != nil { - return "", err - } - - clientFactory, err := armstorage.NewClientFactory(subscriptionID, cred, nil) - if err != nil { - return "", errors.Wrap(err, "failed to create client factory") - } - keys, err := clientFactory.NewAccountsClient().ListKeys(ctx, resourceGroupName, accountName, nil) - if err != nil { - return "", errors.Wrap(err, "failed to list keys") - } - - return *keys.Keys[0].Value, nil -} - -func getAzureSubscription(opt azureRMOption) (string, error) { - if opt.subscriptionID != "" { - return opt.subscriptionID, nil - } - - subscriptionID, err := getDefaultAzureSubscription() - if err != nil { - return "", errors.Wrap(err, "failed to get default subscription") - } - - return subscriptionID, nil -} - -func getDefaultAzureCredential() (*azidentity.DefaultAzureCredential, error) { - cred, err := azidentity.NewDefaultAzureCredential(nil) - if err != nil { - return nil, errors.Wrap(err, "failed to authorize") - } - return cred, nil -} diff --git a/tfstate/remote_gcs.go b/tfstate/remote_gcs.go deleted file mode 100644 index 53726b7..0000000 --- a/tfstate/remote_gcs.go +++ /dev/null @@ -1,55 +0,0 @@ -package tfstate - -import ( - "context" - "encoding/base64" - "io" - "path" - - "cloud.google.com/go/storage" - "google.golang.org/api/option" -) - -func readGCSState(ctx context.Context, config map[string]interface{}, ws string) (io.ReadCloser, error) { - bucket := *strp(config["bucket"]) - prefix := *strpe(config["prefix"]) - credentials := *strpe(config["credentials"]) - encryption_key := *strpe(config["encryption_key"]) - - key := path.Join(prefix, ws+".tfstate") - - return readGCS(ctx, bucket, key, credentials, encryption_key) -} - -func readGCS(ctx context.Context, bucket, key, credentials, encryption_key string) (io.ReadCloser, error) { - var err error - - var client *storage.Client - if credentials != "" { - client, err = storage.NewClient(ctx, option.WithCredentialsFile(credentials)) - } else { - client, err = storage.NewClient(ctx) - } - - if err != nil { - return nil, err - } - - bkt := client.Bucket(bucket) - obj := bkt.Object(key) - - var r *storage.Reader - - if encryption_key != "" { - decodedKey, _ := base64.StdEncoding.DecodeString(encryption_key) - r, err = obj.Key(decodedKey).NewReader(ctx) - } else { - r, err = obj.NewReader(ctx) - } - - if err != nil { - return nil, err - } - - return r, nil -}