Skip to content

Commit cead7e5

Browse files
committed
Release vpc-template and copy-ami-lambda
1 parent 6f8e9e1 commit cead7e5

7 files changed

Lines changed: 690 additions & 8 deletions

File tree

aws/README.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
This repository contains AWS® CloudFormation templates used by multiple [MathWorks Reference Architectures](https://github.com/mathworks-ref-arch) for Amazon Web Services®.
44

5-
Each template configures a specific chunk of infrastructure. MathWorks® reference architectures use a selection of the available templates to create their overall infrastructure by using nested stacks. Learn more about using nested stacks in the [AWS documentation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-nested-stacks.html).
5+
Each template configures specific infrastructure. MathWorks® reference architectures use a selection of the available templates to create their overall infrastructure by using nested stacks. To learn more about using nested stacks, see [Nested Stacks (AWS)](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-nested-stacks.html).
66

77
## Available Templates
88

@@ -11,6 +11,7 @@ Each template configures a specific chunk of infrastructure. MathWorks® refe
1111
| [security-group](security-group) | Creates a security group to control the inbound and outbound traffic for the resources deployed in AWS. |
1212
| [log-location](log-location) | Creates a CloudWatch log group to store log events from AWS services. |
1313
| [storage-location](storage-location) | Creates an Amazon S3™ Bucket to store objects in AWS. |
14+
| [vpc-template](vpc-template) | Creates an Amazon Virtual Private Cloud (VPC) with four subnets evenly distributed across two availability zones, gateway endpoints for Amazon S3 and DynamoDB services, an optional NAT Gateway, and optional interface endpoints for various AWS services. For details, see [Amazon Virtual Private Cloud CloudFormation Template for MATLAB Reference Architectures](vpc-template/v1/README.md). |
1415

1516
## Usage
1617

@@ -19,15 +20,15 @@ The CloudFormation templates in this repository are automatically published to t
1920
s3://mathworks-reference-architectures-templates/
2021
```
2122

22-
Templates in this bucket are publicly accessible. The MathWorks reference architectures directly reference these templates in `AWS::CloudFormation::Stack` resources. For more information about this type of resource, refer to the [AWS documentation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-stack.html).
23+
Templates in this bucket are publicly accessible. The MathWorks reference architectures directly reference these templates in `AWS::CloudFormation::Stack` resources. For details, see [AWS Cloud Formation Stack Resources (AWS)](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-stack.html).
2324

2425
### Example
2526

2627
The following code shows you how to create a nested stack based on the security group template.
2728

2829
The `AWS::CloudFormation::Stack` resource declares the nested stack.
2930
- The `TemplateURL` property defines the template to use. Set it to the Amazon S3 bucket URL of the security group template version `v1.0.0`.
30-
- The `Parameters` property defines the inputs to the nested stack. Set the parameters `VpcId` and `CidrIp` to the values of the root stack. Add subsequent parameters to explicitly allow SSH, NICE DCV, and MATLAB Job Scheduler access but deny RDP access. Leave other parameters at their default values.
31+
- The `Parameters` property defines the inputs to the nested stack. Set the parameters `VpcId` and `CidrIp` to the values of the root stack. Add subsequent parameters to explicitly allow SSH, NICE DCV, and MATLAB Job Scheduler access but deny RDP access. Leave other parameters to their default values.
3132

3233
The [GetAtt](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getatt.html) function retrieves an output value from the nested stack to the root stack.
3334
```json
@@ -67,13 +68,13 @@ The [GetAtt](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intr
6768
}
6869
```
6970

70-
## Related repositories
71-
- [matlab-on-aws](https://github.com/mathworks-ref-arch/matlab-on-aws)
72-
- [matlab-parallel-server-on-aws](https://github.com/mathworks-ref-arch/matlab-parallel-server-on-aws)
73-
- [license-manager-for-matlab-on-aws](https://github.com/mathworks-ref-arch/license-manager-for-matlab-on-aws)
71+
## Related Reference Architectures
72+
- [MATLAB on AWS](https://github.com/mathworks-ref-arch/matlab-on-aws)
73+
- [MATLAB Parallel Server on AWS](https://github.com/mathworks-ref-arch/matlab-parallel-server-on-aws)
74+
- [License Manager for MATLAB on AWS](https://github.com/mathworks-ref-arch/license-manager-for-matlab-on-aws)
7475

7576
## Technical Support
7677
For support, visit [MathWorks Technical Support](https://www.mathworks.com/support/contact_us.html).
7778

7879
---
79-
Copyright 2024 The MathWorks, Inc.
80+
Copyright 2024-2025 The MathWorks, Inc.

aws/copy-ami-lambda/v1/.version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
v1.0.0
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
# Copyright 2025 The MathWorks, Inc.
2+
AWSTemplateFormatVersion: '2010-09-09'
3+
4+
Transform: AWS::LanguageExtensions
5+
6+
Description: 'MathWorks Reference Architectures: AMI Copy Template - Copies a specified AMI from a source region into the current region.'
7+
8+
Metadata:
9+
AWS::CloudFormation::Interface:
10+
ParameterGroups:
11+
- Label:
12+
default: "AMI Copy Configuration"
13+
Parameters:
14+
- SourceAmiId
15+
- SourceRegion
16+
- AmiName
17+
- ReferenceTag
18+
- MWTemplateUrl
19+
ParameterLabels:
20+
SourceAmiId:
21+
default: "Source AMI ID"
22+
SourceRegion:
23+
default: "Source Region"
24+
AmiName:
25+
default: "AMI Name"
26+
ReferenceTag:
27+
default: "Link to reference documentation for the copied AMI"
28+
MWTemplateUrl:
29+
default: "MathWorks Reference Architecture Template URL."
30+
31+
Parameters:
32+
SourceAmiId:
33+
Type: String
34+
Description: The ID of the AMI to copy from the source region.
35+
AllowedPattern: ^ami-[a-f0-9]{8,17}$
36+
ConstraintDescription: Must be a valid AMI ID (e.g., ami-xxxxxxxxxxxxxxxxx).
37+
38+
SourceRegion:
39+
Type: String
40+
Description: The AWS region where the source AMI resides.
41+
AllowedPattern: ^[a-z-]+-\d{1}$
42+
43+
AmiName:
44+
Type: String
45+
Description: Name for the copied AMI.
46+
Default: ''
47+
ReferenceTag:
48+
Type: String
49+
Description: Optional reference link saved as tag on the copied AMI.
50+
Default: ''
51+
MWTemplateUrl:
52+
Type: String
53+
Description: >-
54+
(Optional) S3 URL of MathWorks Reference Architecture CFT that the copied AMI will be used with.
55+
Default: ''
56+
57+
Resources:
58+
AmiCopyLambda:
59+
Type: AWS::Lambda::Function
60+
Properties:
61+
Code:
62+
ZipFile: |
63+
import boto3
64+
import cfnresponse
65+
66+
def lambda_handler(event, context):
67+
response_data = {}
68+
try:
69+
if event['RequestType'] == 'Create':
70+
props = event['ResourceProperties']
71+
source_ami = props['SourceAmiId']
72+
source_region = props['SourceRegion']
73+
target_name = props.get('AmiName', '')
74+
reference = props['ReferenceTag']
75+
76+
ec2_source = boto3.client('ec2', region_name=source_region)
77+
ec2_dest = boto3.client('ec2')
78+
79+
images = ec2_source.describe_images(ImageIds=[source_ami])['Images']
80+
if not images:
81+
raise Exception(f"Source AMI {source_ami} not found in region {source_region}")
82+
source_name = images[0].get('Name', f"Copied-{source_ami}")
83+
description = f"Copied from {source_ami} {source_name} in {source_region}"
84+
85+
if not target_name:
86+
target_name = f"Copied from {source_name}"
87+
if not reference:
88+
reference = "https://github.com/mathworks-ref-arch/iac-building-blocks/tree/main/aws/ami-copy-lambda"
89+
90+
response = ec2_dest.copy_image(
91+
Name=target_name,
92+
SourceImageId=source_ami,
93+
SourceRegion=source_region,
94+
Description=description
95+
)
96+
97+
copied_ami_id = response['ImageId']
98+
response_data['CopiedAmiId'] = copied_ami_id
99+
100+
ec2_dest.create_tags(
101+
Resources=[copied_ami_id],
102+
Tags=[
103+
{'Key': 'SourceAmiId', 'Value': source_ami},
104+
{'Key': 'Reference', 'Value': reference}
105+
]
106+
)
107+
cfnresponse.send(event, context, cfnresponse.SUCCESS, response_data)
108+
else:
109+
print(f"No action for event type: {event['RequestType']}")
110+
cfnresponse.send(event, context, cfnresponse.SUCCESS, response_data)
111+
except Exception as e:
112+
response_data['Error'] = str(e)
113+
cfnresponse.send(event, context, cfnresponse.FAILED, response_data)
114+
115+
Handler: index.lambda_handler
116+
Runtime: python3.13
117+
Timeout: 300
118+
Role: !GetAtt AmiCopyLambdaRole.Arn
119+
120+
AmiCopyLambdaRole:
121+
Type: AWS::IAM::Role
122+
Properties:
123+
AssumeRolePolicyDocument:
124+
Version: '2012-10-17'
125+
Statement:
126+
- Effect: Allow
127+
Principal:
128+
Service: [lambda.amazonaws.com]
129+
Action: ['sts:AssumeRole']
130+
Path: /
131+
Policies:
132+
- PolicyName: ami-copy-lambda-policy
133+
PolicyDocument:
134+
Version: '2012-10-17'
135+
Statement:
136+
- Sid: CloudWatchLogs
137+
Effect: Allow
138+
Action:
139+
- logs:CreateLogGroup
140+
- logs:CreateLogStream
141+
- logs:PutLogEvents
142+
Resource: '*'
143+
- Sid: AmiCopy
144+
Effect: Allow
145+
Action:
146+
- ec2:CopyImage
147+
- ec2:DescribeImages
148+
Resource: '*'
149+
- Sid: AmiTagging
150+
Effect: Allow
151+
Action:
152+
- ec2:CreateTags
153+
Resource: '*'
154+
155+
AmiCopyTrigger:
156+
Type: Custom::AmiCopyLambdaTrigger
157+
DependsOn:
158+
- AmiCopyLambda
159+
- AmiCopyLambdaRole
160+
Properties:
161+
ServiceToken: !GetAtt AmiCopyLambda.Arn
162+
SourceAmiId: !Ref SourceAmiId
163+
SourceRegion: !Ref SourceRegion
164+
AmiName: !Ref AmiName
165+
ReferenceTag: !Ref ReferenceTag
166+
167+
Outputs:
168+
CopiedAmiId:
169+
Description: The ID of the copied AMI in the current region.
170+
Value: !GetAtt AmiCopyTrigger.CopiedAmiId
171+
CopiedAmiConsoleLink:
172+
Description: Console link to view the copied AMI. You can use this link to check the readiness of the copied AMI.
173+
Value: !Sub
174+
- "https://console.aws.amazon.com/ec2/home?region=${AWS::Region}#ImageDetails:imageId=${CopiedAmiId}"
175+
- CopiedAmiId: !GetAtt AmiCopyTrigger.CopiedAmiId
176+
LaunchClusterWithCopiedAmi:
177+
Condition: ShowDeploymentLink
178+
Description: Launch a new cluster stack using the copied AMI in your account. This link will open the CloudFormation console to create a new stack, with the custom AMI ID prepopulated. You should only click this link when the AMI is ready, which may take 5-15 minutes.
179+
Value: !Sub
180+
- "https://${AWS::Region}.console.aws.amazon.com/cloudformation/home?region=${AWS::Region}#/stacks/create/review?templateURL=${MWTemplateUrl}&param_customAmiId=${CopiedAmiId}&param_InstanceAmiCustom=${CopiedAmiId}"
181+
-
182+
MWTemplateUrl: !Ref MWTemplateUrl
183+
CopiedAmiId: !GetAtt AmiCopyTrigger.CopiedAmiId
184+
185+
Conditions:
186+
ShowDeploymentLink: !Not [!Equals [!Ref MWTemplateUrl, ""]]

aws/vpc-template/v1/.version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
v1.0.0

aws/vpc-template/v1/README.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Amazon Virtual Private Cloud (VPC) CloudFormation Template for MATLAB Reference Architectures
2+
3+
To create a virtual private cloud (VPC) for deploying MATLAB or MATLAB Parallel Server on AWS, use the CloudFormation template [vpc-template.yml](vpc-template.yml) in this folder.
4+
5+
## Overview
6+
7+
You can use this CloudFormation template to:
8+
9+
- Deploy [MATLAB on AWS](https://github.com/mathworks-ref-arch/matlab-on-aws) in a private network.
10+
- Deploy [MATLAB Parallel Server on AWS](https://github.com/mathworks-ref-arch/matlab-parallel-server-on-aws) in a private network.
11+
12+
13+
The CloudFormation template creates these resources:
14+
15+
| Resource | Description |
16+
|----------|-------------|
17+
| **VPC** | Virtual Private Cloud with user-defined CIDR block (default: `10.0.0.0/16`) |
18+
| **PublicSubnetA** | Public subnet in Availability Zone 1 (default size: `/24`) |
19+
| **PublicSubnetB** | Public subnet in Availability Zone 2 (default size: `/24`) |
20+
| **PrivateSubnetA** | Private subnet in Availability Zone 1 (default size: `/24`) |
21+
| **PrivateSubnetB** | Private subnet in Availability Zone 2 (default size: `/24`) |
22+
| **Internet Gateway** | Enables internet access for the public subnets |
23+
| **Public Route Table** | Associated with public subnets; routes internet-bound traffic through the Internet Gateway |
24+
| **Private Route Table** | Associated with private subnets; routes traffic to S3/DynamoDB through Gateway Endpoints and internet traffic through NAT Gateway (if enabled) |
25+
| **S3 Gateway Endpoint** | Gateway Endpoint for Amazon S3 service |
26+
| **DynamoDB Gateway Endpoint** | Gateway Endpoint for Amazon DynamoDB service |
27+
| **NAT Gateway** | Optional. Deployed in PublicSubnetA (AZ 1) to enable internet access for private subnets |
28+
| **EC2 API Interface Endpoint** | Optional VPC Interface Endpoint for EC2 API (`com.amazonaws.<region>.ec2`) deployed in PrivateSubnetA |
29+
| **CloudWatch Logs Interface Endpoint** | Optional VPC Interface Endpoint for CloudWatch Logs (`com.amazonaws.<region>.logs`) deployed in PrivateSubnetA |
30+
| **EC2 Auto Scaling Interface Endpoint** | Optional VPC Interface Endpoint for EC2 Auto Scaling (`com.amazonaws.<region>.autoscaling`) deployed in PrivateSubnetA |
31+
| **CloudFormation Interface Endpoint** | Optional VPC Interface Endpoint for CloudFormation (`com.amazonaws.<region>.cloudformation`) deployed in PrivateSubnetA |
32+
| **Interface Endpoints Security Group** | Security group for interface endpoints allowing inbound HTTPS traffic from the VPC CIDR block |
33+
34+
The created VPC has this architecture:
35+
36+
![VPC Architecture Diagram](./img/VPCArchitecture.jpg)
37+
38+
## Instructions
39+
40+
For general instructions on creating a new stack using a CloudFormation template, see
41+
See [Creating a Stack (AWS CloudFormation Documentation)](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-console-create-stack.html).
42+
43+
You can either use the template from this folder directly, or you can use the S3 link:
44+
```
45+
https://mathworks-reference-architectures-templates.s3.amazonaws.com/vpc-template/v1/0/0/vpc-template.yml
46+
```
47+
48+
MathWorks recommends these practices:
49+
50+
- Deploy private compute resources in `PrivateSubnetA` to minimize Inter-AZ (Availability Zone) data transfer costs between the compute resources and the NAT Gateway or VPC interface endpoints.
51+
- Use the public subnets for bastion hosts and public compute resources if needed.
52+
- To optimize costs, see [Pricing for VPC interface endpoints (AWS Documentation)](https://aws.amazon.com/privatelink/pricing/) and [Pricing for NAT Gateway (AWS Documentation)](https://aws.amazon.com/vpc/pricing/).
53+
---
54+
Copyright 2025 The MathWorks, Inc.
207 KB
Loading

0 commit comments

Comments
 (0)