Connector Deployment Cloudformation
Author:
Fluent Commerce
Changed on:
23 Oct 2023
Key Points
- Prerequisites
- Manual Deployments
- Stack Provisioned
Steps
Download the Connector YAML "connectors.yaml"
1AWSTemplateFormatVersion: "2010-09-09"
2Description: "Fluent Account Connectors deployment"
3
4Parameters:
5 Connector:
6 Description: "Connector name"
7 Type: String
8
9 Environment:
10 Description: "Environment name"
11 Type: String
12 Default: test
13
14 FluentAccount:
15 Description: "Fluent Account"
16 Type: String
17 Default: CNCTSSO
18
19 ImageURI:
20 Description: "Fully qualified docker image URI to run"
21 Type: String
22
23 CPU:
24 Description: Number of CPUs to assign to the task
25 Type: Number
26 Default: 512
27 AllowedValues:
28 - 256
29 - 512
30 - 1024
31
32 Memory:
33 Description: Amount of memory to assign to the task in GB
34 Type: Number
35 Default: 1024
36 AllowedValues:
37 - 512
38 - 1024
39 - 2048
40 - 3072
41
42 ContainerPort:
43 Description: Container port to expose to load balancer
44 Type: Number
45 Default: 8080
46
47 MinCapacity:
48 Type: Number
49 Default: 1
50
51 MaxCapacity:
52 Type: Number
53 Default: 6
54
55 VpcId:
56 Description: VPC Id
57 Type: AWS::SSM::Parameter::Value<String>
58
59 VpcCidr:
60 Description: VPC CIDR Block
61 Type: AWS::SSM::Parameter::Value<String>
62
63 PublicHostedZoneName:
64 Description: Public hosted zone (domain name)
65 Type: AWS::SSM::Parameter::Value<String>
66
67 PublicHostedZoneId:
68 Description: Public hosted zone id
69 Type: AWS::SSM::Parameter::Value<String>
70
71 PublicSubnets:
72 Description: Public Subnet IDs
73 Type: AWS::SSM::Parameter::Value<List<String>>
74
75 PrivateSubnets:
76 Description: Private Subnet IDs
77 Type: AWS::SSM::Parameter::Value<List<String>>
78
79Mappings:
80 RegionMap:
81 us-east-1:
82 RegionCode: use1
83 us-east-2:
84 RegionCode: use2
85 us-west-1:
86 RegionCode: usw1
87 us-west-2:
88 RegionCode: usw2
89 af-south-1:
90 RegionCode: afs1
91 ap-east-1:
92 RegionCode: ape1
93 ap-south-1:
94 RegionCode: aps1
95 ap-northeast-1:
96 RegionCode: apne1
97 ap-northeast-2:
98 RegionCode: apne2
99 ap-northeast-3:
100 RegionCode: apne3
101 ap-southeast-1:
102 RegionCode: apse1
103 ap-southeast-2:
104 RegionCode: apse2
105 ap-southeast-3:
106 RegionCode: apse3
107 ca-central-1:
108 RegionCode: cac1
109 eu-central-1:
110 RegionCode: euc1
111 eu-west-1:
112 RegionCode: euw1
113 eu-west-2:
114 RegionCode: euw2
115 eu-west-3:
116 RegionCode: euw3
117 eu-south-1:
118 RegionCode: eus1
119 eu-north-1:
120 RegionCode: eun1
121 me-south-1:
122 RegionCode: mes1
123 me-central-1:
124 RegionCode: mec1
125 sa-east-1:
126 RegionCode: sae1
127
128Resources:
129 ALBSecurityGroup:
130 Type: AWS::EC2::SecurityGroup
131 Properties:
132 GroupName: !Sub "${Connector}-${Environment}-connectors-alb-sg"
133 GroupDescription: !Sub "${Environment} ${AWS::Region} ${Connector} connector load balancer Security Group"
134 VpcId: !Ref VpcId
135 SecurityGroupIngress:
136 - IpProtocol: tcp
137 FromPort: 443
138 ToPort: 443
139 CidrIp: 0.0.0.0/0
140 Tags:
141 - Key: Name
142 Value: !Sub "${Connector}-${Environment}-connectors-alb-sg"
143 - Key: Region
144 Value: !Ref AWS::Region
145
146 ConnectorSecurityGroup:
147 Type: AWS::EC2::SecurityGroup
148 Properties:
149 GroupName: !Sub ${Environment}-${Connector}-connectors-sg
150 GroupDescription: !Sub "${Environment} ${AWS::Region} ${Connector} connector Security Group"
151 VpcId: !Ref VpcId
152 SecurityGroupIngress:
153 - CidrIp: !Ref VpcCidr
154 Description: "oms connectors access"
155 FromPort: 443
156 ToPort: 443
157 IpProtocol: -1
158 Tags:
159 - Key: Name
160 Value: !Sub "${Connector}-${Environment}-connectors-sg"
161 - Key: Region
162 Value: !Ref AWS::Region
163
164 LogGroup:
165 Type: AWS::Logs::LogGroup
166 Properties:
167 RetentionInDays: 7
168 LogGroupName: !Sub "/${Connector}/${Environment}/connectors"
169
170 LoadBalancer:
171 Type: AWS::ElasticLoadBalancingV2::LoadBalancer
172 Properties:
173 Name: !Sub "${Connector}-${Environment}-connect-alb"
174 Scheme: internet-facing
175 SecurityGroups:
176 - !Ref ALBSecurityGroup
177 Subnets: !Ref PublicSubnets
178
179 Certificate:
180 Type: "AWS::CertificateManager::Certificate"
181 Properties:
182 DomainName:
183 Fn::Sub:
184 - "${Connector}.${RegionCode}.${Environment}.${PublicHostedZoneName}"
185 - RegionCode: !FindInMap [RegionMap, !Ref AWS::Region, RegionCode]
186 ValidationMethod: DNS
187 DomainValidationOptions:
188 - DomainName:
189 Fn::Sub:
190 - "${Connector}.${RegionCode}.${Environment}.${PublicHostedZoneName}"
191 - RegionCode: !FindInMap [RegionMap, !Ref AWS::Region, RegionCode]
192 HostedZoneId: !Ref PublicHostedZoneId
193
194 RecordSet:
195 Type: AWS::Route53::RecordSet
196 Properties:
197 Name:
198 Fn::Sub:
199 - "${Connector}.${RegionCode}.${Environment}.${PublicHostedZoneName}"
200 - RegionCode: !FindInMap [RegionMap, !Ref AWS::Region, RegionCode]
201 Comment: !Sub "Alias for connectors endpoint of ${Connector} in ${AWS::Region}"
202 Type: CNAME
203 HostedZoneId: !Ref PublicHostedZoneId
204 TTL: 60
205 ResourceRecords:
206 - !GetAtt LoadBalancer.DNSName
207
208 HttpsTargetGroup:
209 Type: AWS::ElasticLoadBalancingV2::TargetGroup
210 Properties:
211 Name: !Sub ${Connector}-${Environment}-https-tg
212 HealthCheckPath: /actuator/health
213 HealthCheckPort: !Ref ContainerPort
214 HealthCheckIntervalSeconds: 60
215 HealthCheckTimeoutSeconds: 2
216 HealthyThresholdCount: 2
217 UnhealthyThresholdCount: 5
218 Port: 443
219 Protocol: HTTP
220 TargetType: ip
221 TargetGroupAttributes:
222 - Key: deregistration_delay.timeout_seconds
223 Value: "60"
224 VpcId: !Ref VpcId
225
226 HttpsListener:
227 Type: "AWS::ElasticLoadBalancingV2::Listener"
228 Properties:
229 LoadBalancerArn: !Ref LoadBalancer
230 Protocol: HTTPS
231 SslPolicy: ELBSecurityPolicy-TLS-1-2-2017-01
232 Port: 443
233 Certificates:
234 - CertificateArn: !Ref Certificate
235 DefaultActions:
236 - Type: "forward"
237 TargetGroupArn: !Ref HttpsTargetGroup
238
239 ECSCluster:
240 Type: AWS::ECS::Cluster
241 Properties:
242 ClusterName: !Sub "${Connector}-${Environment}-connectors-cluster"
243
244 TaskExecutionRole:
245 Type: AWS::IAM::Role
246 Properties:
247 RoleName: !Sub "${Connector}-${Environment}-connectors-task-execution-role"
248 AssumeRolePolicyDocument:
249 Version: 2012-10-17
250 Statement:
251 - Effect: Allow
252 Principal:
253 Service:
254 - ecs-tasks.amazonaws.com
255 Action:
256 - "sts:AssumeRole"
257 ManagedPolicyArns:
258 - arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
259
260 TaskRole:
261 Type: AWS::IAM::Role
262 Properties:
263 RoleName: !Sub "${Connector}-${Environment}-connectors-task-role"
264 AssumeRolePolicyDocument:
265 Version: 2012-10-17
266 Statement:
267 - Effect: Allow
268 Principal:
269 Service:
270 - ecs-tasks.amazonaws.com
271 Action:
272 - "sts:AssumeRole"
273 Policies:
274 - PolicyName: !Sub "${Connector}-${Environment}-connector-logs"
275 PolicyDocument:
276 Version: 2012-10-17
277 Statement:
278 - Effect: Allow
279 Action:
280 - "logs:CreateLogGroup"
281 - "logs:CreateLogStream"
282 - "logs:PutLogEvents"
283 - "cloudwatch:PutMetricData"
284 Resource:
285 - "*"
286 - PolicyName: !Sub "${Connector}-${Environment}-connector-cfn"
287 PolicyDocument:
288 Version: 2012-10-17
289 Statement:
290 - Effect: Allow
291 Action:
292 - "cloudformation:DescribeStacks"
293 Resource:
294 - "*"
295 - PolicyName: !Sub "${Connector}-${Environment}-connector-secrets"
296 PolicyDocument:
297 Version: 2012-10-17
298 Statement:
299 - Effect: Allow
300 Action:
301 - "secretsmanager:GetResourcePolicy"
302 - "secretsmanager:GetSecretValue"
303 - "secretsmanager:DescribeSecret"
304 - "secretsmanager:ListSecretVersionIds"
305 - "secretsmanager:CreateSecret"
306 - "secretsmanager:DeleteSecret"
307 Resource:
308 - !Sub "arn:aws:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:*"
309
310 - PolicyName: !Sub "${Connector}-${Environment}-connector-sqs"
311 PolicyDocument:
312 Version: 2012-10-17
313 Statement:
314 - Effect: Allow
315 Action:
316 - "sqs:*"
317 Resource:
318 - !Sub "arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:*"
319 - PolicyName: !Sub "${Connector}-${Environment}-container-access"
320 PolicyDocument:
321 Version: 2012-10-17
322 Statement:
323 - Effect: "Allow"
324 Action:
325 - "ssmmessages:CreateControlChannel"
326 - "ssmmessages:CreateDataChannel"
327 - "ssmmessages:OpenControlChannel"
328 - "ssmmessages:OpenDataChannel"
329 Resource: "*"
330
331 TaskDefinition:
332 Type: AWS::ECS::TaskDefinition
333 Properties:
334 Family: !Sub "${Connector}-${Environment}-connector"
335 Cpu: !Ref CPU
336 Memory: !Ref Memory
337 NetworkMode: awsvpc
338 ExecutionRoleArn: !GetAtt TaskExecutionRole.Arn
339 TaskRoleArn: !GetAtt TaskRole.Arn
340 RequiresCompatibilities:
341 - FARGATE
342 ContainerDefinitions:
343 - Name: connector
344 Image: !Ref ImageURI
345 Essential: true
346 PortMappings:
347 - ContainerPort: !Ref ContainerPort
348 Environment:
349 - Name: FLUENT_CONNECT_MOCK_ACCOUNTID
350 Value: !Ref FluentAccount
351 - Name: CONNECTOR_NAME
352 Value: !Ref Connector
353 - Name: SPRING_PROFILES_ACTIVE
354 Value: !Ref Environment
355 - Name: REGION
356 Value: !Ref AWS::Region
357 - Name: AWS_SECRETSMANAGER_DEFAULT_CONTEXT
358 Value: application
359 - Name: AWS_SECRETSMANAGER_FAIL_FAST
360 Value: false
361 - Name: AWS_SECRETSMANAGER_PREFIX
362 Value: /fc
363 - Name: AWS_SECRETSMANAGER_ENABLED
364 Value: true
365 - Name: MANAGEMENT_METRICS_EXPORT_CLOUDWATCH_ENABLED
366 Value: true
367 - Name: MANAGEMENT_METRICS_EXPORT_CLOUDWATCH_NAMESPACE
368 Value: !Sub "fc-scim-${Environment}"
369 LogConfiguration:
370 LogDriver: awslogs
371 Options:
372 awslogs-group: !Ref LogGroup
373 awslogs-region: !Ref AWS::Region
374 awslogs-stream-prefix: connectors
375
376 ECSService:
377 DependsOn:
378 - HttpsListener
379 Type: AWS::ECS::Service
380 Properties:
381 ServiceName: !Sub "${Connector}-${Environment}-connectors"
382 Cluster: !Ref ECSCluster
383 TaskDefinition: !Ref TaskDefinition
384 EnableExecuteCommand: true
385 DesiredCount: 1
386 DeploymentConfiguration:
387 MinimumHealthyPercent: 100
388 MaximumPercent: 200
389 EnableECSManagedTags: true
390 LaunchType: FARGATE
391 HealthCheckGracePeriodSeconds: 120
392 LoadBalancers:
393 - TargetGroupArn: !Ref HttpsTargetGroup
394 ContainerPort: !Ref ContainerPort
395 ContainerName: connector
396 NetworkConfiguration:
397 AwsvpcConfiguration:
398 AssignPublicIp: DISABLED
399 SecurityGroups:
400 - !Ref ConnectorSecurityGroup
401 Subnets: !Ref PrivateSubnets
402 PropagateTags: SERVICE
403
404 ScalingPolicy:
405 Type: AWS::ApplicationAutoScaling::ScalingPolicy
406 Properties:
407 PolicyName: "connectors autoscaling policy"
408 PolicyType: TargetTrackingScaling
409 ScalingTargetId: !Ref AutoScalingTarget
410 TargetTrackingScalingPolicyConfiguration:
411 DisableScaleIn: False
412 PredefinedMetricSpecification:
413 PredefinedMetricType: ECSServiceAverageMemoryUtilization
414 ScaleInCooldown: 300
415 ScaleOutCooldown: 120
416 TargetValue: 60.0
417
418 AutoScalingTarget:
419 Type: AWS::ApplicationAutoScaling::ScalableTarget
420 Properties:
421 MinCapacity: !Ref MinCapacity
422 MaxCapacity: !Ref MaxCapacity
423 ResourceId: !Sub
424 - service/${ClusterName}/${ServiceName}
425 - ServiceName: !GetAtt ECSService.Name
426 ClusterName: !Ref ECSCluster
427 ScalableDimension: ecs:service:DesiredCount
428 ServiceNamespace: ecs
429 RoleARN: !Sub "arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService"
430
431 ApiConnection:
432 Type: AWS::Events::Connection
433 Properties:
434 AuthorizationType: BASIC
435 Description: !Sub "Connection to ${Connector} ${Environment} connector endpoint"
436 AuthParameters:
437 BasicAuthParameters:
438 Username: admin
439 Password: "pass"
440 InvocationHttpParameters: {}
441
442 RuleTargetRole:
443 Type: AWS::IAM::Role
444 Properties:
445 RoleName: !Sub "${Connector}-${Environment}-invoke-api-destination"
446 AssumeRolePolicyDocument:
447 Version: 2012-10-17
448 Statement:
449 - Effect: Allow
450 Principal:
451 Service:
452 - events.amazonaws.com
453 Action:
454 - "sts:AssumeRole"
455 Policies:
456 - PolicyName: !Sub "${Connector}-${Environment}-invoke-api-destination"
457 PolicyDocument:
458 Version: 2012-10-17
459 Statement:
460 - Effect: Allow
461 Action:
462 - events:InvokeApiDestination
463 Resource:
464 - !Sub "arn:aws:events:${AWS::Region}:${AWS::AccountId}:api-destination/*"
465
466
467
468
469Outputs:
470 ConnectorsPublicURL:
471 Description: "The public URL of the connectors endpoint"
472 Value:
473 Fn::Sub:
474 - "https://${Connector}.${RegionCode}.${Environment}.${PublicHostedZoneName}"
475 - RegionCode: !FindInMap [RegionMap, !Ref AWS::Region, RegionCode]
Language: plain_text
Name: SCIM Connector CloudFormation Template
Description:
[Warning: empty required content area]Manual Deployments
When manually deploying the template through the Cloudformation console, you need to provide several Parameters applicable to your environment.
Note: There will be a few Parameters with default values. The ones that are environment-specific have been enclosed in angle brackets. You can replace these with values specific to your environment.
After successfully deploying the stack, you can get the public endpoint by going to the “Outputs” tab on the stack. It will be listed next to “ConnectorsPublicURL” logical resource name.
Stack Provisioned
- Secrets Manager - Used for credential storage.
- CloudWatch - Steams container logs and collects metrics from the containers running.
- ECS - Runs the SCIM Connector containers.
- ELB / API endpoints - Exposes the Connector to the web, explained in more detail below.
There are 3 key endpoints provided as part of the SCIM Connector:
- Scim endpoint (/Users/**): This is required to be public and there can't be any form of security for it
- Spring Actuators (/actuator/): Provides health status for the container along with other useful information, and it is best to keep it private.**
As the connector has a web server running, endpoints are protected by
`connect-sdk-core-web-security`