-
Notifications
You must be signed in to change notification settings - Fork 55
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
First commit after repackage and removal of build/ which included AWS… #40
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
# Byte-compiled / optimized / DLL files | ||
__pycache__/ | ||
*.py[cod] | ||
*$py.class | ||
|
||
# C extensions | ||
*.so | ||
|
||
# Distribution / packaging | ||
.Python | ||
build/ | ||
develop-eggs/ | ||
dist/ | ||
downloads/ | ||
eggs/ | ||
.eggs/ | ||
lib/ | ||
lib64/ | ||
parts/ | ||
sdist/ | ||
var/ | ||
wheels/ | ||
pip-wheel-metadata/ | ||
share/python-wheels/ | ||
*.egg-info/ | ||
.installed.cfg | ||
*.egg | ||
MANIFEST | ||
|
||
# PyInstaller | ||
# Usually these files are written by a python script from a template | ||
# before PyInstaller builds the exe, so as to inject date/other infos into it. | ||
*.manifest | ||
*.spec | ||
|
||
# Installer logs | ||
pip-log.txt | ||
pip-delete-this-directory.txt | ||
|
||
# Unit test / coverage reports | ||
htmlcov/ | ||
.tox/ | ||
.nox/ | ||
.coverage | ||
.coverage.* | ||
.cache | ||
nosetests.xml | ||
coverage.xml | ||
*.cover | ||
.hypothesis/ | ||
.pytest_cache/ | ||
|
||
# Translations | ||
*.mo | ||
*.pot | ||
|
||
# Django stuff: | ||
*.log | ||
local_settings.py | ||
db.sqlite3 | ||
db.sqlite3-journal | ||
|
||
# Flask stuff: | ||
instance/ | ||
.webassets-cache | ||
|
||
# Scrapy stuff: | ||
.scrapy | ||
|
||
# Sphinx documentation | ||
docs/_build/ | ||
|
||
# PyBuilder | ||
target/ | ||
|
||
# Jupyter Notebook | ||
.ipynb_checkpoints | ||
|
||
# IPython | ||
profile_default/ | ||
ipython_config.py | ||
|
||
# pyenv | ||
.python-version | ||
|
||
# pipenv | ||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. | ||
# However, in case of collaboration, if having platform-specific dependencies or dependencies | ||
# having no cross-platform support, pipenv may install dependencies that don't work, or not | ||
# install all needed dependencies. | ||
#Pipfile.lock | ||
|
||
# celery beat schedule file | ||
celerybeat-schedule | ||
|
||
# SageMath parsed files | ||
*.sage.py | ||
|
||
# Environments | ||
.env | ||
.venv | ||
env/ | ||
venv/ | ||
ENV/ | ||
env.bak/ | ||
venv.bak/ | ||
|
||
# Spyder project settings | ||
.spyderproject | ||
.spyproject | ||
|
||
# Rope project settings | ||
.ropeproject | ||
|
||
# mkdocs documentation | ||
/site | ||
|
||
# mypy | ||
.mypy_cache/ | ||
.dmypy.json | ||
dmypy.json | ||
|
||
# Pyre type checker | ||
.pyre/ | ||
|
||
# contains credentials | ||
sam-tests/ | ||
|
||
rpdk.log* | ||
|
||
.DS_Store |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{ | ||
"artifact_type": "HOOK", | ||
"typeName": "AWSSamples::Ec2SsmSmOnly::Hook", | ||
"language": "python36", | ||
"runtime": "python3.6", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be |
||
"entrypoint": "awssamples_ec2ssmsmonly_hook.handlers.hook", | ||
"testEntrypoint": "awssamples_ec2ssmsmonly_hook.handlers.test_entrypoint", | ||
"settings": { | ||
"version": false, | ||
"subparser_name": null, | ||
"verbose": 0, | ||
"force": false, | ||
"type_name": null, | ||
"artifact_type": null, | ||
"endpoint_url": null, | ||
"region": null, | ||
"target_schemas": [], | ||
"use_docker": true, | ||
"protocolVersion": "2.0.0" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
# AWSSamples::Ec2SsmSmOnly::Hook | ||
|
||
This AWS CloudFormation Hook validates that an EC2 instance to be deployed, can only be accessed using [AWS Systems Manager Session Manager](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager.html). | ||
|
||
The Hook currently checks [AWS::EC2::Instance](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html) and [AWS::EC2::LaunchTemplate](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-launchtemplate.html) resource types. Instances deploed via [AWS::AutoScaling::LaunchConfiguration](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-autoscaling-launchconfiguration.html) are not currently checked. | ||
|
||
### Validation Overview ### | ||
The validation consists of the following high-level steps: | ||
1. Ensure the instance has a [IamInstanceProfile](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-iaminstanceprofile) assigned | ||
2. Simulate the [IamInstanceProfile](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-iaminstanceprofile) role to ensure it 'Allows' the following permissions: | ||
* `ssmmessages:CreateControlChannel` | ||
* `ssmmessages:CreateDataChannel` | ||
* `ssmmessages:OpenControlChannel` | ||
* `ssmmessages:OpenDataChannel` | ||
|
||
3. 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: | ||
* `SecurityGroupIds` property (non-default VPC) | ||
* `SecurityGroups` property (EC2-Classic, default VPC) | ||
* `NetworkInterfaces` property | ||
|
||
### Requiring KMS Encrypted SSM Sessions | ||
The hook can enforce KMS key encryption of SSM Session data by requiring the instance [IamInstanceProfile](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-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. | ||
|
||
<pre> | ||
{ | ||
"CloudFormationConfiguration": { | ||
"HookConfiguration": { | ||
"TargetStacks": "ALL", | ||
"FailureMode": "FAIL", | ||
"Properties": { | ||
<b>"requireSessionManagerEncryption": true</b> | ||
} | ||
} | ||
} | ||
} | ||
</pre> | ||
See [Defining the account-level configuration of an extension](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/resource-type-model.html#resource-type-howto-configuration) in the *CloudFormation CLI User Guide*. | ||
|
||
### Testing | ||
|
||
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 `False` to remove the [IamInstanceProfile](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-iaminstanceprofile) property which should result in an `IamInstanceProfile property missing or empty value` error | ||
|
||
* `ManagedOrManualIAMPolicy (Managed|Manual)` | ||
|
||
Set to `Managed` to generate the [IamInstanceProfile](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-iaminstanceprofile) role policy using the `arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore` IAM Managed policy. | ||
|
||
Set to `Manual` to generate the [IamInstanceProfile](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html#cfn-ec2-instance-iaminstanceprofile) role policy using an inline policy containing the required SSM Session Manager permissions | ||
* `TestIllegalManualSSMPolicies (True|False)` | ||
|
||
Set to `True` to omit the `ssmmessages:OpenControlChannel` permission from the policy which should result in an `ssmmessages:OpenControlChannel: Implicit Deny` error | ||
|
||
* `IncludeExplicitSecurityGroup (True|False)` | ||
|
||
Set to `True` to include a Security Group for the instance that does not reference port 22/SSH | ||
|
||
* `IncludeExplicitSSHSecurityGroup (True|False)` | ||
|
||
Set to `True` to include a Security Group for the instance that does includes an ingress rule for 22/SSH. This should result in an `Security Group contains an SSH ingress rule` error | ||
|
||
* `UseProvidedDefaultVpcValues (True|False)` | ||
|
||
Set to `False` to have the template create a custom VPC and Subnet, and deploy the instance into it | ||
|
||
Set to `True` to deploy the instance into the *default* VPC and Subnet you provide using the `DefaultVpc` and `DefaultVpcSubnetId` parameters. | ||
|
||
* `IncludeSSMKMS (True|False)` | ||
|
||
Set to 'True' to have the template generate an KMS key and reference it with the `kms:decrypt` action in the IAMInstanceRole. | ||
|
||
If `requireSessionManagerEncryption` property in the Hook Configuration is set to `True` and you set `IncludeSSMKMS` to `False`, you should get a `kms:decrypt: Implicit Deny` error | ||
|
||
> **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. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"properties": { | ||
"requireSessionManagerEncryption": { | ||
"type": "boolean", | ||
"description": "Set to 'true' to require kms:decrypt action with a valid key-name resource", | ||
"enum": [ | ||
true, | ||
false | ||
], | ||
"default": false | ||
} | ||
}, | ||
"additionalProperties": false, | ||
"definitions": {}, | ||
"typeName": "AWSSamples::Ec2SsmSmOnly::Hook" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
{ | ||
"typeName": "AWSSamples::Ec2SsmSmOnly::Hook", | ||
"description": "Checks that EC2 instances being deployed are configured to only allow use of SSM Session Manager to access the instance", | ||
"sourceUrl": "https://github.com/aws-cloudformation/example-sse-hook", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please update the URL accordingly. |
||
"documentationUrl": "https://github.com/aws-cloudformation/example-sse-hook/blob/master/README.md", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please update the URL accordingly. |
||
"typeConfiguration": { | ||
"properties": { | ||
"requireSessionManagerEncryption": { | ||
"type": "boolean", | ||
"description": "Set to 'true' to require kms:decrypt action with a valid key-name resource", | ||
"enum": [ | ||
true, | ||
false | ||
], | ||
"default": false | ||
} | ||
}, | ||
"additionalProperties": false | ||
}, | ||
"required": [], | ||
"handlers": { | ||
"preCreate": { | ||
"targetNames": [ | ||
"AWS::EC2::Instance", | ||
"AWS::EC2::LaunchTemplate" | ||
], | ||
"permissions": [ | ||
"ec2:DescribeSecurityGroups", | ||
"ec2:DescribeImages", | ||
"iam:GetInstanceProfile", | ||
"iam:SimulatePrincipalPolicy", | ||
"iam:GetRole" | ||
] | ||
}, | ||
"preUpdate": { | ||
"targetNames": [ | ||
"AWS::EC2::Instance", | ||
"AWS::EC2::LaunchTemplate" | ||
], | ||
"permissions": [ | ||
"ec2:DescribeSecurityGroups", | ||
"ec2:DescribeImages", | ||
"iam:GetInstanceProfile", | ||
"iam:SimulatePrincipalPolicy", | ||
"iam:GetRole" | ||
] | ||
} | ||
}, | ||
"additionalProperties": false | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
AWSTemplateFormatVersion: "2010-09-09" | ||
Description: > | ||
This CloudFormation template creates a role assumed by CloudFormation | ||
during Hook operations on behalf of the customer. | ||
|
||
Resources: | ||
ExecutionRole: | ||
Type: AWS::IAM::Role | ||
Properties: | ||
MaxSessionDuration: 8400 | ||
AssumeRolePolicyDocument: | ||
Version: '2012-10-17' | ||
Statement: | ||
- Effect: Allow | ||
Principal: | ||
Service: | ||
- hooks.cloudformation.amazonaws.com | ||
- resources.cloudformation.amazonaws.com | ||
Action: sts:AssumeRole | ||
Condition: | ||
StringEquals: | ||
aws:SourceAccount: | ||
Ref: AWS::AccountId | ||
StringLike: | ||
aws:SourceArn: | ||
Fn::Sub: arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:type/hook/AWSSamples-Ec2SsmSmOnly-Hook/* | ||
Path: "/" | ||
Policies: | ||
- PolicyName: HookTypePolicy | ||
PolicyDocument: | ||
Version: '2012-10-17' | ||
Statement: | ||
- Effect: Allow | ||
Action: | ||
- "ec2:DescribeImages" | ||
- "ec2:DescribeSecurityGroups" | ||
- "iam:GetInstanceProfile" | ||
- "iam:GetRole" | ||
- "iam:SimulatePrincipalPolicy" | ||
Resource: "*" | ||
Outputs: | ||
ExecutionRoleArn: | ||
Value: | ||
Fn::GetAtt: ExecutionRole.Arn |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
cloudformation-cli-python-lib==2.2.hooks | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
AWSTemplateFormatVersion: "2010-09-09" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This file does not seem to be needed - please remove it, or clarify. |
||
Description: > | ||
This CloudFormation template creates a role assumed by CloudFormation | ||
during Hook operations on behalf of the customer. | ||
|
||
Resources: | ||
ExecutionRole: | ||
Type: AWS::IAM::Role | ||
Properties: | ||
MaxSessionDuration: 8400 | ||
AssumeRolePolicyDocument: | ||
Version: '2012-10-17' | ||
Statement: | ||
- Effect: Allow | ||
Principal: | ||
Service: cfnhooksservice.cloudformation.aws.internal | ||
Action: sts:AssumeRole | ||
Path: "/" | ||
Policies: | ||
- PolicyName: ResourceTypePolicy | ||
PolicyDocument: | ||
Version: '2012-10-17' | ||
Statement: | ||
- Effect: Allow | ||
Action: | ||
- "iam:GetInstanceProfile" | ||
- "iam:SimulatePrincipalPolicy" | ||
Resource: "*" | ||
Outputs: | ||
ExecutionRoleArn: | ||
Value: | ||
Fn::GetAtt: ExecutionRole.Arn |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be
python37
at least.