Hi all, I'm getting to grips with CF templates and the below template is one I've created to deploy a Windows Server instance then download and run a couple of powershell scripts from an S3 bucket, these deploy ADDS to make the server a domain controller.
This template deploys the server but does not pull the files from the bucket in S3, it always throws a http 403 error.
Any thoughts based on the template?
Cheers!
AWSTemplateFormatVersion: 2010-09-09
Description: CloudFormation Template to deploy an EC2 instance and then install ADDS
Parameters:
KeyName:
Description: Name of an existing EC2 KeyPair
Type: AWS::EC2::KeyPair::KeyName
ConstraintDescription: must be the name of an existing EC2 KeyPair.
Hostname:
Type: String
Description: Hostname - maximum 15 characters
MaxLength: '15'
Default: ad
InstanceName:
Description: Name of instance in AWS. Replace CUSTOMERNAME with your actual customer
domain name.
Type: String
Default: ad-CUSTOMERNAME-test-local
InstanceAMIId:
Description: The AMI ID from which this instance will be deployed. Search Windows_Server-2016-English-Full-Base-
in the AMI menu
Type: AWS::EC2::Image::Id
DomainDNSName:
Type: String
Description: Fully Qualified Domain Name - replace CUSTOMERNAME here
Default: CUSTOMERNAME.test.local
DomainNetBiosName:
Type: String
Description: NETBIOS Domain Name - replace CUSTOMERNAME here
Default: CUSTOMERNAME
DomainMode:
Type: String
Description: Domain Mode, use 7 for Windows Server 2016
Default: 7
ForestMode:
Type: String
Description: Domain Mode, use 7 for Windows Server 2016
Default: 7
SafeModeAdministratorPassword:
MinLength: '8'
NoEcho: 'true'
Type: String
Description: SafeModeAdministrator Password - used when creating ADDS
CAName:
Description: the name of the Certificate Authority server. Replace CUSTOMERNAME
here.
Type: String
Default: CUSTOMERNAMEtestCA
SubnetId:
Description: Use Service Internal 1
Type: AWS::EC2::Subnet::Id
ConstraintDescription: must be the name of an existing EC2 KeyPair.
RoleSecurityGroup:
Description: The ID of the Security Group defining access to this instance based
on it's defined role.
Type: AWS::EC2::SecurityGroup::Id
ConstraintDescription: This must be the ID of an existing Security Group composed
to support this role.
AccessSecurityGroup:
Description: The IDs of the Security Group defining access from this instance
into other groups.
Type: AWS::EC2::SecurityGroup::Id
ConstraintDescription: This must be the ID of an existing Security Group composed to support required access.
InstanceType:
Description: Amazon EC2 instance type
Type: String
Default: t3.medium
AllowedValues:
- t2.micro
- t2.small
- t2.medium
- t2.large
- m4.large
- m4.xlarge
- m4.2xlarge
- t3.medium
- t3.large
- t3.xlarge
- r5.xlarge
- r5a.xlarge
ConstraintDescription: must be a valid EC2 instance type.
AvailabilityZone:
Type: String
Description: Default AZ.
IAMRole:
Description: This is the IAM Role that will enable required access for the deployment of this instance
Type: String
Default: CFInstanceBasePermissionsRole
BootVolumeSize:
Description: This is the size (in GB) of the boot volume from which this instance will operate.
Type: String
Default: '80'
EnableTerminationProtection:
Description: The setting that determines whether delete/termination protection
is enabled for the instance.
Type: String
Default: 'True'
ConstraintDescription: This can only be True or False.
S3BucketName:
Default: general-application-setup
Description: S3 bucket for boot artefacts
Type: String
Resources:
Profile:
Type: 'AWS::IAM::InstanceProfile'
Properties:
Roles:
- !Ref HostRole
Path: /
InstanceProfileName: !Join
- ''
- - 'instance-profile-'
- !Ref S3BucketName
HostRole:
Type: 'AWS::IAM::Role'
Properties:
RoleName: !Join
- ''
- - 'role-s3-read-'
- !Ref S3BucketName
Policies:
- PolicyDocument:
Version: 2012-10-17
Statement:
- Action:
- 's3:GetObject'
Effect: Allow
Resource: !Join
- ''
- - 'arn:aws:s3:::'
- !Ref S3BucketName
- '/*'
PolicyName: s3-policy-read
Path: /
AssumeRolePolicyDocument:
Statement:
- Action:
- 'sts:AssumeRole'
Principal:
Service:
- ec2.amazonaws.com
Effect: Allow
Version: 2012-10-17
Instance:
Type: 'AWS::EC2::Instance'
Metadata:
'AWS::CloudFormation::Authentication':
S3AccessCreds:
type: S3
buckets:
- !Ref S3BucketName
roleName: !Ref HostRole
'AWS::CloudFormation::Init':
configSets:
config:
- get-files
- configure-instance
get-files:
files:
'c:\generalFiles\npp.8.5.3.Installer.x64.exe':
source: https://general-application-setup.s3.us-west-1.amazonaws.com/test-tools/npp.8.5.3.Installer.x64.exe
authentication: S3AccessCreds
'c:\generalFiles\Add-WindowsComponents.ps1':
source: https://general-application-setup.s3.us-west-1.amazonaws.com/test-tools/scripts/Add-WindowsComponents.ps1
authentication: S3AccessCreds
'c:\generalFiles\Configure-ADForest.ps1':
source: https://general-application-setup.s3.us-west-1.amazonaws.com/test-tools/scripts/Configure-ADForest.ps1
authentication: S3AccessCreds
configure-instance:
commands:
1-set-powershell-execution-policy:
command: >-
powershell.exe -Command "Set-ExecutionPolicy UnRestricted -Force"
waitAfterCompletion: '0'
2-rename-computer:
command: !Join
- ''
- - >-
- powershell.exe -Command "Rename-Computer -Restart -NewName "
- !Ref Hostname
waitAfterCompletion: forever
3-install-windows-components:
command: >-
powershell.exe -Command "c:\generalFiles\Add-WindowsComponents.ps1"
waitAfterCompletion: '0'
4-install-ADForest:
command: !Join
- ''
- - >-
- powershell.exe -Command "c:\generalFiles\Configure-ADForest.ps1 -DomainName '
- !Ref DomainDNSName
- ''' -DomainNetBiosName '''
- !Ref DomainNetBiosName
- ''' -DomainMode '''
- !Ref DomainMode
- ''' -ForestMode '''
- !Ref ForestMode
- ''' -SafeModeAdministratorPassword '''
- !Ref SafeModeAdministratorPassword
- '''"'
waitAfterCompletion: forever
Properties:
DisableApiTermination: 'false'
AvailabilityZone: !Sub "${AvailabilityZone}"
DisableApiTermination: !Ref EnableTerminationProtection
IamInstanceProfile: !Ref Profile
InstanceType: !Ref InstanceType
ImageId: !Ref InstanceAMIId
SecurityGroupIds:
- Ref: RoleSecurityGroup
- Ref: AccessSecurityGroup
SubnetId: !Ref SubnetId
KeyName: !Ref KeyName
Tags:
- Key: Name
Value:
Ref: InstanceName
BlockDeviceMappings:
- DeviceName: "/dev/sda1"
Ebs:
VolumeSize: !Ref BootVolumeSize
VolumeType: gp2
KeyName: !Ref KeyName
UserData: !Base64
'Fn::Join':
- ''
- - "<powershell>\n"
- "cfn-init.exe "
- " --stack "
- "Ref": "AWS::StackId"
- " --resource Instance"
- " --region "
- "Ref": "AWS::Region"
- " --configsets config"
- " -v \n"
- "cfn-signal.exe "
- " ---exit-code 0"
- " --region "
- "Ref": "AWS::Region"
- " --resource Instance"
- " --stack "
- "Ref": "AWS::StackName"
- "\n"
- "</powershell>\n"
Outputs:
InstanceId:
Description: 'InstanceId'
Value: !Ref Instance
InstancePrivateIP:
Description: 'InstancePrivateIP'
Value: !GetAtt Instance.PrivateIp
@myronix88, I believe
s3:PutObjectAcl
also needs to be granted to the IAM role or IAM user which @ThatKears is using for the deployment as both the actions work in conjunction and I have seen scenarios wheres3:PutObject
doesn't work alone until thes3:PutObjectAcl
permission is granted. You can refer this for more insights https://giuseppeborgese.medium.com/fix-the-error-http-403-access-denied-from-amazon-s3-df53a4f1f530