From 85645f465d82dc849dc51fcbd54a395ac185b6b6 Mon Sep 17 00:00:00 2001 From: Domas Monkus Date: Fri, 18 Nov 2022 14:07:33 +0200 Subject: [PATCH] Add structure for passing hardcoded credentials to task. (#722) Co-authored-by: Domas Monkus Co-authored-by: Helio Machado <0x2b3bfa0+git@googlemail.com> --- task/aws/client/client.go | 18 ++++- task/az/client/client.go | 82 ++++++++++++-------- task/az/resources/data_source_credentials.go | 9 +-- task/common/cloud.go | 37 ++++++++- task/gcp/client/client.go | 4 + task/k8s/client/client.go | 4 + 6 files changed, 111 insertions(+), 43 deletions(-) diff --git a/task/aws/client/client.go b/task/aws/client/client.go index a97260cc..8806e15f 100644 --- a/task/aws/client/client.go +++ b/task/aws/client/client.go @@ -7,6 +7,7 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/credentials" "github.com/aws/aws-sdk-go-v2/service/autoscaling" "github.com/aws/aws-sdk-go-v2/service/ec2" "github.com/aws/aws-sdk-go-v2/service/s3" @@ -29,7 +30,22 @@ func New(ctx context.Context, cloud common.Cloud, tags map[string]string) (*Clie region = val } - config, err := config.LoadDefaultConfig(ctx, config.WithRegion(region)) + options := []func(*config.LoadOptions) error{ + config.WithRegion(region), + } + + if awsCredentials := cloud.Credentials.AWSCredentials; awsCredentials != nil { + options = append(options, config.WithCredentialsProvider(credentials.StaticCredentialsProvider{ + Value: aws.Credentials{ + AccessKeyID: awsCredentials.AccessKeyID, + SecretAccessKey: awsCredentials.SecretAccessKey, + SessionToken: awsCredentials.SessionToken, + Source: "user-specified credentials", + }, + })) + } + + config, err := config.LoadDefaultConfig(ctx, options...) if err != nil { return nil, err } diff --git a/task/az/client/client.go b/task/az/client/client.go index 9261c993..1a22cbc7 100644 --- a/task/az/client/client.go +++ b/task/az/client/client.go @@ -9,6 +9,7 @@ import ( "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2020-06-01/resources" "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2021-04-01/storage" + "github.com/Azure/go-autorest/autorest" "github.com/Azure/go-autorest/autorest/azure/auth" "terraform-provider-iterative/task/common" @@ -16,26 +17,44 @@ import ( ) func New(ctx context.Context, cloud common.Cloud, tags map[string]string) (*Client, error) { - settings, err := auth.GetSettingsFromEnvironment() - if err != nil { - return nil, err - } - - subscription := settings.GetSubscriptionID() - if subscription == "" { - return nil, errors.New("subscription environment variable not found") - } - - authorizer, err := settings.GetAuthorizer() - if err != nil { - return nil, err + var authorizer autorest.Authorizer + + if azCredentials := cloud.Credentials.AZCredentials; azCredentials != nil { + au, err := auth.NewClientCredentialsConfig( + azCredentials.ClientID, + azCredentials.ClientSecret, + azCredentials.TenantID, + ).Authorizer() + if err != nil { + return nil, err + } + authorizer = au + } else { + settings, err := auth.GetSettingsFromEnvironment() + if err != nil { + return nil, err + } + credentials, err := settings.GetClientCredentials() + if err != nil { + return nil, err + } + authorizer, err = settings.GetAuthorizer() + if err != nil { + return nil, err + } + + cloud.Credentials.AZCredentials = &common.AZCredentials{ + SubscriptionID: settings.GetSubscriptionID(), + ClientID: credentials.ClientID, + ClientSecret: credentials.ClientSecret, + TenantID: credentials.TenantID, + } } agent := "tpi" c := &Client{ - Cloud: cloud, - Settings: settings, + Cloud: cloud, } for key, value := range tags { @@ -54,75 +73,79 @@ func New(ctx context.Context, cloud common.Cloud, tags map[string]string) (*Clie region = val } + if cloud.Credentials.AZCredentials.SubscriptionID == "" { + return nil, errors.New("subscription environment variable not found") + } + c.Region = region - c.Services.Groups = resources.NewGroupsClient(subscription) + c.Services.Groups = resources.NewGroupsClient(cloud.Credentials.AZCredentials.SubscriptionID) c.Services.Groups.Authorizer = authorizer if err := c.Services.Groups.AddToUserAgent(agent); err != nil { return nil, err } - c.Services.SecurityGroups = network.NewSecurityGroupsClient(subscription) + c.Services.SecurityGroups = network.NewSecurityGroupsClient(cloud.Credentials.AZCredentials.SubscriptionID) c.Services.SecurityGroups.Authorizer = authorizer if err := c.Services.SecurityGroups.AddToUserAgent(agent); err != nil { return nil, err } - c.Services.PublicIPPrefixes = network.NewPublicIPPrefixesClient(subscription) + c.Services.PublicIPPrefixes = network.NewPublicIPPrefixesClient(cloud.Credentials.AZCredentials.SubscriptionID) c.Services.PublicIPPrefixes.Authorizer = authorizer if err := c.Services.PublicIPPrefixes.AddToUserAgent(agent); err != nil { return nil, err } - c.Services.PublicIPAddresses = network.NewPublicIPAddressesClient(subscription) + c.Services.PublicIPAddresses = network.NewPublicIPAddressesClient(cloud.Credentials.AZCredentials.SubscriptionID) c.Services.PublicIPAddresses.Authorizer = authorizer if err := c.Services.PublicIPAddresses.AddToUserAgent(agent); err != nil { return nil, err } - c.Services.VirtualNetworks = network.NewVirtualNetworksClient(subscription) + c.Services.VirtualNetworks = network.NewVirtualNetworksClient(cloud.Credentials.AZCredentials.SubscriptionID) c.Services.VirtualNetworks.Authorizer = authorizer if err := c.Services.VirtualNetworks.AddToUserAgent(agent); err != nil { return nil, err } - c.Services.Subnets = network.NewSubnetsClient(subscription) + c.Services.Subnets = network.NewSubnetsClient(cloud.Credentials.AZCredentials.SubscriptionID) c.Services.Subnets.Authorizer = authorizer if err := c.Services.Subnets.AddToUserAgent(agent); err != nil { return nil, err } - c.Services.Interfaces = network.NewInterfacesClient(subscription) + c.Services.Interfaces = network.NewInterfacesClient(cloud.Credentials.AZCredentials.SubscriptionID) c.Services.Interfaces.Authorizer = authorizer if err := c.Services.Interfaces.AddToUserAgent(agent); err != nil { return nil, err } - c.Services.VirtualMachines = compute.NewVirtualMachinesClient(subscription) + c.Services.VirtualMachines = compute.NewVirtualMachinesClient(cloud.Credentials.AZCredentials.SubscriptionID) c.Services.VirtualMachines.Authorizer = authorizer if err := c.Services.VirtualMachines.AddToUserAgent(agent); err != nil { return nil, err } - c.Services.VirtualMachineScaleSets = compute.NewVirtualMachineScaleSetsClient(subscription) + c.Services.VirtualMachineScaleSets = compute.NewVirtualMachineScaleSetsClient(cloud.Credentials.AZCredentials.SubscriptionID) c.Services.VirtualMachineScaleSets.Authorizer = authorizer if err := c.Services.VirtualMachineScaleSets.AddToUserAgent(agent); err != nil { return nil, err } - c.Services.VirtualMachineScaleSetVMs = compute.NewVirtualMachineScaleSetVMsClient(subscription) + c.Services.VirtualMachineScaleSetVMs = compute.NewVirtualMachineScaleSetVMsClient(cloud.Credentials.AZCredentials.SubscriptionID) c.Services.VirtualMachineScaleSetVMs.Authorizer = authorizer if err := c.Services.VirtualMachineScaleSetVMs.AddToUserAgent(agent); err != nil { return nil, err } - c.Services.StorageAccounts = storage.NewAccountsClient(subscription) + c.Services.StorageAccounts = storage.NewAccountsClient(cloud.Credentials.AZCredentials.SubscriptionID) c.Services.StorageAccounts.Authorizer = authorizer if err := c.Services.StorageAccounts.AddToUserAgent(agent); err != nil { return nil, err } - c.Services.BlobContainers = storage.NewBlobContainersClient(subscription) + c.Services.BlobContainers = storage.NewBlobContainersClient(cloud.Credentials.AZCredentials.SubscriptionID) c.Services.BlobContainers.Authorizer = authorizer if err := c.Services.BlobContainers.AddToUserAgent(agent); err != nil { return nil, err @@ -153,10 +176,7 @@ type Client struct { } func (c *Client) GetKeyPair(ctx context.Context) (*ssh.DeterministicSSHKeyPair, error) { - credentials, err := c.Settings.GetClientCredentials() - if err != nil { - return nil, err - } + credentials := c.Cloud.Credentials.AZCredentials if len(credentials.ClientSecret) == 0 { return nil, errors.New("unable to find client secret") diff --git a/task/az/resources/data_source_credentials.go b/task/az/resources/data_source_credentials.go index c39b6d23..e3e292fc 100644 --- a/task/az/resources/data_source_credentials.go +++ b/task/az/resources/data_source_credentials.go @@ -30,10 +30,7 @@ type Credentials struct { } func (c *Credentials) Read(ctx context.Context) error { - credentials, err := c.client.Settings.GetClientCredentials() - if err != nil { - return err - } + credentials := c.client.Cloud.Credentials.AZCredentials if len(credentials.ClientSecret) == 0 { return errors.New("unable to find client secret") @@ -44,12 +41,10 @@ func (c *Credentials) Read(ctx context.Context) error { return err } - subscriptionID := c.client.Settings.GetSubscriptionID() - c.Resource = map[string]string{ "AZURE_CLIENT_ID": credentials.ClientID, "AZURE_CLIENT_SECRET": credentials.ClientSecret, - "AZURE_SUBSCRIPTION_ID": subscriptionID, + "AZURE_SUBSCRIPTION_ID": credentials.SubscriptionID, "AZURE_TENANT_ID": credentials.TenantID, "RCLONE_REMOTE": connectionString, "TPI_TASK_CLOUD_PROVIDER": string(c.client.Cloud.Provider), diff --git a/task/common/cloud.go b/task/common/cloud.go index 2ddb4e97..3e80c1e3 100644 --- a/task/common/cloud.go +++ b/task/common/cloud.go @@ -6,10 +6,11 @@ import ( ) type Cloud struct { - Timeouts Timeouts - Provider Provider - Region Region - Tags map[string]string + Timeouts Timeouts + Provider Provider + Credentials Credentials + Region Region + Tags map[string]string } type Timeouts struct { @@ -29,6 +30,34 @@ const ( ProviderK8S Provider = "k8s" ) +type Credentials struct { + AWSCredentials *AWSCredentials + GCPCredentials *GCPCredentials + AZCredentials *AZCredentials + K8SCredentials *K8SCredentials +} + +type AWSCredentials struct { + AccessKeyID string // AWS_ACCESS_KEY_ID + SecretAccessKey string // AWS_SECRET_ACCESS_KEY + SessionToken string // AWS_SESSION_TOKEN +} + +type GCPCredentials struct { + ApplicationCredentials string // GOOGLE_APPLICATION_CREDENTIALS (contents of file) +} + +type AZCredentials struct { + ClientID string // AZURE_CLIENT_ID + ClientSecret string // AZURE_CLIENT_SECRET + SubscriptionID string // AZURE_SUBSCRIPTION_ID + TenantID string // AZURE_TENANT_ID +} + +type K8SCredentials struct { + Config string // KUBECONFIG (contents of file) +} + func (c *Cloud) GetClosestRegion(regions map[string]Region) (string, error) { for key, value := range regions { if value == c.Region { diff --git a/task/gcp/client/client.go b/task/gcp/client/client.go index 6b3f1057..9717af35 100644 --- a/task/gcp/client/client.go +++ b/task/gcp/client/client.go @@ -23,6 +23,10 @@ func New(ctx context.Context, cloud common.Cloud, tags map[string]string) (*Clie credentialsData := []byte(os.Getenv("GOOGLE_APPLICATION_CREDENTIALS_DATA")) + if gcpCredentials := cloud.Credentials.GCPCredentials; gcpCredentials != nil { + credentialsData = []byte(gcpCredentials.ApplicationCredentials) + } + var err error var credentials *google.Credentials if len(credentialsData) > 0 { diff --git a/task/k8s/client/client.go b/task/k8s/client/client.go index 8c789fe9..214f89ad 100644 --- a/task/k8s/client/client.go +++ b/task/k8s/client/client.go @@ -22,6 +22,10 @@ func New(ctx context.Context, cloud common.Cloud, tags map[string]string) (*Clie kubeconfig = os.Getenv("KUBECONFIG_DATA") } + if k8sCredentials := cloud.Credentials.K8SCredentials; k8sCredentials != nil { + kubeconfig = k8sCredentials.Config + } + config, err := clientcmd.NewClientConfigFromBytes([]byte(kubeconfig)) if err != nil || kubeconfig == "" { config = clientcmd.NewNonInteractiveDeferredLoadingClientConfig(