Browse Source

Implement and test logic for external id field when assuming IAM role for AWS (#2023)

Added external id field to struct. Wrote test in AWS provider to check
external ID field in IAM role. Added external id info to current log
when starting an aws session.

Signed-off-by: Cindy <choilmto@gmail.com>
choilmto 3 years ago
parent
commit
5267c6ee5d

+ 3 - 0
apis/externalsecrets/v1beta1/secretstore_aws_types.go

@@ -83,4 +83,7 @@ type AWSProvider struct {
 	// AdditionalRoles is a chained list of Role ARNs which the SecretManager provider will sequentially assume before assuming Role
 	// AdditionalRoles is a chained list of Role ARNs which the SecretManager provider will sequentially assume before assuming Role
 	// +optional
 	// +optional
 	AdditionalRoles []string `json:"additionalRoles,omitempty"`
 	AdditionalRoles []string `json:"additionalRoles,omitempty"`
+
+	// AWS External ID set on assumed IAM roles
+	ExternalID string `json:"externalID,omitempty"`
 }
 }

+ 3 - 0
config/crds/bases/external-secrets.io_clustersecretstores.yaml

@@ -2015,6 +2015,9 @@ spec:
                                 type: object
                                 type: object
                             type: object
                             type: object
                         type: object
                         type: object
+                      externalID:
+                        description: AWS External ID set on assumed IAM roles
+                        type: string
                       region:
                       region:
                         description: AWS Region to be used for the provider
                         description: AWS Region to be used for the provider
                         type: string
                         type: string

+ 3 - 0
config/crds/bases/external-secrets.io_secretstores.yaml

@@ -2015,6 +2015,9 @@ spec:
                                 type: object
                                 type: object
                             type: object
                             type: object
                         type: object
                         type: object
+                      externalID:
+                        description: AWS External ID set on assumed IAM roles
+                        type: string
                       region:
                       region:
                         description: AWS Region to be used for the provider
                         description: AWS Region to be used for the provider
                         type: string
                         type: string

+ 6 - 0
deploy/crds/bundle.yaml

@@ -1909,6 +1909,9 @@ spec:
                                   type: object
                                   type: object
                               type: object
                               type: object
                           type: object
                           type: object
+                        externalID:
+                          description: AWS External ID set on assumed IAM roles
+                          type: string
                         region:
                         region:
                           description: AWS Region to be used for the provider
                           description: AWS Region to be used for the provider
                           type: string
                           type: string
@@ -5337,6 +5340,9 @@ spec:
                                   type: object
                                   type: object
                               type: object
                               type: object
                           type: object
                           type: object
+                        externalID:
+                          description: AWS External ID set on assumed IAM roles
+                          type: string
                         region:
                         region:
                           description: AWS Region to be used for the provider
                           description: AWS Region to be used for the provider
                           type: string
                           type: string

+ 11 - 0
docs/api/spec.md

@@ -230,6 +230,17 @@ string
 <p>AdditionalRoles is a chained list of Role ARNs which the SecretManager provider will sequentially assume before assuming Role</p>
 <p>AdditionalRoles is a chained list of Role ARNs which the SecretManager provider will sequentially assume before assuming Role</p>
 </td>
 </td>
 </tr>
 </tr>
+<tr>
+<td>
+<code>externalID</code></br>
+<em>
+string
+</em>
+</td>
+<td>
+<p>AWS External ID set on assumed IAM roles</p>
+</td>
+</tr>
 </tbody>
 </tbody>
 </table>
 </table>
 <h3 id="external-secrets.io/v1beta1.AWSServiceType">AWSServiceType
 <h3 id="external-secrets.io/v1beta1.AWSServiceType">AWSServiceType

+ 10 - 2
pkg/provider/aws/auth/auth.go

@@ -126,11 +126,19 @@ func New(ctx context.Context, store esv1beta1.GenericStore, kube client.Client,
 		sess.Config.WithCredentials(stscreds.NewCredentialsWithClient(stsclient, aRole))
 		sess.Config.WithCredentials(stscreds.NewCredentialsWithClient(stsclient, aRole))
 	}
 	}
 
 
+	sessExtID := prov.ExternalID
 	if prov.Role != "" {
 	if prov.Role != "" {
 		stsclient := assumeRoler(sess)
 		stsclient := assumeRoler(sess)
-		sess.Config.WithCredentials(stscreds.NewCredentialsWithClient(stsclient, prov.Role))
+		if sessExtID != "" {
+			var setExternalID = func(p *stscreds.AssumeRoleProvider) {
+				p.ExternalID = aws.String(sessExtID)
+			}
+			sess.Config.WithCredentials(stscreds.NewCredentialsWithClient(stsclient, prov.Role, setExternalID))
+		} else {
+			sess.Config.WithCredentials(stscreds.NewCredentialsWithClient(stsclient, prov.Role))
+		}
 	}
 	}
-	log.Info("using aws session", "region", *sess.Config.Region, "credentials", creds)
+	log.Info("using aws session", "region", *sess.Config.Region, "external id", sessExtID, "credentials", creds)
 	return sess, nil
 	return sess, nil
 }
 }
 
 

+ 39 - 0
pkg/provider/aws/auth/auth_test.go

@@ -405,6 +405,45 @@ func TestNewSession(t *testing.T) {
 			expectedKeyID:     "3333",
 			expectedKeyID:     "3333",
 			expectedSecretKey: "4444",
 			expectedSecretKey: "4444",
 		},
 		},
+		{
+			name: "configure aws using environment variables + assume role + check external id",
+			stsProvider: func(*awssess.Session) stsiface.STSAPI {
+				return &fakesess.AssumeRoler{
+					AssumeRoleFunc: func(input *sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error) {
+						assert.Equal(t, *input.ExternalId, "12345678")
+						return &sts.AssumeRoleOutput{
+							AssumedRoleUser: &sts.AssumedRoleUser{
+								Arn:           aws.String("1123132"),
+								AssumedRoleId: aws.String("xxxxx"),
+							},
+							Credentials: &sts.Credentials{
+								AccessKeyId:     aws.String("3333"),
+								SecretAccessKey: aws.String("4444"),
+								Expiration:      aws.Time(time.Now().Add(time.Hour)),
+								SessionToken:    aws.String("6666"),
+							},
+						}, nil
+					},
+				}
+			},
+			store: &esv1beta1.SecretStore{
+				Spec: esv1beta1.SecretStoreSpec{
+					Provider: &esv1beta1.SecretStoreProvider{
+						AWS: &esv1beta1.AWSProvider{
+							Role:       "foo-bar-baz",
+							ExternalID: "12345678",
+						},
+					},
+				},
+			},
+			env: map[string]string{
+				"AWS_ACCESS_KEY_ID":     "1111",
+				"AWS_SECRET_ACCESS_KEY": "2222",
+			},
+			expectProvider:    true,
+			expectedKeyID:     "3333",
+			expectedSecretKey: "4444",
+		},
 	}
 	}
 	for i := range rows {
 	for i := range rows {
 		row := rows[i]
 		row := rows[i]