github.com/diggerhq/digger/libs@v0.0.0-20240604170430-9d61cdf01cc5/locking/aws/envprovider/envprovider.go (about)

     1  package envprovider
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"log"
     8  	"os"
     9  
    10  	"github.com/aws/aws-sdk-go-v2/service/sts"
    11  
    12  	"github.com/aws/aws-sdk-go-v2/aws"
    13  	"github.com/aws/aws-sdk-go-v2/config"
    14  )
    15  
    16  // EnvProviderName provides a name of Env provider
    17  const EnvProviderName = "DiggerEnvProvider"
    18  
    19  var (
    20  	// ErrAccessKeyIDNotFound is returned when the AWS Access Key ID can't be
    21  	// found in the process's environment.
    22  	ErrAccessKeyIDNotFound = errors.New("EnvAccessKeyNotFound: DIGGER_AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY not found in environment")
    23  
    24  	// ErrSecretAccessKeyNotFound is returned when the AWS Secret Access Key
    25  	// can't be found in the process's environment.
    26  	ErrSecretAccessKeyNotFound = errors.New("EnvSecretNotFound: DIGGER_AWS_SECRET_ACCESS_KEY or AWS_SECRET_ACCESS_KEY or AWS_SECRET_KEY not found in environment")
    27  
    28  	ErrRoleNotValid = errors.New("EnvRoleNotValid: AWS_ROLE_ARN not valid")
    29  )
    30  
    31  // A EnvProvider retrieves credentials from the environment variables of the
    32  // running process. Environment credentials never expire.
    33  //
    34  // Environment variables used:
    35  //
    36  // * Access Key ID:     DIGGER_AWS_ACCESS_KEY_ID or DIGGER_AWS_ACCESS_KEY, AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY
    37  //
    38  // * Secret Access Key: DIGGER_AWS_SECRET_ACCESS_KEY or DIGGER_AWS_SECRET_KEY, AWS_SECRET_ACCESS_KEY or AWS_SECRET_KEY
    39  type EnvProvider struct {
    40  	retrieved bool
    41  	// roleToAssume *string
    42  }
    43  
    44  // TODO: Refactor this to start using the same Envprovider interface
    45  // Also it might be worth using `AssumeRoleProvider` interface
    46  type RoleProvider interface {
    47  	GetKeysFromRole(role string) (*aws.Credentials, error)
    48  }
    49  
    50  type AwsRoleProvider struct{}
    51  
    52  func (a AwsRoleProvider) GetKeysFromRole(role string) (*aws.Credentials, error) {
    53  	cfg, err := config.LoadDefaultConfig(context.TODO())
    54  	if err != nil {
    55  		return nil, fmt.Errorf("GetKeysFromRole: Could not create aws session, %v", err)
    56  	}
    57  	stsService := sts.NewFromConfig(cfg)
    58  
    59  	params := &sts.AssumeRoleInput{
    60  		RoleArn:         aws.String(role),
    61  		RoleSessionName: aws.String(EnvProviderName),
    62  		ExternalId:      aws.String(EnvProviderName),
    63  	}
    64  
    65  	resp, err := stsService.AssumeRole(context.Background(), params)
    66  	if err != nil {
    67  		log.Printf("error in GetkeysFromRole %v", err)
    68  		return nil, ErrRoleNotValid
    69  	}
    70  	akey := *resp.Credentials.AccessKeyId
    71  	asecret := *resp.Credentials.SecretAccessKey
    72  	asesstoken := *resp.Credentials.SessionToken
    73  
    74  	return &aws.Credentials{
    75  		AccessKeyID:     akey,
    76  		SecretAccessKey: asecret,
    77  		SessionToken:    asesstoken,
    78  	}, nil
    79  }
    80  
    81  // Retrieve retrieves the keys from the environment.
    82  func (e *EnvProvider) Retrieve(ctx context.Context) (aws.Credentials, error) {
    83  	e.retrieved = false
    84  	//assign id from env vars
    85  	idEnvVars := []string{"DIGGER_AWS_ACCESS_KEY_ID", "AWS_ACCESS_KEY_ID", "AWS_ACCESS_KEY"}
    86  	id, err := assignEnv(idEnvVars)
    87  	if err != nil {
    88  		return aws.Credentials{}, ErrAccessKeyIDNotFound
    89  	}
    90  
    91  	//assign secret from env vars
    92  	secretEnvVars := []string{"DIGGER_AWS_SECRET_ACCESS_KEY", "AWS_SECRET_ACCESS_KEY", "AWS_SECRET_KEY"}
    93  	secret, err := assignEnv(secretEnvVars)
    94  	if err != nil {
    95  		return aws.Credentials{}, ErrSecretAccessKeyNotFound
    96  	}
    97  
    98  	e.retrieved = true
    99  	return aws.Credentials{
   100  		AccessKeyID:     id,
   101  		SecretAccessKey: secret,
   102  		SessionToken:    os.Getenv("AWS_SESSION_TOKEN"),
   103  	}, nil
   104  
   105  }
   106  
   107  // Assign first non-nil env var
   108  func assignEnv(envVars []string) (string, error) {
   109  	var v string
   110  	for _, envVar := range envVars {
   111  		if value, ok := os.LookupEnv(envVar); ok {
   112  			v = value
   113  			return v, nil
   114  		}
   115  	}
   116  	return "", errors.New("not found")
   117  }
   118  
   119  // IsExpired returns if the credentials have been retrieved.
   120  func (e *EnvProvider) IsExpired() bool {
   121  	return !e.retrieved
   122  }