mirror of
https://github.com/Sea-Haven-Industries/seahaven-org-baseline.git
synced 2026-10-06 14:31:59 +00:00
* feat(hcptf): import hcptf-paychex-integrations apply and plan roles into seahaven-hcptf (PLAT-251) PaychexIntegrationsRoles is nested in the prod seahaven-hcptf stack for the paychex-integrations-prod workspace. The two roles already exist and are imported with -c hcptfPaychexImport=true, which names the live inline policies and omits role tags and outputs. The default template replaces the inline policies with managed policies at /tf-managed/: - paychex-integrations-hcptf-iam: the ported scoped IAM document plus CreateRole and the write set on tf-managed/githubdeploy-paychex-integrations (no permissions boundary) and iam:GetOpenIDConnectProvider. TagHcptfRoles is dropped; the roles are no longer Terraform-managed. - paychex-integrations-hcptf-services: the ported services document plus SSM writes on /paychex-integrations/deploy/* and DescribeParameters. - paychex-integrations-hcptf-plan: the ported refresh document plus the deploy role, the GitHub OIDC provider, and the deploy parameters. Trust is unchanged. Every resource is Retain. * docs(hcptf): describe the paychex-integrations import as a sequence * chore(ci): retrigger checks after the GitHub Actions incident
688 lines
23 KiB
TypeScript
688 lines
23 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 paychex-integrations HCP workspace (PLAT-251).
|
|
*
|
|
* Nested in the prod seahaven-hcptf stack. `hcptf-paychex-integrations` and
|
|
* `hcptf-paychex-integrations-plan` already exist. They were created by
|
|
* create-hcptf-bootstrap-roles.sh and then managed by the paychex-integrations
|
|
* workspace itself through a bootstrap credential swap. That workspace forgets
|
|
* them with `removed` blocks before this construct imports them. Do not create
|
|
* them. A plain create fails because the roles already exist.
|
|
*
|
|
* Import identifiers are the two role names. Construct ids stay ApplyRole and
|
|
* PlanRole under PaychexIntegrations. The three /tf-managed/ managed policies
|
|
* do not exist before the deploy that follows the import.
|
|
*
|
|
* `importExisting` is the `-c hcptfPaychexImport=true` template. It names the
|
|
* roles' live inline policies (`paychex-integrations-services`,
|
|
* `scoped-iam-management`, `paychex-integrations-plan-refresh`) so the
|
|
* following deploy can delete them, and it omits role tags and the role ARN
|
|
* outputs. CloudFormation rejects both on an IAM role import. The default
|
|
* template is the managed-policy state.
|
|
*
|
|
* Beyond the ported documents, the apply role can create and manage
|
|
* `githubdeploy-paychex-integrations` at /tf-managed/ with no permissions
|
|
* boundary, and can write the deploy contract under SSM
|
|
* /paychex-integrations/deploy/*. The plan role can refresh both.
|
|
*/
|
|
export interface PaychexIntegrationsRolesProps {
|
|
/** Synthesize the import template. Set from `-c hcptfPaychexImport=true`. */
|
|
importExisting?: boolean;
|
|
}
|
|
|
|
const VIEW_ONLY = "arn:aws:iam::aws:policy/job-function/ViewOnlyAccess";
|
|
const WORKSPACE =
|
|
"organization:seahaven:project:seahaven-prod:workspace:paychex-integrations-prod";
|
|
|
|
export class PaychexIntegrationsRoles extends Construct {
|
|
constructor(scope: Construct, id: string, props: PaychexIntegrationsRolesProps = {}) {
|
|
super(scope, id);
|
|
|
|
const importing = props.importExisting === true;
|
|
// Overrides the parent stack's Project=payments-dashboard tag.
|
|
cdk.Tags.of(this).add("Project", "paychex-integrations", { priority: 200 });
|
|
if (importing) {
|
|
const roleOnly = { priority: 300, includeResourceTypes: ["AWS::IAM::Role"] };
|
|
cdk.Tags.of(this).remove("Project", roleOnly);
|
|
cdk.Tags.of(this).remove("Owner", roleOnly);
|
|
cdk.Tags.of(this).remove("ManagedBy", roleOnly);
|
|
}
|
|
|
|
const account = cdk.Stack.of(this).account;
|
|
const hcpOidc = `arn:aws:iam::${account}:oidc-provider/app.terraform.io`;
|
|
const deployRole = `arn:aws:iam::${account}:role/tf-managed/githubdeploy-paychex-integrations`;
|
|
const deployParams = `arn:aws:ssm:us-east-1:${account}:parameter/paychex-integrations/deploy/*`;
|
|
|
|
const iamDocument = scopedIamPolicy(account, deployRole);
|
|
const servicesDocument = servicesPolicy(account, deployParams);
|
|
const planDocument = planPolicy(account, deployRole, deployParams);
|
|
|
|
const apply = new iam.CfnRole(this, "ApplyRole", {
|
|
roleName: "hcptf-paychex-integrations",
|
|
maxSessionDuration: 3600,
|
|
assumeRolePolicyDocument: trust(hcpOidc, "apply"),
|
|
...(importing
|
|
? {
|
|
policies: [
|
|
{ policyName: "paychex-integrations-services", policyDocument: servicesDocument },
|
|
{ policyName: "scoped-iam-management", policyDocument: iamDocument },
|
|
],
|
|
}
|
|
: {
|
|
managedPolicyArns: [
|
|
managedPolicy(this, "IamPolicy", "paychex-integrations-hcptf-iam", iamDocument).ref,
|
|
managedPolicy(
|
|
this,
|
|
"ServicesPolicy",
|
|
"paychex-integrations-hcptf-services",
|
|
servicesDocument,
|
|
).ref,
|
|
],
|
|
tags: roleTags(),
|
|
}),
|
|
});
|
|
retain(apply);
|
|
|
|
const plan = new iam.CfnRole(this, "PlanRole", {
|
|
roleName: "hcptf-paychex-integrations-plan",
|
|
maxSessionDuration: 3600,
|
|
assumeRolePolicyDocument: trust(hcpOidc, "plan"),
|
|
...(importing
|
|
? {
|
|
managedPolicyArns: [VIEW_ONLY],
|
|
policies: [
|
|
{ policyName: "paychex-integrations-plan-refresh", policyDocument: planDocument },
|
|
],
|
|
}
|
|
: {
|
|
managedPolicyArns: [
|
|
VIEW_ONLY,
|
|
managedPolicy(this, "PlanPolicy", "paychex-integrations-hcptf-plan", planDocument).ref,
|
|
],
|
|
tags: roleTags(),
|
|
}),
|
|
});
|
|
retain(plan);
|
|
|
|
if (!importing) {
|
|
const applyArn = new cdk.CfnOutput(this, "ApplyRoleArn", { value: apply.attrArn });
|
|
const planArn = new cdk.CfnOutput(this, "PlanRoleArn", { value: plan.attrArn });
|
|
applyArn.overrideLogicalId("PaychexIntegrationsApplyRoleArn");
|
|
planArn.overrideLogicalId("PaychexIntegrationsPlanRoleArn");
|
|
}
|
|
}
|
|
}
|
|
|
|
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: "paychex-integrations" },
|
|
{ key: "Owner", value: "adam@seahavenind.com" },
|
|
{ key: "ManagedBy", value: "cdk" },
|
|
];
|
|
}
|
|
|
|
function trust(providerArn: string, phase: "apply" | "plan"): object {
|
|
return {
|
|
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": `${WORKSPACE}:run_phase:${phase}`,
|
|
},
|
|
},
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
/** Ported from paychex-integrations terraform/hcp_iam.tf hcptf_scoped_iam plus the deploy role. */
|
|
function scopedIamPolicy(account: string, deployRole: string): object {
|
|
const execRoles = `arn:aws:iam::${account}:role/tf-managed/paychex-*`;
|
|
const execBoundaries = [
|
|
`arn:aws:iam::${account}:policy/tf-managed/paychex-*`,
|
|
`arn:aws:iam::${account}:policy/seahaven-lambda-execution-boundary-paychex-integrations`,
|
|
];
|
|
return {
|
|
Version: "2012-10-17",
|
|
Statement: [
|
|
{
|
|
Sid: "DenyCreatePolicy",
|
|
Effect: "Deny",
|
|
Action: ["iam:CreatePolicy", "iam:CreatePolicyVersion"],
|
|
Resource: "*",
|
|
},
|
|
{
|
|
Sid: "CreateExecRoleWithBoundary",
|
|
Effect: "Allow",
|
|
Action: "iam:CreateRole",
|
|
Resource: execRoles,
|
|
Condition: { StringLike: { "iam:PermissionsBoundary": execBoundaries } },
|
|
},
|
|
{
|
|
Sid: "MutateExecRoleWithBoundary",
|
|
Effect: "Allow",
|
|
Action: ["iam:AttachRolePolicy", "iam:PutRolePolicy", "iam:PutRolePermissionsBoundary"],
|
|
Resource: execRoles,
|
|
Condition: { StringLike: { "iam:PermissionsBoundary": execBoundaries } },
|
|
},
|
|
{
|
|
Sid: "WriteExecRoles",
|
|
Effect: "Allow",
|
|
Action: [
|
|
"iam:DeleteRole",
|
|
"iam:DeleteRolePolicy",
|
|
"iam:DetachRolePolicy",
|
|
"iam:TagRole",
|
|
"iam:UntagRole",
|
|
"iam:UpdateAssumeRolePolicy",
|
|
"iam:UpdateRole",
|
|
"iam:UpdateRoleDescription",
|
|
],
|
|
Resource: execRoles,
|
|
},
|
|
{
|
|
Sid: "PassExecRolesToLambda",
|
|
Effect: "Allow",
|
|
Action: "iam:PassRole",
|
|
Resource: execRoles,
|
|
Condition: { StringEquals: { "iam:PassedToService": "lambda.amazonaws.com" } },
|
|
},
|
|
{
|
|
Sid: "PassPayrollScheduleToScheduler",
|
|
Effect: "Allow",
|
|
Action: "iam:PassRole",
|
|
Resource: `arn:aws:iam::${account}:role/tf-managed/paychex-payroll-schedule-invoke`,
|
|
Condition: { StringEquals: { "iam:PassedToService": "scheduler.amazonaws.com" } },
|
|
},
|
|
{
|
|
// GitHub Actions deploy role, owned by the workspace. Path /tf-managed/
|
|
// keeps it outside DenySelfMutation's role/githubdeploy-* pattern. No
|
|
// permissions boundary: it is not a Lambda execution role.
|
|
Sid: "CreateDeployRole",
|
|
Effect: "Allow",
|
|
Action: "iam:CreateRole",
|
|
Resource: deployRole,
|
|
Condition: { Null: { "iam:PermissionsBoundary": "true" } },
|
|
},
|
|
{
|
|
Sid: "WriteDeployRole",
|
|
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: "IamReadOnly",
|
|
Effect: "Allow",
|
|
Action: [
|
|
"iam:GetOpenIDConnectProvider",
|
|
"iam:GetPolicy",
|
|
"iam:GetPolicyVersion",
|
|
"iam:GetRole",
|
|
"iam:GetRolePolicy",
|
|
"iam:ListAttachedRolePolicies",
|
|
"iam:ListInstanceProfilesForRole",
|
|
"iam:ListPolicies",
|
|
"iam:ListPolicyTags",
|
|
"iam:ListPolicyVersions",
|
|
"iam:ListRolePolicies",
|
|
"iam:ListRoles",
|
|
"iam:ListRoleTags",
|
|
],
|
|
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-*`,
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
/** Ported from paychex-integrations terraform/hcp_iam.tf hcptf_apply_services plus the deploy contract. */
|
|
function servicesPolicy(account: string, deployParams: string): object {
|
|
const functions = `arn:aws:lambda:us-east-1:${account}:function:paychex-*`;
|
|
const artifacts = `arn:aws:s3:::paychex-integrations-artifacts-${account}`;
|
|
return {
|
|
Version: "2012-10-17",
|
|
Statement: [
|
|
{
|
|
Sid: "LambdaAll",
|
|
Effect: "Allow",
|
|
Action: "lambda:*",
|
|
Resource: functions,
|
|
},
|
|
{
|
|
Sid: "LambdaEventSourceMappingRead",
|
|
Effect: "Allow",
|
|
Action: [
|
|
"lambda:GetEventSourceMapping",
|
|
"lambda:ListTags",
|
|
"lambda:TagResource",
|
|
"lambda:UntagResource",
|
|
],
|
|
Resource: "*",
|
|
},
|
|
{
|
|
Sid: "LambdaEventSourceMappings",
|
|
Effect: "Allow",
|
|
Action: [
|
|
"lambda:CreateEventSourceMapping",
|
|
"lambda:DeleteEventSourceMapping",
|
|
"lambda:UpdateEventSourceMapping",
|
|
],
|
|
Resource: "*",
|
|
Condition: { "ForAnyValue:StringLike": { "lambda:FunctionArn": functions } },
|
|
},
|
|
{
|
|
Sid: "LambdaList",
|
|
Effect: "Allow",
|
|
Action: [
|
|
"lambda:ListFunctions",
|
|
"lambda:ListLayers",
|
|
"lambda:ListEventSourceMappings",
|
|
"lambda:GetAccountSettings",
|
|
],
|
|
Resource: "*",
|
|
},
|
|
{
|
|
Sid: "CloudWatchLogs",
|
|
Effect: "Allow",
|
|
Action: [
|
|
"logs:CreateLogGroup",
|
|
"logs:DeleteLogGroup",
|
|
"logs:PutRetentionPolicy",
|
|
"logs:DeleteRetentionPolicy",
|
|
"logs:TagResource",
|
|
"logs:UntagResource",
|
|
"logs:ListTagsForResource",
|
|
],
|
|
Resource: [
|
|
`arn:aws:logs:us-east-1:${account}:log-group:/aws/lambda/paychex-*`,
|
|
`arn:aws:logs:us-east-1:${account}:log-group:/aws/apigateway/paychex-webhooks`,
|
|
`arn:aws:logs:us-east-1:${account}:log-group:/aws/apigateway/paychex-webhooks:*`,
|
|
],
|
|
},
|
|
{
|
|
Sid: "CloudWatchLogsDescribe",
|
|
Effect: "Allow",
|
|
Action: "logs:DescribeLogGroups",
|
|
Resource: "*",
|
|
},
|
|
{
|
|
// HTTP API access logging is delivered through CloudWatch vended logs.
|
|
// None of these actions accept a resource ARN.
|
|
Sid: "CloudWatchLogsDelivery",
|
|
Effect: "Allow",
|
|
Action: [
|
|
"logs:CreateLogDelivery",
|
|
"logs:GetLogDelivery",
|
|
"logs:UpdateLogDelivery",
|
|
"logs:DeleteLogDelivery",
|
|
"logs:ListLogDeliveries",
|
|
"logs:PutResourcePolicy",
|
|
"logs:DescribeResourcePolicies",
|
|
],
|
|
Resource: "*",
|
|
},
|
|
{
|
|
Sid: "LambdaArtifactsBucket",
|
|
Effect: "Allow",
|
|
Action: "s3:*",
|
|
Resource: [artifacts, `${artifacts}/*`],
|
|
},
|
|
{
|
|
Sid: "CloudWatchAlarms",
|
|
Effect: "Allow",
|
|
Action: "cloudwatch:*",
|
|
Resource: `arn:aws:cloudwatch:us-east-1:${account}:alarm:paychex-*`,
|
|
},
|
|
{
|
|
Sid: "SiteAlertsSns",
|
|
Effect: "Allow",
|
|
Action: ["sns:Publish", "sns:GetTopicAttributes"],
|
|
Resource: `arn:aws:sns:us-east-1:${account}:site-alerts`,
|
|
},
|
|
{
|
|
Sid: "PaychexSecretShell",
|
|
Effect: "Allow",
|
|
Action: [
|
|
"secretsmanager:DeleteSecret",
|
|
"secretsmanager:DescribeSecret",
|
|
"secretsmanager:GetResourcePolicy",
|
|
"secretsmanager:PutResourcePolicy",
|
|
"secretsmanager:DeleteResourcePolicy",
|
|
"secretsmanager:TagResource",
|
|
"secretsmanager:UntagResource",
|
|
],
|
|
Resource: `arn:aws:secretsmanager:us-east-1:${account}:secret:paychex-integrations/*`,
|
|
},
|
|
{
|
|
Sid: "PaychexSecretCreate",
|
|
Effect: "Allow",
|
|
Action: "secretsmanager:CreateSecret",
|
|
Resource: "*",
|
|
Condition: { StringLike: { "secretsmanager:Name": "paychex-integrations/*" } },
|
|
},
|
|
{
|
|
Sid: "DynamoDBTable",
|
|
Effect: "Allow",
|
|
Action: "dynamodb:*",
|
|
Resource: [
|
|
`arn:aws:dynamodb:us-east-1:${account}:table/paychex-worker-ledger`,
|
|
`arn:aws:dynamodb:us-east-1:${account}:table/paychex-worker-ledger/index/*`,
|
|
`arn:aws:dynamodb:us-east-1:${account}:table/paychex-webhook-notifications`,
|
|
`arn:aws:dynamodb:us-east-1:${account}:table/paychex-webhook-notifications/index/*`,
|
|
`arn:aws:dynamodb:us-east-1:${account}:table/paychex-payroll-notices`,
|
|
`arn:aws:dynamodb:us-east-1:${account}:table/paychex-payroll-notices/index/*`,
|
|
`arn:aws:dynamodb:us-east-1:${account}:table/paychex-checkcomponents-posted`,
|
|
`arn:aws:dynamodb:us-east-1:${account}:table/paychex-checkcomponents-posted/index/*`,
|
|
`arn:aws:dynamodb:us-east-1:${account}:table/paychex-checkcomponents-period`,
|
|
`arn:aws:dynamodb:us-east-1:${account}:table/paychex-checkcomponents-period/index/*`,
|
|
],
|
|
},
|
|
{
|
|
Sid: "DynamoDBList",
|
|
Effect: "Allow",
|
|
Action: "dynamodb:ListTables",
|
|
Resource: "*",
|
|
},
|
|
{
|
|
Sid: "SqsQueues",
|
|
Effect: "Allow",
|
|
Action: "sqs:*",
|
|
Resource: queueArns(account),
|
|
},
|
|
{
|
|
Sid: "SqsList",
|
|
Effect: "Allow",
|
|
Action: "sqs:ListQueues",
|
|
Resource: "*",
|
|
},
|
|
{
|
|
Sid: "HttpApi",
|
|
Effect: "Allow",
|
|
Action: "apigateway:*",
|
|
Resource: [
|
|
"arn:aws:apigateway:us-east-1::/apis",
|
|
"arn:aws:apigateway:us-east-1::/apis/*",
|
|
"arn:aws:apigateway:us-east-1::/tags/*",
|
|
],
|
|
},
|
|
{
|
|
Sid: "PayrollSchedules",
|
|
Effect: "Allow",
|
|
Action: [
|
|
"scheduler:CreateSchedule",
|
|
"scheduler:UpdateSchedule",
|
|
"scheduler:DeleteSchedule",
|
|
"scheduler:GetSchedule",
|
|
"scheduler:ListTagsForResource",
|
|
"scheduler:TagResource",
|
|
"scheduler:UntagResource",
|
|
],
|
|
Resource: scheduleArns(account),
|
|
},
|
|
{
|
|
// Deploy contract read by the thin deploy.yaml caller.
|
|
Sid: "WriteDeployContract",
|
|
Effect: "Allow",
|
|
Action: [
|
|
"ssm:AddTagsToResource",
|
|
"ssm:DeleteParameter",
|
|
"ssm:GetParameter",
|
|
"ssm:GetParameters",
|
|
"ssm:ListTagsForResource",
|
|
"ssm:PutParameter",
|
|
"ssm:RemoveTagsFromResource",
|
|
],
|
|
Resource: deployParams,
|
|
},
|
|
{
|
|
// DescribeParameters accepts only Resource "*".
|
|
Sid: "DescribeParameters",
|
|
Effect: "Allow",
|
|
Action: "ssm:DescribeParameters",
|
|
Resource: "*",
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
/** Ported from paychex-integrations terraform/hcp_iam.tf hcptf_plan_refresh plus the deploy role and contract. */
|
|
function planPolicy(account: string, deployRole: string, deployParams: string): object {
|
|
const artifacts = `arn:aws:s3:::paychex-integrations-artifacts-${account}`;
|
|
return {
|
|
Version: "2012-10-17",
|
|
Statement: [
|
|
{
|
|
Sid: "RefreshIamRoles",
|
|
Effect: "Allow",
|
|
Action: [
|
|
"iam:GetRole",
|
|
"iam:GetRolePolicy",
|
|
"iam:ListRolePolicies",
|
|
"iam:ListAttachedRolePolicies",
|
|
],
|
|
Resource: [
|
|
`arn:aws:iam::${account}:role/tf-managed/paychex-*`,
|
|
deployRole,
|
|
`arn:aws:iam::${account}:role/hcptf-paychex-integrations`,
|
|
`arn:aws:iam::${account}:role/hcptf-paychex-integrations-plan`,
|
|
],
|
|
},
|
|
{
|
|
Sid: "RefreshGithubOidcProvider",
|
|
Effect: "Allow",
|
|
Action: "iam:GetOpenIDConnectProvider",
|
|
Resource: `arn:aws:iam::${account}:oidc-provider/token.actions.githubusercontent.com`,
|
|
},
|
|
{
|
|
Sid: "RefreshManagedPolicies",
|
|
Effect: "Allow",
|
|
Action: ["iam:GetPolicy", "iam:GetPolicyVersion"],
|
|
Resource: "*",
|
|
},
|
|
{
|
|
Sid: "RefreshLambda",
|
|
Effect: "Allow",
|
|
Action: "lambda:Get*",
|
|
Resource: `arn:aws:lambda:us-east-1:${account}:function:paychex-*`,
|
|
},
|
|
{
|
|
Sid: "RefreshLambdaList",
|
|
Effect: "Allow",
|
|
Action: [
|
|
"lambda:ListFunctions",
|
|
"lambda:ListEventSourceMappings",
|
|
"lambda:GetEventSourceMapping",
|
|
"lambda:GetAccountSettings",
|
|
],
|
|
Resource: "*",
|
|
},
|
|
{
|
|
Sid: "RefreshArtifactsBucket",
|
|
Effect: "Allow",
|
|
Action: ["s3:Get*", "s3:ListBucket"],
|
|
Resource: [artifacts, `${artifacts}/*`],
|
|
},
|
|
{
|
|
Sid: "RefreshCloudWatchAlarms",
|
|
Effect: "Allow",
|
|
Action: ["cloudwatch:DescribeAlarms", "cloudwatch:ListTagsForResource"],
|
|
Resource: `arn:aws:cloudwatch:us-east-1:${account}:alarm:paychex-*`,
|
|
},
|
|
{
|
|
Sid: "RefreshLogs",
|
|
Effect: "Allow",
|
|
Action: ["logs:DescribeLogGroups", "logs:ListTagsForResource"],
|
|
Resource: "*",
|
|
},
|
|
{
|
|
Sid: "RefreshSecrets",
|
|
Effect: "Allow",
|
|
Action: [
|
|
"secretsmanager:DescribeSecret",
|
|
"secretsmanager:GetResourcePolicy",
|
|
"secretsmanager:ListSecretVersionIds",
|
|
],
|
|
Resource: `arn:aws:secretsmanager:us-east-1:${account}:secret:paychex-integrations/*`,
|
|
},
|
|
{
|
|
Sid: "RefreshDynamoDB",
|
|
Effect: "Allow",
|
|
Action: [
|
|
"dynamodb:DescribeTable",
|
|
"dynamodb:DescribeTimeToLive",
|
|
"dynamodb:DescribeContinuousBackups",
|
|
"dynamodb:ListTagsOfResource",
|
|
],
|
|
Resource: [
|
|
`arn:aws:dynamodb:us-east-1:${account}:table/paychex-worker-ledger`,
|
|
`arn:aws:dynamodb:us-east-1:${account}:table/paychex-webhook-notifications`,
|
|
`arn:aws:dynamodb:us-east-1:${account}:table/paychex-payroll-notices`,
|
|
`arn:aws:dynamodb:us-east-1:${account}:table/paychex-checkcomponents-posted`,
|
|
`arn:aws:dynamodb:us-east-1:${account}:table/paychex-checkcomponents-period`,
|
|
],
|
|
},
|
|
{
|
|
Sid: "RefreshSqs",
|
|
Effect: "Allow",
|
|
Action: ["sqs:GetQueueAttributes", "sqs:GetQueueUrl", "sqs:ListQueueTags"],
|
|
Resource: queueArns(account),
|
|
},
|
|
{
|
|
Sid: "RefreshSqsList",
|
|
Effect: "Allow",
|
|
Action: "sqs:ListQueues",
|
|
Resource: "*",
|
|
},
|
|
{
|
|
Sid: "RefreshHttpApi",
|
|
Effect: "Allow",
|
|
Action: "apigateway:GET",
|
|
Resource: [
|
|
"arn:aws:apigateway:us-east-1::/apis",
|
|
"arn:aws:apigateway:us-east-1::/apis/*",
|
|
"arn:aws:apigateway:us-east-1::/tags/*",
|
|
],
|
|
},
|
|
{
|
|
Sid: "RefreshPayrollSchedules",
|
|
Effect: "Allow",
|
|
Action: ["scheduler:GetSchedule", "scheduler:ListTagsForResource"],
|
|
Resource: scheduleArns(account),
|
|
},
|
|
{
|
|
Sid: "RefreshDeployContract",
|
|
Effect: "Allow",
|
|
Action: ["ssm:GetParameter", "ssm:GetParameters", "ssm:ListTagsForResource"],
|
|
Resource: deployParams,
|
|
},
|
|
{
|
|
// DescribeParameters accepts only Resource "*". The AWS provider
|
|
// calls it while refreshing aws_ssm_parameter.
|
|
Sid: "DescribeParameters",
|
|
Effect: "Allow",
|
|
Action: "ssm:DescribeParameters",
|
|
Resource: "*",
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
function queueArns(account: string): string[] {
|
|
return [
|
|
"paychex-webhook-events",
|
|
"paychex-webhook-events-dlq",
|
|
"paychex-login-delay",
|
|
"paychex-login-delay-dlq",
|
|
"paychex-checkcomponents",
|
|
"paychex-checkcomponents-dlq",
|
|
"paychex-payroll-schedule",
|
|
"paychex-payroll-schedule-dlq",
|
|
].map((name) => `arn:aws:sqs:us-east-1:${account}:${name}`);
|
|
}
|
|
|
|
function scheduleArns(account: string): string[] {
|
|
return [
|
|
`arn:aws:scheduler:us-east-1:${account}:schedule/default/paychex-payroll-monday`,
|
|
`arn:aws:scheduler:us-east-1:${account}:schedule/default/paychex-payroll-thursday`,
|
|
];
|
|
}
|