sigs.k8s.io/cluster-api-provider-aws@v1.5.5/pkg/cloud/identity/identity.go (about) 1 /* 2 Copyright 2021 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package identity 18 19 import ( 20 "bytes" 21 "crypto/sha256" 22 "encoding/gob" 23 "time" 24 25 "github.com/aws/aws-sdk-go/aws" 26 "github.com/aws/aws-sdk-go/aws/credentials" 27 "github.com/aws/aws-sdk-go/aws/credentials/stscreds" 28 "github.com/aws/aws-sdk-go/aws/session" 29 "github.com/aws/aws-sdk-go/service/sts/stsiface" 30 "github.com/go-logr/logr" 31 corev1 "k8s.io/api/core/v1" 32 33 infrav1 "sigs.k8s.io/cluster-api-provider-aws/api/v1beta1" 34 ) 35 36 // AWSPrincipalTypeProvider defines the interface for AWS Principal Type Provider. 37 type AWSPrincipalTypeProvider interface { 38 credentials.Provider 39 // Hash returns a unique hash of the data forming the credentials 40 // for this Principal 41 Hash() (string, error) 42 Name() string 43 } 44 45 // NewAWSStaticPrincipalTypeProvider will create a new AWSStaticPrincipalTypeProvider from a given AWSClusterStaticIdentity. 46 func NewAWSStaticPrincipalTypeProvider(identity *infrav1.AWSClusterStaticIdentity, secret *corev1.Secret) *AWSStaticPrincipalTypeProvider { 47 accessKeyID := string(secret.Data["AccessKeyID"]) 48 secretAccessKey := string(secret.Data["SecretAccessKey"]) 49 sessionToken := string(secret.Data["SessionToken"]) 50 51 return &AWSStaticPrincipalTypeProvider{ 52 Principal: identity, 53 credentials: credentials.NewStaticCredentials(accessKeyID, secretAccessKey, sessionToken), 54 AccessKeyID: accessKeyID, 55 SecretAccessKey: secretAccessKey, 56 SessionToken: sessionToken, 57 } 58 } 59 60 // GetAssumeRoleCredentials will return the Credentials of a given AWSRolePrincipalTypeProvider. 61 func GetAssumeRoleCredentials(roleIdentityProvider *AWSRolePrincipalTypeProvider, awsConfig *aws.Config) *credentials.Credentials { 62 sess := session.Must(session.NewSession(awsConfig)) 63 64 creds := stscreds.NewCredentials(sess, roleIdentityProvider.Principal.Spec.RoleArn, func(p *stscreds.AssumeRoleProvider) { 65 if roleIdentityProvider.Principal.Spec.ExternalID != "" { 66 p.ExternalID = aws.String(roleIdentityProvider.Principal.Spec.ExternalID) 67 } 68 p.RoleSessionName = roleIdentityProvider.Principal.Spec.SessionName 69 if roleIdentityProvider.Principal.Spec.InlinePolicy != "" { 70 p.Policy = aws.String(roleIdentityProvider.Principal.Spec.InlinePolicy) 71 } 72 p.Duration = time.Duration(roleIdentityProvider.Principal.Spec.DurationSeconds) * time.Second 73 // For testing 74 if roleIdentityProvider.stsClient != nil { 75 p.Client = roleIdentityProvider.stsClient 76 } 77 }) 78 return creds 79 } 80 81 // NewAWSRolePrincipalTypeProvider will create a new AWSRolePrincipalTypeProvider from an AWSClusterRoleIdentity. 82 func NewAWSRolePrincipalTypeProvider(identity *infrav1.AWSClusterRoleIdentity, sourceProvider *AWSPrincipalTypeProvider, log logr.Logger) *AWSRolePrincipalTypeProvider { 83 return &AWSRolePrincipalTypeProvider{ 84 credentials: nil, 85 stsClient: nil, 86 Principal: identity, 87 sourceProvider: sourceProvider, 88 log: log.WithName("AWSRolePrincipalTypeProvider"), 89 } 90 } 91 92 // AWSStaticPrincipalTypeProvider defines the specs for a static AWSPrincipalTypeProvider. 93 type AWSStaticPrincipalTypeProvider struct { 94 Principal *infrav1.AWSClusterStaticIdentity 95 credentials *credentials.Credentials 96 // these are for tests :/ 97 AccessKeyID string 98 SecretAccessKey string 99 SessionToken string 100 } 101 102 // Hash returns the byte encoded AWSStaticPrincipalTypeProvider. 103 func (p *AWSStaticPrincipalTypeProvider) Hash() (string, error) { 104 var roleIdentityValue bytes.Buffer 105 err := gob.NewEncoder(&roleIdentityValue).Encode(p) 106 if err != nil { 107 return "", err 108 } 109 hash := sha256.New() 110 return string(hash.Sum(roleIdentityValue.Bytes())), nil 111 } 112 113 // Retrieve returns the credential values for the AWSStaticPrincipalTypeProvider. 114 func (p *AWSStaticPrincipalTypeProvider) Retrieve() (credentials.Value, error) { 115 return p.credentials.Get() 116 } 117 118 // Name returns the name of the AWSStaticPrincipalTypeProvider. 119 func (p *AWSStaticPrincipalTypeProvider) Name() string { 120 return p.Principal.Name 121 } 122 123 // IsExpired checks the expiration state of the AWSStaticPrincipalTypeProvider. 124 func (p *AWSStaticPrincipalTypeProvider) IsExpired() bool { 125 return p.credentials.IsExpired() 126 } 127 128 // AWSRolePrincipalTypeProvider defines the specs for a AWSPrincipalTypeProvider with a role. 129 type AWSRolePrincipalTypeProvider struct { 130 Principal *infrav1.AWSClusterRoleIdentity 131 credentials *credentials.Credentials 132 sourceProvider *AWSPrincipalTypeProvider 133 log logr.Logger 134 stsClient stsiface.STSAPI 135 } 136 137 // Hash returns the byte encoded AWSRolePrincipalTypeProvider. 138 func (p *AWSRolePrincipalTypeProvider) Hash() (string, error) { 139 var roleIdentityValue bytes.Buffer 140 err := gob.NewEncoder(&roleIdentityValue).Encode(p) 141 if err != nil { 142 return "", err 143 } 144 hash := sha256.New() 145 return string(hash.Sum(roleIdentityValue.Bytes())), nil 146 } 147 148 // Name returns the name of the AWSRolePrincipalTypeProvider. 149 func (p *AWSRolePrincipalTypeProvider) Name() string { 150 return p.Principal.Name 151 } 152 153 // Retrieve returns the credential values for the AWSRolePrincipalTypeProvider. 154 func (p *AWSRolePrincipalTypeProvider) Retrieve() (credentials.Value, error) { 155 if p.credentials == nil || p.IsExpired() { 156 awsConfig := aws.NewConfig() 157 if p.sourceProvider != nil { 158 sourceCreds, err := (*p.sourceProvider).Retrieve() 159 if err != nil { 160 return credentials.Value{}, err 161 } 162 awsConfig = awsConfig.WithCredentials(credentials.NewStaticCredentialsFromCreds(sourceCreds)) 163 } 164 165 creds := GetAssumeRoleCredentials(p, awsConfig) 166 // Update credentials 167 p.credentials = creds 168 } 169 return p.credentials.Get() 170 } 171 172 // IsExpired checks the expiration state of the AWSRolePrincipalTypeProvider. 173 func (p *AWSRolePrincipalTypeProvider) IsExpired() bool { 174 return p.credentials.IsExpired() 175 }