mirror of
https://github.com/Sea-Haven-Industries/seahaven-org-baseline.git
synced 2026-10-06 20:21:58 +00:00
564 lines
17 KiB
TypeScript
564 lines
17 KiB
TypeScript
|
|
import * as cdk from "aws-cdk-lib";
|
||
|
|
import * as iam from "aws-cdk-lib/aws-iam";
|
||
|
|
import { Construct } from "constructs";
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Prod exec roles for the mta-sts HCP workspace (PLAT-243).
|
||
|
|
*
|
||
|
|
* Nested in the prod seahaven-hcptf stack beside SeahavenSiteRoles. These
|
||
|
|
* roles are new. Plain CloudFormation create, no import template.
|
||
|
|
*
|
||
|
|
* The workspace owns four S3 origin buckets named `mta-sts-prod-<slug>`,
|
||
|
|
* four CloudFront distributions with OACs, four exact-name ACM
|
||
|
|
* certificates tagged Project=mta-sts, the SSM deploy contract under
|
||
|
|
* `/mta-sts/deploy/`, and the GitHub content-deploy role
|
||
|
|
* `githubdeploy-mta-sts` with its boundary. Policy files are published by
|
||
|
|
* GitHub Actions, not Terraform, so no object-level grants beyond the
|
||
|
|
* bucket itself are needed here.
|
||
|
|
*
|
||
|
|
* CloudFront distribution and ACM writes are gated on Project=mta-sts
|
||
|
|
* request and resource tags. The workspace provider must set that tag in
|
||
|
|
* default_tags, or the first apply fails on CreateDistribution.
|
||
|
|
*
|
||
|
|
* Inline policies are managed policies at /tf-managed/. Do not rename
|
||
|
|
* the roles.
|
||
|
|
*/
|
||
|
|
export class MtaStsRoles extends Construct {
|
||
|
|
constructor(scope: Construct, id: string) {
|
||
|
|
super(scope, id);
|
||
|
|
|
||
|
|
// Overrides the parent stack's Project=payments-dashboard tag.
|
||
|
|
cdk.Tags.of(this).add("Project", "mta-sts", { priority: 200 });
|
||
|
|
|
||
|
|
const account = cdk.Stack.of(this).account;
|
||
|
|
const deployRole = `arn:aws:iam::${account}:role/tf-managed/githubdeploy-mta-sts`;
|
||
|
|
const boundary = `arn:aws:iam::${account}:policy/tf-managed/mta-sts-githubdeploy-boundary`;
|
||
|
|
// One ARN covers the four buckets and their objects. `*` spans `/`, so a
|
||
|
|
// second `mta-sts-prod-*/*` entry is redundant (Access Analyzer flags it).
|
||
|
|
const buckets = ["arn:aws:s3:::mta-sts-prod-*"];
|
||
|
|
const deployParams = `arn:aws:ssm:us-east-1:${account}:parameter/mta-sts/deploy/*`;
|
||
|
|
const wafParam = `arn:aws:ssm:us-east-1:${account}:parameter/seahaven/waf/app-web-acl-arn`;
|
||
|
|
const githubOidc = `arn:aws:iam::${account}:oidc-provider/token.actions.githubusercontent.com`;
|
||
|
|
const hcpOidc = `arn:aws:iam::${account}:oidc-provider/app.terraform.io`;
|
||
|
|
|
||
|
|
const iamPolicy = managedPolicy(
|
||
|
|
this,
|
||
|
|
"IamPolicy",
|
||
|
|
"mta-sts-hcptf-iam",
|
||
|
|
scopedIamPolicy(account, deployRole, boundary),
|
||
|
|
);
|
||
|
|
const services = managedPolicy(
|
||
|
|
this,
|
||
|
|
"ServicesPolicy",
|
||
|
|
"mta-sts-hcptf-services",
|
||
|
|
servicesPolicy(account, buckets, deployParams, wafParam, githubOidc),
|
||
|
|
);
|
||
|
|
const planRefresh = managedPolicy(
|
||
|
|
this,
|
||
|
|
"PlanPolicy",
|
||
|
|
"mta-sts-hcptf-plan",
|
||
|
|
planPolicy(buckets, deployParams, wafParam, githubOidc, deployRole, boundary),
|
||
|
|
);
|
||
|
|
|
||
|
|
const apply = new iam.CfnRole(this, "ApplyRole", {
|
||
|
|
roleName: "hcptf-mta-sts",
|
||
|
|
maxSessionDuration: 3600,
|
||
|
|
assumeRolePolicyDocument: trust(hcpOidc, "apply"),
|
||
|
|
managedPolicyArns: [iamPolicy.ref, services.ref],
|
||
|
|
tags: roleTags(),
|
||
|
|
});
|
||
|
|
retain(apply);
|
||
|
|
|
||
|
|
const plan = new iam.CfnRole(this, "PlanRole", {
|
||
|
|
roleName: "hcptf-mta-sts-plan",
|
||
|
|
maxSessionDuration: 3600,
|
||
|
|
assumeRolePolicyDocument: trust(hcpOidc, "plan"),
|
||
|
|
managedPolicyArns: [
|
||
|
|
"arn:aws:iam::aws:policy/job-function/ViewOnlyAccess",
|
||
|
|
planRefresh.ref,
|
||
|
|
],
|
||
|
|
tags: roleTags(),
|
||
|
|
});
|
||
|
|
retain(plan);
|
||
|
|
|
||
|
|
const applyArn = new cdk.CfnOutput(this, "ApplyRoleArn", { value: apply.attrArn });
|
||
|
|
const planArn = new cdk.CfnOutput(this, "PlanRoleArn", { value: plan.attrArn });
|
||
|
|
applyArn.overrideLogicalId("MtaStsApplyRoleArn");
|
||
|
|
planArn.overrideLogicalId("MtaStsPlanRoleArn");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function managedPolicy(
|
||
|
|
scope: Construct,
|
||
|
|
id: string,
|
||
|
|
name: string,
|
||
|
|
policyDocument: object,
|
||
|
|
): iam.CfnManagedPolicy {
|
||
|
|
const policy = new iam.CfnManagedPolicy(scope, id, {
|
||
|
|
managedPolicyName: name,
|
||
|
|
path: "/tf-managed/",
|
||
|
|
policyDocument,
|
||
|
|
});
|
||
|
|
retain(policy);
|
||
|
|
return policy;
|
||
|
|
}
|
||
|
|
|
||
|
|
function retain(resource: cdk.CfnResource): void {
|
||
|
|
resource.cfnOptions.deletionPolicy = cdk.CfnDeletionPolicy.RETAIN;
|
||
|
|
resource.cfnOptions.updateReplacePolicy = cdk.CfnDeletionPolicy.RETAIN;
|
||
|
|
}
|
||
|
|
|
||
|
|
function roleTags(): cdk.CfnTag[] {
|
||
|
|
return [
|
||
|
|
{ key: "Project", value: "mta-sts" },
|
||
|
|
{ key: "Owner", value: "adam@seahavenind.com" },
|
||
|
|
{ key: "ManagedBy", value: "cdk" },
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
function trust(providerArn: string, phase: "apply" | "plan"): iam.PolicyDocument {
|
||
|
|
return iam.PolicyDocument.fromJson({
|
||
|
|
Version: "2012-10-17",
|
||
|
|
Statement: [
|
||
|
|
{
|
||
|
|
Sid: phase === "apply" ? "HcpApply" : "HcpPlan",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: "sts:AssumeRoleWithWebIdentity",
|
||
|
|
Principal: { Federated: providerArn },
|
||
|
|
Condition: {
|
||
|
|
StringEquals: {
|
||
|
|
"app.terraform.io:aud": "aws.workload.identity",
|
||
|
|
"app.terraform.io:sub":
|
||
|
|
`organization:seahaven:project:seahaven-prod:workspace:mta-sts-prod:run_phase:${phase}`,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
},
|
||
|
|
],
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
function servicesPolicy(
|
||
|
|
account: string,
|
||
|
|
buckets: string[],
|
||
|
|
deployParams: string,
|
||
|
|
wafParam: string,
|
||
|
|
githubOidc: string,
|
||
|
|
): object {
|
||
|
|
const distributions = `arn:aws:cloudfront::${account}:distribution/*`;
|
||
|
|
const oacs = `arn:aws:cloudfront::${account}:origin-access-control/*`;
|
||
|
|
return {
|
||
|
|
Version: "2012-10-17",
|
||
|
|
Statement: [
|
||
|
|
{
|
||
|
|
Sid: "OriginBuckets",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: "s3:*",
|
||
|
|
Resource: buckets,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
Sid: "ReadGithubOidcProvider",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: "iam:GetOpenIDConnectProvider",
|
||
|
|
Resource: githubOidc,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
Sid: "CloudFrontRead",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: [
|
||
|
|
"cloudfront:GetDistribution",
|
||
|
|
"cloudfront:GetDistributionConfig",
|
||
|
|
"cloudfront:GetInvalidation",
|
||
|
|
"cloudfront:GetOriginAccessControl",
|
||
|
|
"cloudfront:ListTagsForResource",
|
||
|
|
],
|
||
|
|
Resource: "*",
|
||
|
|
},
|
||
|
|
{
|
||
|
|
// The provider calls the CreateDistributionWithTags API, authorized
|
||
|
|
// as cloudfront:CreateDistribution. That action has no resource type
|
||
|
|
// and only accepts Resource "*". Request tags come from the
|
||
|
|
// workspace's default_tags.
|
||
|
|
Sid: "CloudFrontCreateTagged",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: "cloudfront:CreateDistribution",
|
||
|
|
Resource: "*",
|
||
|
|
Condition: { StringEquals: { "aws:RequestTag/Project": "mta-sts" } },
|
||
|
|
},
|
||
|
|
{
|
||
|
|
// Tagging at create time, before the distribution has any tags. The
|
||
|
|
// Null condition keeps this off every distribution that already has
|
||
|
|
// a Project tag, so another workspace's distribution cannot be
|
||
|
|
// re-tagged into CloudFrontManageTagged's scope.
|
||
|
|
Sid: "CloudFrontTagUntagged",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: "cloudfront:TagResource",
|
||
|
|
Resource: distributions,
|
||
|
|
Condition: {
|
||
|
|
StringEquals: { "aws:RequestTag/Project": "mta-sts" },
|
||
|
|
Null: { "aws:ResourceTag/Project": "true" },
|
||
|
|
},
|
||
|
|
},
|
||
|
|
{
|
||
|
|
// Mutation of a distribution another workspace owns is denied by the
|
||
|
|
// resource tag, the same pattern AcmManageTagged uses.
|
||
|
|
Sid: "CloudFrontManageTagged",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: [
|
||
|
|
"cloudfront:CreateInvalidation",
|
||
|
|
"cloudfront:DeleteDistribution",
|
||
|
|
"cloudfront:TagResource",
|
||
|
|
"cloudfront:UntagResource",
|
||
|
|
"cloudfront:UpdateDistribution",
|
||
|
|
],
|
||
|
|
Resource: distributions,
|
||
|
|
Condition: { StringEquals: { "aws:ResourceTag/Project": "mta-sts" } },
|
||
|
|
},
|
||
|
|
{
|
||
|
|
// CreateOriginAccessControl has no resource type; Resource "*" only.
|
||
|
|
Sid: "CloudFrontCreateOac",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: "cloudfront:CreateOriginAccessControl",
|
||
|
|
Resource: "*",
|
||
|
|
},
|
||
|
|
{
|
||
|
|
// Origin access controls do not support tags, so the OAC ARN type is
|
||
|
|
// the tightest available scope.
|
||
|
|
Sid: "CloudFrontManageOac",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: [
|
||
|
|
"cloudfront:DeleteOriginAccessControl",
|
||
|
|
"cloudfront:UpdateOriginAccessControl",
|
||
|
|
],
|
||
|
|
Resource: oacs,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
Sid: "AcmCreate",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: "acm:RequestCertificate",
|
||
|
|
Resource: "*",
|
||
|
|
Condition: { StringEquals: { "aws:RequestTag/Project": "mta-sts" } },
|
||
|
|
},
|
||
|
|
{
|
||
|
|
Sid: "AcmListTags",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: "acm:ListTagsForCertificate",
|
||
|
|
Resource: "*",
|
||
|
|
},
|
||
|
|
{
|
||
|
|
// The aws_acm_certificate resource reads with DescribeCertificate and
|
||
|
|
// reconciles tags with Add and Remove. No GetCertificate, Renew, or
|
||
|
|
// ListCertificates; those belong to the data source and early renewal.
|
||
|
|
Sid: "AcmManageTagged",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: [
|
||
|
|
"acm:AddTagsToCertificate",
|
||
|
|
"acm:DeleteCertificate",
|
||
|
|
"acm:DescribeCertificate",
|
||
|
|
"acm:RemoveTagsFromCertificate",
|
||
|
|
],
|
||
|
|
Resource: "*",
|
||
|
|
Condition: { StringEquals: { "aws:ResourceTag/Project": "mta-sts" } },
|
||
|
|
},
|
||
|
|
{
|
||
|
|
Sid: "ReadAppWebAclSsm",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: ["ssm:GetParameter", "ssm:GetParameters"],
|
||
|
|
Resource: wafParam,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
Sid: "WriteDeployContract",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: [
|
||
|
|
"ssm:AddTagsToResource",
|
||
|
|
"ssm:DeleteParameter",
|
||
|
|
"ssm:GetParameter",
|
||
|
|
"ssm:GetParameters",
|
||
|
|
"ssm:ListTagsForResource",
|
||
|
|
"ssm:PutParameter",
|
||
|
|
"ssm:RemoveTagsFromResource",
|
||
|
|
],
|
||
|
|
Resource: deployParams,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
Sid: "DescribeParameters",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: "ssm:DescribeParameters",
|
||
|
|
Resource: "*",
|
||
|
|
},
|
||
|
|
{
|
||
|
|
Sid: "ReadWafWebAcl",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: [
|
||
|
|
"wafv2:GetWebACL",
|
||
|
|
"wafv2:GetWebACLForResource",
|
||
|
|
"wafv2:ListResourcesForWebACL",
|
||
|
|
"wafv2:ListWebACLs",
|
||
|
|
],
|
||
|
|
Resource: "*",
|
||
|
|
},
|
||
|
|
],
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
function scopedIamPolicy(account: string, deployRole: string, boundary: string): object {
|
||
|
|
return {
|
||
|
|
Version: "2012-10-17",
|
||
|
|
Statement: [
|
||
|
|
{
|
||
|
|
Sid: "DenyUntaggedCreatePolicy",
|
||
|
|
Effect: "Deny",
|
||
|
|
Action: "iam:CreatePolicy",
|
||
|
|
Resource: "*",
|
||
|
|
Condition: { Null: { "aws:RequestTag/BoundaryFor": "true" } },
|
||
|
|
},
|
||
|
|
{
|
||
|
|
Sid: "DenyOtherCreatePolicy",
|
||
|
|
Effect: "Deny",
|
||
|
|
Action: "iam:CreatePolicy",
|
||
|
|
Resource: "*",
|
||
|
|
Condition: {
|
||
|
|
StringNotEquals: { "aws:RequestTag/BoundaryFor": "githubdeploy-mta-sts" },
|
||
|
|
},
|
||
|
|
},
|
||
|
|
{
|
||
|
|
Sid: "DenyOtherPolicyVersions",
|
||
|
|
Effect: "Deny",
|
||
|
|
Action: [
|
||
|
|
"iam:CreatePolicyVersion",
|
||
|
|
"iam:DeletePolicy",
|
||
|
|
"iam:DeletePolicyVersion",
|
||
|
|
"iam:SetDefaultPolicyVersion",
|
||
|
|
],
|
||
|
|
NotResource: boundary,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
// Only the boundary ARN may be created. The request tag stays as a
|
||
|
|
// second gate so the two Deny statements above keep their meaning.
|
||
|
|
Sid: "CreateDeployBoundary",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: "iam:CreatePolicy",
|
||
|
|
Resource: boundary,
|
||
|
|
Condition: {
|
||
|
|
StringEquals: { "aws:RequestTag/BoundaryFor": "githubdeploy-mta-sts" },
|
||
|
|
},
|
||
|
|
},
|
||
|
|
{
|
||
|
|
Sid: "ManageDeployBoundary",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: [
|
||
|
|
"iam:CreatePolicyVersion",
|
||
|
|
"iam:DeletePolicy",
|
||
|
|
"iam:DeletePolicyVersion",
|
||
|
|
"iam:GetPolicy",
|
||
|
|
"iam:GetPolicyVersion",
|
||
|
|
"iam:ListPolicyTags",
|
||
|
|
"iam:SetDefaultPolicyVersion",
|
||
|
|
"iam:TagPolicy",
|
||
|
|
"iam:UntagPolicy",
|
||
|
|
],
|
||
|
|
Resource: boundary,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
// Fresh role. Creation requires the deploy boundary to be set.
|
||
|
|
Sid: "CreateDeployRoleWithBoundary",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: "iam:CreateRole",
|
||
|
|
Resource: deployRole,
|
||
|
|
Condition: { StringEquals: { "iam:PermissionsBoundary": boundary } },
|
||
|
|
},
|
||
|
|
{
|
||
|
|
Sid: "WriteDeployRoles",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: [
|
||
|
|
"iam:AttachRolePolicy",
|
||
|
|
"iam:DeleteRole",
|
||
|
|
"iam:DeleteRolePolicy",
|
||
|
|
"iam:DetachRolePolicy",
|
||
|
|
"iam:PutRolePolicy",
|
||
|
|
"iam:TagRole",
|
||
|
|
"iam:UntagRole",
|
||
|
|
"iam:UpdateAssumeRolePolicy",
|
||
|
|
"iam:UpdateRole",
|
||
|
|
"iam:UpdateRoleDescription",
|
||
|
|
],
|
||
|
|
Resource: deployRole,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
Sid: "PutDeployRoleBoundary",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: "iam:PutRolePermissionsBoundary",
|
||
|
|
Resource: deployRole,
|
||
|
|
Condition: { StringEquals: { "iam:PermissionsBoundary": boundary } },
|
||
|
|
},
|
||
|
|
{
|
||
|
|
Sid: "IamReadOnly",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: [
|
||
|
|
"iam:GetPolicy",
|
||
|
|
"iam:GetPolicyVersion",
|
||
|
|
"iam:GetRole",
|
||
|
|
"iam:GetRolePolicy",
|
||
|
|
"iam:ListAttachedRolePolicies",
|
||
|
|
"iam:ListInstanceProfilesForRole",
|
||
|
|
"iam:ListPolicies",
|
||
|
|
"iam:ListPolicyVersions",
|
||
|
|
"iam:ListRolePolicies",
|
||
|
|
"iam:ListRoleTags",
|
||
|
|
"iam:ListRoles",
|
||
|
|
],
|
||
|
|
Resource: "*",
|
||
|
|
},
|
||
|
|
{
|
||
|
|
Sid: "DenySelfMutation",
|
||
|
|
Effect: "Deny",
|
||
|
|
Action: [
|
||
|
|
"iam:AttachRolePolicy",
|
||
|
|
"iam:DeleteRole",
|
||
|
|
"iam:DeleteRolePolicy",
|
||
|
|
"iam:DeleteRolePermissionsBoundary",
|
||
|
|
"iam:DetachRolePolicy",
|
||
|
|
"iam:PutRolePolicy",
|
||
|
|
"iam:PutRolePermissionsBoundary",
|
||
|
|
"iam:UpdateAssumeRolePolicy",
|
||
|
|
"iam:UpdateRole",
|
||
|
|
"iam:UpdateRoleDescription",
|
||
|
|
],
|
||
|
|
Resource: [
|
||
|
|
`arn:aws:iam::${account}:role/hcptf-*`,
|
||
|
|
`arn:aws:iam::${account}:role/github-cfn-execution-role`,
|
||
|
|
`arn:aws:iam::${account}:role/githubdeploy-*`,
|
||
|
|
`arn:aws:iam::${account}:role/cdk-hnb659fds-*`,
|
||
|
|
`arn:aws:iam::${account}:role/OrganizationAccountAccessRole`,
|
||
|
|
`arn:aws:iam::${account}:role/seahaven-*`,
|
||
|
|
],
|
||
|
|
},
|
||
|
|
{
|
||
|
|
Sid: "DenyBoundaryTampering",
|
||
|
|
Effect: "Deny",
|
||
|
|
Action: ["iam:DeleteRolePermissionsBoundary", "iam:DeleteUserPermissionsBoundary"],
|
||
|
|
Resource: [`arn:aws:iam::${account}:role/*`, `arn:aws:iam::${account}:user/*`],
|
||
|
|
},
|
||
|
|
{
|
||
|
|
Sid: "DenyBoundaryPolicyEdit",
|
||
|
|
Effect: "Deny",
|
||
|
|
Action: [
|
||
|
|
"iam:CreatePolicyVersion",
|
||
|
|
"iam:DeletePolicy",
|
||
|
|
"iam:DeletePolicyVersion",
|
||
|
|
"iam:SetDefaultPolicyVersion",
|
||
|
|
],
|
||
|
|
Resource: `arn:aws:iam::${account}:policy/seahaven-*`,
|
||
|
|
},
|
||
|
|
],
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
function planPolicy(
|
||
|
|
buckets: string[],
|
||
|
|
deployParams: string,
|
||
|
|
wafParam: string,
|
||
|
|
githubOidc: string,
|
||
|
|
deployRole: string,
|
||
|
|
boundary: string,
|
||
|
|
): object {
|
||
|
|
return {
|
||
|
|
Version: "2012-10-17",
|
||
|
|
Statement: [
|
||
|
|
{
|
||
|
|
Sid: "RefreshDeployRole",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: [
|
||
|
|
"iam:GetRole",
|
||
|
|
"iam:GetRolePolicy",
|
||
|
|
"iam:ListAttachedRolePolicies",
|
||
|
|
"iam:ListRolePolicies",
|
||
|
|
"iam:ListRoleTags",
|
||
|
|
],
|
||
|
|
Resource: deployRole,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
Sid: "RefreshGithubOidcProvider",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: "iam:GetOpenIDConnectProvider",
|
||
|
|
Resource: githubOidc,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
// The boundary is the only managed policy in Terraform state.
|
||
|
|
// ViewOnlyAccess carries iam:List* but not GetPolicy or
|
||
|
|
// GetPolicyVersion, so those are granted here on the exact ARN.
|
||
|
|
Sid: "RefreshDeployBoundary",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: [
|
||
|
|
"iam:GetPolicy",
|
||
|
|
"iam:GetPolicyVersion",
|
||
|
|
"iam:ListPolicyTags",
|
||
|
|
"iam:ListPolicyVersions",
|
||
|
|
],
|
||
|
|
Resource: boundary,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
Sid: "RefreshOriginBuckets",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: [
|
||
|
|
"s3:GetAccelerateConfiguration",
|
||
|
|
"s3:GetBucketAcl",
|
||
|
|
"s3:GetBucketCORS",
|
||
|
|
"s3:GetBucketLocation",
|
||
|
|
"s3:GetBucketLogging",
|
||
|
|
"s3:GetBucketObjectLockConfiguration",
|
||
|
|
"s3:GetBucketOwnershipControls",
|
||
|
|
"s3:GetBucketPolicy",
|
||
|
|
"s3:GetBucketPolicyStatus",
|
||
|
|
"s3:GetBucketPublicAccessBlock",
|
||
|
|
"s3:GetBucketRequestPayment",
|
||
|
|
"s3:GetBucketTagging",
|
||
|
|
"s3:GetBucketVersioning",
|
||
|
|
"s3:GetBucketWebsite",
|
||
|
|
"s3:GetEncryptionConfiguration",
|
||
|
|
"s3:GetLifecycleConfiguration",
|
||
|
|
"s3:GetReplicationConfiguration",
|
||
|
|
"s3:ListBucket",
|
||
|
|
],
|
||
|
|
Resource: buckets,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
Sid: "RefreshCloudFront",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: [
|
||
|
|
"cloudfront:GetDistribution",
|
||
|
|
"cloudfront:GetDistributionConfig",
|
||
|
|
"cloudfront:GetOriginAccessControl",
|
||
|
|
"cloudfront:ListTagsForResource",
|
||
|
|
],
|
||
|
|
Resource: "*",
|
||
|
|
},
|
||
|
|
{
|
||
|
|
Sid: "RefreshAcm",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: ["acm:DescribeCertificate", "acm:ListTagsForCertificate"],
|
||
|
|
Resource: "*",
|
||
|
|
},
|
||
|
|
{
|
||
|
|
Sid: "RefreshSsm",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: ["ssm:GetParameter", "ssm:GetParameters", "ssm:ListTagsForResource"],
|
||
|
|
Resource: [wafParam, deployParams],
|
||
|
|
},
|
||
|
|
{
|
||
|
|
// DescribeParameters accepts only Resource "*". The AWS provider
|
||
|
|
// calls it while refreshing aws_ssm_parameter.
|
||
|
|
Sid: "DescribeParameters",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: "ssm:DescribeParameters",
|
||
|
|
Resource: "*",
|
||
|
|
},
|
||
|
|
{
|
||
|
|
Sid: "RefreshWafWebAcl",
|
||
|
|
Effect: "Allow",
|
||
|
|
Action: ["wafv2:GetWebACL", "wafv2:ListWebACLs"],
|
||
|
|
Resource: "*",
|
||
|
|
},
|
||
|
|
],
|
||
|
|
};
|
||
|
|
}
|