AWS Configuration Files
The following configuration files are required to deploy and manage your AWS infrastructure resources:
CloudFormation template
The CloudFormation template is used to deploy the Commander environment in AWS.
Copy the example template below and save it as a .template
file.
You'll need to configure several parameters in the CloudFormation template. For more information, see Customize the CloudFormation Template.
You must also configure the mappings to specify the AMI IDs to use for each region that you want to deploy your EC2 instances.
The provided CloudFormation template is an example only and should not be used as is.
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "CFT to install Commander using an RDS instance",
"Parameters": {
"VpcId": {
"Type": "AWS::EC2::VPC::Id",
"Description": "VpcId of your existing Virtual Private Cloud (VPC)",
"ConstraintDescription": "must be the VPC Id of an existing Virtual Private Cloud."
},
"EC2SubnetId": {
"Type": "AWS::EC2::Subnet::Id",
"Description": "The SubnetId for the EC2 instance in your Virtual Private Cloud (VPC)",
"ConstraintDescription": "Must be residing in the selected Virtual Private Cloud."
},
"IamInstanceProfile" : {
"Type" : "String",
"Default": "",
"Description" : "The name of an instance profile or a reference to an AWS::IAM::InstanceProfile resource",
"ConstraintDescription" : "Must be residing in the selected Virtual Private Cloud."
},
"RDSSubnetIds": {
"Type": "List<AWS::EC2::Subnet::Id>",
"Description": "The SubnetIds for the RDS instance in your Virtual Private Cloud (VPC)",
"ConstraintDescription": "Must be residing in the selected Virtual Private Cloud."
},
"ALBSubnetIds": {
"Type": "List<AWS::EC2::Subnet::Id>",
"Description": "The SubnetIds for the Load Balancer instance in your Virtual Private Cloud (VPC)",
"ConstraintDescription": "Must be residing in the selected Virtual Private Cloud."
},
"KeyName": {
"Description": "Name of an existing EC2 KeyPair to enable RDP access to the instances",
"Type": "AWS::EC2::KeyPair::KeyName",
"ConstraintDescription": "must be the name of an existing EC2 KeyPair."
},
"DBUser": {
"NoEcho": "true",
"Description": "Username for SQL Server database access",
"Type": "String",
"MinLength": "1",
"MaxLength": "16",
"AllowedPattern": "[a-zA-Z][a-zA-Z0-9]*",
"ConstraintDescription": "Must begin with a letter and contain only alphanumeric characters and be between 1 and 16 characters in length."
},
"DBPassword": {
"NoEcho": "true",
"Description": "Password for SQL Server database access",
"Type": "String",
"MinLength": "8",
"MaxLength": "30",
"AllowedPattern": "[a-zA-Z0-9]*",
"ConstraintDescription": "Must contain only alphanumeric characters and be between 8 and 30 characters in length."
},
"DBAllocatedStorage": {
"Default": "50",
"Description": "The size of the database (Gb)",
"Type": "Number",
"MinValue": "10",
"MaxValue": "16384",
"ConstraintDescription": "must be between 10 and 16384GB."
},
"DBInstanceType": {
"Description": "The database instance type",
"Type": "String",
"Default": "db.m5.large",
"AllowedValues": [
"db.m5.large",
"db.m5.xlarge",
"db.m5.2xlarge",
"db.r4.large",
"db.r4.xlarge",
"db.r4.2xlarge"
],
"ConstraintDescription": "must select a valid database instance type."
},
"EC2InstanceType": {
"Description": "Commander EC2 instance type",
"Type": "String",
"Default": "t3.large",
"AllowedValues": [
"t2.large",
"t3.large",
"m5.xlarge",
"c5.xlarge",
"c5.2xlarge"
],
"ConstraintDescription": "must be a valid EC2 instance type."
},
"WebLocation": {
"Description": " The IP address range that can be used to access EC2 instance via HTTPS",
"Type": "String",
"MinLength": "9",
"MaxLength": "18",
"Default": "0.0.0.0/0",
"AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
"ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x."
},
"RDPLocation": {
"Description": "The IP address range that can be used to access EC2 instance via RDP",
"Type": "String",
"MinLength": "9",
"MaxLength": "18",
"Default": "0.0.0.0/0",
"AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
"ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x."
},
"CertificateARN": {
"Description": "Certificate ARN in AWS in the form of arn:aws:acm:region-xxxx-x:XXXXXXXXXX:certificate/XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXX",
"Type": "String",
"ConstraintDescription": "Certificate ARN must be provided"
}
},
"Mappings": {
"AWSRegion2AMI": {
"region-xxxx-x": {
"AMI": "ami-xxxxxxxxxxxxxxxxx"
},
}
},
"Resources": {
"WebSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Enable HTTPS and RDP access via port 443,3389",
"SecurityGroupIngress": [
{
"IpProtocol": "tcp",
"FromPort": "443",
"ToPort": "443",
"CidrIp": {
"Ref": "WebLocation"
}
},
{
"IpProtocol": "tcp",
"FromPort": "3389",
"ToPort": "3389",
"CidrIp": {
"Ref": "RDPLocation"
}
}
],
"VpcId": {
"Ref": "VpcId"
}
}
},
"EC2InstanceOne": {
"Type": "AWS::EC2::Instance",
"Properties": {
"ImageId": {
"Fn::FindInMap": [
"AWSRegion2AMI",
{
"Ref": "AWS::Region"
},
"AMI"
]
},
"Tenancy": "default",
"InstanceType": {
"Ref": "EC2InstanceType"
},
"KeyName": {
"Ref": "KeyName"
},
"NetworkInterfaces": [
{
"AssociatePublicIpAddress": true,
"DeleteOnTermination": true,
"DeviceIndex": "0",
"SubnetId": {
"Ref": "EC2SubnetId"
},
"GroupSet": [
"Ref": "WebSecurityGroup"
]
}
],
"IamInstanceProfile": {
"Ref": "IamInstanceProfile"
},
"Tags": [
{
"Key": "Name",
"Value": "Commander"
}
]
},
"DependsOn": [
"SQLServerDatabase"
]
},
"DBEC2SecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Open database for access",
"SecurityGroupIngress": [
{
"IpProtocol": "tcp",
"FromPort": "1433",
"ToPort": "1433",
"SourceSecurityGroupId": {
"Ref": "WebSecurityGroup"
}
}
],
"VpcId": {
"Ref": "VpcId"
}
}
},
"SQLServerDatabase": {
"Type": "AWS::RDS::DBInstance",
"Properties": {
"Engine": "sqlserver-se",
"EngineVersion": "14.00.3035.2.v1",
"LicenseModel": "license-included",
"Iops": "1000",
"StorageType": "io1",
"MultiAZ": "true",
"MasterUsername": {
"Ref": "DBUser"
},
"MasterUserPassword": {
"Ref": "DBPassword"
},
"DBInstanceClass": {
"Ref": "DBInstanceType"
},
"AllocatedStorage": {
"Ref": "DBAllocatedStorage"
},
"VPCSecurityGroups": [
{
"Fn::GetAtt": [
"DBEC2SecurityGroup",
"GroupId"
]
}
],
"DBSubnetGroupName": {
"Ref": "DbSubnetGroup"
},
"Tags": [
{
"Key": "Name",
"Value": "Commander-DB"
}
]
}
},
"DbSubnetGroup": {
"Type": "AWS::RDS::DBSubnetGroup",
"Properties": {
"DBSubnetGroupDescription": "Subnets available for the RDS DB Instance",
"SubnetIds": {
"Ref": "RDSSubnetIds"
}
}
},
"ElasticLoadBalancer": {
"Type": "AWS::ElasticLoadBalancingV2::LoadBalancer",
"Properties": {
"Scheme": "internet-facing",
"Name": {
"Fn::Join": [
"-",
[
{
"Ref": "AWS::StackName"
},
"LoadBalancer"
]
]
},
"Subnets": {
"Ref": "ALBSubnetIds"
},
"SecurityGroups": [
{
"Ref": "WebSecurityGroup"
}
]
},
"DependsOn": [
"EC2InstanceOne"
]
},
"TargetGroupService": {
"Type": "AWS::ElasticLoadBalancingV2::TargetGroup",
"Properties": {
"Targets": [
{
"Id": {
"Ref": "EC2InstanceOne"
},
"Port": "443"
}
],
"Name": {
"Fn::Join": [
"-",
[
{
"Ref": "AWS::StackName"
},
"TgtGrpSrv"
]
]
},
"Port": "443",
"Protocol": "HTTPS",
"HealthCheckPath": "/webservices/services/rest/v2/active",
"VpcId": {
"Ref": "VpcId"
}
},
"DependsOn": [
"EC2InstanceOne"
]
},
"Listener": {
"Type": "AWS::ElasticLoadBalancingV2::Listener",
"Properties": {
"DefaultActions": [
{
"Type": "forward",
"TargetGroupArn": {
"Ref": "TargetGroupService"
}
}
],
"LoadBalancerArn": {
"Ref": "ElasticLoadBalancer"
},
"Port": "443",
"Protocol": "HTTPS",
"Certificates": [
{
"CertificateArn": {
"Ref": "CertificateARN"
}
}
]
},
"DependsOn": [
"EC2InstanceOne"
]
},
"ListenerRuleService": {
"Type": "AWS::ElasticLoadBalancingV2::ListenerRule",
"Properties": {
"Actions": [
{
"TargetGroupArn": {
"Ref": "TargetGroupService"
},
"Type": "forward"
}
],
"Conditions": [
{
"Field": "path-pattern",
"Values": [
"/"
]
}
],
"ListenerArn": {
"Ref": "Listener"
},
"Priority": 1
},
"DependsOn": [
"EC2InstanceOne"
]
}
},
"Outputs": {
"CommanderURL": {
"Description": "URL for Commander UI",
"Value": {
"Fn::Join": [
"",
[
"https://",
{
"Fn::GetAtt": [
"ElasticLoadBalancer",
"DNSName"
]
}
]
]
}
}
}
}
IAM policy
The IAM policy defines the permissions that Commander will use to manage AWS.
Copy the sample policy below to use when you create the IAM role.
Click the link below to download a sample IAM policy. The policy provides permissions for full read and write access for an AWS cloud account. These permissions allow you to discover and view resources in inventory as well as deploy and manage them.
It's recommended that you customize the downloaded policy as required. For example:
- For read only access (including access to billing records), remove the “EmboticsCommanderWritePolicyForOperations” block.
- For read access without access to billing records, remove the “s3:GetObject” and “s3:ListBucket” permissions in the "EmboticsCommanderReadOnlyPolicyOptional" block and also remove the "EmboticsCommanderWritePolicyForOperations” block.
- The policy doesn't allow you to deploy resources through CloudFormation templates that include anything other than EC2 instances. Therefore, you can use it as a base policy that you can extend to cover the types of AWS services that you want to provision.
- If you're using additional services such as Key Management Service (KMS), you'll need the appropriate permissions for Commander.