Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ecs): canContainersAccessInstanceRole is ignored when passed in AsgCapacityProvider constructor #20522

Merged
merged 8 commits into from
May 27, 2022
14 changes: 13 additions & 1 deletion packages/@aws-cdk/aws-ecs/lib/cluster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,10 @@ export class Cluster extends Resource implements ICluster {
}
this._hasEc2Capacity = true;
this.configureAutoScalingGroup(provider.autoScalingGroup, {
...options,
...{
daschaa marked this conversation as resolved.
Show resolved Hide resolved
...options,
canContainersAccessInstanceRole: provider.canContainersAccessInstanceRole || options.canContainersAccessInstanceRole,
daschaa marked this conversation as resolved.
Show resolved Hide resolved
},
machineImageType: provider.machineImageType,
// Don't enable the instance-draining lifecycle hook if managed termination protection is enabled
taskDrainTime: provider.enableManagedTerminationProtection ? Duration.seconds(0) : options.taskDrainTime,
Expand Down Expand Up @@ -1109,13 +1112,22 @@ export class AsgCapacityProvider extends CoreConstruct {
*/
readonly enableManagedTerminationProtection?: boolean;

/**
* Specifies whether the containers can access the container instance role.
*
* @default false
*/
readonly canContainersAccessInstanceRole?: boolean;

constructor(scope: Construct, id: string, props: AsgCapacityProviderProps) {
super(scope, id);

this.autoScalingGroup = props.autoScalingGroup as autoscaling.AutoScalingGroup;

this.machineImageType = props.machineImageType ?? MachineImageType.AMAZON_LINUX_2;

this.canContainersAccessInstanceRole = props.canContainersAccessInstanceRole;

this.enableManagedTerminationProtection =
props.enableManagedTerminationProtection === undefined ? true : props.enableManagedTerminationProtection;

Expand Down
98 changes: 98 additions & 0 deletions packages/@aws-cdk/aws-ecs/test/cluster.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2306,3 +2306,101 @@ test('throws when ASG Capacity Provider with capacityProviderName starting with
cluster.addAsgCapacityProvider(capacityProviderAl2);
}).toThrow(/Invalid Capacity Provider Name: ecscp, If a name is specified, it cannot start with aws, ecs, or fargate./);
});

describe('Accessing container instance role', function () {

const addUserDataMock = jest.fn();
const autoScalingGroup: autoscaling.AutoScalingGroup = {
addUserData: addUserDataMock,
addToRolePolicy: jest.fn(),
protectNewInstancesFromScaleIn: jest.fn(),
} as unknown as autoscaling.AutoScalingGroup;

afterEach(() => {
addUserDataMock.mockClear();
});

test('block ecs from accessing metadata service when canContainersAccessInstanceRole not set', () => {
// GIVEN
const app = new cdk.App();
const stack = new cdk.Stack(app, 'test');
const cluster = new ecs.Cluster(stack, 'EcsCluster');

// WHEN

const capacityProvider = new ecs.AsgCapacityProvider(stack, 'Provider', {
autoScalingGroup: autoScalingGroup,
});

cluster.addAsgCapacityProvider(capacityProvider);

// THEN
expect(autoScalingGroup.addUserData).toHaveBeenCalledWith('sudo iptables --insert FORWARD 1 --in-interface docker+ --destination 169.254.169.254/32 --jump DROP');
expect(autoScalingGroup.addUserData).toHaveBeenCalledWith('sudo service iptables save');
expect(autoScalingGroup.addUserData).toHaveBeenCalledWith('echo ECS_AWSVPC_BLOCK_IMDS=true >> /etc/ecs/ecs.config');
});

test('allow ecs accessing metadata service when canContainersAccessInstanceRole is set on addAsgCapacityProvider', () => {
// GIVEN
const app = new cdk.App();
const stack = new cdk.Stack(app, 'test');
const cluster = new ecs.Cluster(stack, 'EcsCluster');

// WHEN
const capacityProvider = new ecs.AsgCapacityProvider(stack, 'Provider', {
autoScalingGroup: autoScalingGroup,
});

cluster.addAsgCapacityProvider(capacityProvider, {
canContainersAccessInstanceRole: true,
});

// THEN
expect(autoScalingGroup.addUserData).not.toHaveBeenCalledWith('sudo iptables --insert FORWARD 1 --in-interface docker+ --destination 169.254.169.254/32 --jump DROP');
expect(autoScalingGroup.addUserData).not.toHaveBeenCalledWith('sudo service iptables save');
expect(autoScalingGroup.addUserData).not.toHaveBeenCalledWith('echo ECS_AWSVPC_BLOCK_IMDS=true >> /etc/ecs/ecs.config');
});

test('allow ecs accessing metadata service when canContainersAccessInstanceRole is set on AsgCapacityProvider instantiation', () => {
// GIVEN
const app = new cdk.App();
const stack = new cdk.Stack(app, 'test');
const cluster = new ecs.Cluster(stack, 'EcsCluster');

// WHEN
const capacityProvider = new ecs.AsgCapacityProvider(stack, 'Provider', {
autoScalingGroup: autoScalingGroup,
canContainersAccessInstanceRole: true,
});

cluster.addAsgCapacityProvider(capacityProvider);

// THEN
expect(autoScalingGroup.addUserData).not.toHaveBeenCalledWith('sudo iptables --insert FORWARD 1 --in-interface docker+ --destination 169.254.169.254/32 --jump DROP');
expect(autoScalingGroup.addUserData).not.toHaveBeenCalledWith('sudo service iptables save');
expect(autoScalingGroup.addUserData).not.toHaveBeenCalledWith('echo ECS_AWSVPC_BLOCK_IMDS=true >> /etc/ecs/ecs.config');
});

test('allow ecs accessing metadata service when canContainersAccessInstanceRole is set on constructor and method', () => {
// GIVEN
const app = new cdk.App();
const stack = new cdk.Stack(app, 'test');
const cluster = new ecs.Cluster(stack, 'EcsCluster');

// WHEN
const capacityProvider = new ecs.AsgCapacityProvider(stack, 'Provider', {
autoScalingGroup: autoScalingGroup,
canContainersAccessInstanceRole: true,
});

cluster.addAsgCapacityProvider(capacityProvider, {
canContainersAccessInstanceRole: true,
});

// THEN
expect(autoScalingGroup.addUserData).not.toHaveBeenCalledWith('sudo iptables --insert FORWARD 1 --in-interface docker+ --destination 169.254.169.254/32 --jump DROP');
expect(autoScalingGroup.addUserData).not.toHaveBeenCalledWith('sudo service iptables save');
expect(autoScalingGroup.addUserData).not.toHaveBeenCalledWith('echo ECS_AWSVPC_BLOCK_IMDS=true >> /etc/ecs/ecs.config');
});
});