Skip to content

Commit bee4938

Browse files
committed
create role to allow user to run service catalogue's CLI package
1 parent 054bbe5 commit bee4938

File tree

4 files changed

+168
-11
lines changed

4 files changed

+168
-11
lines changed

package-lock.json

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/cdk/lib/__snapshots__/service-catalogue.test.ts.snap

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ exports[`The ServiceCatalogue stack matches the snapshot 1`] = `
1111
"GuLoggingStreamNameParameter",
1212
"GuStringParameter",
1313
"GuStringParameter",
14+
"GuDeveloperPolicyExperimental",
1415
"GuDistributionBucketParameter",
1516
"GuScheduledLambda",
1617
"GuAnghammaradTopicParameter",
@@ -24140,6 +24141,110 @@ spec:
2414024141
"Type": "AWS::SecretsManager::Secret",
2414124142
"UpdateReplacePolicy": "Delete",
2414224143
},
24144+
"ServiceCatalogueCliPolicy7789F330": {
24145+
"Properties": {
24146+
"Description": "Service Catalogue CLI",
24147+
"Path": "/developer-policy/service-catalogue-cli/",
24148+
"PolicyDocument": {
24149+
"Statement": [
24150+
{
24151+
"Action": [
24152+
"ecs:RunTask",
24153+
"ecs:List*",
24154+
"ecs:Describe*",
24155+
],
24156+
"Effect": "Allow",
24157+
"Resource": {
24158+
"Fn::Join": [
24159+
"",
24160+
[
24161+
"arn:",
24162+
{
24163+
"Ref": "AWS::Partition",
24164+
},
24165+
":ecs:eu-west-1:",
24166+
{
24167+
"Ref": "AWS::AccountId",
24168+
},
24169+
":task/",
24170+
{
24171+
"Ref": "servicecatalogueCluster5FC34DC5",
24172+
},
24173+
"/*",
24174+
],
24175+
],
24176+
},
24177+
},
24178+
{
24179+
"Action": "ssm:GetParameter",
24180+
"Effect": "Allow",
24181+
"Resource": [
24182+
{
24183+
"Fn::Join": [
24184+
"",
24185+
[
24186+
"arn:",
24187+
{
24188+
"Ref": "AWS::Partition",
24189+
},
24190+
":ssm:eu-west-1:",
24191+
{
24192+
"Ref": "AWS::AccountId",
24193+
},
24194+
":parameter//PROD/deploy/service-catalogue/*",
24195+
],
24196+
],
24197+
},
24198+
{
24199+
"Fn::Join": [
24200+
"",
24201+
[
24202+
"arn:",
24203+
{
24204+
"Ref": "AWS::Partition",
24205+
},
24206+
":ssm:eu-west-1:",
24207+
{
24208+
"Ref": "AWS::AccountId",
24209+
},
24210+
":parameter//PROD/deploy/riff-raff/external-database-access-security-group",
24211+
],
24212+
],
24213+
},
24214+
{
24215+
"Fn::Join": [
24216+
"",
24217+
[
24218+
"arn:",
24219+
{
24220+
"Ref": "AWS::Partition",
24221+
},
24222+
":ssm:eu-west-1:",
24223+
{
24224+
"Ref": "AWS::AccountId",
24225+
},
24226+
":parameter//account/vpc/primary/subnets/private",
24227+
],
24228+
],
24229+
},
24230+
],
24231+
},
24232+
{
24233+
"Action": [
24234+
"secretsmanager:GetSecretValue",
24235+
"secretsmanager:ListSecrets",
24236+
],
24237+
"Effect": "Allow",
24238+
"Resource": {
24239+
"Ref": "PostgresInstance1SecretAttachmentBA0D257D",
24240+
},
24241+
},
24242+
],
24243+
"Version": "2012-10-17",
24244+
},
24245+
},
24246+
"Type": "AWS::IAM::ManagedPolicy",
24247+
},
2414324248
"TopicBFC7AF6E": {
2414424249
"Properties": {
2414524250
"Tags": [

packages/cdk/lib/cloudquery/index.ts

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
import { GuardianAwsAccounts } from '@guardian/aws-account-setup';
2+
import { NAMED_SSM_PARAMETER_PATHS } from '@guardian/cdk/lib/constants';
23
import type { GuStack } from '@guardian/cdk/lib/constructs/core';
34
import { GuStringParameter } from '@guardian/cdk/lib/constructs/core';
45
import { GuSecurityGroup } from '@guardian/cdk/lib/constructs/ec2';
56
import { GuS3Bucket } from '@guardian/cdk/lib/constructs/s3';
7+
import type { GuWorkloadPolicyProps } from '@guardian/cdk/lib/experimental/constructs/iam/policies';
8+
import { GuDeveloperPolicyExperimental } from '@guardian/cdk/lib/experimental/constructs/iam/policies';
69
import { Duration } from 'aws-cdk-lib';
710
import type { IVpc } from 'aws-cdk-lib/aws-ec2';
811
import { Secret } from 'aws-cdk-lib/aws-ecs';
912
import { Schedule } from 'aws-cdk-lib/aws-events';
10-
import type { PolicyStatement } from 'aws-cdk-lib/aws-iam';
13+
import { Effect, PolicyStatement } from 'aws-cdk-lib/aws-iam';
1114
import type { DatabaseInstance } from 'aws-cdk-lib/aws-rds';
1215
import { Secret as SecretsManager } from 'aws-cdk-lib/aws-secretsmanager';
1316
import { StringParameter } from 'aws-cdk-lib/aws-ssm';
@@ -61,6 +64,14 @@ interface CloudqueryEcsClusterProps {
6164
enableCloudquerySchedules: boolean;
6265
}
6366

67+
function ssmArn(stack: GuStack, parameterName: string): string {
68+
return stack.formatArn({
69+
service: 'ssm',
70+
resource: 'parameter',
71+
resourceName: parameterName,
72+
});
73+
}
74+
6475
export function addCloudqueryEcsCluster(
6576
scope: GuStack,
6677
props: CloudqueryEcsClusterProps,
@@ -656,7 +667,7 @@ export function addCloudqueryEcsCluster(
656667
config: endOfLifeSourceConfig(),
657668
};
658669

659-
return new CloudqueryCluster(scope, `${app}Cluster`, {
670+
const cluster = new CloudqueryCluster(scope, `${app}Cluster`, {
660671
enableCloudquerySchedules,
661672
app,
662673
vpc,
@@ -678,4 +689,45 @@ export function addCloudqueryEcsCluster(
678689
],
679690
cloudqueryApiKey,
680691
});
692+
693+
const SSMPolicy = new PolicyStatement({
694+
effect: Effect.ALLOW,
695+
actions: ['ssm:GetParameter'],
696+
resources: [
697+
ssmArn(scope, `/${stage}/${stack}/${app}/*`),
698+
ssmArn(
699+
scope,
700+
`/${stage}/deploy/riff-raff/external-database-access-security-group`,
701+
),
702+
ssmArn(scope, NAMED_SSM_PARAMETER_PATHS.PrimaryVpcPrivateSubnets.path),
703+
],
704+
});
705+
706+
const cloudqueryClusterArnForTasks = cluster.arnForTasks('*');
707+
708+
const ecsPolicy = new PolicyStatement({
709+
effect: Effect.ALLOW,
710+
actions: ['ecs:RunTask', 'ecs:List*', 'ecs:Describe*'],
711+
resources: [cloudqueryClusterArnForTasks],
712+
});
713+
714+
const dbSecretPolicy = new PolicyStatement({
715+
effect: Effect.ALLOW,
716+
actions: ['secretsmanager:GetSecretValue', 'secretsmanager:ListSecrets'],
717+
resources: [db.secret!.secretArn], // The secret definitely exists, as CloudQuery needs it to connect to the database.
718+
});
719+
720+
const cliPolicyProps: GuWorkloadPolicyProps = {
721+
permission: 'service-catalogue-cli',
722+
description: 'Service Catalogue CLI',
723+
statements: [ecsPolicy, SSMPolicy, dbSecretPolicy],
724+
};
725+
726+
new GuDeveloperPolicyExperimental(
727+
scope,
728+
'ServiceCatalogueCliPolicy',
729+
cliPolicyProps,
730+
);
731+
732+
return cluster;
681733
}

packages/cdk/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
},
1212
"devDependencies": {
1313
"@guardian/aws-account-setup": "github:guardian/aws-account-setup#shared@0.0.1",
14-
"@guardian/cdk": "62.5.1",
14+
"@guardian/cdk": "62.5.3",
1515
"@types/jest": "^30.0.0",
1616
"@types/js-yaml": "^4.0.9",
1717
"aws-cron-parser": "^1.1.12",

0 commit comments

Comments
 (0)