Skip to content

Instantly share code, notes, and snippets.

@abdennour
Last active October 9, 2021 02:58
Show Gist options
  • Save abdennour/a83352f7d016a2a800c1864720d83df5 to your computer and use it in GitHub Desktop.
Save abdennour/a83352f7d016a2a800c1864720d83df5 to your computer and use it in GitHub Desktop.
AWSTemplateFormatVersion: "2010-09-09"
Description: Pipeline env setup
Parameters:
OperatorEmail:
Description: "Email address to notify."
Type: String
Default: tsh-devops@xyz.com
ClusterSettingsArtifactFile:
Type: String
Default: cloudformation.zip
Description: Filename for cluster setting deployment
ClusterSettingsFileName:
Type: String
Default: cloudformation/cluster_settings.yaml
Description: Filename cluster setting deployment
StagingKubernetesSettingsFileName:
Type: String
Default: cloudformation/staging/kubernetes.json
Description: Filename k8s staging cluster setting deployment
TestStackName:
Type: String
Default: staging
Description: A name for the test cluster settings stack
ProdStackName:
Type: String
Default: prod
Description: A name for the prod cluster settings stack
ChangeSetName:
Default: update-prod
Description: A name for the production cluster settings stack change set
Type: String
Resources:
# # Block user without MFA
# BlockUserWithoutMFAEnabledPolicy:
# Type: "AWS::IAM::Policy"
# Properties:
# PolicyName: BlockUserWithoutMFAEnabledPolicy
# PolicyDocument:
# Version: '2012-10-17'
# Statement:
# - Sid: AllowAllUsersToListAccounts
# Effect: Allow
# Action:
# - iam:ListAccountAliases
# - iam:ListUsers
# - iam:GetAccountSummary
# Resource: "*"
# - Sid: AllowIndividualUserToSeeAndManageOnlyTheirOwnAccountInformation
# Effect: Allow
# Action:
# - iam:ChangePassword
# - iam:CreateAccessKey
# - iam:CreateLoginProfile
# - iam:DeleteAccessKey
# - iam:DeleteLoginProfile
# - iam:GetAccountPasswordPolicy
# - iam:GetLoginProfile
# - iam:ListAccessKeys
# - iam:UpdateAccessKey
# - iam:UpdateLoginProfile
# - iam:ListSigningCertificates
# - iam:DeleteSigningCertificate
# - iam:UpdateSigningCertificate
# - iam:UploadSigningCertificate
# - iam:ListSSHPublicKeys
# - iam:GetSSHPublicKey
# - iam:DeleteSSHPublicKey
# - iam:UpdateSSHPublicKey
# - iam:UploadSSHPublicKey
# Resource: arn:aws:iam::accountid:user/${aws:username}
# - Sid: AllowIndividualUserToListOnlyTheirOwnMFA
# Effect: Allow
# Action:
# - iam:ListVirtualMFADevices
# - iam:ListMFADevices
# Resource:
# - arn:aws:iam::accountid:mfa/*
# - arn:aws:iam::accountid:user/${aws:username}
# - Sid: AllowIndividualUserToManageTheirOwnMFA
# Effect: Allow
# Action:
# - iam:CreateVirtualMFADevice
# - iam:DeleteVirtualMFADevice
# - iam:RequestSmsMfaRegistration
# - iam:FinalizeSmsMfaRegistration
# - iam:EnableMFADevice
# - iam:ResyncMFADevice
# Resource:
# - !Join ["",["arn:aws:iam:::", !Ref "AWS::AccountId", "${aws:username}"]]arn:aws:iam::accountid:mfa/${aws:username}
# - arn:aws:iam::accountid:user/${aws:username}
# - Sid: AllowIndividualUserToDeactivateOnlyTheirOwnMFAOnlyWhenUsingMFA
# Effect: Allow
# Action:
# - iam:DeactivateMFADevice
# Resource:
# - arn:aws:iam::accountid:mfa/${aws:username}
# - arn:aws:iam::accountid:user/${aws:username}
# Condition:
# Bool:
# aws:MultiFactorAuthPresent: 'true'
# - Sid: BlockAnyAccessOtherThanAboveUnlessSignedInWithMFA
# Effect: Deny
# NotAction: iam:*
# Resource: "*"
# Condition:
# BoolIfExists:
# aws:MultiFactorAuthPresent: 'false'
# Bucket for store cloudtrail logs
CloudTrailS3Bucket:
DeletionPolicy: Retain
Type: "AWS::S3::Bucket"
Properties: {}
# Cloudtrail bucket policy
CloudTrailBucketPolicy:
Type: "AWS::S3::BucketPolicy"
Properties:
Bucket:
Ref: CloudTrailS3Bucket
PolicyDocument:
Version: "2012-10-17"
Statement:
-
Sid: "AWSCloudTrailAclCheck"
Effect: "Allow"
Principal:
Service: "cloudtrail.amazonaws.com"
Action: "s3:GetBucketAcl"
Resource:
!Sub |-
arn:aws:s3:::${CloudTrailS3Bucket}
-
Sid: "AWSCloudTrailWrite"
Effect: "Allow"
Principal:
Service: "cloudtrail.amazonaws.com"
Action: "s3:PutObject"
Resource:
!Sub |-
arn:aws:s3:::${CloudTrailS3Bucket}/AWSLogs/${AWS::AccountId}/*
Condition:
StringEquals:
s3:x-amz-acl: "bucket-owner-full-control"
# Cloudtrail
SystemLogsTrail:
DependsOn:
- CloudTrailBucketPolicy
Type: "AWS::CloudTrail::Trail"
Properties:
S3BucketName:
Ref: CloudTrailS3Bucket
IsLogging: true
# Sns topic for Info notifications
DevopsInfoSnsTopic:
Type: "AWS::SNS::Topic"
#devops subscriptions
DevopsInfoSnsTopicSubscription:
DependsOn:
- DevopsInfoSnsTopic
Type: AWS::SNS::Subscription
Properties:
Endpoint: !Ref 'OperatorEmail'
Protocol: email
TopicArn: !Ref 'DevopsInfoSnsTopic'
# Cloudtrail sns topic policy
CloudTrailTopicPolicy:
Type: "AWS::SNS::TopicPolicy"
Properties:
Topics:
- Ref: "DevopsInfoSnsTopic"
PolicyDocument:
Version: "2008-10-17"
Statement:
-
Sid: "AWSCloudTrailSNSPolicy"
Effect: "Allow"
Principal:
Service: "cloudtrail.amazonaws.com"
Resource: "*"
Action: "SNS:Publish"
# Role for TSH devops guys with administrator access
TshDevOpsRole:
DependsOn:
- SystemLogsTrail
Type: "AWS::IAM::Role"
Properties:
RoleName: "TSHTrustedAdminAccounts"
AssumeRolePolicyDocument:
Statement:
- Effect: "Allow"
Principal:
AWS:
- "arn:aws:iam::040229452718:root"
- "arn:aws:iam::415139713725:root"
Action:
- "sts:AssumeRole"
Condition:
Bool:
"aws:MultiFactorAuthPresent": "true"
Path: "/"
ManagedPolicyArns:
- "arn:aws:iam::aws:policy/AdministratorAccess"
#Devops users group
DevopsGroup:
Type: "AWS::IAM::Group"
Properties:
Path: /
# Role for CodeFormation Deployment
CFNRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: ['sts:AssumeRole']
Effect: Allow
Principal:
Service: [cloudformation.amazonaws.com]
Version: '2012-10-17'
Path: /
Policies:
- PolicyName: CloudFormationRole
PolicyDocument:
Version: '2012-10-17'
Statement:
- Action:
- 'ec2:*'
- 's3:*'
- 'elasticfilesystem:*'
- 'rds:*'
- 'route53:*'
- 'ecr:*'
- 'iam:*'
- 'cloudformation:*'
- 'elasticloadbalancing:*'
- 'autoscaling:*'
Effect: Allow
Resource: '*'
#Code Pipeline access role
PipelineRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: ['sts:AssumeRole']
Effect: Allow
Principal:
Service: [codepipeline.amazonaws.com]
Version: '2012-10-17'
Path: /
ManagedPolicyArns:
- "arn:aws:iam::aws:policy/AdministratorAccess"
# Policies:
# - PolicyName: CodePipelineAccess
# PolicyDocument:
# Version: '2012-10-17'
# Statement:
# - Action:
# - 's3:*'
# - "codecommit:*"
# - 'cloudformation:CreateStack'
# - 'cloudformation:DescribeStacks'
# - 'cloudformation:DeleteStack'
# - 'cloudformation:UpdateStack'
# - 'cloudformation:CreateChangeSet'
# - 'cloudformation:ExecuteChangeSet'
# - 'cloudformation:DeleteChangeSet'
# - 'cloudformation:DescribeChangeSet'
# - 'cloudformation:SetStackPolicy'
# - 'iam:PassRole'
# - 'sns:Publish'
# Effect: Allow
# Resource: '*'
# Deployment User
DeploymentUser:
Type: "AWS::IAM::User"
DeploymentUserAccessKey:
Type: AWS::IAM::AccessKey
DependsOn:
- DeploymentUser
Properties:
UserName:
!Ref DeploymentUser
# Bucket for store kubernetes cluster configuration
ClusterSettingsS3Bucket:
Type: "AWS::S3::Bucket"
Properties:
VersioningConfiguration:
Status: Enabled
# deployment bucket policy
ClusterSettingsS3BucketPolicy:
Type: "AWS::S3::BucketPolicy"
DependsOn:
- DeploymentUser
- ClusterSettingsS3Bucket
Properties:
Bucket: !Ref 'ClusterSettingsS3Bucket'
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: "Allow"
Action:
- s3:ListBucket
- s3:GetBucketLocation
Resource: !Join ["",["arn:aws:s3:::", !Ref "ClusterSettingsS3Bucket"]]
Principal:
AWS: !GetAtt [DeploymentUser, Arn]
- Effect: "Allow"
Action:
- s3:PutObject
- s3:ListMultipartUploadParts
- s3:GetObject
- s3:DeleteObject
- s3:PutObjectAcl
Resource: !Join ["",["arn:aws:s3:::", !Ref "ClusterSettingsS3Bucket", "/*"]]
Principal:
AWS: !GetAtt [DeploymentUser, Arn]
# Cluster Setting Delivery Pipeline
ClusterSettingsDeliveryPipeline:
Type: AWS::CodePipeline::Pipeline
Properties:
ArtifactStore:
Location: !Ref 'ClusterSettingsS3Bucket'
Type: S3
Name: "ClusterSettingsDelivery"
RoleArn: !GetAtt [PipelineRole, Arn]
Stages:
- Name: CodeSource
Actions:
- Name: Source
ActionTypeId:
Category: Source
Owner: AWS
Provider: S3
Version: '1'
Configuration:
S3Bucket: !Ref 'ClusterSettingsS3Bucket'
S3ObjectKey: !Ref 'ClusterSettingsArtifactFile'
OutputArtifacts:
- Name: TemplateSource
RunOrder: '1'
- Name: TestStage
Actions:
- Name: CreateStack
ActionTypeId:
Category: Deploy
Owner: AWS
Provider: CloudFormation
Version: '1'
InputArtifacts:
- Name: TemplateSource
Configuration:
Capabilities: CAPABILITY_NAMED_IAM
ActionMode: REPLACE_ON_FAILURE
RoleArn: !GetAtt [CFNRole, Arn]
StackName: !Ref TestStackName
TemplatePath: !Sub "TemplateSource::${ClusterSettingsFileName}"
TemplateConfiguration: "TemplateSource::cloudformation/cluster_settings_configuration.json"
ParameterOverrides: !Sub |
{
"KubernetesStagingClusterBucketUrl": "${ClusterSettingsS3Bucket}"
}
RunOrder: '1'
- Name: ApproveTestStack
ActionTypeId:
Category: Approval
Owner: AWS
Provider: Manual
Version: '1'
Configuration:
NotificationArn: !Ref DevopsInfoSnsTopic
CustomData: !Sub 'Do you want to create a change set against the production stack and delete the TSH ${TestStackName} stack?'
RunOrder: '2'
- Name: DeleteTestStack
ActionTypeId:
Category: Deploy
Owner: AWS
Provider: CloudFormation
Version: '1'
Configuration:
Capabilities: CAPABILITY_NAMED_IAM
ActionMode: DELETE_ONLY
RoleArn: !GetAtt [CFNRole, Arn]
StackName: !Ref TestStackName
RunOrder: '3'
- Name: ProdStage
Actions:
- Name: CreateChangeSet
ActionTypeId:
Category: Deploy
Owner: AWS
Provider: CloudFormation
Version: '1'
InputArtifacts:
- Name: TemplateSource
Configuration:
Capabilities: CAPABILITY_NAMED_IAM
ActionMode: CHANGE_SET_REPLACE
RoleArn: !GetAtt [CFNRole, Arn]
StackName: !Ref ProdStackName
ChangeSetName: !Ref ChangeSetName
TemplatePath: !Sub "TemplateSource::${ClusterSettingsFileName}"
TemplateConfiguration: "TemplateSource::cloudformation/cluster_settings_configuration.json"
ParameterOverrides: !Sub |
{
"KubernetesStagingClusterBucketUrl": "${ClusterSettingsS3Bucket}"
}
RunOrder: '1'
- Name: ApproveChangeSet
ActionTypeId:
Category: Approval
Owner: AWS
Provider: Manual
Version: '1'
Configuration:
NotificationArn: !Ref DevopsInfoSnsTopic
CustomData: !Sub 'A new change set was created for the TSH ${ProdStackName} stack. Do you want to implement the changes?'
RunOrder: '2'
- Name: ExecuteChangeSet
ActionTypeId:
Category: Deploy
Owner: AWS
Provider: CloudFormation
Version: '1'
Configuration:
Capabilities: CAPABILITY_NAMED_IAM
ActionMode: CHANGE_SET_EXECUTE
ChangeSetName: !Ref ChangeSetName
RoleArn: !GetAtt [CFNRole, Arn]
StackName: !Ref ProdStackName
RunOrder: '3'
Outputs:
TshDevopsRoleArn:
Description: Tsh Devops assume role arn
Value: !GetAtt [TshDevOpsRole, Arn]
ClusterSettingsDeliveryPipelineUrl:
Value: !Sub https://console.aws.amazon.com/codepipeline/home?region=${AWS::Region}#/view/${ClusterSettingsDeliveryPipeline}
ClusterSettingsBucket:
Value: !Ref 'ClusterSettingsS3Bucket'
ClusterSettingsBucketUrl:
Value: !GetAtt [ClusterSettingsS3Bucket, WebsiteURL]
DeploymentUserAccessKeyOutput:
Value: !Ref 'DeploymentUserAccessKey'
DeploymentUserSecretKeyOutput:
Value: !GetAtt [DeploymentUserAccessKey, SecretAccessKey]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment