Table of Contents

AWS CLI Commands

Get AWS EC2 instance information and format into a table

aws ec2 describe-instances --filters Name=tag-key,Values=Name --query "Reservations[*].Instances[*].{IP:PrivateIpAddress,Instance:InstanceId,AZ:Placement.AvailabilityZone,Name:Tags[?Key=='Name']|[0].Value}" --output table --color off
aws ec2 describe-instances --query "Reservations[*].Instances[*].{State:State.Name,IP:PrivateIpAddress,Instance:InstanceId,AZ:Placement.AvailabilityZone,Function:Tags[?Key=='Function']|[0].Value,Name:Tags[?Key=='Name']|[0].Value,Owner:Tags[?Key=='Owner']|[0].Value}" --output table --color off
aws ec2 describe-instances --filters "Name=tag:Backup,Values=Yes" --query 'Reservations[*].Instances[*].{InstanceID:InstanceId, Name:Tags[?Key==`Name`].Value|[0],Backup:Tags[?Key==`Backup`].Value|[0],Function:Tags[?Key==`Function`].Value|[0],State:State.Name}' --output table --color off
aws ec2 describe-instances --filters Name=instance-state-name,Values=running --query 'Reservations[*].Instances[*].{InstanceID:InstanceId, Name:Tags[?Key==`Name`].Value|[0],Backup:Tags[?Key==`Backup`].Value|[0],Function:Tags[?Key==`Function`].Value|[0],State:State.Name,Owner:Tags[?Key==`Owner`].Value|[0],BackupPlan:Tags[?Key==`BackupPlan`].Value|[0]}' --output table --color off

Get all AWS EC2 tags formatted into a table

import json
import subprocess
import pandas as pd

# Run AWS CLI command to get instance details in JSON format
cmd = [
    "aws", "ec2", "describe-instances",
    "--filters", "Name=instance-state-name,Values=running",
    "--query", "Reservations[*].Instances[*]",
    "--output", "json"
]

try:
    result = subprocess.run(cmd, capture_output=True, text=True, check=True)
    instances = json.loads(result.stdout)
except subprocess.CalledProcessError as e:
    print("Error executing AWS CLI command:", e)
    exit(1)

# Flatten the instance data and extract unique tag keys
instance_data = []
all_tag_keys = set()

for reservation in instances:
    for instance in reservation:
        instance_id = instance.get("InstanceId", "N/A")
        state = instance.get("State", {}).get("Name", "N/A")
        
        # Extract tag key-value pairs
        tags = {tag["Key"]: tag["Value"] for tag in instance.get("Tags", [])}
        all_tag_keys.update(tags.keys())  # Collect all unique tag keys
        
        # Store instance data
        instance_data.append({"InstanceId": instance_id, "State": state, **tags})

# Convert data to DataFrame and fill missing tags with 'N/A'
df = pd.DataFrame(instance_data).fillna("N/A")

# Sort columns: InstanceId, State first, then all tag columns alphabetically
column_order = ["InstanceId", "State"] + sorted(all_tag_keys)
df = df[column_order]

# Print as a formatted table
df.to_csv("c:\\temp\\ec2_instances_test.csv", index=False)
print("EC2 instance details saved to ec2_instances.csv")

Then run following Python command (where aws_ec2_tags.py is in the c:\temp directory)

python .\aws_ec2_tags.py

Update Tags using python

import pandas as pd
import subprocess
import json

# Load updated CSV file
csv_file = r"c:\temp\updated_ec2_tags.csv"  # Modify path if needed
df = pd.read_csv(csv_file)

# Iterate over each row and update tags in AWS
for _, row in df.iterrows():
    instance_id = row["InstanceId"]
    tags = []

    # Loop through all columns (except InstanceId and State) to create tag key-value pairs
    for col in df.columns:
        if col not in ["InstanceId", "State"]:  # Ignore non-tag columns
            tag_value = row[col]
            if pd.notna(tag_value):  # Only include non-empty values
                tags.append({"Key": col, "Value": str(tag_value)})

    if tags:
        # AWS CLI command to update tags
        cmd = [
            "aws", "ec2", "create-tags",
            "--resources", instance_id,
            "--tags", json.dumps(tags)
        ]

        try:
            result = subprocess.run(cmd, capture_output=True, text=True, check=True)
            print(f"āœ… Successfully updated tags for {instance_id}")
        except subprocess.CalledProcessError as e:
            print(f"āŒ Error updating {instance_id}: {e}")

print("\nāœ… Tag updates completed!")

Then run following Python command (where update_ec2_tags.py is in the c:\temp directory)

python .\update_ec2_tags.py

Get Route 53 Resolver Rules and format into a table

aws route53resolver list-resolver-rules --query "ResolverRules[*].{Name:Name,ID:Id,Domain:DomainName,IPs:TargetIps}" --output table --color off

Start AWS Session Manager to RDP to and EC2 Server

aws ssm start-session --target i-053e069767460be0f --document-name AWS-StartPortForwardingSession --parameters "localPortNumber=55678,portNumber=3389"

AWS Scripts

Replace EC2 IAM Instance role

# Replace 'YOUR_NEW_IAM_ROLE_NAME' with the name of the new IAM role
$NEW_ROLE_NAME = 'InstanceRoleForAmazonSSM'

# Get a list of instance IDs
$instanceIds = (aws ec2 describe-instances --query "Reservations[*].Instances[*].InstanceId" --output text)

foreach ($instanceId in $instanceIds.Split("`n")) {
    # Get the instance's IAM instance profile associations
    $profileAssociations = aws ec2 describe-iam-instance-profile-associations --filters "Name=instance-id,Values=$instanceId" --query "IamInstanceProfileAssociations[*].AssociationId" --output text

    # If there are existing associations, replace the IAM instance profile
    if ($profileAssociations -ne "") {
        $associationId = $profileAssociations.Trim()
        aws ec2 replace-iam-instance-profile-association --iam-instance-profile Name=$NEW_ROLE_NAME --association-id $associationId
        Write-Host "Replaced IAM Role for instance $instanceId"
    } else {
        # If no association is found, associate the new IAM role directly
        aws ec2 associate-iam-instance-profile --instance-id $instanceId --iam-instance-profile Name=$NEW_ROLE_NAME
        Write-Host "Associated IAM Role for instance $instanceId"
    }

}

Amazon Linux 2023 Deploy with UserData installation

---
AWSTemplateFormatVersion: '2010-09-09'
Description: Launch a Linux instance and install Crowdstrike and
attach IAM role to EC2 instance for CS installation
  Version 3.4
Metadata:
  Stack:
    Value: 0
  VersionDate:
    Value: 20190725
  Identifier:
    Value: main
  Input:
    Description: Input of all required parameters in the stack
  Output:
    Description: N/A
  AWS::CloudFormation::Interface:
    ParameterGroups:
    - Label:
        default: EC2 Instance Configuration
      Parameters:
      - AccountOU
      - VPC
      - AMI
      - InstanceType
      - DiskSize
      - DiskType
      - Subnet
      - ExistingSecurityGroupID
      - KeyPair      
    - Label:
        default: Tag Information
      Parameters:
      - TagName
      - TagLinuxServerName
      - TagBackup
      - TagPatched
      - TagOwner
      - TagFunction
      - TagOS
      - TagOSVersion
    ParameterLabels:
      AccountOU:
        default: Account OU
      VPC:
        default: VPC ID
      AMI:
        default: Amazon Machine Image
      InstanceType:
        default: Instance Type
      DiskSize:
        default: System Partition Size
      DiskType:
        default: System Partition Type
      Subnet:
        default: Instance Subnet
      ExistingSecurityGroupID:
        default: Subnet Security Group
      KeyPair:
        default: Access Key Pair      
      TagName:
        default: Name
      TagLinuxServerName:
        default: Linux Server Name
      TagBackup:
        default: Backup
      TagOwner:
        default: Owner
      TagPatched:
        default: Patched
      TagFunction:
        default: Function
      TagOS:
        default: Operating System
      TagOSVersion:
        default: Operating System Version

Parameters:
  InstanceProfileName:
    Description: IAM instance profile name to attach to the EC2 instance
    Type: String
    AllowedValues:
      - s3-bucket-role-cs
    Default: s3-bucket-role-cs
  VPC:
    Type: AWS::EC2::VPC::Id
    Description: Select the VPC to place this instance
  AMI:
    Type: String
    Description: Select a Linux Amazon Machine Image for this Instance
    AllowedValues:
    - Amazonlinux2023
    - Amazonlinux2
  InstanceType:
    Type: String
    Description: Select the Instance Type
    Default: t2.micro
    AllowedValues:
    - t2.micro
    - t2.small
    - t2.medium
    - m1.small
    - m1.medium
    - m1.large
    - m1.xlarge
    - m2.xlarge
    - m2.2xlarge
    - m2.4xlarge
    - m3.medium
    - m3.large
    - m3.xlarge
    - m3.2xlarge
    - m5.xlarge
    - c1.medium
    - c1.xlarge
    - c3.large
    - c3.xlarge
    - c3.2xlarge
    - c3.4xlarge
    - c3.8xlarge
    - c4.large
    - c4.xlarge
    - c4.2xlarge
    - c4.4xlarge
    - c4.8xlarge
    - g2.2xlarge
    - r3.large
    - r3.xlarge
    - r3.2xlarge
    - r3.4xlarge
    - r3.8xlarge
    - i2.xlarge
    - i2.2xlarge
    - i2.4xlarge
    - i2.8xlarge
    - d2.xlarge
    - d2.2xlarge
    - d2.4xlarge
    - d2.8xlarge
    - hi1.4xlarge
    - hs1.8xlarge
    - cr1.8xlarge
    - cc2.8xlarge
    - cg1.4xlarge
    ConstraintDescription: Must be a valid EC2 instance type.
  Subnet:
    Type: AWS::EC2::Subnet::Id
    Description: Select a Subnet to place this instance
  ExistingSecurityGroupID:
    Type: AWS::EC2::SecurityGroup::Id
    Description: Select a Security Group to place this instance
  KeyPair:
    Type: AWS::EC2::KeyPair::KeyName
    Description: Select a KeyPair for this EC2 Instance
  TagName:
    Description: Enter the Name of the EC2 instance
    Type: String
    Default: Name
  TagLinuxServerName:
    Description: Enter Linux Server Name
    Type: String
    Default: Linux
  TagBackup:
    Description: Is the Instance being backed up (Yes or No)
    Type: String
    Default: Yes
  TagOwner:
    Description: Enter the Team/Owner of this Instance (eg. Energy Services, Smart Buildings)
    Type: String
    Default: Team/Owner Name?
  TagFunction:
    Description: Enter the function of the EC2 instance (Monitoring Server)
    Type: String
    Default: Monitoring Server
  TagOS:
    Description: Enter the Operating System of the EC2 instance
    Type: String
    Default: Linux
  TagOSVersion:
    Description: Enter the version of Operating System
    Type: String
    Default: Amazon Linux 2023
  TagPatched:
    Description: Is the instance being Patched
    Type: String
    Default: Yes
Mappings:
  RegionAMIMap:
    eu-west-1:
      Amazonlinux2023: ami-0e309a5f3a6dd97ea
      Amazonlinux2: ami-0a1f6cc8163bdcc75
    eu-west-2:
      Amazonlinux2023: ami-0cf6f2b898ac0b337
      Amazonlinux2: ami-06d0baf788edae448
Resources:
  myEC2InstanceSSM:
    Type: AWS::EC2::Instance
    Properties:
      IamInstanceProfile:
        Ref: InstanceProfileName
      UserData:
        Fn::Base64:
          !Sub |
            #!/bin/bash
            sudo mkdir /mount
            sudo mkdir ~/.aws
            cat <<'EOF' >> ~/.aws/config
            [profile s3-bucket-role-cs]
            role_arn = arn:aws:iam::877968844667:role/s3-bucket-role-CS
            credential_source = Ec2InstanceMetadata
            EOF
            sudo aws s3 cp s3://crowdstrikeinstalls/falcon-sensor-7.03.0-15805.amzn2023.x86_64.rpm /mount --profile s3-bucket-role-cs
            sudo yum -y install ./mount/falcon-sensor-7.03.0-15805.amzn2023.x86_64.rpm
            sudo /opt/CrowdStrike/falconctl -s --cid=C78902F9C85144558CFCCBC3A21AF3C9-75 --tags=LocalIT
            sudo service falcon-sensor start
            sudo systemctl start falcon-sensor
      KeyName:
        Ref: KeyPair
      ImageId: !FindInMap
        - RegionAMIMap
        - Ref: 'AWS::Region'
        - Ref: AMI
      InstanceType:
        Ref: InstanceType
      Tags:
      - Key: Name
        Value: !Ref TagName
      - Key: Linux Server Name
        Value: !Ref TagLinuxServerName
      - Key: Backup
        Value: !Ref TagBackup
      - Key: Patched
        Value: !Ref TagPatched
      - Key: Owner
        Value: !Ref TagOwner
      - Key: Function
        Value: !Ref TagFunction
      - Key: OS
        Value: !Ref TagOS
      - Key: OS Version
        Value: !Ref TagOSVersion
      SubnetId:
        Ref: Subnet
      SecurityGroupIds:
      - Ref: ExistingSecurityGroupID

Windows EC2 Deploy with UserData installation

---
AWSTemplateFormatVersion: '2010-09-09'
Description: Launch a Windows instance and install Crowdstrike and
attach IAM role to EC2 instance for CS installation
  Version 3.4
Metadata:
  Stack:
    Value: 0
  VersionDate:
    Value: 20190725
  Identifier:
    Value: main
  Input:
    Description: Input of all required parameters in the stack
  Output:
    Description: N/A
  AWS::CloudFormation::Interface:
    ParameterGroups:
    - Label:
        default: EC2 Instance Configuration
      Parameters:
      - AccountOU
      - VPC
      - AMI
      - InstanceType
      - DiskSize
      - DiskType
      - Subnet
      - ExistingSecurityGroupID
      - KeyPair      
    - Label:
        default: Tag Information
      Parameters:
      - TagName
      - TagWindowsServerName
      - TagBackup
      - TagPatched
      - TagOwner
      - TagFunction
      - TagOS
      - TagOSVersion
    ParameterLabels:
      AccountOU:
        default: Account OU
      VPC:
        default: VPC ID
      AMI:
        default: Amazon Machine Image
      InstanceType:
        default: Instance Type
      DiskSize:
        default: System Partition Size
      DiskType:
        default: System Partition Type
      Subnet:
        default: Instance Subnet
      ExistingSecurityGroupID:
        default: Subnet Security Group
      KeyPair:
        default: Access Key Pair      
      TagName:
        default: Name
      TagWindowsServerName:
        default: Windows Server Name
      TagBackup:
        default: Backup
      TagOwner:
        default: Owner
      TagPatched:
        default: Patched
      TagFunction:
        default: Function
      TagOS:
        default: Operating System
      TagOSVersion:
        default: Operating System Version

Parameters:
  InstanceProfileName:
    Description: IAM instance profile name to attach to the EC2 instance
    Type: String
    AllowedValues:
      - s3-bucket-role-cs
      - AmazonSSMRoleForInstancesQuickSetup
      - InstanceRoleForAmazonSSM
      - engieuk-hq-inf-services-prod.sysman
    Default: s3-bucket-role-cs
  VPC:
    Type: AWS::EC2::VPC::Id
    Description: Select the VPC to place this instance
  AMI:
    Type: String
    Description: Select a Windows Amazon Machine Image for this Instance
    AllowedValues:
    - Win2019Base
    - Win2016Base  
  InstanceType:
    Type: String
    Description: Select the Instance Type
    Default: t2.micro
    AllowedValues:
    - t2.micro
    - t2.small
    - t2.medium
    - t3.micro
    - t3.small
    - t3.medium
    - m1.small
    - m1.medium
    - m1.large
    - m1.xlarge
    - m2.xlarge
    - m2.2xlarge
    - m2.4xlarge
    - m3.medium
    - m3.large
    - m3.xlarge
    - m3.2xlarge
    - m5.xlarge
    - c1.medium
    - c1.xlarge
    - c3.large
    - c3.xlarge
    - c3.2xlarge
    - c3.4xlarge
    - c3.8xlarge
    - c4.large
    - c4.xlarge
    - c4.2xlarge
    - c4.4xlarge
    - c4.8xlarge
    - g2.2xlarge
    - r3.large
    - r3.xlarge
    - r3.2xlarge
    - r3.4xlarge
    - r3.8xlarge
    - i2.xlarge
    - i2.2xlarge
    - i2.4xlarge
    - i2.8xlarge
    - d2.xlarge
    - d2.2xlarge
    - d2.4xlarge
    - d2.8xlarge
    - hi1.4xlarge
    - hs1.8xlarge
    - cr1.8xlarge
    - cc2.8xlarge
    - cg1.4xlarge
    ConstraintDescription: Must be a valid EC2 instance type.
  DiskSize:
    Description: Instance Primary Disk Size (Gb)
    Type: Number
    Default : 30
  DiskType:
    Description: Select a Volume type (gp2=General Purpose SSD, io1=Provisioned IOPS SSD, st1=Throughput Optimized HDD, sc1=Cold HDD)
    AllowedValues:
    - gp2
    - io1
    - st1
    - sc1
    Type: String
    Default: gp2
  Subnet:
    Type: AWS::EC2::Subnet::Id
    Description: Select a Subnet to place this instance
  ExistingSecurityGroupID:
    Type: AWS::EC2::SecurityGroup::Id
    Description: Select a Security Group to place this instance
  KeyPair:
    Type: AWS::EC2::KeyPair::KeyName
    Description: Select a KeyPair for this EC2 Instance
  TagName:
    Description: Enter the Name of the EC2 instance
    Type: String
    Default: Name
  TagWindowsServerName:
    Description: Enter Windows Server Name
    Type: String
    Default: Windows
  TagBackup:
    Description: Is the Instance being backed up (Yes or No)
    Type: String
    Default: Yes
  TagOwner:
    Description: Enter the Team/Owner of this Instance (eg. Energy Services, Smart Buildings)
    Type: String
    Default: Team/Owner Name?
  TagFunction:
    Description: Enter the function of the EC2 instance (Monitoring Server)
    Type: String
    Default: Monitoring Server
  TagOS:
    Description: Enter the Operating System of the EC2 instance
    Type: String
    Default: Windows
  TagOSVersion:
    Description: Enter the version of Operating System
    Type: String
    Default: Server 2019
  TagPatched:
    Description: Is the instance being Patched
    Type: String
    Default: Yes
Mappings:
  RegionAMIMap:
    eu-west-1:
      Win2019Base: ami-01c8584ce4ac83765
      Win2016Base: ami-0782e691e989998df
    eu-west-2:
      Win2019Base: ami-08ce0f1cd8b30bf4e
      Win2016Base: ami-02a9c04e461574620
Resources:
  myEC2InstanceSSM:
    Type: AWS::EC2::Instance
    Properties:
      IamInstanceProfile:
        Ref: InstanceProfileName
      BlockDeviceMappings:
        -
          DeviceName: "/dev/sda1"
          Ebs:
            Encrypted: True
            VolumeSize: !Ref DiskSize
            VolumeType: !Ref DiskType
      UserData:
        Fn::Base64: |
          <powershell>
          # Download and install AWS CLI silently
          $awsCliInstaller = "AWSCLIV2.msi"
          Invoke-WebRequest -Uri "https://awscli.amazonaws.com/$($awsCliInstaller)" -OutFile $awsCliInstaller
          Start-Process -Wait -FilePath msiexec -ArgumentList '/i', $awsCliInstaller, '/quiet', '/norestart'
          $env:Path += ";C:\Program Files\Amazon\AWSCLIV2\"
          # PowerShell script content here
          # IAM role details
          $roleArn = "arn:aws:iam::877968844667:role/s3-bucket-role-CS"
          # Assume the role using AWS CLI
          $assumeRoleCommand = "aws sts assume-role --role-arn $roleArn --role-session-name AssumedRoleSession --output json"
          $assumeRoleOutput = Invoke-Expression -Command $assumeRoleCommand | ConvertFrom-Json
          # Extract temporary credentials
          $accessKeyId = $assumeRoleOutput.Credentials.AccessKeyId
          $secretAccessKey = $assumeRoleOutput.Credentials.SecretAccessKey
          $sessionToken = $assumeRoleOutput.Credentials.SessionToken
          # Set AWS credentials with the assumed role
          aws configure set aws_access_key_id $accessKeyId
          aws configure set aws_secret_access_key $secretAccessKey
          aws configure set aws_session_token $sessionToken
          # S3 bucket details
          $bucketName = "crowdstrikeinstalls"
          $key = "WindowsSensor.LionLanner.exe" # Specify the source object (file) key in the bucket
          # Local file path
          mkdir c:\temp
          $localFilePath = "C:\temp"
          # Download the file from S3 bucket
          aws s3 cp s3://$bucketName/$key $localFilePath
          # Signal the completion of the installation
          cfn-signal -e 0 --stack ${AWS::StackName} --resource EC2Instance
          # Execute the application installer (replace with the actual installer command)
          Start-Process -Wait -FilePath "$localFilePath\WindowsSensor.LionLanner.exe" "/install /quiet /norestart CID=C78902F9C85144558CFCCBC3A21AF3C9-75 --tags=LocalIT"
          </powershell>
      KeyName:
        Ref: KeyPair
      ImageId: !FindInMap
        - RegionAMIMap
        - Ref: 'AWS::Region'
        - Ref: AMI
      InstanceType:
        Ref: InstanceType
      Tags:
      - Key: Name
        Value: !Ref TagName
      - Key: Windows Server Name
        Value: !Ref TagWindowsServerName
      - Key: Backup
        Value: !Ref TagBackup
      - Key: Patched
        Value: !Ref TagPatched
      - Key: Owner
        Value: !Ref TagOwner
      - Key: Function
        Value: !Ref TagFunction
      - Key: OS
        Value: !Ref TagOS
      - Key: OS Version
        Value: !Ref TagOSVersion
      SubnetId:
        Ref: Subnet
      SecurityGroupIds:
      - Ref: ExistingSecurityGroupID

Route 53 CLI Commands

To use Route53 cli download from:

https://github.com/barnybug/cli53/releases/tag/0.8.18 (For Windows, Linux and Mac)

Then to list Route53 domains do:

cli53-windows-amd64.exe list

To export Route53 Domains do:

cli53-windows-amd64.exe export equans.co.uk

To export Route53 Domains to a file do:

cli53-windows-amd64.exe export equans.co.uk> c:\temp\equans.co.uk.txt

IAM Policies

IAM Policy that enables SSM Port Forwarding Session so that session manager can be used to remote to EC2 instances:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ssm:*"
            ],
            "Resource": [
                "arn:aws:ec2:eu-west-3:684897324199:instance/i-0a88225b9c1fa3189",
                "arn:aws:ec2:eu-west-3:684897324199:instance/i-016a6934b9a373362",
                "arn:aws:ssm:eu-west-3::document/AWS-StartPortForwardingSession"
                ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:*"
            ],
            "Resource": [
                "arn:aws:ec2:eu-west-3:684897324199:instance/i-0a88225b9c1fa3189",
                "arn:aws:ec2:eu-west-3:684897324199:instance/i-016a6934b9a373362"
                ]
            }
    ]
}