Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save daknhh/031fa70fa4c7ccd3410ed12add3511ef to your computer and use it in GitHub Desktop.
Save daknhh/031fa70fa4c7ccd3410ed12add3511ef to your computer and use it in GitHub Desktop.
Set default setting for SSM and encrypts CloudWatch LogGroup
AWSTemplateFormatVersion: 2010-09-09
Description: Set default setting for SSM and encrypts CloudWatch LogGroup
Metadata:
Author:
Description: David Krohn
Parameters:
CloudWatchKey:
Description: Default SSM KMS Key
Type: AWS::SSM::Parameter::Value<String>
Default: /KMS/CW/DEFAULT/ARN
SsmKey:
Description: Default SSM KMS Key
Type: AWS::SSM::Parameter::Value<String>
Default: /KMS/SSM/DEFAULT/ARN
PythonLambdaLayer:
Description: "Python Lambda Layer Arn"
Default: ""
Type: String
Resources:
SessionManagerConfigurationSsmDocumentLambdaFunctionLogGroup:
Type: 'AWS::Logs::LogGroup'
Metadata:
cfn_nag:
rules_to_suppress:
- id: W84
reason: "No encryption needed in LogGroup. Does not contain sensitive information"
Properties:
RetentionInDays: 1
LogGroupName: !Sub /aws/lambda/DelSsmDocLambda-${AWS::Region}
SessionManagerLogGroup:
Type: 'AWS::Logs::LogGroup'
Properties:
RetentionInDays: 7
LogGroupName: /aws/ssm/SessionManagerLogGroup
EncryptCloudwatchLogGroupLambdaFunctionLogGroup:
Type: 'AWS::Logs::LogGroup'
Metadata:
cfn_nag:
rules_to_suppress:
- id: W84
reason: "No encryption needed in LogGroup. Does not contain sensitive information"
Properties:
RetentionInDays: 1
LogGroupName: !Sub /aws/lambda/EncCwLgLambda-${AWS::Region}
DeleteSsmDocumentLambdaExecutionRole:
DependsOn:
- SessionManagerConfigurationSsmDocumentLambdaFunctionLogGroup
- SessionManagerLogGroup
- EncryptCloudwatchLogGroupLambdaFunctionLogGroup
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
Path: /
Policies:
- PolicyName:
Fn::Sub: ${AWS::StackName}-Config-Ssm
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource:
- !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:*'
- Effect: Allow
Action:
- ssm:DeleteDocument
Resource:
- !Sub "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:document/*"
DeleteSsmDocumentLambda:
Type: AWS::Lambda::Function
DependsOn:
- SessionManagerConfigurationSsmDocumentLambdaFunctionLogGroup
- SessionManagerLogGroup
- EncryptCloudwatchLogGroupLambdaFunctionLogGroup
Properties:
FunctionName: !Sub 'DelSsmDocLambda-${AWS::Region}'
Code:
ZipFile: |
import boto3
import botocore
import os
import cfnresponse
from botocore.vendored import requests
client = boto3.client('ssm')
def delete_ssm_document(ssmdocument):
try:
response = client.delete_document(
Name = ssmdocument
)
print("Documentss: {}".format(response))
except botocore.exceptions.ClientError as e:
if e.response['Error']['Code'] == 'InvalidDocument':
print("SSM Document {} does not exist".format(ssmdocument))
# ------------------------------------------------------------------------------
# lambda_handler
# ------------------------------------------------------------------------------
def lambda_handler(event, context):
ssmdocument = os.environ['ssmdocument']
if event['RequestType'] == 'Create':
delete_ssm_document(ssmdocument)
cfnresponse.send(event, context, cfnresponse.SUCCESS,{}, event['LogicalResourceId'])
if event['RequestType'] == 'Delete':
cfnresponse.send(event, context, cfnresponse.SUCCESS,{}, event['LogicalResourceId'])
if event['RequestType'] == 'Update':
cfnresponse.send(event, context, cfnresponse.SUCCESS,{}, event['LogicalResourceId'])
Role:
!GetAtt DeleteSsmDocumentLambdaExecutionRole.Arn
Timeout: 300
Handler: index.lambda_handler
Runtime: python3.8
MemorySize: 128
Layers:
- !Ref PythonLambdaLayer
Environment:
Variables:
ssmdocument: SSM-SessionManagerRunShell
ExecuteDeleteSsmDocumentLambda:
Type: Custom::DeleteSsmDocumentLambda
DependsOn:
- SessionManagerConfigurationSsmDocumentLambdaFunctionLogGroup
- SessionManagerLogGroup
- EncryptCloudwatchLogGroupLambdaFunctionLogGroup
Properties:
ServiceToken:
!GetAtt DeleteSsmDocumentLambda.Arn
SessionManagerConfigurationSsmDocument:
DependsOn:
- ExecuteDeleteSsmDocumentLambda
Type: AWS::SSM::Document
Metadata:
cfn-lint:
config:
ignore_checks:
- E3002
Properties:
Name: 'SSM-SessionManagerRunShell'
Content:
schemaVersion: "1.0"
description: "Document to hold Regional settings for Session Manager"
sessionType: "Standard_Stream"
inputs:
cloudWatchLogGroupName: !Ref SessionManagerLogGroup
cloudWatchEncryptionEnabled: true
kmsKeyId: !Ref SsmKey
DocumentType: Session
EncryptCloudwatchLogGroupLambda:
Type: AWS::Lambda::Function
DependsOn:
- SessionManagerConfigurationSsmDocumentLambdaFunctionLogGroup
- EncryptCloudwatchLogGroupLambdaFunctionLogGroup
Properties:
FunctionName: !Sub 'EncCwLgLambda-${AWS::Region}'
Code:
ZipFile: |
#==================================================================================================
import boto3
import os
import cfnresponse
from botocore.vendored import requests
client = boto3.client('logs')
def encrypt_logs(loggroup,kmskey):
response = client.associate_kms_key(
logGroupName=loggroup,
kmsKeyId=kmskey
)
print("Encrypt logs: {}".format(loggroup))
def decrypt_logs(loggroup):
response = client.disassociate_kms_key(
logGroupName=loggroup
)
print("Decrypt logs: {}".format(loggroup))
# ------------------------------------------------------------------------------
# lambda_handler
# ------------------------------------------------------------------------------
def lambda_handler(event, context):
loggroup = os.environ['loggroup']
kmskey = os.environ['kmskey']
if event['RequestType'] == 'Create':
encrypt_logs(loggroup,kmskey)
cfnresponse.send(event, context, cfnresponse.SUCCESS,{}, event['LogicalResourceId'])
if event['RequestType'] == 'Delete':
decrypt_logs(loggroup)
cfnresponse.send(event, context, cfnresponse.SUCCESS,{}, event['LogicalResourceId'])
if event['RequestType'] == 'Update':
cfnresponse.send(event, context, cfnresponse.SUCCESS,{}, event['LogicalResourceId'])
Role:
!GetAtt EncryptCloudwatchLogGroupLambdaExecutionRole.Arn
Timeout: 300
Handler: index.lambda_handler
Runtime: python3.8
MemorySize: 128
Layers:
- !Ref PythonLambdaLayer
Environment:
Variables:
loggroup: !Ref SessionManagerLogGroup
kmskey: !Ref CloudWatchKey
EncryptCloudwatchLogGroupLambdaExecutionRole:
DependsOn:
- SessionManagerConfigurationSsmDocumentLambdaFunctionLogGroup
- SessionManagerLogGroup
- EncryptCloudwatchLogGroupLambdaFunctionLogGroup
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
Path: /
Policies:
- PolicyName:
Fn::Sub: ${AWS::StackName}-Encrypt-LogGroup
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
- logs:AssociateKmsKey
- logs:DisassociateKmsKey
Resource:
- !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:*'
ExecuteEncryptCloudwatchLogGroupLambda:
Type: Custom::ExecuteEncryptCloudwatchLogGroupLambda
Properties:
ServiceToken:
!GetAtt EncryptCloudwatchLogGroupLambda.Arn
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment