-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathssm-session-mgr-privatelink-example.yaml
275 lines (260 loc) · 10.5 KB
/
ssm-session-mgr-privatelink-example.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
AWSTemplateFormatVersion: 2010-09-09
Description: >
In this template we are demonstrating an EC2 with SSM Session Manager enabled. This instance is in a
private subnet in a VPC with no gateways Internet Gateway, NAT Gateway, or virtual private gateway)
In this case we enable communication using Private Links which keeps all traffic on the Amazon Network.
see: https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-setting-up-vpc.html
Parameters:
LatestAmiId:
# Use public Systems Manager Parameter for AMI Image name
# https://aws.amazon.com/blogs/compute/query-for-the-latest-amazon-linux-ami-ids-using-aws-systems-manager-parameter-store/
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
Description: Select Amazon Linux(1) or 2
Default: /aws/service/ami-amazon-linux-latest/amzn-ami-hvm-x86_64-gp2
AllowedValues:
- /aws/service/ami-amazon-linux-latest/amzn-ami-hvm-x86_64-gp2 # Amazon Linux [1]
- /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 # Amazon Linux 2
InstanceType:
Type: String
Default: t2.nano
Description: Select an instance type
AllowedValues:
- t2.nano
- t2.micro
- t3.nano
- t3.micro
# Parameters for the 'harness' VPC to host this demo. All defaults are fine for our purposes.
VpcCidr:
Description: Please enter the IP range (CIDR notation) for this VPC
Type: String
Default: 10.192.0.0/16
PrivateSubnetWithoutNatCidr:
Description: Please enter the IP range (CIDR notation) for the private subnet in the second Availability Zone
Type: String
Default: 10.192.21.0/24
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: "EC2 Settings"
Parameters:
- LatestAmiId
- InstanceType
- Label:
default: "We create a boilerplate VPC to place the EC2 instance into"
Parameters:
- VpcCidr
- PrivateSubnetWithoutNatCidr
Resources:
Ec2InPrivateSubnetWithouttNatGtwy:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref LatestAmiId
InstanceType: !Ref InstanceType
# KeyName: NO SSH Key needed
IamInstanceProfile: !Ref Ec2InstanceProfile
NetworkInterfaces:
# The SSM Agent running on the EC2 instances must be able to connect to Session Manager's
# public endpoint. You can also set up a PrivateLink connection to allow instances running
# in private VPCs (without Internet access or a public IP address) to connect to Session Manager.
# Here the instance is in a private subnet with a default route to the NAT Gateway so we can use that to
# connect to the SSM's public endpoint
- AssociatePublicIpAddress: false
DeviceIndex: 0
GroupSet:
- !Ref Ec2InstanceSecurityGroup
SubnetId: !Ref PrivateSubnetWithoutNat
Tags:
- Key: Name
Value: Session Manager test Instnace in Private Subnet without NatGtwy
# By default, AWS Systems Manager doesn't have permission to perform actions on your instances.
# You must grant access by using an AWS Identity and Access Management (IAM) instance profile.
# https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-configuring-access-role.html
Ec2InstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Path: /
Roles: [ !Ref Ec2InstanceRole ]
Ec2InstanceRole:
Type: AWS::IAM::Role
Properties:
ManagedPolicyArns:
# ********** This is really the only adjustment we need to make to enable use of SSM Session Manager
# All the AWS::CloudFormation::Init and cloud init script work is setting up cloudwatch logs
# to give visibility to the SSM Agent actions.
- arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: [ ec2.amazonaws.com ]
Action:
- sts:AssumeRole
Path: /
# Attaching an SG with NO Ingress ports open
Ec2InstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: SG with no ingress ports open
VpcId: !Ref Vpc
# ********* Demonstrating SSM Session Manager can connect to Instance with NO Security Group ingress openings
# SecurityGroupIngress:
SecurityGroupEgress:
- IpProtocol: -1 # all
FromPort: -1 # all
ToPort: -1 # all
CidrIp: 0.0.0.0/0
#######################################################
# Everything below here is just a boilerplate VPC
# used to place the EC2 into a private subnet with no route
# to a NAT Gateway.
# We utilize a set of PrivateLinks to enable communication between
# SSM and the EC2 instance.
# We also enable private DNS on the VPC via:
# - EnableDnsSupport: true
# - EnableDnsHostnames: true
# Finally in this scenario we need to open ingress from
# port 443 on the PrivateLink Interfaces (see VpcEndpointSecurityGroup)
# \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/
#######################################################
Vpc:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VpcCidr
# as per docs, we need to enable both EnableDnsHostnames and EnableDnsSupport in this VPC so the SSM agent
# will be able to connect using the regular public DNS names for SSM
# https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-setting-up-vpc.html
EnableDnsSupport: true
EnableDnsHostnames: true
InternetGateway:
Type: AWS::EC2::InternetGateway
InternetGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
InternetGatewayId: !Ref InternetGateway
VpcId: !Ref Vpc
PrivateSubnetWithoutNat:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref Vpc
AvailabilityZone: !Select [ 1, !GetAZs '' ]
CidrBlock: !Ref PrivateSubnetWithoutNatCidr
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value: Private subnet without attachment to NatGtwy
PrivateSubnetWithoutNatRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref Vpc
Tags:
- Key: Name
Value: Private routes for subnet without NatGtwy
PrivateSubnetWithoutNatRouteTableAssoc:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PrivateSubnetWithoutNatRouteTable
SubnetId: !Ref PrivateSubnetWithoutNat
NoIngressSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: "no-ingress-sg"
GroupDescription: "Security group with no ingress rule"
VpcId: !Ref Vpc
# ****************************
# Here we build all the VPC endpoints needed in order for SSM Session Manager to be able to communicate with
# and EC2 instance in a private subnet (with not routes to the Internet)
# Open port 443 for SSM as per the docs
# Incoming connections: https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-setting-up-vpc.html
VpcEndpointSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Open 443 for SSM Session Manager for private subnets
VpcId: !Ref Vpc
# allow traffic on 443 from the private subnets
SecurityGroupIngress:
- IpProtocol: TCP
FromPort: 443
ToPort: 443
CidrIp: !Ref PrivateSubnetWithoutNatCidr
SecurityGroupEgress:
- IpProtocol: -1 # all
FromPort: -1 # all
ToPort: -1 # all
CidrIp: 0.0.0.0/0
VpcEndpointInterfaceSsm:
Type: AWS::EC2::VPCEndpoint
Properties:
VpcId: !Ref Vpc
ServiceName: !Sub com.amazonaws.${AWS::Region}.ssm
VpcEndpointType: Interface
PrivateDnsEnabled: true
SubnetIds:
- !Ref PrivateSubnetWithoutNat
SecurityGroupIds:
- !Ref VpcEndpointSecurityGroup
VpcEndpointInterfaceEc2messages:
Type: AWS::EC2::VPCEndpoint
Properties:
VpcId: !Ref Vpc
ServiceName: !Sub com.amazonaws.${AWS::Region}.ec2messages
VpcEndpointType: Interface
PrivateDnsEnabled: true
SubnetIds:
- !Ref PrivateSubnetWithoutNat
SecurityGroupIds:
- !Ref VpcEndpointSecurityGroup
VpcEndpointInterfaceEc2:
Type: AWS::EC2::VPCEndpoint
Properties:
VpcId: !Ref Vpc
ServiceName: !Sub com.amazonaws.${AWS::Region}.ec2
VpcEndpointType: Interface
PrivateDnsEnabled: true
SubnetIds:
- !Ref PrivateSubnetWithoutNat
SecurityGroupIds:
- !Ref VpcEndpointSecurityGroup
VpcEndpointInterfaceSsmmessages:
Type: AWS::EC2::VPCEndpoint
Properties:
VpcId: !Ref Vpc
ServiceName: !Sub com.amazonaws.${AWS::Region}.ssmmessages
VpcEndpointType: Interface
PrivateDnsEnabled: true
SubnetIds:
- !Ref PrivateSubnetWithoutNat
SecurityGroupIds:
- !Ref VpcEndpointSecurityGroup
VpcEndpointGatewayS3:
Type: AWS::EC2::VPCEndpoint
Properties:
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal: '*'
Action:
- '*'
Resource:
# In a real world scenario we would reduce the scope of this access to the 3 bucket paths in the
# comment below
- arn:aws:s3:::*
# See "Amazon S3 buckets" https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-setting-up-vpc.html
# - !Sub arn:aws:s3:::patch-baseline-snapshot-${AWS::Region}/*
# - !Sub arn:aws:s3:::aws-ssm-${AWS::Region}/*
# If sending Session Manager terminal data logs to an S3 bucket, add the ARN for that bucket here
# See: https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-logging-auditing.html
# - arn:aws:s3:::{{bucket for Session Activity}}
VpcId: !Ref Vpc
RouteTableIds:
- !Ref PrivateSubnetWithoutNatRouteTable
ServiceName: !Sub com.amazonaws.${AWS::Region}.s3
VpcEndpointType: Gateway
Outputs:
SessionManagementListUrl:
Description: The URL to the Session Management Console listing all instances it is aware of
Value: !Sub https://${AWS::Region}.console.aws.amazon.com/systems-manager/session-manager/start-session?region=${AWS::Region}
SessionManagementPrivateSubneWithoutNatInstanceUrl:
Description: The URL to the Session Management Console for this instance
Value: !Sub https://${AWS::Region}.console.aws.amazon.com/systems-manager/session-manager/${Ec2InPrivateSubnetWithouttNatGtwy}?region=${AWS::Region}