Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/@aws-cdk/aws-ecs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,8 @@ const service = new ecs.FargateService(this, 'Service', {
desiredCount: 5
});
```
`Services` by default will create a security group if not provided.
If you'd like to specify which security groups to use you can override the `securityGroups` property.

### Include an application/network load balancer

Expand Down
24 changes: 24 additions & 0 deletions packages/@aws-cdk/aws-ecs/lib/base/base-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,7 @@ export abstract class BaseService extends Resource

/**
* This method is called to create a networkConfiguration.
* @deprecated use configureAwsVpcNetworkingWithSecurityGroups instead.
*/
// tslint:disable-next-line:max-line-length
protected configureAwsVpcNetworking(vpc: ec2.IVpc, assignPublicIp?: boolean, vpcSubnets?: ec2.SubnetSelection, securityGroup?: ec2.ISecurityGroup) {
Expand All @@ -606,6 +607,29 @@ export abstract class BaseService extends Resource
};
}

/**
* This method is called to create a networkConfiguration.
*/
// tslint:disable-next-line:max-line-length
protected configureAwsVpcNetworkingWithSecurityGroups(vpc: ec2.IVpc, assignPublicIp?: boolean, vpcSubnets?: ec2.SubnetSelection, securityGroups?: ec2.ISecurityGroup[]) {
if (vpcSubnets === undefined) {
vpcSubnets = assignPublicIp ? { subnetType: ec2.SubnetType.PUBLIC } : {};
}
if (securityGroups === undefined || securityGroups.length === 0) {
securityGroups = [ new ec2.SecurityGroup(this, 'SecurityGroup', { vpc }) ];
}

securityGroups.forEach((sg) => { this.connections.addSecurityGroup(sg); }, this);

this.networkConfiguration = {
awsvpcConfiguration: {
assignPublicIp: assignPublicIp ? 'ENABLED' : 'DISABLED',
subnets: vpc.selectSubnets(vpcSubnets).subnetIds,
securityGroups: securityGroups.map((sg) => sg.securityGroupId),
},
};
}

private renderServiceRegistry(registry: ServiceRegistry): CfnService.ServiceRegistryProperty {
return {
registryArn: registry.arn,
Expand Down
32 changes: 28 additions & 4 deletions packages/@aws-cdk/aws-ecs/lib/ec2/ec2-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,19 @@ export interface Ec2ServiceProps extends BaseServiceOptions {
* This property is only used for tasks that use the awsvpc network mode.
*
* @default - A new security group is created.
* @deprecated use securityGroups instead.
*/
readonly securityGroup?: ec2.ISecurityGroup;

/**
* The security groups to associate with the service. If you do not specify a security group, the default security group for the VPC is used.
*
* This property is only used for tasks that use the awsvpc network mode.
*
* @default - A new security group is created.
*/
readonly securityGroups?: ec2.ISecurityGroup[];

/**
* The placement constraints to use for tasks in the service. For more information, see
* [Amazon ECS Task Placement Constraints](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-placement-constraints.html).
Expand Down Expand Up @@ -166,6 +176,10 @@ export class Ec2Service extends BaseService implements IEc2Service {
throw new Error('You can only specify either propagateTags or propagateTaskTagsFrom. Alternatively, you can leave both blank');
}

if (props.securityGroup !== undefined && props.securityGroups !== undefined) {
throw new Error('Only one of SecurityGroup or SecurityGroups can be populated.');
}

const propagateTagsFromSource = props.propagateTaskTagsFrom !== undefined ? props.propagateTaskTagsFrom
: (props.propagateTags !== undefined ? props.propagateTags : PropagatedTagSource.NONE);

Expand All @@ -191,8 +205,15 @@ export class Ec2Service extends BaseService implements IEc2Service {
this.strategies = [];
this.daemon = props.daemon || false;

let securityGroups;
if (props.securityGroup !== undefined) {
securityGroups = [ props.securityGroup ];
} else if (props.securityGroups !== undefined) {
securityGroups = props.securityGroups;
}

if (props.taskDefinition.networkMode === NetworkMode.AWS_VPC) {
this.configureAwsVpcNetworking(props.cluster.vpc, props.assignPublicIp, props.vpcSubnets, props.securityGroup);
this.configureAwsVpcNetworkingWithSecurityGroups(props.cluster.vpc, props.assignPublicIp, props.vpcSubnets, securityGroups);
} else {
// Either None, Bridge or Host networking. Copy SecurityGroups from ASG.
// We have to be smart here -- by default future Security Group rules would be created
Expand Down Expand Up @@ -251,11 +272,14 @@ export class Ec2Service extends BaseService implements IEc2Service {
}

/**
* Validate combinations of networking arguments
* Validate combinations of networking arguments.
*/
function validateNoNetworkingProps(props: Ec2ServiceProps) {
if (props.vpcSubnets !== undefined || props.securityGroup !== undefined || props.assignPublicIp) {
throw new Error('vpcSubnets, securityGroup and assignPublicIp can only be used in AwsVpc networking mode');
if (props.vpcSubnets !== undefined
|| props.securityGroup !== undefined
|| props.securityGroups !== undefined
|| props.assignPublicIp) {
throw new Error('vpcSubnets, securityGroup(s) and assignPublicIp can only be used in AwsVpc networking mode');
}
}

Expand Down
21 changes: 20 additions & 1 deletion packages/@aws-cdk/aws-ecs/lib/fargate/fargate-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,17 @@ export interface FargateServiceProps extends BaseServiceOptions {
* The security groups to associate with the service. If you do not specify a security group, the default security group for the VPC is used.
*
* @default - A new security group is created.
* @deprecated use securityGroups instead.
*/
readonly securityGroup?: ec2.ISecurityGroup;

/**
* The security groups to associate with the service. If you do not specify a security group, the default security group for the VPC is used.
*
* @default - A new security group is created.
*/
readonly securityGroups?: ec2.ISecurityGroup[];

/**
* The platform version on which to run your service.
*
Expand Down Expand Up @@ -128,6 +136,10 @@ export class FargateService extends BaseService implements IFargateService {
throw new Error('You can only specify either propagateTags or propagateTaskTagsFrom. Alternatively, you can leave both blank');
}

if (props.securityGroup !== undefined && props.securityGroups !== undefined) {
throw new Error('Only one of SecurityGroup or SecurityGroups can be populated.');
}

const propagateTagsFromSource = props.propagateTaskTagsFrom !== undefined ? props.propagateTaskTagsFrom
: (props.propagateTags !== undefined ? props.propagateTags : PropagatedTagSource.NONE);

Expand All @@ -143,7 +155,14 @@ export class FargateService extends BaseService implements IFargateService {
platformVersion: props.platformVersion,
}, props.taskDefinition);

this.configureAwsVpcNetworking(props.cluster.vpc, props.assignPublicIp, props.vpcSubnets, props.securityGroup);
let securityGroups;
if (props.securityGroup !== undefined) {
securityGroups = [ props.securityGroup ];
} else if (props.securityGroups !== undefined) {
securityGroups = props.securityGroups;
}

this.configureAwsVpcNetworkingWithSecurityGroups(props.cluster.vpc, props.assignPublicIp, props.vpcSubnets, securityGroups);

if (!props.taskDefinition.defaultContainer) {
throw new Error('A TaskDefinition must have at least one essential container');
Expand Down
Loading