mirror of
https://github.com/Sea-Haven-Industries/seahaven-org-baseline.git
synced 2026-09-30 09:13:17 +00:00
feat(iam): move seahaven-site exec roles into their own stack (PLAT-225)
Drop the retained roles from the substrate template so the new stack can import them without a second owner.
This commit is contained in:
parent
2b2f09a7f4
commit
5b63c703bc
5 changed files with 467 additions and 187 deletions
3
.github/workflows/deploy.yaml
vendored
3
.github/workflows/deploy.yaml
vendored
|
|
@ -56,6 +56,9 @@ jobs:
|
|||
uses: Sea-Haven-Industries/.github/.github/workflows/cd-cdk.yaml@e5691d8a7f96ac4d5a841a82975ff0a4354d53ac # v1.0.7
|
||||
with:
|
||||
node-version: "24"
|
||||
# seahaven-site-hcptf stays off this list until `cdk import` adopts the
|
||||
# live roles. A create fails, and a failed create blocks the import.
|
||||
# Add the id here in the change that follows a successful import.
|
||||
stacks: "prod-baseline dynamodb-cmk-prod alarm-topic-prod deploy-substrate-prod terraform-substrate-prod app-web-acl-prod"
|
||||
stack-name: "seahaven-prod-baseline"
|
||||
secrets:
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ are noted):
|
|||
| `seahaven-org-governance` | 328440206208 | us-east-1 | AWS Organizations OU tree + SCPs (incl. the cdk-imported external-dev guardrails) |
|
||||
| `seahaven-external-dev-baseline` | 396287094661 | us-east-1 | Member-account baseline: Config, GuardDuty, Security Hub (FSBP + CIS v3.0), Access Analyzer, flow logs, budget |
|
||||
| `seahaven-terraform-substrate` | 011934824531, 710827005802 | us-east-1 | Prod/dev HCP substrate: OIDC + shared IAM manager + eight existing `hcptf-*` pairs (DeletionPolicy Retain). Pending PLAT-147 delete after consumer imports. New prod/dev HCP IAM is not added here. |
|
||||
| `seahaven-site-hcptf` | 011934824531 | us-east-1 | Imported `hcptf-seahaven-site` apply and plan roles (PLAT-225). Adopt with `cdk import` after the site workspace drops them from state. Do not create. |
|
||||
| `seahaven-terraform-substrate` | 396287094661 | us-east-1 | Staged manually for SHOC backend/frontend adoption; exact HCP roles and deploy boundaries referencing the existing OIDC provider. Stays (PLAT-148). |
|
||||
| `seahaven-security-baseline` | 001520130573 | us-east-1 | Member-account baseline for the delegated security-admin account (same construct set) |
|
||||
| `seahaven-dev-baseline` | 710827005802 | us-east-1 | Member-account baseline for internal dev/staging (org-managed detection — no local GuardDuty/SecurityHub) |
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { DeploySubstrateStack } from "../lib/deploy-substrate-stack";
|
|||
import { TerraformSubstrateStack } from "../lib/terraform-substrate-stack";
|
||||
import { DynamoDbCmkStack } from "../lib/dynamodb-cmk-stack";
|
||||
import { AppWebAclStack } from "../lib/app-web-acl-stack";
|
||||
import { SeahavenSiteHcptfStack } from "../lib/seahaven-site-hcptf-stack";
|
||||
import { MemberBaselineStack } from "../lib/member-baseline-stack";
|
||||
import { OrgGovernanceStack } from "../lib/org-governance-stack";
|
||||
|
||||
|
|
@ -227,6 +228,14 @@ new AppWebAclStack(app, "app-web-acl-prod", {
|
|||
env: { account: PROD_ACCOUNT, region: "us-east-1" },
|
||||
});
|
||||
|
||||
// seahaven-site exec roles (PLAT-225). Not part of terraform-substrate.
|
||||
// First operation is `cdk import`, after the site workspace drops the roles
|
||||
// from its state. A create fails because the roles already exist.
|
||||
new SeahavenSiteHcptfStack(app, "seahaven-site-hcptf", {
|
||||
stackName: "seahaven-site-hcptf",
|
||||
env: { account: PROD_ACCOUNT, region: "us-east-1" },
|
||||
});
|
||||
|
||||
const terraformSubstrateDev = new TerraformSubstrateStack(
|
||||
app,
|
||||
"terraform-substrate-dev",
|
||||
|
|
|
|||
451
lib/seahaven-site-hcptf-stack.ts
Normal file
451
lib/seahaven-site-hcptf-stack.ts
Normal file
|
|
@ -0,0 +1,451 @@
|
|||
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 seahaven-site HCP workspace (PLAT-225).
|
||||
*
|
||||
* These roles already exist. Adopt them. Do not create them. The substrate
|
||||
* template no longer declares them. Its next deploy drops them from that
|
||||
* stack and retains the live roles.
|
||||
*
|
||||
* Import only after that deploy, and after seahaven-site-prod applies its
|
||||
* `removed` blocks:
|
||||
*
|
||||
* npx cdk import seahaven-site-hcptf
|
||||
*
|
||||
* Import identifiers are the role names `hcptf-seahaven-site` and
|
||||
* `hcptf-seahaven-site-plan`. The stack stays off the prod deploy job until
|
||||
* that import succeeds. A plain create fails because the roles already
|
||||
* exist, and a failed create blocks the import.
|
||||
*/
|
||||
export class SeahavenSiteHcptfStack extends cdk.Stack {
|
||||
constructor(scope: Construct, id: string, props: cdk.StackProps) {
|
||||
super(scope, id, props);
|
||||
|
||||
const account = this.account;
|
||||
const deployRole = `arn:aws:iam::${account}:role/tf-managed/githubdeploy-seahaven-site`;
|
||||
const boundary = `arn:aws:iam::${account}:policy/tf-managed/seahaven-site-githubdeploy-boundary`;
|
||||
const bucket = "arn:aws:s3:::seahaven-site-prod";
|
||||
const functionArn = `arn:aws:cloudfront::${account}:function/seahaven-site-prod-directory-index`;
|
||||
const deployParams = `arn:aws:ssm:us-east-1:${account}:parameter/seahaven-site/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 apply = new iam.CfnRole(this, "ApplyRole", {
|
||||
roleName: "hcptf-seahaven-site",
|
||||
maxSessionDuration: 3600,
|
||||
assumeRolePolicyDocument: trust(hcpOidc, "apply"),
|
||||
managedPolicyArns: [],
|
||||
policies: [
|
||||
{
|
||||
policyName: "seahaven-site-services",
|
||||
policyDocument: servicesPolicy(bucket, deployParams, wafParam, githubOidc),
|
||||
},
|
||||
{
|
||||
policyName: "scoped-iam-management",
|
||||
policyDocument: scopedIamPolicy(account, deployRole, boundary),
|
||||
},
|
||||
],
|
||||
tags: roleTags(),
|
||||
});
|
||||
retain(apply);
|
||||
|
||||
const plan = new iam.CfnRole(this, "PlanRole", {
|
||||
roleName: "hcptf-seahaven-site-plan",
|
||||
maxSessionDuration: 3600,
|
||||
assumeRolePolicyDocument: trust(hcpOidc, "plan"),
|
||||
managedPolicyArns: ["arn:aws:iam::aws:policy/job-function/ViewOnlyAccess"],
|
||||
policies: [
|
||||
{
|
||||
policyName: "seahaven-site-plan-refresh",
|
||||
policyDocument: planPolicy(account, bucket, functionArn, deployParams, wafParam, githubOidc, deployRole),
|
||||
},
|
||||
],
|
||||
tags: roleTags(),
|
||||
});
|
||||
retain(plan);
|
||||
|
||||
cdk.Tags.of(this).add("Project", "seahaven-site");
|
||||
cdk.Tags.of(this).add("Owner", "adam@seahavenind.com");
|
||||
cdk.Tags.of(this).add("ManagedBy", "cdk");
|
||||
}
|
||||
}
|
||||
|
||||
function retain(role: iam.CfnRole): void {
|
||||
role.cfnOptions.deletionPolicy = cdk.CfnDeletionPolicy.RETAIN;
|
||||
role.cfnOptions.updateReplacePolicy = cdk.CfnDeletionPolicy.RETAIN;
|
||||
}
|
||||
|
||||
function roleTags(): cdk.CfnTag[] {
|
||||
return [
|
||||
{ key: "Project", value: "seahaven-site" },
|
||||
{ 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:seahaven-site-prod:run_phase:${phase}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
function servicesPolicy(
|
||||
bucket: string,
|
||||
deployParams: string,
|
||||
wafParam: string,
|
||||
githubOidc: string,
|
||||
): iam.PolicyDocument {
|
||||
return iam.PolicyDocument.fromJson({
|
||||
Version: "2012-10-17",
|
||||
Statement: [
|
||||
{
|
||||
Sid: "OriginBucket",
|
||||
Effect: "Allow",
|
||||
Action: "s3:*",
|
||||
Resource: [bucket, `${bucket}/*`],
|
||||
},
|
||||
{
|
||||
Sid: "ReadGithubOidcProvider",
|
||||
Effect: "Allow",
|
||||
Action: "iam:GetOpenIDConnectProvider",
|
||||
Resource: githubOidc,
|
||||
},
|
||||
{
|
||||
Sid: "CloudFrontManage",
|
||||
Effect: "Allow",
|
||||
Action: "cloudfront:*",
|
||||
Resource: "*",
|
||||
},
|
||||
{
|
||||
Sid: "AcmCreate",
|
||||
Effect: "Allow",
|
||||
Action: "acm:RequestCertificate",
|
||||
Resource: "*",
|
||||
Condition: { StringEquals: { "aws:RequestTag/Project": "seahaven-site" } },
|
||||
},
|
||||
{
|
||||
Sid: "AcmList",
|
||||
Effect: "Allow",
|
||||
Action: ["acm:ListCertificates", "acm:ListTagsForCertificate"],
|
||||
Resource: "*",
|
||||
},
|
||||
{
|
||||
Sid: "AcmManageTagged",
|
||||
Effect: "Allow",
|
||||
Action: [
|
||||
"acm:AddTagsToCertificate",
|
||||
"acm:DeleteCertificate",
|
||||
"acm:DescribeCertificate",
|
||||
"acm:GetCertificate",
|
||||
"acm:RemoveTagsFromCertificate",
|
||||
"acm:RenewCertificate",
|
||||
],
|
||||
Resource: "*",
|
||||
Condition: { StringEquals: { "aws:ResourceTag/Project": "seahaven-site" } },
|
||||
},
|
||||
{
|
||||
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): iam.PolicyDocument {
|
||||
return iam.PolicyDocument.fromJson({
|
||||
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-seahaven-site" },
|
||||
},
|
||||
},
|
||||
{
|
||||
Sid: "DenyOtherPolicyVersions",
|
||||
Effect: "Deny",
|
||||
Action: [
|
||||
"iam:CreatePolicyVersion",
|
||||
"iam:DeletePolicy",
|
||||
"iam:DeletePolicyVersion",
|
||||
"iam:SetDefaultPolicyVersion",
|
||||
],
|
||||
NotResource: boundary,
|
||||
},
|
||||
{
|
||||
Sid: "CreateDeployBoundary",
|
||||
Effect: "Allow",
|
||||
Action: "iam:CreatePolicy",
|
||||
Resource: "*",
|
||||
Condition: {
|
||||
StringEquals: { "aws:RequestTag/BoundaryFor": "githubdeploy-seahaven-site" },
|
||||
},
|
||||
},
|
||||
{
|
||||
Sid: "ManageDeployBoundary",
|
||||
Effect: "Allow",
|
||||
Action: [
|
||||
"iam:CreatePolicyVersion",
|
||||
"iam:DeletePolicy",
|
||||
"iam:DeletePolicyVersion",
|
||||
"iam:GetPolicy",
|
||||
"iam:GetPolicyVersion",
|
||||
"iam:TagPolicy",
|
||||
],
|
||||
Resource: boundary,
|
||||
},
|
||||
{
|
||||
Sid: "WriteDeployRoles",
|
||||
Effect: "Allow",
|
||||
Action: [
|
||||
"iam:AttachRolePolicy",
|
||||
"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(
|
||||
account: string,
|
||||
bucket: string,
|
||||
functionArn: string,
|
||||
deployParams: string,
|
||||
wafParam: string,
|
||||
githubOidc: string,
|
||||
deployRole: string,
|
||||
): iam.PolicyDocument {
|
||||
return iam.PolicyDocument.fromJson({
|
||||
Version: "2012-10-17",
|
||||
Statement: [
|
||||
{
|
||||
Sid: "RefreshDeployRole",
|
||||
Effect: "Allow",
|
||||
Action: [
|
||||
"iam:GetRole",
|
||||
"iam:GetRolePolicy",
|
||||
"iam:ListAttachedRolePolicies",
|
||||
"iam:ListRolePolicies",
|
||||
"iam:ListRoleTags",
|
||||
],
|
||||
Resource: [
|
||||
deployRole,
|
||||
`arn:aws:iam::${account}:role/hcptf-seahaven-site`,
|
||||
`arn:aws:iam::${account}:role/hcptf-seahaven-site-plan`,
|
||||
],
|
||||
},
|
||||
{
|
||||
Sid: "RefreshGithubOidcProvider",
|
||||
Effect: "Allow",
|
||||
Action: "iam:GetOpenIDConnectProvider",
|
||||
Resource: githubOidc,
|
||||
},
|
||||
{
|
||||
Sid: "RefreshManagedPolicies",
|
||||
Effect: "Allow",
|
||||
Action: ["iam:GetPolicy", "iam:GetPolicyVersion"],
|
||||
Resource: "*",
|
||||
},
|
||||
{
|
||||
Sid: "RefreshOriginBucket",
|
||||
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: [bucket, `${bucket}/*`],
|
||||
},
|
||||
{
|
||||
Sid: "RefreshCloudFront",
|
||||
Effect: "Allow",
|
||||
Action: [
|
||||
"cloudfront:GetDistribution",
|
||||
"cloudfront:GetDistributionConfig",
|
||||
"cloudfront:GetOriginAccessControl",
|
||||
"cloudfront:ListTagsForResource",
|
||||
],
|
||||
Resource: "*",
|
||||
},
|
||||
{
|
||||
Sid: "RefreshCloudFrontFunction",
|
||||
Effect: "Allow",
|
||||
Action: ["cloudfront:DescribeFunction", "cloudfront:GetFunction"],
|
||||
Resource: functionArn,
|
||||
},
|
||||
{
|
||||
Sid: "RefreshAcm",
|
||||
Effect: "Allow",
|
||||
Action: [
|
||||
"acm:DescribeCertificate",
|
||||
"acm:GetCertificate",
|
||||
"acm:ListCertificates",
|
||||
"acm:ListTagsForCertificate",
|
||||
],
|
||||
Resource: "*",
|
||||
},
|
||||
{
|
||||
Sid: "RefreshAppWebAclSsm",
|
||||
Effect: "Allow",
|
||||
Action: ["ssm:GetParameter", "ssm:GetParameters", "ssm:ListTagsForResource"],
|
||||
Resource: [wafParam, deployParams],
|
||||
},
|
||||
{
|
||||
Sid: "RefreshWafWebAcl",
|
||||
Effect: "Allow",
|
||||
Action: ["wafv2:GetWebACL", "wafv2:ListWebACLs"],
|
||||
Resource: "*",
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
|
@ -1648,193 +1648,9 @@ Resources:
|
|||
Resource:
|
||||
- !Sub "arn:aws:secretsmanager:us-east-1:${AWS::AccountId}:secret:procurement-ingest/web-ui-auth-token-*"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# seahaven-site-prod (PLAT-91) — static site S3 + CloudFront + ACM + GHA
|
||||
# content-deploy role. No Lambda → no boundary widen. No Route53 (apex DNS
|
||||
# stays OOB in mgmt). Plan role: ViewOnly + plan-refresh sidecar.
|
||||
# ---------------------------------------------------------------------------
|
||||
HcptfSeahavenSitePlanRole:
|
||||
Type: AWS::IAM::Role
|
||||
Condition: IsProdAccount
|
||||
DeletionPolicy: Retain
|
||||
UpdateReplacePolicy: Retain
|
||||
Properties:
|
||||
RoleName: hcptf-seahaven-site-plan
|
||||
AssumeRolePolicyDocument:
|
||||
Version: "2012-10-17"
|
||||
Statement:
|
||||
- Effect: Allow
|
||||
Principal:
|
||||
Federated: !Sub "arn:aws:iam::${AWS::AccountId}:oidc-provider/app.terraform.io"
|
||||
Action: sts:AssumeRoleWithWebIdentity
|
||||
Condition:
|
||||
StringEquals:
|
||||
"app.terraform.io:aud": aws.workload.identity
|
||||
"app.terraform.io:sub": organization:seahaven:project:seahaven-prod:workspace:seahaven-site-prod:run_phase:plan
|
||||
ManagedPolicyArns:
|
||||
- arn:aws:iam::aws:policy/job-function/ViewOnlyAccess
|
||||
Policies:
|
||||
- PolicyName: seahaven-site-plan-refresh
|
||||
PolicyDocument:
|
||||
Version: "2012-10-17"
|
||||
Statement:
|
||||
- Sid: RefreshDeployRole
|
||||
Effect: Allow
|
||||
Action:
|
||||
- iam:GetRole
|
||||
- iam:GetRolePolicy
|
||||
- iam:ListRolePolicies
|
||||
- iam:ListAttachedRolePolicies
|
||||
- iam:ListRoleTags
|
||||
Resource:
|
||||
- !Sub "arn:aws:iam::${AWS::AccountId}:role/tf-managed/githubdeploy-seahaven-site"
|
||||
- Sid: RefreshGithubOidcProvider
|
||||
Effect: Allow
|
||||
Action:
|
||||
- iam:GetOpenIDConnectProvider
|
||||
Resource:
|
||||
- !Sub "arn:aws:iam::${AWS::AccountId}:oidc-provider/token.actions.githubusercontent.com"
|
||||
- Sid: RefreshManagedPolicies
|
||||
Effect: Allow
|
||||
Action:
|
||||
- iam:GetPolicy
|
||||
- iam:GetPolicyVersion
|
||||
Resource: "*"
|
||||
- Sid: RefreshOriginBucket
|
||||
Effect: Allow
|
||||
Action:
|
||||
- s3:Get*
|
||||
- s3:ListBucket
|
||||
Resource:
|
||||
- arn:aws:s3:::seahaven-site-prod
|
||||
- arn:aws:s3:::seahaven-site-prod/*
|
||||
- Sid: RefreshCloudFront
|
||||
Effect: Allow
|
||||
Action:
|
||||
- cloudfront:Get*
|
||||
- cloudfront:List*
|
||||
Resource: "*"
|
||||
# aws_cloudfront_function refresh reads DEVELOPMENT via
|
||||
# DescribeFunction. Get* does not cover that API (PLAT-106).
|
||||
- Sid: RefreshCloudFrontFunction
|
||||
Effect: Allow
|
||||
Action:
|
||||
- cloudfront:DescribeFunction
|
||||
Resource:
|
||||
- !Sub "arn:aws:cloudfront::${AWS::AccountId}:function/seahaven-site-prod-directory-index"
|
||||
- Sid: RefreshAcm
|
||||
Effect: Allow
|
||||
Action:
|
||||
- acm:DescribeCertificate
|
||||
- acm:ListCertificates
|
||||
- acm:ListTagsForCertificate
|
||||
- acm:GetCertificate
|
||||
Resource: "*"
|
||||
- Sid: RefreshAppWebAclSsm
|
||||
Effect: Allow
|
||||
Action:
|
||||
- ssm:GetParameter
|
||||
- ssm:GetParameters
|
||||
Resource:
|
||||
- !Sub "arn:aws:ssm:us-east-1:${AWS::AccountId}:parameter/seahaven/waf/app-web-acl-arn"
|
||||
- Sid: RefreshWafWebAcl
|
||||
Effect: Allow
|
||||
Action:
|
||||
- wafv2:GetWebACL
|
||||
- wafv2:ListWebACLs
|
||||
Resource: "*"
|
||||
|
||||
HcptfSeahavenSiteApplyRole:
|
||||
Type: AWS::IAM::Role
|
||||
Condition: IsProdAccount
|
||||
DeletionPolicy: Retain
|
||||
UpdateReplacePolicy: Retain
|
||||
Properties:
|
||||
RoleName: hcptf-seahaven-site
|
||||
AssumeRolePolicyDocument:
|
||||
Version: "2012-10-17"
|
||||
Statement:
|
||||
- Effect: Allow
|
||||
Principal:
|
||||
Federated: !Sub "arn:aws:iam::${AWS::AccountId}:oidc-provider/app.terraform.io"
|
||||
Action: sts:AssumeRoleWithWebIdentity
|
||||
Condition:
|
||||
StringEquals:
|
||||
"app.terraform.io:aud": aws.workload.identity
|
||||
"app.terraform.io:sub": organization:seahaven:project:seahaven-prod:workspace:seahaven-site-prod:run_phase:apply
|
||||
ManagedPolicyArns:
|
||||
- !Ref HcptfIamManagementPolicy
|
||||
Policies:
|
||||
- PolicyName: seahaven-site-services
|
||||
PolicyDocument:
|
||||
Version: "2012-10-17"
|
||||
Statement:
|
||||
- Sid: OriginBucket
|
||||
Effect: Allow
|
||||
Action:
|
||||
- s3:*
|
||||
Resource:
|
||||
- arn:aws:s3:::seahaven-site-prod
|
||||
- arn:aws:s3:::seahaven-site-prod/*
|
||||
- Sid: ReadGithubOidcProvider
|
||||
Effect: Allow
|
||||
Action:
|
||||
- iam:GetOpenIDConnectProvider
|
||||
Resource:
|
||||
- !Sub "arn:aws:iam::${AWS::AccountId}:oidc-provider/token.actions.githubusercontent.com"
|
||||
- Sid: CloudFrontManage
|
||||
Effect: Allow
|
||||
Action:
|
||||
- cloudfront:*
|
||||
Resource: "*"
|
||||
# RequestCertificate is account-level; pin via RequestTag matching
|
||||
# provider default_tags (Project=seahaven-site). Post-create manage
|
||||
# requires the same ResourceTag.
|
||||
- Sid: AcmCreate
|
||||
Effect: Allow
|
||||
Action:
|
||||
- acm:RequestCertificate
|
||||
Resource: "*"
|
||||
Condition:
|
||||
StringEquals:
|
||||
"aws:RequestTag/Project": seahaven-site
|
||||
- Sid: AcmList
|
||||
Effect: Allow
|
||||
Action:
|
||||
- acm:ListCertificates
|
||||
- acm:ListTagsForCertificate
|
||||
Resource: "*"
|
||||
- Sid: AcmManageTagged
|
||||
Effect: Allow
|
||||
Action:
|
||||
- acm:DescribeCertificate
|
||||
- acm:GetCertificate
|
||||
- acm:DeleteCertificate
|
||||
- acm:AddTagsToCertificate
|
||||
- acm:RemoveTagsFromCertificate
|
||||
- acm:RenewCertificate
|
||||
Resource: "*"
|
||||
Condition:
|
||||
StringEquals:
|
||||
"aws:ResourceTag/Project": seahaven-site
|
||||
# CloudFront web_acl_id is set via UpdateDistribution (cloudfront:*
|
||||
# above). Read the shared ACL ARN from SSM (PLAT-92) and allow
|
||||
# WAFv2 describe so plans/applies can validate the association.
|
||||
- Sid: ReadAppWebAclSsm
|
||||
Effect: Allow
|
||||
Action:
|
||||
- ssm:GetParameter
|
||||
- ssm:GetParameters
|
||||
Resource:
|
||||
- !Sub "arn:aws:ssm:us-east-1:${AWS::AccountId}:parameter/seahaven/waf/app-web-acl-arn"
|
||||
- Sid: ReadWafWebAcl
|
||||
Effect: Allow
|
||||
Action:
|
||||
- wafv2:GetWebACL
|
||||
- wafv2:GetWebACLForResource
|
||||
- wafv2:ListWebACLs
|
||||
- wafv2:ListResourcesForWebACL
|
||||
Resource: "*"
|
||||
# seahaven-site-prod exec roles moved to stack seahaven-site-hcptf (PLAT-225).
|
||||
# DeletionPolicy on the removed resources was Retain, so dropping them here
|
||||
# keeps the live roles for that stack to import.
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# meal-order-manager-prod (PLAT-70, imported to the app workspace in PLAT-146).
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue