Overview
Want to deploy a bunch of Canaries and have them pre-configured during the deployment? We can do this using the equivalent cloud-init for each of our cloud and virtual platforms:
- AWS and GCP using the user-data of the instance via a cloud-init yaml file. (jump)
- Azure using the json user-data file of the instance via the instance metadata api. (jump)
- Hyper-V using a base64 encoded key-value pair via the Hyper-V VMbus. (jump)
- VMware using Advanced Configuration Parameters available on vSphere and ESXi. (jump)
What can we set during bootstrapping?
All of the cloud and virtual platforms can set:
- Initial profile
- Initial settings
- Network DNS settings
- Network device name
The VMware birds can also set:
- Network IP and netmask
- DHCP enabled or disabled
AWS and GCP Canaries
Both AWS and GCP make use of cloud init directives and require the '#cloud-config' line at the top of the file to work correctly.
#cloud-config canary_cloud_init: autocommission_token: 87b543236c5054706218 initial_profile: oracle-linux-8 initial_settings: eyJmdHAuYmFubmVyIjogIlRlc3QgRlRQIGJhbm5lciIsICJmdHAuZW5hYmxlZCI6IHRydWUsICJmdHAucG9ydCI6IDIxfQ== network: custom_dns: true dns1: 1.1.1.1 dns2: 8.8.8.8 name: test-cloud-init
where the initial settings is a base64 encoded string for the settings json block defined as
{ "ftp.banner": "Test FTP banner", "ftp.enabled": True, "ftp.port": 21 }
Launching a new AWS canary with user-data
Using the AWS cli the user-data can easily be added on by using '--user-data' parameter
For example:
aws ec2 run-instances --image-id <ami-id> --subnet-id <subnet-id> --security-group-ids <security-group-id> --region eu-west-1 --instance-type t3.micro --user-data file://canary_cloud_init.yaml
Launching a new GCP canary with user-data
Using the GCP cli the user-data can be configure using the '--metadata-from-file' parameter.
For example:
gcloud compute instances create DevOpsStaging-1A --machine-type=e2-micro --image=<image-name> --zone=europe-west4-a --network-interface subnet=<subnet-name> --metadata-from-file user-data=canary_cloud_init.yaml
Azure Canaries
Azure canaries are configure using a json formatted user-date file:
{ "autocommission_token": "87b543236c5054706218", "initial_profile": "oracle-linux-8", "initial_settings": "eyJmdHAuYmFubmVyIjogIlRlc3QgRlRQIGJhbm5lciIsICJmdHAuZW5hYmxlZCI6IHRydWUsICJmdHAucG9ydCI6IDIxfQ==", "network": { "name": "test-cloud-init", "custom_dns": true, "dns1": "1.1.1.1", "dns2": "8.8.8.8" } }
where the initial settings is a base64 encoded string for the settings json block defined as
{ "ftp.banner": "Test FTP banner", "ftp.enabled": True, "ftp.port": 21 }
Launching a new Azure canary with user-data
Using the Azure cli the user-data can be configure using the '--user-data' parameter.
For example:
az vm create --name DevOpsStaging-1A --resource-group <resource-group-name> --image <image-name> --vnet-name <vmnet-name> --nsg <network-security-group-name> --subnet <subnet-name> --user-data canary_cloud_init.json
Hyper-V Canaries
Hyper-V canaries require the whole file to be a base64 encoded string
eyJhdXRvY29tbWlzc2lvbl90b2tlbiI6ICI4N2I1NDMyMzZjNTA1NDcwNjIxOCIsICJpbml0aWFsX3Byb2ZpbGUiOiAib3JhY2xlLWxpbnV4LTgiLCAiaW5pdGlhbF9zZXR0aW5ncyI6ICJleUptZEhBdVltRnVibVZ5SWpvZ0lsUmxjM1FnUmxSUUlHSmhibTVsY2lJc0lDSm1kSEF1Wlc1aFlteGxaQ0k2SUhSeWRXVXNJQ0ptZEhBdWNHOXlkQ0k2SURJeGZRPT0iLCAibmV0d29yayI6IHsibmFtZSI6ICJ0ZXN0LWNsb3VkLWluaXQiLCAiY3VzdG9tX2RucyI6IHRydWUsICJkbnMxIjogIjEuMS4xLjEiLCAiZG5zMiI6ICI4LjguOC44In19
with the config being defined as
{ "autocommission_token": "87b543236c5054706218", "initial_profile": "oracle-linux-8", "initial_settings": "eyJmdHAuYmFubmVyIjogIlRlc3QgRlRQIGJhbm5lciIsICJmdHAuZW5hYmxlZCI6IHRydWUsICJmdHAucG9ydCI6IDIxfQ==", "network": { "name": "test-cloud-init", "custom_dns": true, "dns1": "1.1.1.1", "dns2": "8.8.8.8" } }
where the initial settings is a base64 encoded string for the settings json block defined as
{ "ftp.banner": "Test FTP banner", "ftp.enabled": True, "ftp.port": 21 }
Launching a new Hyper-V canary with user-data
The Hyper-V Canary expects the key of the KVP to be 'UserData'
Note: Do not power on your Canary before configuring the KVP parameters.
The KVP information can be set using a powershell script for example:
# Define variables for the VM name, key, and data $vmName = "DevOpsStaging-1A" $keyName = "UserData" $keyData = "eyJhdXRvY29tbWlzc2lvbl90b2tlbiI6ICI4N2I1NDMyMzZjNTA1NDcwNjIxOCIsICJpbml0aWFsX3Byb2ZpbGUiOiAib3JhY2xlLWxpbnV4LTgiLCAiaW5pdGlhbF9zZXR0aW5ncyI6ICJleUptZEhBdVltRnVibVZ5SWpvZ0lsUmxjM1FnUmxSUUlHSmhibTVsY2lJc0lDSm1kSEF1Wlc1aFlteGxaQ0k2SUhSeWRXVXNJQ0ptZEhBdWNHOXlkQ0k2SURJeGZRPT0iLCAibmV0d29yayI6IHsibmFtZSI6ICJ0ZXN0LWNsb3VkLWluaXQiLCAiY3VzdG9tX2RucyI6IHRydWUsICJkbnMxIjogIjEuMS4xLjEiLCAiZG5zMiI6ICI4LjguOC44In19" # Get the Virtual System Management Service $VmMgmt = Get-WmiObject -Namespace root\virtualization\v2 -Class Msvm_VirtualSystemManagementService # Get the VM object by its name $vm = Get-WmiObject -Namespace root\virtualization\v2 -Class Msvm_ComputerSystem -Filter "ElementName='$vmName'" # Create an instance of the KVP Exchange Data Item $kvpDataItem = ([WMIClass][String]::Format("\\{0}\{1}:{2}", ` $VmMgmt.ClassPath.Server, ` $VmMgmt.ClassPath.NamespacePath, ` "Msvm_KvpExchangeDataItem")).CreateInstance() # Set the key-value pair $kvpDataItem.Name = $keyName $kvpDataItem.Data = $keyData $kvpDataItem.Source = 0 # Source 0 indicates that the data is from the host to the guest # Add the KVP to the VM $VmMgmt.AddKvpItems($vm, $kvpDataItem.PSBase.GetText(1)) # Output the data being set Write-Output "Key Name: $($kvpDataItem.Name)" Write-Output "Key Data: $($kvpDataItem.Data)"
VMware Canaries
See the dedicated article for