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, GCP and OCI 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
- Auto Commission Token
Configuring Initial Settings and Services for a Virtual Canary
Initial settings is a json block that has been base64 encoded. If you were to configure the Canary to boot with the FTP service enabled.
You would need to convert the following json:
{"ftp.banner": "Test FTP banner", "ftp.enabled": True, "ftp.port": 21}Using Linux/MacOS
- echo -n '{"ftp.banner": "Test FTP banner", "ftp.enabled": true, "ftp.port": 21}' | base64
Using Windows
- [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes('{"ftp.banner": "Test FTP banner", "ftp.enabled": true, "ftp.port": 21}'))
into base64:
eyJmdHAuYmFubmVyIjogIlRlc3QgRlRQIGJhbm5lciIsICJmdHAuZW5hYmxlZCI6IFRydWUsICJmdHAucG9ydCI6IDIxfQ==The VMware birds can also set:
- Network IP and netmask
- DHCP enabled or disabled
AWS, GCP and OCI Canaries
AWS, GCP and OCI 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-initwhere 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.yamlLaunching 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.yamlLaunching a new OCI Canary with user-data
User-data can be defined under the Advanced options section of the OCI new VM UI.
For example:
Azure Canaries
Azure Canaries are configure using a json formatted user-data 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.jsonHyper-V Canaries
Hyper-V Canaries require the whole file to be a base64 encoded string
eyJhdXRvY29tbWlzc2lvbl90b2tlbiI6ICI4N2I1NDMyMzZjNTA1NDcwNjIxOCIsICJpbml0aWFsX3Byb2ZpbGUiOiAib3JhY2xlLWxpbnV4LTgiLCAiaW5pdGlhbF9zZXR0aW5ncyI6ICJleUptZEhBdVltRnVibVZ5SWpvZ0lsUmxjM1FnUmxSUUlHSmhibTVsY2lJc0lDSm1kSEF1Wlc1aFlteGxaQ0k2SUhSeWRXVXNJQ0ptZEhBdWNHOXlkQ0k2SURJeGZRPT0iLCAibmV0d29yayI6IHsibmFtZSI6ICJ0ZXN0LWNsb3VkLWluaXQiLCAiY3VzdG9tX2RucyI6IHRydWUsICJkbnMxIjogIjEuMS4xLjEiLCAiZG5zMiI6ICI4LjguOC44In19with 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'
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