def test_parameter_label_replace(self): t = Template() p1 = t.add_parameter(Parameter("Foo")) t.add_parameter(Parameter("Bar")) t.set_parameter_label(p1, "Foo label") t.set_parameter_label("Foo", "Bar label") self.assertEqual(t.metadata, { "AWS::CloudFormation::Interface": { "ParameterLabels": { "Foo": {"default": "Bar label"}, }, }, })
import custom_resources.awslambda import custom_resources.cloudformation import cfnutils.output template = Template() custom_resources.use_custom_resources_stack_name_parameter(template) param_role = template.add_parameter( Parameter( "Role", Default="arn:aws:iam::000000000000:role/xxx", Type=constants.STRING, Description="ARN of role to run as", )) template.set_parameter_label(param_role, "Lambda role ARN") param_s3_bucket_name = template.add_parameter( Parameter( "S3BucketName", Default="", Type=constants.STRING, Description="Location of the Lambda ZIP file, bucket name", )) template.set_parameter_label(param_s3_bucket_name, "Lambda S3 bucket") param_s3_key = template.add_parameter( Parameter( "S3Key", Default="", Type=constants.STRING,
param_authorizer_param_stack = template.add_parameter( Parameter( "AuthorizerParamStackParam", Type=constants.STRING, Default="authorizer-params", Description="StackName of the Params stack", )) param_authorizer_lae_arn = template.add_parameter( Parameter( "AuthorizerLaeParam", Type="AWS::SSM::Parameter::Value<String>", Default='/authorizer/lae-arn', Description="Parameter name to get Lambda@Edge ARN from", )) template.set_parameter_label(param_authorizer_lae_arn, "Authorizer Lambda@Edge parameter") param_label = template.add_parameter( Parameter( "Label", Default="example.authorizer", Type=constants.STRING, Description= "Label inside the Hosted Zone to create. e.g. 'authorizer' for 'authorizer.example.org'", )) template.set_parameter_label(param_label, "Label") param_hosted_zone_name = template.add_parameter( Parameter( "HostedZone", Default="example.org",
Description='SSH keypair that the instance will be deployed with.', Type=constants.KEY_PAIR_NAME, )) instance_type = t.add_parameter(Parameter( 'InstanceType', Description='The EC2 instance type.', Default='t3.small', Type='String', AllowedValues=[ 't3.micro', 't3.small', 't3.small', 't3.medium', 't3.large', 't3.xlarge', ], )) t.set_parameter_label(instance_type, 'Instance Type') ########################################### # Security Group ########################################### ec2_security_group = t.add_resource(SecurityGroup( 'Ec2SecurityGroup', VpcId=Ref(vpc), GroupDescription='Security group for Minecraft EC2 instance.', Tags=Tags( Name=Sub('$minecraft-sg'), ) )) ec2_minecraft_tcp_ingress = t.add_resource(SecurityGroupIngress(
GetAtt, ImportValue import custom_resources.ssm import custom_resources.cloudformation import cfnutils.output template = Template() custom_resources.use_custom_resources_stack_name_parameter(template) param_authorizer_stack = template.add_parameter( Parameter( "ParamAuthorizerStack", Default="authorizer", Type=constants.STRING, )) template.set_parameter_label(param_authorizer_stack, "Authorizer StackName") param_laearn = template.add_parameter( Parameter( "ParamLaeArn", Type=constants.STRING, Description="ARN of the Lambda@Edge function", )) template.set_parameter_label(param_laearn, "Lambda@Edge ARN") cloudformation_tags = template.add_resource( custom_resources.cloudformation.Tags("CfnTags")) # Don't simply import-output the Lambda@Edge ARN, but do it via a Parameter # This allows us to migrate to a new L@E function gradually (otherwise, the output value would be locked and can't # change)
import cfnutils.output template = Template() custom_resources.use_custom_resources_stack_name_parameter(template) template.add_transform('AWS::Serverless-2016-10-31') param_s3_bucket_name = template.add_parameter( Parameter( "S3BucketName", Default="", Type=constants.STRING, Description="Location of the Lambda ZIP file, bucket name", )) template.set_parameter_label(param_s3_bucket_name, "Lambda S3 bucket") param_s3_key = template.add_parameter( Parameter( "S3Key", Default="", Type=constants.STRING, Description="Location of the Lambda ZIP file, path", )) template.set_parameter_label(param_s3_key, "Lambda S3 key") param_label = template.add_parameter( Parameter( "Label", Default="authorizer", Type=constants.STRING,
def main(): t = Template() AddAMIMap(t) t.set_version("2010-09-09") t.set_description( "DCV 2017 Remote Desktop with Xilinx Vivado (using AWS FPGA Developer AMI)" ) tags = Tags(Name=Ref("AWS::StackName")) # user data InstUserData = list() InstUserData = [ '#!/usr/bin/env bash\n', '\n', 'set -x\n', '\n', '##exit 0\n', # use this to disable all user-data and bring up files '\n', 'my_wait_handle="', Ref('InstanceWaitHandle'), '"\n', 'user_name="', Ref('UserName'), '"\n', 'user_pass="******"\n', '\n', ] with open('_include/dcv-install.sh', 'r',) as ud_file: user_data_file = ud_file.readlines() for l in user_data_file: InstUserData.append(l) VPCId = t.add_parameter(Parameter( 'VPCId', Type="AWS::EC2::VPC::Id", Description="VPC ID for where the remote desktop instance should be launched" )) t.set_parameter_label(VPCId, "VPC ID") t.add_parameter_to_group(VPCId, "Instance Configuration") Subnet = t.add_parameter(Parameter( 'Subnet', Type="AWS::EC2::Subnet::Id", Description="For the Subnet ID, you should choose one in the " "Availability Zone where you want the instance launched" )) t.set_parameter_label(Subnet, "Subnet ID") t.add_parameter_to_group(Subnet, "Instance Configuration") ExistingSecurityGroup = t.add_parameter(Parameter( 'ExistingSecurityGroup', Type="String", Default="NO_VALUE", Description="OPTIONAL: Needs to be a SG ID, for example sg-abcd1234efgh. " "This is an already existing Security Group ID that is " "in the same VPC, this is an addition to the security groups that " "are automatically created to enable access to the remote desktop," "leave as NO_VALUE if you choose not to use this" )) t.set_parameter_label(ExistingSecurityGroup, "OPTIONAL: Existing Security Group (e.g. sg-abcd1234efgh)") t.add_parameter_to_group(ExistingSecurityGroup, "Instance Configuration") remoteDesktopInstanceType = t.add_parameter(Parameter( 'remoteDesktopInstanceType', Type="String", Description="This is the instance type that will be used. As this is a " "2D workstation, we are not supporting GPU instance types.", Default="m4.xlarge", AllowedValues=[ "m4.large", "m4.xlarge", "m4.2xlarge", "m4.4xlarge", "m4.10xlarge", "m5.large", "m5.xlarge", "m5.2xlarge", "m5.4xlarge", "m5.12xlarge", "m5.24xlarge", "z1d.large", "z1d.xlarge", "z1d.2xlarge", "z1d.3xlarge", "z1d.6xlarge", "z1d.12xlarge", "z1d.metal" ], ConstraintDescription= "Must an EC2 instance type from the list" )) t.set_parameter_label(remoteDesktopInstanceType, "Remote Desktop Instance Type") t.add_parameter_to_group(remoteDesktopInstanceType, "Instance Configuration") EC2KeyName = t.add_parameter(Parameter( 'EC2KeyName', Type="AWS::EC2::KeyPair::KeyName", Description="Name of an existing EC2 KeyPair to enable SSH access to the instance.", ConstraintDescription="REQUIRED: Must be a valid EC2 key pair" )) t.set_parameter_label(EC2KeyName, "EC2 Key Name") t.add_parameter_to_group(EC2KeyName, "Instance Configuration") OperatingSystem = t.add_parameter(Parameter( 'OperatingSystem', Type="String", Description="Operating System of the AMI", Default="centos7", AllowedValues=[ "centos7" ], ConstraintDescription="Must be: centos7" )) t.set_parameter_label(OperatingSystem, "Operating System of AMI") t.add_parameter_to_group(OperatingSystem, "Instance Configuration") StaticPrivateIpAddress = t.add_parameter(Parameter( 'StaticPrivateIpAddress', Type="String", Default="NO_VALUE", Description="OPTIONAL: If you already have a private VPC address range, you can " "specify the private IP address to use, leave as NO_VALUE if you choose not to use this", )) t.set_parameter_label(StaticPrivateIpAddress, "OPTIONAL: Static Private IP Address") t.add_parameter_to_group(StaticPrivateIpAddress, "Instance Configuration") UsePublicIp = t.add_parameter(Parameter( 'UsePublicIp', Type="String", Description="Should a public IP address be given to the instance, " "this is overridden by CreateElasticIP=True", Default="True", ConstraintDescription="True/False", AllowedValues=[ "True", "False" ] )) t.set_parameter_label(UsePublicIp, "Assign a public IP Address") t.add_parameter_to_group(UsePublicIp, "Instance Configuration") CreateElasticIP = t.add_parameter(Parameter( 'CreateElasticIP', Type="String", Description="Should an Elastic IP address be created and assigned, " "this allows for persistent IP address assignment", Default="True", ConstraintDescription="True/False", AllowedValues=[ "True", "False" ] )) t.set_parameter_label(CreateElasticIP, "Create an Elastic IP address") t.add_parameter_to_group(CreateElasticIP, "Instance Configuration") S3BucketName = t.add_parameter(Parameter( 'S3BucketName', Type="String", Default="NO_VALUE", Description="OPTIONAL: S3 bucket to allow this instance read access (List and Get)," "leave as NO_VALUE if you choose not to use this" )) t.set_parameter_label(S3BucketName, "OPTIONAL: S3 bucket for read access") t.add_parameter_to_group(S3BucketName, "Instance Configuration") AccessCidr = t.add_parameter(Parameter( 'AccessCidr', Type="String", Description="This is the CIDR block for allowing remote access, for ports 22 and 8443", Default="111.222.333.444/32", AllowedPattern="(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})", ConstraintDescription="Must be a valid CIDR x.x.x.x/x" )) t.set_parameter_label(AccessCidr, "CIDR block for remote access (ports 22 and 8443)") t.add_parameter_to_group(AccessCidr, "Instance Configuration") UserName = t.add_parameter(Parameter( 'UserName', Type="String", Description="User name for DCV remote desktop login, default is \"simuser\".", Default="simuser", MinLength="4", )) t.set_parameter_label(UserName, "User name for DCV login") t.add_parameter_to_group(UserName, "DCV Configuration") UserPass = t.add_parameter(Parameter( 'UserPass', Type="String", Description="Password for DCV remote desktop login. The default password is Ch4ng3M3!", Default="Ch4ng3M3!", MinLength="8", AllowedPattern="^((?=.*[a-z])(?=.*[A-Z])(?=.*[\\d])|(?=.*[a-z])(?=.*[A-Z])(?=.*[\\W_])|(?=.*[a-z])(?=.*[\\d])(?=.*[\\W_])|(?=.*[A-Z])(?=.*[\\d])(?=.*[\\W_])).+$", ConstraintDescription="Password must contain at least one element from three of the following sets: lowercase letters, uppercase letters, base 10 digits, non-alphanumeric characters", NoEcho=True )) t.set_parameter_label(UserPass, "Password for DCV login") t.add_parameter_to_group(UserPass, "DCV Configuration") # end parameters RootRole = t.add_resource(iam.Role( "RootRole", AssumeRolePolicyDocument={ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": ["ec2.amazonaws.com"], }, "Action": ["sts:AssumeRole"] }] } )) dcvBucketPolicy= t.add_resource(PolicyType( "dcvBucketPolicy", PolicyName="dcvBucketPolicy", Roles=[Ref(RootRole)], PolicyDocument={ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["s3:GetObject"], "Resource": "arn:aws:s3:::dcv-license.us-east-1/*" } ], }, )), BucketPolicy= t.add_resource(PolicyType( "BucketPolicy", PolicyName="BucketPolicy", Roles=[Ref(RootRole)], PolicyDocument={ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["s3:GetObject"], "Resource": {"Fn::Join":["", ["arn:aws:s3:::", {"Ref": "S3BucketName"},"/*"]]} }, { "Effect": "Allow", "Action": [ "s3:ListBucket"], "Resource": {"Fn::Join":["", ["arn:aws:s3:::", {"Ref": "S3BucketName"}]]} } ], }, Condition="Has_Bucket" )), remoteDesktopSecurityGroup = t.add_resource(SecurityGroup( "remoteDesktopSecurityGroup", VpcId = Ref(VPCId), GroupDescription = "Remote Desktop Secuirty group", SecurityGroupIngress=[ ec2.SecurityGroupRule( IpProtocol="tcp", FromPort="8443", ToPort="8443", CidrIp=Ref(AccessCidr), ), ] )) SshSecurityGroup = t.add_resource(SecurityGroup( "SshSecurityGroup", VpcId = Ref(VPCId), GroupDescription = "SSH Secuirty group", SecurityGroupIngress=[ ec2.SecurityGroupRule( IpProtocol="tcp", FromPort="22", ToPort="22", CidrIp=Ref(AccessCidr), ), ] )) RootInstanceProfile = t.add_resource(InstanceProfile( "RootInstanceProfile", Roles=[Ref(RootRole)] )) remoteDesktopInstance = t.add_resource(ec2.Instance( 'remoteDesktopInstance', ImageId=FindInMap("AWSRegionAMI", Ref("AWS::Region"), Ref(OperatingSystem)), KeyName=Ref(EC2KeyName), InstanceType=(Ref(remoteDesktopInstanceType)), DisableApiTermination='false', NetworkInterfaces=[ NetworkInterfaceProperty( SubnetId=Ref(Subnet), GroupSet=If( "not_existing_sg", [Ref(remoteDesktopSecurityGroup), Ref(SshSecurityGroup)], [Ref(remoteDesktopSecurityGroup), Ref(SshSecurityGroup), Ref(ExistingSecurityGroup)] ), AssociatePublicIpAddress=Ref(UsePublicIp), DeviceIndex='0', DeleteOnTermination='true', PrivateIpAddress=If( "Has_Static_Private_IP", Ref(StaticPrivateIpAddress), Ref("AWS::NoValue"), ) ) ], IamInstanceProfile=(Ref(RootInstanceProfile)), UserData=Base64(Join('', InstUserData)), )) EIPAddress = t.add_resource(EIP( 'EIPAddress', Domain='vpc', InstanceId=Ref(remoteDesktopInstance), Condition="create_elastic_ip" )) t.add_condition( "not_existing_sg", Equals(Ref(ExistingSecurityGroup), "NO_VALUE") ) t.add_condition( "Has_Public_Ip", Equals(Ref(UsePublicIp), "True") ) t.add_condition( "Has_Bucket", Not(Equals(Ref(S3BucketName), "NO_VALUE")) ) t.add_condition( "create_elastic_ip", Equals(Ref(CreateElasticIP), "True") ) t.add_condition( "Has_Static_Private_IP", Not(Equals(Ref(StaticPrivateIpAddress), "NO_VALUE")) ) waithandle = t.add_resource(WaitConditionHandle('InstanceWaitHandle')) instanceWaitCondition = t.add_resource(WaitCondition( "instanceWaitCondition", Handle=Ref(waithandle), Timeout="3600", DependsOn="remoteDesktopInstance" )) t.add_output([ Output( "DCVConnectionLink", Description="Connect to the DCV Remote Desktop with this URL", Value=Join("", [ "https://", GetAtt("remoteDesktopInstance", 'PublicIp'), ":8443" ]) ), Output( "DCVUserName", Description="Login name for DCV session", Value=(Ref(UserName)) ), Output( "SSHTunnelCommand", Description='Command for setting up SSH tunnel to remote desktop, use "localhost:18443" for DCV client', Value=Join("", [ "ssh -i <file.pem> -L 18443:localhost:8443 -l centos ", GetAtt("remoteDesktopInstance", 'PublicIp') ]) ), ]) #print(t.to_json(indent=2)) print(to_yaml(t.to_json(indent=2), clean_up=True))
parser.add_argument( '--output-dir', help='Where to place the Zip-files and the CloudFormation template', default='output') args = parser.parse_args() template = Template("Custom Resources") s3_bucket = template.add_parameter( troposphere.Parameter( "S3Bucket", Type=constants.STRING, Description="S3 bucket where the ZIP files are located", )) template.set_parameter_label(s3_bucket, "S3 bucket") lambda_code_location = template.add_parameter_to_group(s3_bucket, "Lambda code location") s3_path = template.add_parameter( troposphere.Parameter( "S3Path", Type=constants.STRING, Default='', Description= "Path prefix where the ZIP files are located (should probably end with a '/')", )) template.set_parameter_label(s3_path, "S3 path") template.add_parameter_to_group(s3_path, lambda_code_location)