This AWS CloudFormation Hook validates that an EC2 instance to be deployed, can only be accessed using AWS Systems Manager Session Manager.
The Hook currently checks AWS::EC2::Instance and AWS::EC2::LaunchTemplate resource types. Instances deploed via AWS::AutoScaling::LaunchConfiguration are not currently checked.
The validation consists of the following high-level steps:
-
Ensure the instance has a IamInstanceProfile assigned
-
Simulate the IamInstanceProfile role to ensure it 'Allows' the following permissions:
ssmmessages:CreateControlChannelssmmessages:CreateDataChannelssmmessages:OpenControlChannelssmmessages:OpenDataChannel
-
Verify none of the instance security groups allow ingress on 22/SSH if a Linux instance or 3389/RDP if a Windows instance.
Security Groups are checked depending on how specified for the instance:
SecurityGroupIdsproperty (non-default VPC)SecurityGroupsproperty (EC2-Classic, default VPC)NetworkInterfacesproperty
The hook can enforce KMS key encryption of SSM Session data by requiring the instance IamInstanceProfile role to include the kms:decrypt permission. You can control this by setting the requireSessionManagerEncryption property in the Hook Configuration JSON as shown below.
{
"CloudFormationConfiguration": {
"HookConfiguration": {
"TargetStacks": "ALL",
"FailureMode": "FAIL",
"Properties": {
"requireSessionManagerEncryption": true
}
}
}
}
See Defining the account-level configuration of an extension in the CloudFormation CLI User Guide.
An AWS CloudFormation template is provided in the testing folder to exercise various failure use-cases by manipulating the provided template parameters:
-
IncludeInstanceProfile: (True|False)Set to
Falseto remove the IamInstanceProfile property which should result in anIamInstanceProfile property missing or empty valueerror -
ManagedOrManualIAMPolicy (Managed|Manual)Set to
Managedto generate the IamInstanceProfile role policy using thearn:aws:iam::aws:policy/AmazonSSMManagedInstanceCoreIAM Managed policy.Set to
Manualto generate the IamInstanceProfile role policy using an inline policy containing the required SSM Session Manager permissions -
TestIllegalManualSSMPolicies (True|False)Set to
Trueto omit thessmmessages:OpenControlChannelpermission from the policy which should result in anssmmessages:OpenControlChannel: Implicit Denyerror -
IncludeExplicitSecurityGroup (True|False)Set to
Trueto include a Security Group for the instance that does not reference port 22/SSH -
IncludeExplicitSSHSecurityGroup (True|False)Set to
Trueto include a Security Group for the instance that does includes an ingress rule for 22/SSH. This should result in anSecurity Group contains an SSH ingress ruleerror -
UseProvidedDefaultVpcValues (True|False)Set to
Falseto have the template create a custom VPC and Subnet, and deploy the instance into itSet to
Trueto deploy the instance into the default VPC and Subnet you provide using theDefaultVpcandDefaultVpcSubnetIdparameters. -
IncludeSSMKMS (True|False)Set to 'True' to have the template generate an KMS key and reference it with the
kms:decryptaction in the IAMInstanceRole.If
requireSessionManagerEncryptionproperty in the Hook Configuration is set toTrueand you setIncludeSSMKMStoFalse, you should get akms:decrypt: Implicit Denyerror
IMPORTANT
During a stack update, if a dependant property of the instance is changed, the hook will not be called. This means its possible during a stack update, to bypass the validation checks such as adding an 22/SSH ingress rule to the instances' referenced Security Group.