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 }