add iam:CreateServiceLinkedRole to DeployService (#44194)

If the ECS service-linked role managed by AWS does not exist yet, then
when the OIDC integration calls ecs:CreateCluster it will fail.
Adding this permission will allow the API call to automatically
create the service-linked role on first use of ECS.
This commit is contained in:
Gavin Frazar
2024-07-16 19:57:11 +00:00
committed by GitHub
parent 70849a67f6
commit 8e7ff7efd3
2 changed files with 20 additions and 0 deletions
+3
View File
@@ -65,6 +65,9 @@ func StatementForECSManageService() *Statement {
// EC2 DescribeSecurityGroups is required so that the user can list the SG and then pick which ones they want to apply to the ECS Service.
"ec2:DescribeSecurityGroups",
// IAM CreateServiceLinkedRole is required to ensure the ECS Service linked role exists.
"iam:CreateServiceLinkedRole",
},
Resources: allResources,
}
+17
View File
@@ -26,6 +26,7 @@ import (
"time"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/aws/retry"
"github.com/aws/aws-sdk-go-v2/service/ecs"
ecsTypes "github.com/aws/aws-sdk-go-v2/service/ecs/types"
"github.com/aws/aws-sdk-go-v2/service/sts"
@@ -557,6 +558,22 @@ func upsertCluster(ctx context.Context, clt DeployServiceClient, clusterName str
ClusterName: aws.String(clusterName),
CapacityProviders: requiredCapacityProviders,
Tags: resourceCreationTags.ToECSTags(),
}, func(o *ecs.Options) {
o.Retryer = retry.NewStandard(func(so *retry.StandardOptions) {
so.MaxAttempts = 10
so.MaxBackoff = time.Minute
// Retry if an error is a missing ECS service-linked role.
// This is a retryable error because the ECS service-linked role
// will be created automatically when the caller has
// iam:CreateServiceLinkedRole permission (we should).
// https://docs.aws.amazon.com/AmazonECS/latest/developerguide/using-service-linked-roles.html#create-slr
so.Retryables = append(so.Retryables, retry.IsErrorRetryableFunc(func(err error) aws.Ternary {
if err != nil && strings.Contains(err.Error(), "verify that the ECS service linked role exists") {
return aws.TrueTernary
}
return aws.FalseTernary
}))
})
})
if err != nil {
return nil, trace.Wrap(err)