github.com/defang-io/defang/src@v0.0.0-20240505002154-bdf411911834/pkg/clouds/aws/common.go (about)

     1  package aws
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"os/exec"
     7  	"strings"
     8  
     9  	"github.com/aws/aws-sdk-go-v2/aws"
    10  	"github.com/aws/aws-sdk-go-v2/config"
    11  	"github.com/aws/aws-sdk-go-v2/credentials/processcreds"
    12  )
    13  
    14  type Region string
    15  
    16  type Aws struct {
    17  	Region Region
    18  }
    19  
    20  func (r Region) String() string {
    21  	return string(r)
    22  }
    23  
    24  func (a *Aws) LoadConfig(ctx context.Context) (aws.Config, error) {
    25  	cfg, err := LoadDefaultConfig(ctx, a.Region)
    26  	if err != nil {
    27  		return cfg, err
    28  	}
    29  	if cfg.Region == "" {
    30  		return cfg, errors.New("missing AWS region: set AWS_REGION or edit your AWS profile")
    31  	}
    32  	a.Region = Region(cfg.Region)
    33  	return cfg, err
    34  }
    35  
    36  func LoadDefaultConfig(ctx context.Context, region Region) (aws.Config, error) {
    37  	cfg, err := config.LoadDefaultConfig(ctx, config.WithRegion(string(region)))
    38  	if err != nil {
    39  		return cfg, err
    40  	}
    41  
    42  	// cliProvider invokes aws cli to obtain credentials aws cli is using
    43  	// Based on https://github.com/aws/aws-sdk-go-v2/issues/1433
    44  	cliProvider := processcreds.NewProviderCommand(
    45  		processcreds.NewCommandBuilderFunc(
    46  			func(ctx context.Context) (*exec.Cmd, error) {
    47  				return exec.CommandContext(ctx, "aws", "configure", "export-credentials", "--format", "process"), nil
    48  			},
    49  		),
    50  	)
    51  
    52  	cfg.Credentials = newChainProvider(
    53  		cliProvider,
    54  		cfg.Credentials,
    55  	)
    56  	return cfg, nil
    57  }
    58  
    59  func GetAccountID(arn string) string {
    60  	parts := strings.Split(arn, ":")
    61  	return parts[4]
    62  }
    63  
    64  func newChainProvider(providers ...aws.CredentialsProvider) aws.CredentialsProvider {
    65  	return aws.NewCredentialsCache(
    66  		aws.CredentialsProviderFunc(func(ctx context.Context) (aws.Credentials, error) {
    67  			var errs []error
    68  
    69  			for _, p := range providers {
    70  				creds, err := p.Retrieve(ctx)
    71  				if err == nil {
    72  					return creds, nil
    73  				}
    74  
    75  				errs = append(errs, err)
    76  			}
    77  
    78  			return aws.Credentials{}, errors.Join(errs...)
    79  		}),
    80  	)
    81  }