Automating Windows Workloads in AWS using Systems Manager and PowerShell DSC with Terragrunt Part1.

Cloud people!

In this opportunity, I want to share a scenary for automated and cover workloads in windows and runned automations based on powershell dsc with systems manager.

Check github repository for the code

Requirements

Step 1.

The first step is configuring the network layer, it is using the vpc module of registry, all information about this module in this link.

For effects practices only two subnets are created, one private subnet and one public subnet, this demo not need more.

module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "5.1.2" name = local.name cidr = local.vpc_cidr azs = local.azs public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 6, k)] private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 6, k + 10)] enable_nat_gateway = true create_igw = true enable_dns_hostnames = true single_nat_gateway = true manage_default_network_acl = true default_network_acl_tags = { Name = "${local.name}-default" } manage_default_route_table = true default_route_table_tags = { Name = "${local.name}-default" } manage_default_security_group = true default_security_group_tags = { Name = "${local.name}-default" } tags = local.tags
}
Enter fullscreen mode
Exit fullscreen mode

Step 2.

The second step is related to create security group, in this case the open ports are 3389 and 80, and like step 1 it is using the security group module of registry, all information about this module in this link.

module "security_group_bastion" { source = "terraform-aws-modules/security-group/aws" version = "5.1.0" name = "windows security group" description = "windows security group" vpc_id = var.vpc_id ingress_with_cidr_blocks = [ { from_port = 3389 to_port = 3389 protocol = "tcp" description = "rdp ports" cidr_blocks = "172.16.0.0/16" }, { from_port = 3389 to_port = 3389 protocol = "tcp" description = "rdp ports" cidr_blocks = "0.0.0.0/0" }, { from_port = 5986 to_port = 5986 protocol = "tcp" description = "winrm" cidr_blocks = "0.0.0.0/0" }, { from_port = 80 to_port = 80 protocol = "tcp" description = "http" cidr_blocks = "0.0.0.0/0" }, ] egress_with_cidr_blocks = [ { description = "Allowing outbound traffic" to_port = 0 protocol = "-1" cidr_blocks = "0.0.0.0/0" from_port = 0 }, ]
}
Enter fullscreen mode
Exit fullscreen mode

Step 3.

This step is to deploy the ec2 instance and use the userdata for to prepare the instance with the necessary. But for this simple scenary all modules are installed by default so not is neccesary install modules in userdata process. If you need other modules, you can find in this link the modules, I hope cover other modules in the future.

userdata

<powershell> New-NetFirewallRule -DisplayName 'Allow local VPC' -Direction Inbound -LocalAddress 172.16.0.0/16 -LocalPort Any -Action Allow
# Instalar y cargar el proveedor NuGet
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
Import-PackageProvider -Name NuGet -Force
Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
#DSC module IIS
Install-Module -Name WebAdministrationDsc -RequiredVersion 4.1.0 -Confirm:$false -Force </powershell>
Enter fullscreen mode
Exit fullscreen mode

If you need install by example an module dsc different you need to add in the userdata these installation.
Something like this:

Install-Module -Name ComputerManagementDsc -RequiredVersion 9.0.0
-Force -Confirm:$false
Enter fullscreen mode
Exit fullscreen mode

Important: As best practice, always specific the module version because variables or functions can be changed between version and your configuration can be affected, additional your instance always need to have installed the module that is using your configuration.

Windows Ec2

module "ec2-instance" { source = "terraform-aws-modules/ec2-instance/aws" version = "5.6.0" name = "windows-server" ami = "ami-00d990e7e5ece7974" #Microsoft Windows Server 2022 Base instance_type = "t3.medium" subnet_id = element(var.public_subnet_ids, 0) key_name = "clustersql2" monitoring = true vpc_security_group_ids = [var.security_group_id] associate_public_ip_address = true create_iam_instance_profile = true iam_role_description = "IAM role for EC2 instance" iam_role_policies = { AmazonSSMManagedInstanceCore = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" } user_data = base64encode("${path.module}/userdata/bastion_user_data.ps1") user_data_replace_on_change = true tags = local.tags }
Enter fullscreen mode
Exit fullscreen mode

Modules by default with windows.

DSC Modules by default with windows.

Step 4.

In this step it is necessary add the script in some part for add to the instance, for this case the script will be add in the s3 bucket for in the next step the automation of systems manager can be downloaded and execute locally in ec2. it is using the s3module of registry, all information about this module in this link.

module "s3-bucket" { source = "terraform-aws-modules/s3-bucket/aws" version = "4.1.2" bucket = "s3-script-dsc-${random_string.script_suffix.result}" force_destroy = true } module "s3-bucket_object" { source = "terraform-aws-modules/s3-bucket/aws//modules/object" version = "4.1.2" bucket = module.s3-bucket.s3_bucket_id key = "dsc.ps1" file_source = "../../scripts/dsc.ps1" } resource "random_string" "script_suffix" { length = 6 special = false lower = true upper = false
}
Enter fullscreen mode
Exit fullscreen mode

DSC uses a Pull and Push mode, for this scenario it is using the push mode, with a pull mode this step would not be necessary.

Review script

This script automated the deploy of a website in IIS, create a folder with a index.html and add new content, additional stoped the default website.

configuration website { Import-DscResource -ModuleName WebAdministrationDsc -ModuleVersion 4.1.0 Node $env:COMPUTERNAME { WindowsFeature IIS { Ensure = 'Present' Name = 'Web-Server' } WindowsFeature AspNet45 { Ensure = 'Present' Name = 'Web-Asp-Net45' } WebSite DefaultSite { Ensure = 'Present' Name = 'Default Web Site' State = 'Stopped' ServerAutoStart = $false PhysicalPath = 'C:\inetpub\wwwroot' DependsOn = '[WindowsFeature]IIS' } File WebContent { Ensure = 'Present' DestinationPath = 'C:\segoja7\www\index.html' Recurse = $true Type = 'File' Contents = 'cloud people website using dsc' DependsOn = '[WindowsFeature]AspNet45' } WebSite NewWebsite { Ensure = 'Present' Name = 'segoja7' State = 'Started' ServerAutoStart = $true PhysicalPath = 'C:\segoja7\www\' DependsOn = '[File]WebContent' } }
} website -OutputPath ".\website"
Start-DscConfiguration -Path ".\website" -Wait -Force -ComputerName $env:COMPUTERNAME
Enter fullscreen mode
Exit fullscreen mode

You can use the command, for know the submodule structure

Get-DscResource -Name WindowsFeature -Syntax
Enter fullscreen mode
Exit fullscreen mode

Get-DscResource -Name WindowsFeature -Syntax

S3 dsc script

With the script in s3, The next step is create automation for run in windows ec2 instance.

Step 5.

In this step it is created an automation and a document, the document is associated in the automation and the automation is associated with an association for trigger the automations when this is created.

resource "aws_ssm_document" "dsc-automation" { name = "dsc-automation" document_type = "Automation" document_format = "YAML" content = templatefile("${path.module}/documents/automation.yaml", { instance_id = var.instance_id Assume_role = aws_iam_role.dsc-automationssm-role.arn })
} resource "aws_ssm_document" "dsc-script" { name = "dsc-script" document_type = "Command" document_format = "YAML" content = templatefile("${path.module}/documents/dsc-script.yaml", { names3bucket = var.s3_bucket_id })
} resource "aws_ssm_association" "dsc-association" { name = aws_ssm_document.dsc-automation.name association_name = aws_ssm_document.dsc-automation.name # apply_only_at_cron_interval = true parameters = { Instance = var.instance_id } } resource "aws_iam_role" "dsc-automationssm-role" { name = "wsfc-automationssm-role" assume_role_policy = jsonencode( { "Version" : "2012-10-17", "Statement" : [ { "Effect" : "Allow", "Principal" : { "Service" : [ "ssm.amazonaws.com" ] }, "Action" : "sts:AssumeRole", "Condition" : { "StringEquals" : { "aws:SourceAccount" : "${data.aws_caller_identity.current.account_id}" }, "ArnLike" : { "aws:SourceArn" : "arn:aws:ssm:*:${data.aws_caller_identity.current.account_id}:automation-execution/*" } } } ] } )
} resource "aws_iam_role_policy_attachment" "dsc-policy-attachment" { policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonSSMAutomationRole" role = aws_iam_role.dsc-automationssm-role.name
} 
Enter fullscreen mode
Exit fullscreen mode

When the automation is created with terraform, this is executed using the instance ID as target.
ssm automation

Step 6.

It is time for validate the automation, that bassically executed the document dsc-script the step 5, the document make a download of the script located in s3 bucket, later this is executed from C:\Scripts\dsc.ps1.

output

Step 7.

With the script executed it is time for check the site web using the public dns of ec2 instance.

web site using dsc

Conclusion, DSC is a great tool for obtain a state desired of a machine in windows there are many things for cover about of DSC powershell I hope in other oportunity write other blog related to this tool.

If you have any questions, please leave them in the comments!

Successful!!


Discover more from Coursity

Subscribe to get the latest posts sent to your email.

Leave a Comment

Your email address will not be published. Required fields are marked *

Discover more from Coursity

Subscribe now to keep reading and get access to the full archive.

Continue reading

Scroll to Top