From 41d18f28ef7d0f37b160f5af848cf512aafa06ca Mon Sep 17 00:00:00 2001 From: Daniel Van Der Ploeg Date: Wed, 13 Sep 2023 15:36:59 +0930 Subject: [PATCH 1/2] feat: add read only user to access ecs --- packages/graphql-mesh-server/lib/fargate.ts | 71 ++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/packages/graphql-mesh-server/lib/fargate.ts b/packages/graphql-mesh-server/lib/fargate.ts index 10081be1..9c819a79 100644 --- a/packages/graphql-mesh-server/lib/fargate.ts +++ b/packages/graphql-mesh-server/lib/fargate.ts @@ -1,5 +1,5 @@ import { Construct } from 'constructs'; -import { Duration, Token } from 'aws-cdk-lib'; +import { CfnOutput, Duration } from 'aws-cdk-lib'; import { RemovalPolicy } from 'aws-cdk-lib'; import * as acm from 'aws-cdk-lib/aws-certificatemanager'; import * as ecs from 'aws-cdk-lib/aws-ecs'; @@ -8,11 +8,21 @@ import * as ecsPatterns from 'aws-cdk-lib/aws-ecs-patterns'; import * as iam from 'aws-cdk-lib/aws-iam'; import * as ssm from 'aws-cdk-lib/aws-ssm'; import * as auto_scaling from 'aws-cdk-lib/aws-autoscaling'; +import * as logs from 'aws-cdk-lib/aws-logs'; import { Port, SecurityGroup, Vpc } from 'aws-cdk-lib/aws-ec2'; import { RedisService } from './redis-construct'; import { ManagedRule, Scope, WebApplicationFirewall } from './web-application-firewall'; export interface MeshServiceProps { + /** + * Name of the read only role used to access logs + */ + readOnlyRoleName?: string; + /** + * ARN of the account to allow access to assume role from + * If provided a read only user will be created + */ + awsAccountArn?: string; /** * VPC to attach Redis instance to */ @@ -142,6 +152,9 @@ export class MeshService extends Construct { for (const [key, ssm] of Object.entries(props.secrets)) { secrets[key] = ecs.Secret.fromSsmParameter(ssm); } + + const logGroup = new logs.LogGroup(this, "log-group"); + // Create a load-balanced Fargate service and make it public const fargateService = new ecsPatterns.ApplicationLoadBalancedFargateService( @@ -161,6 +174,10 @@ export class MeshService extends Construct { containerPort: 4000, // graphql mesh gateway port secrets: secrets, environment: environment, + logDriver: new ecs.AwsLogDriver({ + logGroup: logGroup, + streamPrefix: "mesh", + }), }, publicLoadBalancer: true, // default, taskSubnets: { @@ -216,5 +233,57 @@ export class MeshService extends Construct { ], adjustmentType: auto_scaling.AdjustmentType.CHANGE_IN_CAPACITY, }); + + // Cross account role to get read only access to mesh + // and the relevant logs + if (props.readOnlyRoleName) { + const readOnlyRole = new iam.Role(this, "read-only-role", { + assumedBy: new iam.AccountPrincipal(props.awsAccountArn), + description: "Read Only Role for Mesh Developers", + roleName: props.readOnlyRoleName, + }); + + const readOnlyPolicy = new iam.ManagedPolicy(this, "read-only-policy"); + readOnlyPolicy.addStatements( + new iam.PolicyStatement({ + effect: iam.Effect.ALLOW, + actions: [ + "logs:Describe*", + "logs:Get*", + "logs:List*", + "logs:StartQuery", + "logs:StopQuery", + "logs:TestMetricFilter", + "logs:FilterLogEvents", + "logs:StartLiveTail", + "logs:StopLiveTail", + ], + resources: [logGroup.logGroupArn], + }), + new iam.PolicyStatement({ + effect: iam.Effect.ALLOW, + actions: [ + "ecs:DescribeClusters", + "ecs:DescribeServices", + "ecs:DescribeTasks", + "ecs:DescribeTaskDefinition", + "esc:DescribeContainerInstances", + "ecs:ListClusters", + "ecs:ListContainerInstances", + "ecs:ListServices", + "ecs:ListTaskDefinitions", + "ecs:ListTasks", + ], + resources: ["*"], + }) + ); + + readOnlyRole.addManagedPolicy(readOnlyPolicy); + + new CfnOutput(this, "read-only-role-arn", { + description: "ReadOnlyRoleArn", + value: readOnlyRole.roleArn, + }); + } } } From 40aa7dfe01af83ad37e1abc8fd76e2a818401a3a Mon Sep 17 00:00:00 2001 From: Daniel Van Der Ploeg Date: Mon, 18 Sep 2023 11:18:31 +0930 Subject: [PATCH 2/2] feat: add default for read only role name --- packages/graphql-mesh-server/lib/fargate.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/graphql-mesh-server/lib/fargate.ts b/packages/graphql-mesh-server/lib/fargate.ts index 9c819a79..1cf44488 100644 --- a/packages/graphql-mesh-server/lib/fargate.ts +++ b/packages/graphql-mesh-server/lib/fargate.ts @@ -15,7 +15,7 @@ import { ManagedRule, Scope, WebApplicationFirewall } from './web-application-fi export interface MeshServiceProps { /** - * Name of the read only role used to access logs + * Name of the read only role used to access logs (default: graphql-mesh-read-only-role) */ readOnlyRoleName?: string; /** @@ -236,11 +236,12 @@ export class MeshService extends Construct { // Cross account role to get read only access to mesh // and the relevant logs - if (props.readOnlyRoleName) { + if (props.awsAccountArn) { + const readOnlyRoleName = props.readOnlyRoleName || 'graphql-mesh-read-only-role'; const readOnlyRole = new iam.Role(this, "read-only-role", { assumedBy: new iam.AccountPrincipal(props.awsAccountArn), description: "Read Only Role for Mesh Developers", - roleName: props.readOnlyRoleName, + roleName: readOnlyRoleName, }); const readOnlyPolicy = new iam.ManagedPolicy(this, "read-only-policy");