mirror of
https://github.com/Sea-Haven-Industries/afi-backup-monitor.git
synced 2026-09-30 04:53:11 +00:00
feat(iam): import hcptf roles into app Terraform (PLAT-146) (#68)
* feat(iam): import hcptf roles into app Terraform (PLAT-146) Move the existing prod plan/apply pair into this repo. First apply uses the bootstrap window because DenySelfMutation blocks self-detach of seahaven-hcptf-iam-management. * fix(iam): let the plan role refresh imported hcptf roles (PLAT-146) The scoped plan-refresh sidecar only covered tf-managed/afi-*. After import, plans need GetRole on the hcptf pair in this workspace. * style(iam): terraform fmt hcp_iam.tf (PLAT-146) CI terraform fmt -check failed on alignment in the apply-services document. * fix(iam): tighten plan-refresh and scoped boundary pin (PLAT-146) Plan-refresh copied lambda:* from apply, so a plan session could mutate afi functions. Drop the unsuffixed org-wide Lambda boundary so scoped apply cannot retarget exec roles onto that ceiling. * fix(iam): replace deprecated managed_policy_arns (PLAT-146) Keep exclusive attachment control so the apply role stays empty and the plan role keeps ViewOnlyAccess. * ci(iam): retrigger HCP commit status (PLAT-146)
This commit is contained in:
parent
0efcece365
commit
c54997fe5c
1 changed files with 430 additions and 0 deletions
430
terraform/hcp_iam.tf
Normal file
430
terraform/hcp_iam.tf
Normal file
|
|
@ -0,0 +1,430 @@
|
||||||
|
# HCP plan/apply roles imported from seahaven-terraform-substrate (PLAT-146).
|
||||||
|
# Import, do not recreate. Role names stay hcptf-afi-backup-monitor /
|
||||||
|
# hcptf-afi-backup-monitor-plan.
|
||||||
|
#
|
||||||
|
# Live seahaven-hcptf-iam-management DenySelfMutation blocks DetachRolePolicy
|
||||||
|
# and PutRolePolicy on hcptf-* (including this role). Import apply sequence:
|
||||||
|
# 1. seahaven-org-baseline scripts/create-hcptf-bootstrap-roles.sh
|
||||||
|
# --account prod --allow-workspace afi-backup-monitor-prod
|
||||||
|
# 2. Point this workspace's TFC_AWS_* at hcptf-bootstrap /
|
||||||
|
# hcptf-bootstrap-plan (workspace vars, never a project set).
|
||||||
|
# 3. One Manual apply (import + detach seahaven-hcptf-iam-management +
|
||||||
|
# put scoped inline).
|
||||||
|
# 4. Point TFC_AWS_* back at hcptf-afi-backup-monitor /
|
||||||
|
# hcptf-afi-backup-monitor-plan.
|
||||||
|
# 5. Re-run the script without --allow-workspace to pin trust back to
|
||||||
|
# iam-bootstrap-prod only.
|
||||||
|
# Lambda permissions_boundary remains
|
||||||
|
# seahaven-lambda-execution-boundary-afi-backup-monitor.
|
||||||
|
|
||||||
|
import {
|
||||||
|
to = aws_iam_role.hcptf_apply
|
||||||
|
id = "hcptf-afi-backup-monitor"
|
||||||
|
}
|
||||||
|
|
||||||
|
import {
|
||||||
|
to = aws_iam_role.hcptf_plan
|
||||||
|
id = "hcptf-afi-backup-monitor-plan"
|
||||||
|
}
|
||||||
|
|
||||||
|
import {
|
||||||
|
to = aws_iam_role_policy.hcptf_apply_services
|
||||||
|
id = "hcptf-afi-backup-monitor:afi-backup-monitor-services"
|
||||||
|
}
|
||||||
|
|
||||||
|
import {
|
||||||
|
to = aws_iam_role_policy.hcptf_plan_refresh
|
||||||
|
id = "hcptf-afi-backup-monitor-plan:afi-backup-monitor-plan-refresh"
|
||||||
|
}
|
||||||
|
|
||||||
|
import {
|
||||||
|
to = aws_iam_role_policy_attachments_exclusive.hcptf_apply
|
||||||
|
id = "hcptf-afi-backup-monitor"
|
||||||
|
}
|
||||||
|
|
||||||
|
import {
|
||||||
|
to = aws_iam_role_policy_attachment.hcptf_plan_viewonly
|
||||||
|
id = "hcptf-afi-backup-monitor-plan/arn:aws:iam::aws:policy/job-function/ViewOnlyAccess"
|
||||||
|
}
|
||||||
|
|
||||||
|
import {
|
||||||
|
to = aws_iam_role_policy_attachments_exclusive.hcptf_plan
|
||||||
|
id = "hcptf-afi-backup-monitor-plan"
|
||||||
|
}
|
||||||
|
|
||||||
|
data "aws_iam_policy_document" "hcptf_apply_trust" {
|
||||||
|
statement {
|
||||||
|
sid = "HcpApply"
|
||||||
|
effect = "Allow"
|
||||||
|
actions = ["sts:AssumeRoleWithWebIdentity"]
|
||||||
|
|
||||||
|
principals {
|
||||||
|
type = "Federated"
|
||||||
|
identifiers = ["arn:aws:iam::${local.account_id}:oidc-provider/app.terraform.io"]
|
||||||
|
}
|
||||||
|
|
||||||
|
condition {
|
||||||
|
test = "StringEquals"
|
||||||
|
variable = "app.terraform.io:aud"
|
||||||
|
values = ["aws.workload.identity"]
|
||||||
|
}
|
||||||
|
|
||||||
|
condition {
|
||||||
|
test = "StringEquals"
|
||||||
|
variable = "app.terraform.io:sub"
|
||||||
|
values = [
|
||||||
|
"organization:seahaven:project:seahaven-prod:workspace:afi-backup-monitor-prod:run_phase:apply",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data "aws_iam_policy_document" "hcptf_plan_trust" {
|
||||||
|
statement {
|
||||||
|
sid = "HcpPlan"
|
||||||
|
effect = "Allow"
|
||||||
|
actions = ["sts:AssumeRoleWithWebIdentity"]
|
||||||
|
|
||||||
|
principals {
|
||||||
|
type = "Federated"
|
||||||
|
identifiers = ["arn:aws:iam::${local.account_id}:oidc-provider/app.terraform.io"]
|
||||||
|
}
|
||||||
|
|
||||||
|
condition {
|
||||||
|
test = "StringEquals"
|
||||||
|
variable = "app.terraform.io:aud"
|
||||||
|
values = ["aws.workload.identity"]
|
||||||
|
}
|
||||||
|
|
||||||
|
condition {
|
||||||
|
test = "StringEquals"
|
||||||
|
variable = "app.terraform.io:sub"
|
||||||
|
values = [
|
||||||
|
"organization:seahaven:project:seahaven-prod:workspace:afi-backup-monitor-prod:run_phase:plan",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data "aws_iam_policy_document" "hcptf_scoped_iam" {
|
||||||
|
statement {
|
||||||
|
sid = "DenyCreatePolicy"
|
||||||
|
effect = "Deny"
|
||||||
|
actions = ["iam:CreatePolicy", "iam:CreatePolicyVersion"]
|
||||||
|
resources = ["*"]
|
||||||
|
}
|
||||||
|
|
||||||
|
statement {
|
||||||
|
sid = "CreateExecRoleWithBoundary"
|
||||||
|
effect = "Allow"
|
||||||
|
actions = ["iam:CreateRole"]
|
||||||
|
resources = ["arn:aws:iam::${local.account_id}:role/tf-managed/afi-*"]
|
||||||
|
|
||||||
|
condition {
|
||||||
|
test = "StringLike"
|
||||||
|
variable = "iam:PermissionsBoundary"
|
||||||
|
values = [
|
||||||
|
"arn:aws:iam::${local.account_id}:policy/tf-managed/afi-*",
|
||||||
|
"arn:aws:iam::${local.account_id}:policy/seahaven-lambda-execution-boundary-afi-backup-monitor",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
statement {
|
||||||
|
sid = "MutateExecRoleWithBoundary"
|
||||||
|
effect = "Allow"
|
||||||
|
actions = [
|
||||||
|
"iam:AttachRolePolicy",
|
||||||
|
"iam:PutRolePolicy",
|
||||||
|
"iam:PutRolePermissionsBoundary",
|
||||||
|
]
|
||||||
|
resources = ["arn:aws:iam::${local.account_id}:role/tf-managed/afi-*"]
|
||||||
|
|
||||||
|
condition {
|
||||||
|
test = "StringLike"
|
||||||
|
variable = "iam:PermissionsBoundary"
|
||||||
|
values = [
|
||||||
|
"arn:aws:iam::${local.account_id}:policy/tf-managed/afi-*",
|
||||||
|
"arn:aws:iam::${local.account_id}:policy/seahaven-lambda-execution-boundary-afi-backup-monitor",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
statement {
|
||||||
|
sid = "WriteExecRoles"
|
||||||
|
effect = "Allow"
|
||||||
|
actions = [
|
||||||
|
"iam:DeleteRole",
|
||||||
|
"iam:DeleteRolePolicy",
|
||||||
|
"iam:DetachRolePolicy",
|
||||||
|
"iam:TagRole",
|
||||||
|
"iam:UntagRole",
|
||||||
|
"iam:UpdateAssumeRolePolicy",
|
||||||
|
"iam:UpdateRole",
|
||||||
|
"iam:UpdateRoleDescription",
|
||||||
|
]
|
||||||
|
resources = ["arn:aws:iam::${local.account_id}:role/tf-managed/afi-*"]
|
||||||
|
}
|
||||||
|
|
||||||
|
statement {
|
||||||
|
sid = "PassExecRolesToLambda"
|
||||||
|
effect = "Allow"
|
||||||
|
actions = ["iam:PassRole"]
|
||||||
|
resources = ["arn:aws:iam::${local.account_id}:role/tf-managed/afi-*"]
|
||||||
|
|
||||||
|
condition {
|
||||||
|
test = "StringEquals"
|
||||||
|
variable = "iam:PassedToService"
|
||||||
|
values = ["lambda.amazonaws.com"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
statement {
|
||||||
|
sid = "IamReadOnly"
|
||||||
|
effect = "Allow"
|
||||||
|
actions = [
|
||||||
|
"iam:GetPolicy",
|
||||||
|
"iam:GetPolicyVersion",
|
||||||
|
"iam:GetRole",
|
||||||
|
"iam:GetRolePolicy",
|
||||||
|
"iam:ListAttachedRolePolicies",
|
||||||
|
"iam:ListPolicies",
|
||||||
|
"iam:ListPolicyVersions",
|
||||||
|
"iam:ListRolePolicies",
|
||||||
|
"iam:ListRoles",
|
||||||
|
]
|
||||||
|
resources = ["*"]
|
||||||
|
}
|
||||||
|
|
||||||
|
statement {
|
||||||
|
sid = "DenySelfMutation"
|
||||||
|
effect = "Deny"
|
||||||
|
actions = [
|
||||||
|
"iam:AttachRolePolicy",
|
||||||
|
"iam:DeleteRole",
|
||||||
|
"iam:DeleteRolePolicy",
|
||||||
|
"iam:DeleteRolePermissionsBoundary",
|
||||||
|
"iam:DetachRolePolicy",
|
||||||
|
"iam:PutRolePolicy",
|
||||||
|
"iam:PutRolePermissionsBoundary",
|
||||||
|
"iam:UpdateAssumeRolePolicy",
|
||||||
|
"iam:UpdateRole",
|
||||||
|
"iam:UpdateRoleDescription",
|
||||||
|
]
|
||||||
|
resources = [
|
||||||
|
"arn:aws:iam::${local.account_id}:role/hcptf-*",
|
||||||
|
"arn:aws:iam::${local.account_id}:role/github-cfn-execution-role",
|
||||||
|
"arn:aws:iam::${local.account_id}:role/githubdeploy-*",
|
||||||
|
"arn:aws:iam::${local.account_id}:role/cdk-hnb659fds-*",
|
||||||
|
"arn:aws:iam::${local.account_id}:role/OrganizationAccountAccessRole",
|
||||||
|
"arn:aws:iam::${local.account_id}:role/seahaven-*",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
statement {
|
||||||
|
sid = "DenyBoundaryTampering"
|
||||||
|
effect = "Deny"
|
||||||
|
actions = [
|
||||||
|
"iam:DeleteRolePermissionsBoundary",
|
||||||
|
"iam:DeleteUserPermissionsBoundary",
|
||||||
|
]
|
||||||
|
resources = [
|
||||||
|
"arn:aws:iam::${local.account_id}:role/*",
|
||||||
|
"arn:aws:iam::${local.account_id}:user/*",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
statement {
|
||||||
|
sid = "DenyBoundaryPolicyEdit"
|
||||||
|
effect = "Deny"
|
||||||
|
actions = [
|
||||||
|
"iam:CreatePolicyVersion",
|
||||||
|
"iam:DeletePolicy",
|
||||||
|
"iam:DeletePolicyVersion",
|
||||||
|
"iam:SetDefaultPolicyVersion",
|
||||||
|
]
|
||||||
|
resources = ["arn:aws:iam::${local.account_id}:policy/seahaven-*"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data "aws_iam_policy_document" "hcptf_apply_services" {
|
||||||
|
statement {
|
||||||
|
sid = "LambdaAll"
|
||||||
|
effect = "Allow"
|
||||||
|
actions = ["lambda:*"]
|
||||||
|
resources = [
|
||||||
|
"arn:aws:lambda:us-east-1:${local.account_id}:function:afi-*",
|
||||||
|
"arn:aws:lambda:us-east-1:${local.account_id}:layer:afi-shared*",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
statement {
|
||||||
|
sid = "LambdaList"
|
||||||
|
effect = "Allow"
|
||||||
|
actions = ["lambda:ListFunctions", "lambda:ListLayers", "lambda:GetAccountSettings"]
|
||||||
|
resources = ["*"]
|
||||||
|
}
|
||||||
|
|
||||||
|
statement {
|
||||||
|
sid = "EventBridgeRules"
|
||||||
|
effect = "Allow"
|
||||||
|
actions = ["events:*"]
|
||||||
|
resources = ["arn:aws:events:us-east-1:${local.account_id}:rule/afi-*"]
|
||||||
|
}
|
||||||
|
|
||||||
|
statement {
|
||||||
|
sid = "CloudWatchLogs"
|
||||||
|
effect = "Allow"
|
||||||
|
actions = [
|
||||||
|
"logs:CreateLogGroup",
|
||||||
|
"logs:DeleteLogGroup",
|
||||||
|
"logs:PutRetentionPolicy",
|
||||||
|
"logs:DeleteRetentionPolicy",
|
||||||
|
"logs:TagResource",
|
||||||
|
"logs:UntagResource",
|
||||||
|
"logs:ListTagsForResource",
|
||||||
|
]
|
||||||
|
resources = ["arn:aws:logs:us-east-1:${local.account_id}:log-group:/aws/lambda/afi-*"]
|
||||||
|
}
|
||||||
|
|
||||||
|
statement {
|
||||||
|
sid = "CloudWatchLogsDescribe"
|
||||||
|
effect = "Allow"
|
||||||
|
actions = ["logs:DescribeLogGroups"]
|
||||||
|
resources = ["*"]
|
||||||
|
}
|
||||||
|
|
||||||
|
statement {
|
||||||
|
sid = "LambdaArtifactsBucket"
|
||||||
|
effect = "Allow"
|
||||||
|
actions = ["s3:*"]
|
||||||
|
resources = [
|
||||||
|
"arn:aws:s3:::afi-backup-monitor-artifacts-${local.account_id}",
|
||||||
|
"arn:aws:s3:::afi-backup-monitor-artifacts-${local.account_id}/*",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data "aws_iam_policy_document" "hcptf_plan_refresh" {
|
||||||
|
statement {
|
||||||
|
sid = "RefreshIamRoles"
|
||||||
|
effect = "Allow"
|
||||||
|
actions = [
|
||||||
|
"iam:GetRole",
|
||||||
|
"iam:GetRolePolicy",
|
||||||
|
"iam:ListRolePolicies",
|
||||||
|
"iam:ListAttachedRolePolicies",
|
||||||
|
]
|
||||||
|
resources = [
|
||||||
|
"arn:aws:iam::${local.account_id}:role/tf-managed/afi-*",
|
||||||
|
"arn:aws:iam::${local.account_id}:role/hcptf-afi-backup-monitor",
|
||||||
|
"arn:aws:iam::${local.account_id}:role/hcptf-afi-backup-monitor-plan",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
statement {
|
||||||
|
sid = "RefreshManagedPolicies"
|
||||||
|
effect = "Allow"
|
||||||
|
actions = ["iam:GetPolicy", "iam:GetPolicyVersion"]
|
||||||
|
resources = ["*"]
|
||||||
|
}
|
||||||
|
|
||||||
|
statement {
|
||||||
|
sid = "RefreshEventBridge"
|
||||||
|
effect = "Allow"
|
||||||
|
actions = [
|
||||||
|
"events:DescribeRule",
|
||||||
|
"events:ListTargetsByRule",
|
||||||
|
"events:ListTagsForResource",
|
||||||
|
]
|
||||||
|
resources = ["arn:aws:events:us-east-1:${local.account_id}:rule/afi-*"]
|
||||||
|
}
|
||||||
|
|
||||||
|
statement {
|
||||||
|
sid = "RefreshLambda"
|
||||||
|
effect = "Allow"
|
||||||
|
# Read-only refresh for plan. Mutate APIs stay on the apply role.
|
||||||
|
actions = ["lambda:Get*", "lambda:List*"]
|
||||||
|
resources = [
|
||||||
|
"arn:aws:lambda:us-east-1:${local.account_id}:function:afi-*",
|
||||||
|
"arn:aws:lambda:us-east-1:${local.account_id}:layer:afi-shared*",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
statement {
|
||||||
|
sid = "RefreshArtifactsBucket"
|
||||||
|
effect = "Allow"
|
||||||
|
actions = ["s3:Get*", "s3:ListBucket"]
|
||||||
|
resources = [
|
||||||
|
"arn:aws:s3:::afi-backup-monitor-artifacts-${local.account_id}",
|
||||||
|
"arn:aws:s3:::afi-backup-monitor-artifacts-${local.account_id}/*",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
statement {
|
||||||
|
sid = "RefreshLogs"
|
||||||
|
effect = "Allow"
|
||||||
|
actions = ["logs:DescribeLogGroups", "logs:ListTagsForResource"]
|
||||||
|
resources = ["*"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_iam_role" "hcptf_apply" {
|
||||||
|
name = "hcptf-afi-backup-monitor"
|
||||||
|
assume_role_policy = data.aws_iam_policy_document.hcptf_apply_trust.json
|
||||||
|
max_session_duration = 3600
|
||||||
|
|
||||||
|
tags = {
|
||||||
|
Project = "afi-backup-monitor"
|
||||||
|
Owner = "adam@seahavenind.com"
|
||||||
|
ManagedBy = "terraform"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Empty exclusive set keeps seahaven-hcptf-iam-management detached.
|
||||||
|
resource "aws_iam_role_policy_attachments_exclusive" "hcptf_apply" {
|
||||||
|
role_name = aws_iam_role.hcptf_apply.name
|
||||||
|
policy_arns = []
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_iam_role" "hcptf_plan" {
|
||||||
|
name = "hcptf-afi-backup-monitor-plan"
|
||||||
|
assume_role_policy = data.aws_iam_policy_document.hcptf_plan_trust.json
|
||||||
|
max_session_duration = 3600
|
||||||
|
|
||||||
|
tags = {
|
||||||
|
Project = "afi-backup-monitor"
|
||||||
|
Owner = "adam@seahavenind.com"
|
||||||
|
ManagedBy = "terraform"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_iam_role_policy_attachment" "hcptf_plan_viewonly" {
|
||||||
|
role = aws_iam_role.hcptf_plan.name
|
||||||
|
policy_arn = "arn:aws:iam::aws:policy/job-function/ViewOnlyAccess"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_iam_role_policy_attachments_exclusive" "hcptf_plan" {
|
||||||
|
role_name = aws_iam_role.hcptf_plan.name
|
||||||
|
policy_arns = [
|
||||||
|
aws_iam_role_policy_attachment.hcptf_plan_viewonly.policy_arn,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_iam_role_policy" "hcptf_scoped_iam" {
|
||||||
|
name = "scoped-iam-management"
|
||||||
|
role = aws_iam_role.hcptf_apply.id
|
||||||
|
policy = data.aws_iam_policy_document.hcptf_scoped_iam.json
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_iam_role_policy" "hcptf_apply_services" {
|
||||||
|
name = "afi-backup-monitor-services"
|
||||||
|
role = aws_iam_role.hcptf_apply.id
|
||||||
|
policy = data.aws_iam_policy_document.hcptf_apply_services.json
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_iam_role_policy" "hcptf_plan_refresh" {
|
||||||
|
name = "afi-backup-monitor-plan-refresh"
|
||||||
|
role = aws_iam_role.hcptf_plan.id
|
||||||
|
policy = data.aws_iam_policy_document.hcptf_plan_refresh.json
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue