From 78b92c12870e2c9ab9c39eb1b050d00c809b8280 Mon Sep 17 00:00:00 2001 From: Gerben Kleijn Date: Fri, 6 Feb 2026 14:43:30 -0700 Subject: [PATCH 1/6] create challenges for Azure --- .gitignore | 12 +- aws/terraform.tfvars.example | 2 +- .../challenges/Cloud Jumping/cloudjumping.tf | 264 ++++++++++++++ .../data/container/.~lock.important.odt# | 1 + .../data/container/important.odt | Bin 0 -> 15732 bytes .../Cloud Jumping/data/container/urgent.pdf | Bin 0 -> 11765 bytes azure/challenges/Cloud Jumping/data/flag.txt | 1 + .../data/jump-host-template.json | 339 ++++++++++++++++++ azure/challenges/Cloud Jumping/variables.tf | 15 + .../image-inationcontinuation.tf | 204 +++++++++++ .../Image-ination Continuation/variables.tf | 15 + .../Image-ination Station/data/Dockerfile | 7 + .../image-inationstation.tf | 45 +++ .../Image-ination Station/variables.tf | 19 + .../Not so secret/data/cinderella.txt | 1 + .../Not so secret/data/contacts.csv | 51 +++ .../Not so secret/data/employeePolicy.txt | 1 + .../Not so secret/data/employees.csv | 51 +++ azure/challenges/Not so secret/data/flag.txt | 1 + .../data/jack_and_the_beanstalk.txt | 1 + .../data/little_red_riding_hood.txt | 1 + .../Not so secret/data/snow_white.txt | 1 + azure/challenges/Not so secret/notsosecret.tf | 203 +++++++++++ azure/challenges/Not so secret/variables.tf | 15 + azure/challenges/Permisery/permisery.tf | 226 ++++++++++++ azure/challenges/Permisery/variables.tf | 15 + azure/challenges/VM I Am/variables.tf | 15 + azure/challenges/VM I Am/vmiam.tf | 201 +++++++++++ azure/main.tf | 148 ++++++++ azure/terraform.tfvars.example | 45 +++ azure/variables.tf | 13 + 31 files changed, 1911 insertions(+), 2 deletions(-) create mode 100644 azure/challenges/Cloud Jumping/cloudjumping.tf create mode 100644 azure/challenges/Cloud Jumping/data/container/.~lock.important.odt# create mode 100755 azure/challenges/Cloud Jumping/data/container/important.odt create mode 100755 azure/challenges/Cloud Jumping/data/container/urgent.pdf create mode 100644 azure/challenges/Cloud Jumping/data/flag.txt create mode 100644 azure/challenges/Cloud Jumping/data/jump-host-template.json create mode 100644 azure/challenges/Cloud Jumping/variables.tf create mode 100644 azure/challenges/Image-ination Continuation/image-inationcontinuation.tf create mode 100644 azure/challenges/Image-ination Continuation/variables.tf create mode 100644 azure/challenges/Image-ination Station/data/Dockerfile create mode 100644 azure/challenges/Image-ination Station/image-inationstation.tf create mode 100644 azure/challenges/Image-ination Station/variables.tf create mode 100755 azure/challenges/Not so secret/data/cinderella.txt create mode 100755 azure/challenges/Not so secret/data/contacts.csv create mode 100644 azure/challenges/Not so secret/data/employeePolicy.txt create mode 100755 azure/challenges/Not so secret/data/employees.csv create mode 100644 azure/challenges/Not so secret/data/flag.txt create mode 100755 azure/challenges/Not so secret/data/jack_and_the_beanstalk.txt create mode 100755 azure/challenges/Not so secret/data/little_red_riding_hood.txt create mode 100755 azure/challenges/Not so secret/data/snow_white.txt create mode 100644 azure/challenges/Not so secret/notsosecret.tf create mode 100644 azure/challenges/Not so secret/variables.tf create mode 100644 azure/challenges/Permisery/permisery.tf create mode 100644 azure/challenges/Permisery/variables.tf create mode 100644 azure/challenges/VM I Am/variables.tf create mode 100644 azure/challenges/VM I Am/vmiam.tf create mode 100644 azure/main.tf create mode 100644 azure/terraform.tfvars.example create mode 100644 azure/variables.tf diff --git a/.gitignore b/.gitignore index 57207e7..1560dc9 100644 --- a/.gitignore +++ b/.gitignore @@ -43,5 +43,15 @@ response.json .ctf config +# challenge specific files +azure/challenges/Cloud Jumping/data/container/tmp.txt +azure/challenges/Image-ination Continuation/data/logicapp_identity.txt +azure/challenges/Image-ination Station/data/sp-creds.json +azure/challenges/Not so secret/data/assets.csv +azure/challenges/Permisery/data/app.py +azure/challenges/Permisery/data/requirements.txt +azure/challenges/Permisery/zip/ - +# other azure files +azure/credentials.txt +azure/terraform.tfvars diff --git a/aws/terraform.tfvars.example b/aws/terraform.tfvars.example index 0efeb28..fa45b7f 100755 --- a/aws/terraform.tfvars.example +++ b/aws/terraform.tfvars.example @@ -36,7 +36,7 @@ aws_local_profile = "default" # Specify your IP address here to bre used with security groups (so that "public" challenges are only accessible to you) # If you don't specify anything, the default behavior is to use https://ifconfig.me to pull your IP address -#user_ip = "[YOUR_IP_ADDRESS]" +user_ip = "72.217.56.164" ###################### diff --git a/azure/challenges/Cloud Jumping/cloudjumping.tf b/azure/challenges/Cloud Jumping/cloudjumping.tf new file mode 100644 index 0000000..5cdfbd1 --- /dev/null +++ b/azure/challenges/Cloud Jumping/cloudjumping.tf @@ -0,0 +1,264 @@ +data "azuread_domains" "domain" { + only_initial = true +} + +data "azurerm_subscription" "current" {} + +data "http" "current_ip" { + url = "https://icanhazip.com" +} + +locals { + user_ip = chomp(data.http.current_ip.response_body) +} + +resource "random_password" "read_user_password" { + length = 16 + special = true +} + +resource "local_file" "credentials" { + filename = "${path.module}/data/container/tmp.txt" + content = <<-EOF + "az.reader@${data.azuread_domains.domain.domains.0.domain_name}" + ${random_password.read_user_password.result} + EOF +} + +resource "azuread_user" "read_user" { + user_principal_name = "az.reader@${data.azuread_domains.domain.domains.0.domain_name}" + display_name = "Azure Reader" + password = random_password.read_user_password.result +} + +resource "azuread_directory_role_assignment" "global_reader_assigment" { + role_id = "f2ef992c-3afb-46b9-b7cf-a126ee74c451" + principal_object_id = azuread_user.read_user.object_id +} + +resource "azurerm_role_assignment" "subscription_reader_access" { + scope = data.azurerm_subscription.current.id + role_definition_name = "Reader" + principal_id = azuread_user.read_user.object_id +} + +/*---------------------------------------------*/ + + +################################################# +// Create publicly accessible blob container +################################################# + +resource "random_id" "challenge_instance_id" { + byte_length = 4 +} + +locals { + uploaded_files = fileset("${path.module}/data/container", "*") +} + +resource "azurerm_storage_account" "sa" { + name = "cloudjumping${random_id.challenge_instance_id.hex}" + resource_group_name = var.resource_group_name + location = var.resource_group_location + account_tier = "Standard" + account_replication_type = "LRS" + allow_nested_items_to_be_public = true + + network_rules { + default_action = "Deny" + bypass = ["AzureServices"] + ip_rules = [ + local.user_ip + ] + } +} + +resource "azurerm_storage_container" "container" { + name = "files" + storage_account_id = azurerm_storage_account.sa.id + container_access_type = "container" +} + +resource "azurerm_storage_blob" "blob" { + for_each = { for file in local.uploaded_files : file => file } + name = each.value + storage_account_name = azurerm_storage_account.sa.name + storage_container_name = azurerm_storage_container.container.name + type = "Block" + source = "${path.module}/data/container/${each.value}" +} + +resource "azurerm_role_assignment" "user_reader" { + scope = var.resource_group_id + role_definition_name = "Reader" + principal_id = var.player_object_id +} + +/*---------------------------------------------*/ + + +################################################# +// Create a managed identity +################################################# + +resource "azurerm_user_assigned_identity" "contributor_managed_identity" { + name = "contributor-managed-identity" + resource_group_name = var.resource_group_name + location = var.resource_group_location +} + +resource "azurerm_role_assignment" "contributor" { + scope = data.azurerm_subscription.current.id + role_definition_name = "Contributor" + principal_id = azurerm_user_assigned_identity.contributor_managed_identity.principal_id +} + +/*---------------------------------------------*/ + + +################################################# +// Create Linux VM with a managed identity +################################################# + +data "local_file" "jump_host_template" { + filename = "${path.module}/data/jump-host-template.json" +} + +resource "random_password" "jump_host_user_password" { + length = 16 + special = true +} + +resource "azurerm_resource_group_template_deployment" "jump_host_vm" { + name = "jump_host" + resource_group_name = var.resource_group_name + deployment_mode = "Incremental" + template_content = data.local_file.jump_host_template.content + parameters_content = jsonencode({ + adminPasswordOrKey = { + value = random_password.jump_host_user_password.result + } + }) + + depends_on = [ + azurerm_role_assignment.contributor + ] +} + +/*---------------------------------------------*/ + + +################################################# +// Create Linux VM with the flag +################################################# + +resource "random_password" "linux_vm_user_password" { + length = 16 + special = true +} + +resource "azurerm_virtual_network" "linux_vm_vnet" { + name = "production-vnet" + address_space = ["10.2.0.0/16"] + location = var.resource_group_location + resource_group_name = var.resource_group_name +} + +resource "azurerm_subnet" "linux_vm_subnet" { + name = "production-subnet" + resource_group_name = var.resource_group_name + virtual_network_name = azurerm_virtual_network.linux_vm_vnet.name + address_prefixes = ["10.2.1.0/24"] +} + +resource "azurerm_public_ip" "linux_vm_ip" { + name = "production-public-ip" + location = var.resource_group_location + resource_group_name = var.resource_group_name + allocation_method = "Static" +} + +resource "azurerm_network_interface" "linux_vm_nic" { + name = "production-vm-nic" + location = var.resource_group_location + resource_group_name = var.resource_group_name + + ip_configuration { + name = "internal" + subnet_id = azurerm_subnet.linux_vm_subnet.id + private_ip_address_allocation = "Dynamic" + public_ip_address_id = azurerm_public_ip.linux_vm_ip.id + } + + depends_on = [ + azurerm_public_ip.linux_vm_ip + ] +} + +resource "azurerm_network_security_group" "ctf_nsg" { + name = "ctf-nsg" + location = var.resource_group_location + resource_group_name = var.resource_group_name + + security_rule { + name = "Allow-SSH" + priority = 1001 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_range = "22" + source_address_prefix = local.user_ip + destination_address_prefix = "*" + } +} + +resource "azurerm_subnet_network_security_group_association" "ctf_subnet_assoc" { + subnet_id = azurerm_subnet.linux_vm_subnet.id + network_security_group_id = azurerm_network_security_group.ctf_nsg.id +} + +resource "azurerm_linux_virtual_machine" "linux_vm" { + name = "production-server" + resource_group_name = var.resource_group_name + location = var.resource_group_location + size = "Standard_B1s" + admin_username = "azureadmin" + admin_password = random_password.linux_vm_user_password.result + disable_password_authentication = false + + network_interface_ids = [ + azurerm_network_interface.linux_vm_nic.id + ] + + os_disk { + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + name = "production-server-disk" + } + + source_image_reference { + publisher = "Canonical" + offer = "0001-com-ubuntu-server-focal" + sku = "20_04-lts" + version = "latest" + } + + connection { + type = "ssh" + host = azurerm_public_ip.linux_vm_ip.ip_address + user = "azureadmin" + password = random_password.linux_vm_user_password.result + } + + provisioner "file" { + source = "${path.module}/data/flag.txt" + destination = "/home/azureadmin/flag.txt" + } + + depends_on = [ + azurerm_public_ip.linux_vm_ip, + azurerm_network_interface.linux_vm_nic + ] +} \ No newline at end of file diff --git a/azure/challenges/Cloud Jumping/data/container/.~lock.important.odt# b/azure/challenges/Cloud Jumping/data/container/.~lock.important.odt# new file mode 100644 index 0000000..918380a --- /dev/null +++ b/azure/challenges/Cloud Jumping/data/container/.~lock.important.odt# @@ -0,0 +1 @@ +,kali,kali,06.02.2026 13:23,file:///home/kali/.config/libreoffice/4; \ No newline at end of file diff --git a/azure/challenges/Cloud Jumping/data/container/important.odt b/azure/challenges/Cloud Jumping/data/container/important.odt new file mode 100755 index 0000000000000000000000000000000000000000..6224d74df7ca815b52c3f6185f0cd5c3662a309a GIT binary patch literal 15732 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 literal 0 HcmV?d00001 diff --git a/azure/challenges/Cloud Jumping/data/container/urgent.pdf b/azure/challenges/Cloud Jumping/data/container/urgent.pdf new file mode 100755 index 0000000000000000000000000000000000000000..398307ff67c67c5ae11418d4b8837980485da937 GIT binary patch literal 11765 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 literal 0 HcmV?d00001 diff --git a/azure/challenges/Cloud Jumping/data/flag.txt b/azure/challenges/Cloud Jumping/data/flag.txt new file mode 100644 index 0000000..9f2ef19 --- /dev/null +++ b/azure/challenges/Cloud Jumping/data/flag.txt @@ -0,0 +1 @@ +FLAG{just_another_day_cloudsurfing} \ No newline at end of file diff --git a/azure/challenges/Cloud Jumping/data/jump-host-template.json b/azure/challenges/Cloud Jumping/data/jump-host-template.json new file mode 100644 index 0000000..44aa264 --- /dev/null +++ b/azure/challenges/Cloud Jumping/data/jump-host-template.json @@ -0,0 +1,339 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.34.1.11899", + "templateHash": "6608977399677963554" + } + }, + "parameters": { + "vmName": { + "type": "string", + "defaultValue": "jump-host", + "metadata": { + "description": "The name of your Virtual Machine." + } + }, + "adminUsername": { + "type": "string", + "defaultValue": "azureuser", + "metadata": { + "description": "Username for the Virtual Machine." + } + }, + "authenticationType": { + "type": "string", + "defaultValue": "password", + "allowedValues": [ + "sshPublicKey", + "password" + ], + "metadata": { + "description": "Type of authentication to use on the Virtual Machine. SSH key is recommended." + } + }, + "adminPasswordOrKey": { + "type": "string", + "metadata": { + "description": "SSH Key or password for the Virtual Machine. SSH key is recommended." + } + }, + "dnsLabelPrefix": { + "type": "string", + "defaultValue": "[toLower(format('{0}-{1}', parameters('vmName'), uniqueString(resourceGroup().id)))]", + "metadata": { + "description": "Unique DNS Name for the Public IP used to access the Virtual Machine." + } + }, + "ubuntuOSVersion": { + "type": "string", + "defaultValue": "Ubuntu-2204", + "allowedValues": [ + "Ubuntu-2004", + "Ubuntu-2204" + ], + "metadata": { + "description": "The Ubuntu version for the VM. This will pick a fully patched image of this given Ubuntu version." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Location for all resources." + } + }, + "vmSize": { + "type": "string", + "defaultValue": "Standard_B1s", + "metadata": { + "description": "The size of the VM" + } + }, + "virtualNetworkName": { + "type": "string", + "defaultValue": "vNet", + "metadata": { + "description": "Name of the VNET" + } + }, + "subnetName": { + "type": "string", + "defaultValue": "Subnet", + "metadata": { + "description": "Name of the subnet in the virtual network" + } + }, + "networkSecurityGroupName": { + "type": "string", + "defaultValue": "SecGroupNet", + "metadata": { + "description": "Name of the Network Security Group" + } + }, + "securityType": { + "type": "string", + "defaultValue": "TrustedLaunch", + "allowedValues": [ + "Standard", + "TrustedLaunch" + ], + "metadata": { + "description": "Security Type of the Virtual Machine." + } + } + }, + "variables": { + "imageReference": { + "Ubuntu-2004": { + "publisher": "Canonical", + "offer": "0001-com-ubuntu-server-focal", + "sku": "20_04-lts-gen2", + "version": "latest" + }, + "Ubuntu-2204": { + "publisher": "Canonical", + "offer": "0001-com-ubuntu-server-jammy", + "sku": "22_04-lts-gen2", + "version": "latest" + } + }, + "publicIPAddressName": "[format('{0}PublicIP', parameters('vmName'))]", + "networkInterfaceName": "[format('{0}NetInt', parameters('vmName'))]", + "osDiskType": "Standard_LRS", + "subnetAddressPrefix": "10.1.0.0/24", + "addressPrefix": "10.1.0.0/16", + "linuxConfiguration": { + "disablePasswordAuthentication": true, + "ssh": { + "publicKeys": [ + { + "path": "[format('/home/{0}/.ssh/authorized_keys', parameters('adminUsername'))]", + "keyData": "[parameters('adminPasswordOrKey')]" + } + ] + } + }, + "securityProfileJson": { + "uefiSettings": { + "secureBootEnabled": true, + "vTpmEnabled": true + }, + "securityType": "[parameters('securityType')]" + }, + "extensionName": "GuestAttestation", + "extensionPublisher": "Microsoft.Azure.Security.LinuxAttestation", + "extensionVersion": "1.0", + "maaTenantName": "GuestAttestation", + "maaEndpoint": "[substring('emptystring', 0, 0)]" + }, + "resources": [ + { + "type": "Microsoft.Network/networkInterfaces", + "apiVersion": "2023-09-01", + "name": "[variables('networkInterfaceName')]", + "location": "[parameters('location')]", + "properties": { + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "subnet": { + "id": "[reference(resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworkName')), '2023-09-01').subnets[0].id]" + }, + "privateIPAllocationMethod": "Dynamic", + "publicIPAddress": { + "id": "[resourceId('Microsoft.Network/publicIPAddresses', variables('publicIPAddressName'))]" + } + } + } + ], + "networkSecurityGroup": { + "id": "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('networkSecurityGroupName'))]" + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('networkSecurityGroupName'))]", + "[resourceId('Microsoft.Network/publicIPAddresses', variables('publicIPAddressName'))]", + "[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworkName'))]" + ] + }, + { + "type": "Microsoft.Network/networkSecurityGroups", + "apiVersion": "2023-09-01", + "name": "[parameters('networkSecurityGroupName')]", + "location": "[parameters('location')]", + "properties": { + "securityRules": [ + { + "name": "SSH", + "properties": { + "priority": 1000, + "protocol": "Tcp", + "access": "Allow", + "direction": "Inbound", + "sourceAddressPrefix": "*", + "sourcePortRange": "*", + "destinationAddressPrefix": "*", + "destinationPortRange": "22" + } + } + ] + } + }, + { + "type": "Microsoft.Network/virtualNetworks", + "apiVersion": "2023-09-01", + "name": "[parameters('virtualNetworkName')]", + "location": "[parameters('location')]", + "properties": { + "addressSpace": { + "addressPrefixes": [ + "[variables('addressPrefix')]" + ] + }, + "subnets": [ + { + "name": "[parameters('subnetName')]", + "properties": { + "networkSecurityGroup": { + "id": "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('networkSecurityGroupName'))]" + }, + "addressPrefix": "[variables('subnetAddressPrefix')]", + "privateEndpointNetworkPolicies": "Enabled", + "privateLinkServiceNetworkPolicies": "Enabled" + } + } + ] + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('networkSecurityGroupName'))]" + ] + }, + { + "type": "Microsoft.Network/publicIPAddresses", + "apiVersion": "2023-09-01", + "name": "[variables('publicIPAddressName')]", + "location": "[parameters('location')]", + "sku": { + "name": "Basic" + }, + "properties": { + "publicIPAllocationMethod": "Dynamic", + "publicIPAddressVersion": "IPv4", + "dnsSettings": { + "domainNameLabel": "[parameters('dnsLabelPrefix')]" + }, + "idleTimeoutInMinutes": 4 + } + }, + { + "type": "Microsoft.Compute/virtualMachines", + "apiVersion": "2023-09-01", + "name": "[parameters('vmName')]", + "location": "[parameters('location')]", + "identity": { + "type": "UserAssigned", + "userAssignedIdentities": { + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'contributor-managed-identity')]": {} + } + }, + "properties": { + "hardwareProfile": { + "vmSize": "[parameters('vmSize')]" + }, + "storageProfile": { + "osDisk": { + "createOption": "FromImage", + "managedDisk": { + "storageAccountType": "[variables('osDiskType')]" + } + }, + "imageReference": "[variables('imageReference')[parameters('ubuntuOSVersion')]]" + }, + "networkProfile": { + "networkInterfaces": [ + { + "id": "[resourceId('Microsoft.Network/networkInterfaces', variables('networkInterfaceName'))]" + } + ] + }, + "osProfile": { + "computerName": "[parameters('vmName')]", + "adminUsername": "[parameters('adminUsername')]", + "adminPassword": "[parameters('adminPasswordOrKey')]", + "linuxConfiguration": "[if(equals(parameters('authenticationType'), 'password'), null(), variables('linuxConfiguration'))]" + }, + "securityProfile": "[if(equals(parameters('securityType'), 'TrustedLaunch'), variables('securityProfileJson'), null())]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/networkInterfaces', variables('networkInterfaceName'))]" + ] + }, + { + "condition": "[and(and(equals(parameters('securityType'), 'TrustedLaunch'), variables('securityProfileJson').uefiSettings.secureBootEnabled), variables('securityProfileJson').uefiSettings.vTpmEnabled)]", + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2023-09-01", + "name": "[format('{0}/{1}', parameters('vmName'), variables('extensionName'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "[variables('extensionPublisher')]", + "type": "[variables('extensionName')]", + "typeHandlerVersion": "[variables('extensionVersion')]", + "autoUpgradeMinorVersion": true, + "enableAutomaticUpgrade": true, + "settings": { + "AttestationConfig": { + "MaaSettings": { + "maaEndpoint": "[variables('maaEndpoint')]", + "maaTenantName": "[variables('maaTenantName')]" + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('vmName'))]" + ] + } + ], + "outputs": { + "adminUsername": { + "type": "string", + "value": "[parameters('adminUsername')]" + }, + "adminPassword": { + "type": "string", + "value": "[parameters('adminPasswordOrKey')]" + }, + "hostname": { + "type": "string", + "value": "[reference(resourceId('Microsoft.Network/publicIPAddresses', variables('publicIPAddressName')), '2023-09-01').dnsSettings.fqdn]" + }, + "sshCommand": { + "type": "string", + "value": "[format('ssh {0}@{1}', parameters('adminUsername'), reference(resourceId('Microsoft.Network/publicIPAddresses', variables('publicIPAddressName')), '2023-09-01').dnsSettings.fqdn)]" + } + } + } \ No newline at end of file diff --git a/azure/challenges/Cloud Jumping/variables.tf b/azure/challenges/Cloud Jumping/variables.tf new file mode 100644 index 0000000..c65c556 --- /dev/null +++ b/azure/challenges/Cloud Jumping/variables.tf @@ -0,0 +1,15 @@ +variable "resource_group_name" { + type = string +} + +variable "resource_group_location" { + type = string +} + +variable "player_upn" { + type = string +} + +variable "player_object_id" { + type = string +} \ No newline at end of file diff --git a/azure/challenges/Image-ination Continuation/image-inationcontinuation.tf b/azure/challenges/Image-ination Continuation/image-inationcontinuation.tf new file mode 100644 index 0000000..5abecc1 --- /dev/null +++ b/azure/challenges/Image-ination Continuation/image-inationcontinuation.tf @@ -0,0 +1,204 @@ +resource "random_id" "suffix" { + byte_length = 4 +} + +resource "random_password" "sp_pwd" { + length = 20 + special = true +} + +data "azurerm_client_config" "current" {} + +# create a key vault +resource "azurerm_key_vault" "ctf" { + name = "ctfkv${random_id.suffix.hex}" + location = var.resource_group_location + resource_group_name = var.resource_group_name + tenant_id = data.azurerm_client_config.current.tenant_id + sku_name = "standard" + purge_protection_enabled = false + soft_delete_retention_days = 7 + enable_rbac_authorization = true +} + +# place the flag in the key vault +resource "azurerm_key_vault_secret" "flag" { + name = "flag" + value = "Flag{protect_those_service_principal_creds}" + key_vault_id = azurerm_key_vault.ctf.id +} + +# create an identity for the logic app +resource "azurerm_user_assigned_identity" "logicapp_identity" { + name = "logicapp-mi-${random_id.suffix.hex}" + location = var.resource_group_location + resource_group_name = var.resource_group_name +} + +locals { + logicapp_name = "flag-logicapp-${random_id.suffix.hex}" +} + +# create a deployment template for the logic app +resource "azurerm_resource_group_template_deployment" "logicapp_with_flag" { + name = "logicapp-deploy-${random_id.suffix.hex}" + resource_group_name = var.resource_group_name + deployment_mode = "Incremental" + + template_content = jsonencode({ + "$schema" = "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion" = "1.0.0.0", + "parameters" = {}, + "resources" = [ + { + "type" = "Microsoft.Logic/workflows", + "apiVersion" = "2019-05-01", + "name" = "${local.logicapp_name}", + "location" = var.resource_group_location, + "identity" = { + "type" = "SystemAssigned" + }, + "properties" = { + "definition" = { + "$schema" = "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#", + "actions" = { + "GetFlag" = { + "type" = "Http", + "inputs" = { + "method" = "GET", + "uri" = "${azurerm_key_vault_secret.flag.id}?api-version=7.2", + "authentication" = { + "type" = "ManagedServiceIdentity", + "audience": "https://vault.azure.net" + } + }, + "runAfter" = {} + }, + "Response" = { + "type" = "Response", + "inputs" = { + "body" = { + "flag" = "@body('GetFlag').value" + }, + "statusCode" = 200 + }, + "runAfter" = { + "GetFlag" = ["Succeeded"] + } + } + }, + "triggers" = { + "manual" = { + "type" = "Request", + "kind" = "Http", + "inputs" = { + "schema" = {} + } + } + }, + "outputs" = {} + }, + "state" = "Enabled" + } + } + ] + }) +} + +# provide admin permissions to the key vault for the terraform deployment user, which should be azure admin +resource "azurerm_role_assignment" "kv_admin" { + principal_id = data.azurerm_client_config.current.object_id + role_definition_name = "Key Vault Administrator" + scope = azurerm_key_vault.ctf.id +} + +# get the logic app identity and store in a local file +resource "null_resource" "get_logicapp_identity" { + provisioner "local-exec" { + command = < logicapp_identity.txt + EOT + interpreter = ["/bin/bash", "-c"] + } + + triggers = { + always_run = timestamp() + } + + depends_on = [azurerm_resource_group_template_deployment.logicapp_with_flag] +} + +data "local_file" "logicapp_identity" { + filename = "challenges/Image-ination Continuation/data/logicapp_identity.txt" + depends_on = [null_resource.get_logicapp_identity] +} + +# provide logic app with permissions to get the flag +resource "azurerm_role_assignment" "logicapp_kv_reader" { + principal_id = data.local_file.logicapp_identity.content + role_definition_name = "Key Vault Secrets User" + scope = azurerm_key_vault.ctf.id + + depends_on = [data.local_file.logicapp_identity] +} + +# create the logic app +resource "azuread_application" "sp_app" { + display_name = "ctf-logicapp-access" +} + +# create service principal +resource "azuread_service_principal" "sp" { + client_id = azuread_application.sp_app.client_id +} + +# create service principal password +resource "azuread_service_principal_password" "sp_secret" { + service_principal_id = azuread_service_principal.sp.id + end_date = timeadd(timestamp(), "720h") + + lifecycle { + create_before_destroy = true + } +} + +# give service principal Reader permissions in the environment +resource "azurerm_role_assignment" "sp_reader" { + principal_id = azuread_service_principal.sp.object_id + role_definition_name = "Reader" + scope = "/subscriptions/${data.azurerm_client_config.current.subscription_id}" +} + +# Give service principal logic app contributor permissions +resource "azurerm_role_assignment" "logicapp_reader" { + principal_id = azuread_service_principal.sp.object_id + role_definition_name = "Logic App Contributor" + scope = "/subscriptions/${data.azurerm_client_config.current.subscription_id}/resourceGroups/${var.resource_group_name}/providers/Microsoft.Logic/workflows/flag-logicapp-${random_id.suffix.hex}" + + depends_on = [azurerm_resource_group_template_deployment.logicapp_with_flag] +} + +# generate local file with service principal credentials, which get stored in the container image from the image-ination station challenge +resource "null_resource" "generate_sp_creds" { + triggers = { + password_version = azuread_service_principal_password.sp_secret.key_id + } + + provisioner "local-exec" { + command = < challenges/Image-ination\ Station/data/sp-creds.json +EOT + } +} \ No newline at end of file diff --git a/azure/challenges/Image-ination Continuation/variables.tf b/azure/challenges/Image-ination Continuation/variables.tf new file mode 100644 index 0000000..c65c556 --- /dev/null +++ b/azure/challenges/Image-ination Continuation/variables.tf @@ -0,0 +1,15 @@ +variable "resource_group_name" { + type = string +} + +variable "resource_group_location" { + type = string +} + +variable "player_upn" { + type = string +} + +variable "player_object_id" { + type = string +} \ No newline at end of file diff --git a/azure/challenges/Image-ination Station/data/Dockerfile b/azure/challenges/Image-ination Station/data/Dockerfile new file mode 100644 index 0000000..4edb23f --- /dev/null +++ b/azure/challenges/Image-ination Station/data/Dockerfile @@ -0,0 +1,7 @@ +FROM alpine:latest +RUN adduser -D alice +RUN mkdir -p /home/alice && echo "FLAG{Interesting_stuff_can_be_hidden_in_image_files}" > /home/alice/flag.txt && chown -R alice:alice /home/alice +COPY sp-creds.json /tmp/sp-creds.json +RUN cat /tmp/sp-creds.json >> /home/alice/logic_app_creds.json +RUN apk add --no-cache bash coreutils curl wget iputils busybox-extras procps +CMD ["/bin/bash"] diff --git a/azure/challenges/Image-ination Station/image-inationstation.tf b/azure/challenges/Image-ination Station/image-inationstation.tf new file mode 100644 index 0000000..da3d2cb --- /dev/null +++ b/azure/challenges/Image-ination Station/image-inationstation.tf @@ -0,0 +1,45 @@ +resource "random_id" "suffix" { + byte_length = 4 +} + +# create container registry +resource "azurerm_container_registry" "acr" { + name = "myacr${random_id.suffix.hex}" + resource_group_name = var.resource_group_name + location = var.resource_group_location + sku = "Basic" + admin_enabled = true +} + +# push image from data folder to container registry +resource "null_resource" "docker_push" { + provisioner "local-exec" { + command = < + +Test Site + +

Hello World! This is just a test site to generate web requests. Enter the target URL below. Custom headers can be included if needed.

+

Additionally, for testing purposes the system environment variables can be found here. +

+
+

+ +
+ Key: + Value:

+ +
+ Key: + Value:

+ +
+ Key: + Value:

+ + +
+ + {% if result %} +
+

Response from {{ url }}:

+ Status: {{ status }}

+
{{ result }}
+ {% endif %} + + +""" + +@app.route("/", methods=["GET", "POST"]) +def index(): + result = status = url = None + + if request.method == "POST": + url = request.form.get("url") + headers = {} + + for i in range(1, 4): + key = request.form.get(f"header{i}_key") + value = request.form.get(f"header{i}_value") + if key and value: + headers[key] = value + + try: + response = requests.get(url, headers=headers, timeout=3) + status = response.status_code + result = response.text + except Exception as e: + status = "Error" + result = str(e) + + return render_template_string(form_template, result=result, status=status, url=url) + +@app.route("/env") +def show_env(): + env_vars = dict(os.environ) + formatted = "

Environment Variables

{}
".format( + "\n".join(f"{k}={v}" for k, v in sorted(env_vars.items())) + ) + return formatted + +if __name__ == '__main__': + app.run() +EOT +} + +# requirements.txt +resource "local_file" "requirements_txt" { + filename = "challenges/Permisery/data/requirements.txt" + content = < +resource "azuread_user" "ctf_user" { + display_name = "willem" + user_principal_name = "willem${var.domain}" + mail_nickname = "willem" + password = random_password.ctf_user_pw.result + account_enabled = true +} + +module "challenge_notsosecret" { + source = "./challenges/Not so secret" + resource_group_name = azurerm_resource_group.rg.name + resource_group_location = azurerm_resource_group.rg.location + player_upn = azuread_user.ctf_user.user_principal_name + player_object_id = azuread_user.ctf_user.object_id +} + +module "challenge_permisery" { + source = "./challenges/Permisery" + resource_group_name = azurerm_resource_group.rg.name + resource_group_location = azurerm_resource_group.rg.location + player_upn = azuread_user.ctf_user.user_principal_name + player_object_id = azuread_user.ctf_user.object_id +} + +module "challenge_image-inationcontinuation" { + source = "./challenges/Image-ination Continuation" + resource_group_name = azurerm_resource_group.rg.name + resource_group_location = azurerm_resource_group.rg.location + player_upn = azuread_user.ctf_user.user_principal_name + player_object_id = azuread_user.ctf_user.object_id +} + +module "challenge_image-inationstation" { + source = "./challenges/Image-ination Station" + resource_group_name = azurerm_resource_group.rg.name + resource_group_location = azurerm_resource_group.rg.location + player_upn = azuread_user.ctf_user.user_principal_name + player_object_id = azuread_user.ctf_user.object_id + depends_on = [module.challenge_image-inationcontinuation] +} + +module "challenge_vmiam" { + source = "./challenges/VM I Am" + resource_group_name = azurerm_resource_group.rg.name + resource_group_location = azurerm_resource_group.ctf.location + player_upn = azuread_user.ctf_user.user_principal_name + player_object_id = azuread_user.ctf_user.object_id +} + +module "challenge_cloudjumping" { + source = "./challenges/Cloud Jumping" + resource_group_name = azurerm_resource_group.rg.name + resource_group_location = azurerm_resource_group.rg.location + player_upn = azuread_user.ctf_user.user_principal_name + player_object_id = azuread_user.ctf_user.object_id +} + +output "Next_Steps" { + value = <<-EOT + +--------- + | + | +-------------------------------------------------------------------------------------+ + | | Deployment Information: | + | | | + | | Profile Used: TBD | + | | Deployment User: TBD | + | | CloudFoxable deployed to: TBD | + | | Scoreboard URL: https://cloudfoxable.bishopfox.com | + | | CTF Starting User: TBD | + | +-------------------------------------------------------------------------------------+ + | + | Next steps: + | + | 1. Set up your starting user credentials (From within this directory): + | + | TBD + | + | 2. Verify your credentials are working: + | + | TBD + | + | 3. Head back to https://cloudfoxable.bishopfox.com and complete the first challenge! + | + | You'll need this: FLAG{congrats_you_set_up_Terraform_with_Azure} + | + | +---------------------------------+--------------+ + | | Currently Enabled Challenges | Cost/Month | + | +---------------------------------+--------------+ + | | TBD + | +------------------------------------------------+ + | + +--------- + EOT +} + +locals { + credentials_text = <<-EOT + client_id = ${azuread_user.ctf_user.user_principal_name} + password = ${random_password.ctf_user_pw.result} + EOT +} + +output "credentials" { + value = local.credentials_text + sensitive = true +} + +resource "local_file" "credentials" { + filename = "credentials.txt" + content = local.credentials_text + file_permission = "0600" +} \ No newline at end of file diff --git a/azure/terraform.tfvars.example b/azure/terraform.tfvars.example new file mode 100644 index 0000000..5c27722 --- /dev/null +++ b/azure/terraform.tfvars.example @@ -0,0 +1,45 @@ +###################### +# Azure Configuration +###################### + +# Set your subscription_id +subscription_id = "" + +# Set the region to which to deploy resources. The default region is westus2 +# azure_region = "" + +####################### +# User Configuration +####################### + +# Use this variable to set the domain for your CTF users. You can find this by logging into Azure, going to Users, and looking at the domain name associated with the User Principal Name of your user account. For example: @johndoe.onmicrosoft.com +domain = "" + +####################### +# User IP Configuration +####################### + +# Specify your IP address here to bre used with security groups (so that "public" challenges are only accessible to you) +# If you don't specify anything, the default behavior is to use https://icanhazip.com to pull your IP address +# user_ip = "[YOUR_IP_ADDRESS]" + +########################### +# Assume role Configuration +########################### + +# Nothing here + +############################ +# Enabled/Disabled Challenges +############################ + +# Low or No cost - Always on +# TBD + +# This challenges incur noticeable cost. Enable when needed +# TBD + +## Bastion host related challenges +## The following challenges all need `bastion_enabled = true` + +# TBD \ No newline at end of file diff --git a/azure/variables.tf b/azure/variables.tf new file mode 100644 index 0000000..2ebb41b --- /dev/null +++ b/azure/variables.tf @@ -0,0 +1,13 @@ +variable "azure_region" { + description = "The Azure region to deploy to" + type = string + default = "westus2" +} + +variable "subscription_id" { + type = string +} + +variable "domain" { + type = string +} \ No newline at end of file From 3278c331702c59549518d875531c0fee39fc3d34 Mon Sep 17 00:00:00 2001 From: Gerben Kleijn Date: Tue, 10 Feb 2026 13:10:40 -0700 Subject: [PATCH 2/6] created proper resource groups per challenge and fixed some issues --- .../challenges/Cloud Jumping/cloudjumping.tf | 40 ++++++++++-------- .../data/container/.~lock.important.odt# | 1 - .../data/jump-host-template.json | 2 +- azure/challenges/Cloud Jumping/variables.tf | 6 +-- .../image-inationcontinuation.tf | 29 ++++++++----- .../Image-ination Continuation/variables.tf | 6 +-- .../image-inationstation.tf | 13 ++++-- .../Image-ination Station/variables.tf | 6 +-- azure/challenges/Not so secret/notsosecret.tf | 14 +++++-- azure/challenges/Not so secret/variables.tf | 6 +-- azure/challenges/Permisery/permisery.tf | 20 +++++---- azure/challenges/Permisery/variables.tf | 6 +-- azure/challenges/VM I Am/variables.tf | 6 +-- azure/challenges/VM I Am/vmiam.tf | 42 +++++++++++-------- azure/main.tf | 32 ++++++-------- 15 files changed, 118 insertions(+), 111 deletions(-) delete mode 100644 azure/challenges/Cloud Jumping/data/container/.~lock.important.odt# diff --git a/azure/challenges/Cloud Jumping/cloudjumping.tf b/azure/challenges/Cloud Jumping/cloudjumping.tf index 5cdfbd1..1632b5f 100644 --- a/azure/challenges/Cloud Jumping/cloudjumping.tf +++ b/azure/challenges/Cloud Jumping/cloudjumping.tf @@ -1,3 +1,9 @@ +# resource group +resource "azurerm_resource_group" "cloudjumping" { + name = "cloudjumpingRG" + location = var.azure_region +} + data "azuread_domains" "domain" { only_initial = true } @@ -59,8 +65,8 @@ locals { resource "azurerm_storage_account" "sa" { name = "cloudjumping${random_id.challenge_instance_id.hex}" - resource_group_name = var.resource_group_name - location = var.resource_group_location + resource_group_name = azurerm_resource_group.cloudjumping.name + location = azurerm_resource_group.cloudjumping.location account_tier = "Standard" account_replication_type = "LRS" allow_nested_items_to_be_public = true @@ -90,7 +96,7 @@ resource "azurerm_storage_blob" "blob" { } resource "azurerm_role_assignment" "user_reader" { - scope = var.resource_group_id + scope = azurerm_resource_group.cloudjumping.id role_definition_name = "Reader" principal_id = var.player_object_id } @@ -104,8 +110,8 @@ resource "azurerm_role_assignment" "user_reader" { resource "azurerm_user_assigned_identity" "contributor_managed_identity" { name = "contributor-managed-identity" - resource_group_name = var.resource_group_name - location = var.resource_group_location + resource_group_name = azurerm_resource_group.cloudjumping.name + location = azurerm_resource_group.cloudjumping.location } resource "azurerm_role_assignment" "contributor" { @@ -132,7 +138,7 @@ resource "random_password" "jump_host_user_password" { resource "azurerm_resource_group_template_deployment" "jump_host_vm" { name = "jump_host" - resource_group_name = var.resource_group_name + resource_group_name = azurerm_resource_group.cloudjumping.name deployment_mode = "Incremental" template_content = data.local_file.jump_host_template.content parameters_content = jsonencode({ @@ -161,28 +167,28 @@ resource "random_password" "linux_vm_user_password" { resource "azurerm_virtual_network" "linux_vm_vnet" { name = "production-vnet" address_space = ["10.2.0.0/16"] - location = var.resource_group_location - resource_group_name = var.resource_group_name + resource_group_name = azurerm_resource_group.cloudjumping.name + location = azurerm_resource_group.cloudjumping.location } resource "azurerm_subnet" "linux_vm_subnet" { name = "production-subnet" - resource_group_name = var.resource_group_name + resource_group_name = azurerm_resource_group.cloudjumping.name virtual_network_name = azurerm_virtual_network.linux_vm_vnet.name address_prefixes = ["10.2.1.0/24"] } resource "azurerm_public_ip" "linux_vm_ip" { name = "production-public-ip" - location = var.resource_group_location - resource_group_name = var.resource_group_name + resource_group_name = azurerm_resource_group.cloudjumping.name + location = azurerm_resource_group.cloudjumping.location allocation_method = "Static" } resource "azurerm_network_interface" "linux_vm_nic" { name = "production-vm-nic" - location = var.resource_group_location - resource_group_name = var.resource_group_name + resource_group_name = azurerm_resource_group.cloudjumping.name + location = azurerm_resource_group.cloudjumping.location ip_configuration { name = "internal" @@ -198,8 +204,8 @@ resource "azurerm_network_interface" "linux_vm_nic" { resource "azurerm_network_security_group" "ctf_nsg" { name = "ctf-nsg" - location = var.resource_group_location - resource_group_name = var.resource_group_name + resource_group_name = azurerm_resource_group.cloudjumping.name + location = azurerm_resource_group.cloudjumping.location security_rule { name = "Allow-SSH" @@ -221,8 +227,8 @@ resource "azurerm_subnet_network_security_group_association" "ctf_subnet_assoc" resource "azurerm_linux_virtual_machine" "linux_vm" { name = "production-server" - resource_group_name = var.resource_group_name - location = var.resource_group_location + resource_group_name = azurerm_resource_group.cloudjumping.name + location = azurerm_resource_group.cloudjumping.location size = "Standard_B1s" admin_username = "azureadmin" admin_password = random_password.linux_vm_user_password.result diff --git a/azure/challenges/Cloud Jumping/data/container/.~lock.important.odt# b/azure/challenges/Cloud Jumping/data/container/.~lock.important.odt# deleted file mode 100644 index 918380a..0000000 --- a/azure/challenges/Cloud Jumping/data/container/.~lock.important.odt# +++ /dev/null @@ -1 +0,0 @@ -,kali,kali,06.02.2026 13:23,file:///home/kali/.config/libreoffice/4; \ No newline at end of file diff --git a/azure/challenges/Cloud Jumping/data/jump-host-template.json b/azure/challenges/Cloud Jumping/data/jump-host-template.json index 44aa264..e21ceeb 100644 --- a/azure/challenges/Cloud Jumping/data/jump-host-template.json +++ b/azure/challenges/Cloud Jumping/data/jump-host-template.json @@ -88,7 +88,7 @@ }, "networkSecurityGroupName": { "type": "string", - "defaultValue": "SecGroupNet", + "defaultValue": "CJjumpHostSecGroup", "metadata": { "description": "Name of the Network Security Group" } diff --git a/azure/challenges/Cloud Jumping/variables.tf b/azure/challenges/Cloud Jumping/variables.tf index c65c556..72dc9d0 100644 --- a/azure/challenges/Cloud Jumping/variables.tf +++ b/azure/challenges/Cloud Jumping/variables.tf @@ -1,8 +1,4 @@ -variable "resource_group_name" { - type = string -} - -variable "resource_group_location" { +variable "azure_region" { type = string } diff --git a/azure/challenges/Image-ination Continuation/image-inationcontinuation.tf b/azure/challenges/Image-ination Continuation/image-inationcontinuation.tf index 5abecc1..bb9800a 100644 --- a/azure/challenges/Image-ination Continuation/image-inationcontinuation.tf +++ b/azure/challenges/Image-ination Continuation/image-inationcontinuation.tf @@ -1,3 +1,9 @@ +# resource group +resource "azurerm_resource_group" "imageinationcontinuation" { + name = "imageinationcontinuationRG" + location = var.azure_region +} + resource "random_id" "suffix" { byte_length = 4 } @@ -12,12 +18,11 @@ data "azurerm_client_config" "current" {} # create a key vault resource "azurerm_key_vault" "ctf" { name = "ctfkv${random_id.suffix.hex}" - location = var.resource_group_location - resource_group_name = var.resource_group_name + resource_group_name = azurerm_resource_group.imageinationcontinuation.name + location = azurerm_resource_group.imageinationcontinuation.location tenant_id = data.azurerm_client_config.current.tenant_id sku_name = "standard" purge_protection_enabled = false - soft_delete_retention_days = 7 enable_rbac_authorization = true } @@ -31,8 +36,8 @@ resource "azurerm_key_vault_secret" "flag" { # create an identity for the logic app resource "azurerm_user_assigned_identity" "logicapp_identity" { name = "logicapp-mi-${random_id.suffix.hex}" - location = var.resource_group_location - resource_group_name = var.resource_group_name + resource_group_name = azurerm_resource_group.imageinationcontinuation.name + location = azurerm_resource_group.imageinationcontinuation.location } locals { @@ -42,7 +47,7 @@ locals { # create a deployment template for the logic app resource "azurerm_resource_group_template_deployment" "logicapp_with_flag" { name = "logicapp-deploy-${random_id.suffix.hex}" - resource_group_name = var.resource_group_name + resource_group_name = azurerm_resource_group.imageinationcontinuation.name deployment_mode = "Incremental" template_content = jsonencode({ @@ -54,7 +59,7 @@ resource "azurerm_resource_group_template_deployment" "logicapp_with_flag" { "type" = "Microsoft.Logic/workflows", "apiVersion" = "2019-05-01", "name" = "${local.logicapp_name}", - "location" = var.resource_group_location, + "location" = azurerm_resource_group.imageinationcontinuation.location, "identity" = { "type" = "SystemAssigned" }, @@ -119,7 +124,7 @@ resource "null_resource" "get_logicapp_identity" { cd "challenges/Image-ination Continuation/data/" az logic workflow show \ --name ${local.logicapp_name} \ - --resource-group ${var.resource_group_name} \ + --resource-group ${azurerm_resource_group.imageinationcontinuation.name} \ --query "identity.principalId" \ --output tsv > logicapp_identity.txt EOT @@ -178,7 +183,7 @@ resource "azurerm_role_assignment" "sp_reader" { resource "azurerm_role_assignment" "logicapp_reader" { principal_id = azuread_service_principal.sp.object_id role_definition_name = "Logic App Contributor" - scope = "/subscriptions/${data.azurerm_client_config.current.subscription_id}/resourceGroups/${var.resource_group_name}/providers/Microsoft.Logic/workflows/flag-logicapp-${random_id.suffix.hex}" + scope = "/subscriptions/${data.azurerm_client_config.current.subscription_id}/resourceGroups/${azurerm_resource_group.imageinationcontinuation.name}/providers/Microsoft.Logic/workflows/flag-logicapp-${random_id.suffix.hex}" depends_on = [azurerm_resource_group_template_deployment.logicapp_with_flag] } @@ -197,8 +202,12 @@ echo '{ "tenant_id": "${data.azurerm_client_config.current.tenant_id}", "subscription_id": "${data.azurerm_client_config.current.subscription_id}", "resource": "https://management.azure.com/", - "resource_group": "${var.resource_group_name}" + "resource_group": "${azurerm_resource_group.imageinationcontinuation.name}" }' > challenges/Image-ination\ Station/data/sp-creds.json EOT } +} + +output "some_output" { + value = azuread_service_principal_password.sp_secret.key_id } \ No newline at end of file diff --git a/azure/challenges/Image-ination Continuation/variables.tf b/azure/challenges/Image-ination Continuation/variables.tf index c65c556..72dc9d0 100644 --- a/azure/challenges/Image-ination Continuation/variables.tf +++ b/azure/challenges/Image-ination Continuation/variables.tf @@ -1,8 +1,4 @@ -variable "resource_group_name" { - type = string -} - -variable "resource_group_location" { +variable "azure_region" { type = string } diff --git a/azure/challenges/Image-ination Station/image-inationstation.tf b/azure/challenges/Image-ination Station/image-inationstation.tf index da3d2cb..07c3656 100644 --- a/azure/challenges/Image-ination Station/image-inationstation.tf +++ b/azure/challenges/Image-ination Station/image-inationstation.tf @@ -1,3 +1,9 @@ +# resource group +resource "azurerm_resource_group" "imageinationstation" { + name = "imageinationstationRG" + location = var.azure_region +} + resource "random_id" "suffix" { byte_length = 4 } @@ -5,8 +11,8 @@ resource "random_id" "suffix" { # create container registry resource "azurerm_container_registry" "acr" { name = "myacr${random_id.suffix.hex}" - resource_group_name = var.resource_group_name - location = var.resource_group_location + resource_group_name = azurerm_resource_group.imageinationstation.name + location = azurerm_resource_group.imageinationstation.location sku = "Basic" admin_enabled = true } @@ -41,5 +47,4 @@ resource "azurerm_role_assignment" "acr_read_access" { principal_id = var.player_object_id role_definition_name = "Reader" scope = azurerm_container_registry.acr.id -} - +} \ No newline at end of file diff --git a/azure/challenges/Image-ination Station/variables.tf b/azure/challenges/Image-ination Station/variables.tf index fd196f9..45bece9 100644 --- a/azure/challenges/Image-ination Station/variables.tf +++ b/azure/challenges/Image-ination Station/variables.tf @@ -1,8 +1,4 @@ -variable "resource_group_name" { - type = string -} - -variable "resource_group_location" { +variable "azure_region" { type = string } diff --git a/azure/challenges/Not so secret/notsosecret.tf b/azure/challenges/Not so secret/notsosecret.tf index 9133f11..4a039ac 100644 --- a/azure/challenges/Not so secret/notsosecret.tf +++ b/azure/challenges/Not so secret/notsosecret.tf @@ -1,3 +1,9 @@ +# resource group +resource "azurerm_resource_group" "notsosecret" { + name = "notsosecretRG" + location = var.azure_region +} + resource "random_id" "suffix" { byte_length = 5 } @@ -22,8 +28,8 @@ resource "azurerm_role_assignment" "reader" { # create storage account 1 resource "azurerm_storage_account" "storage_account_1" { name = "notsosecret${random_id.suffix.hex}" - resource_group_name = var.resource_group_name - location = var.resource_group_location + resource_group_name = azurerm_resource_group.notsosecret.name + location = azurerm_resource_group.notsosecret.location account_tier = "Standard" account_replication_type = "LRS" } @@ -31,8 +37,8 @@ resource "azurerm_storage_account" "storage_account_1" { # create storage account 2 resource "azurerm_storage_account" "storage_account_2" { name = "notsosecret${random_id.suffix2.hex}" - resource_group_name = var.resource_group_name - location = var.resource_group_location + resource_group_name = azurerm_resource_group.notsosecret.name + location = azurerm_resource_group.notsosecret.location account_tier = "Standard" account_replication_type = "LRS" allow_nested_items_to_be_public = true diff --git a/azure/challenges/Not so secret/variables.tf b/azure/challenges/Not so secret/variables.tf index 129c463..db6b03e 100644 --- a/azure/challenges/Not so secret/variables.tf +++ b/azure/challenges/Not so secret/variables.tf @@ -1,8 +1,4 @@ -variable "resource_group_name" { - type = string -} - -variable "resource_group_location" { +variable "azure_region" { type = string } diff --git a/azure/challenges/Permisery/permisery.tf b/azure/challenges/Permisery/permisery.tf index be54889..cf287e2 100644 --- a/azure/challenges/Permisery/permisery.tf +++ b/azure/challenges/Permisery/permisery.tf @@ -1,3 +1,9 @@ +# resource group +resource "azurerm_resource_group" "permisery" { + name = "permiseryRG" + location = var.azure_region +} + resource "random_id" "suffix" { byte_length = 4 } @@ -20,8 +26,8 @@ locals { # create key vault resource "azurerm_key_vault" "ctf" { name = "ctfkv${random_id.suffix.hex}" - location = var.resource_group_location - resource_group_name = var.resource_group_name + resource_group_name = azurerm_resource_group.permisery.name + location = azurerm_resource_group.permisery.location tenant_id = data.azurerm_client_config.current.tenant_id sku_name = "standard" purge_protection_enabled = false @@ -62,8 +68,8 @@ resource "azurerm_role_assignment" "guest_kv_reader" { # create a service plan (free tier), needed to create the web app resource "azurerm_service_plan" "cloudfoxable" { name = "cloudfoxable" - location = var.resource_group_location - resource_group_name = var.resource_group_name + resource_group_name = azurerm_resource_group.permisery.name + location = azurerm_resource_group.permisery.location os_type = "Linux" sku_name = "F1" } @@ -71,8 +77,8 @@ resource "azurerm_service_plan" "cloudfoxable" { # create web app resource "azurerm_linux_web_app" "webapp" { name = "myfirstwebapp-${random_id.suffix2.hex}" - location = var.resource_group_location - resource_group_name = var.resource_group_name + resource_group_name = azurerm_resource_group.permisery.name + location = azurerm_resource_group.permisery.location service_plan_id = azurerm_service_plan.cloudfoxable.id identity { @@ -215,7 +221,7 @@ data "archive_file" "app_zip" { resource "null_resource" "zip_deploy" { provisioner "local-exec" { command = < Date: Wed, 11 Feb 2026 14:33:38 -0700 Subject: [PATCH 3/6] fixed permission issues, added file to vm --- .../challenges/Cloud Jumping/cloudjumping.tf | 6 +++ .../VM I Am/data/cloud-init.yaml.tftpl | 45 +++++++++++++++++++ azure/challenges/VM I Am/vmiam.tf | 39 +++++++++++++--- 3 files changed, 84 insertions(+), 6 deletions(-) create mode 100644 azure/challenges/VM I Am/data/cloud-init.yaml.tftpl diff --git a/azure/challenges/Cloud Jumping/cloudjumping.tf b/azure/challenges/Cloud Jumping/cloudjumping.tf index 1632b5f..e817956 100644 --- a/azure/challenges/Cloud Jumping/cloudjumping.tf +++ b/azure/challenges/Cloud Jumping/cloudjumping.tf @@ -101,6 +101,12 @@ resource "azurerm_role_assignment" "user_reader" { principal_id = var.player_object_id } +resource "azurerm_role_assignment" "storage_blob_reader" { + principal_id = var.player_object_id + role_definition_name = "Storage Blob Data Reader" + scope = azurerm_storage_account.sa.id +} + /*---------------------------------------------*/ diff --git a/azure/challenges/VM I Am/data/cloud-init.yaml.tftpl b/azure/challenges/VM I Am/data/cloud-init.yaml.tftpl new file mode 100644 index 0000000..2473cdc --- /dev/null +++ b/azure/challenges/VM I Am/data/cloud-init.yaml.tftpl @@ -0,0 +1,45 @@ +#cloud-config +ssh_pwauth: true + +users: + - default + - name: bob + groups: [sudo] + shell: /bin/bash + sudo: "ALL=(ALL) NOPASSWD:ALL" + lock_passwd: true + +write_files: + - path: /home/bob/personalnotes.txt + owner: root:root + permissions: '0640' + content: | + Personal Notes (do not share) + + Shopping list: + - coffee beans + - eggs + - tortillas + - pasta + - canned tomatoes + - laundry detergent + - cat litter + + Birthdays / reminders: + - Mom: May 12 + - Alex: Aug 3 + - Dentist: Apr 18 @ 10:30am + - Car registration due: Sept 30 + + Random stuff: + - Remember to cancel the trial subscription before Friday. + - Replace batteries in the smoke detector. + - Check storage closet for the spare HDMI cable. + + ------------------------------------------------------------ + Personal project notes: + - Key Vault name: ${keyvault_name} + - Secret name: ctf-flag + +runcmd: + - [ bash, -lc, "mkdir -p /home/bob && chown -R bob:bob /home/bob && chmod 750 /home/bob && chown bob:bob /home/bob/personalnotes.txt" ] \ No newline at end of file diff --git a/azure/challenges/VM I Am/vmiam.tf b/azure/challenges/VM I Am/vmiam.tf index 46b666b..72b8f5e 100644 --- a/azure/challenges/VM I Am/vmiam.tf +++ b/azure/challenges/VM I Am/vmiam.tf @@ -33,7 +33,6 @@ resource "azurerm_key_vault" "ctf_kv" { tenant_id = data.azurerm_client_config.current.tenant_id sku_name = "standard" purge_protection_enabled = false - soft_delete_retention_days = 7 enable_rbac_authorization = true } @@ -69,7 +68,7 @@ resource "azurerm_role_assignment" "kv_reader" { scope = azurerm_key_vault.ctf_kv.id } -# VM Newtwork +# VM Network resource "azurerm_virtual_network" "ctf_vnet" { name = "ctf-vnet" address_space = ["10.0.0.0/16"] @@ -91,6 +90,13 @@ resource "azurerm_public_ip" "ctf_ip" { allocation_method = "Static" } +# let user discover the IP +resource "azurerm_role_assignment" "player_ip_reader" { + scope = azurerm_public_ip.ctf_ip.id + role_definition_name = "Reader" + principal_id = var.player_object_id +} + resource "azurerm_network_interface" "ctf_nic" { name = "ctf-nic" resource_group_name = azurerm_resource_group.vmiam.name @@ -105,6 +111,13 @@ resource "azurerm_network_interface" "ctf_nic" { } } +# let user discover the nic +resource "azurerm_role_assignment" "player_nic_reader" { + scope = azurerm_network_interface.ctf_nic.id + role_definition_name = "Reader" + principal_id = var.player_object_id +} + resource "azurerm_network_security_group" "ctf_nsg" { name = "ctf-nsg" resource_group_name = azurerm_resource_group.vmiam.name @@ -158,11 +171,20 @@ resource "azurerm_linux_virtual_machine" "ctf_vm" { type = "UserAssigned" identity_ids = [azurerm_user_assigned_identity.ctf_identity.id] } + + custom_data = base64encode(templatefile("${path.module}/data/cloud-init.yaml.tftpl", { + keyvault_name = azurerm_key_vault.ctf_kv.name + })) + + depends_on = [ + azurerm_key_vault.ctf_kv + ] } -resource "azurerm_role_assignment" "user_vm_reader" { - scope = azurerm_resource_group.vmiam.id - role_definition_name = "Key Vault Reader" +# let user discover the vm +resource "azurerm_role_assignment" "player_vm_reader" { + scope = azurerm_linux_virtual_machine.ctf_vm.id + role_definition_name = "Reader" principal_id = var.player_object_id } @@ -173,7 +195,6 @@ resource "azurerm_key_vault" "ctf2" { tenant_id = data.azurerm_client_config.current.tenant_id sku_name = "standard" purge_protection_enabled = false - soft_delete_retention_days = 7 enable_rbac_authorization = true network_acls { @@ -194,6 +215,12 @@ resource "azurerm_key_vault_secret" "creds" { ] } +resource "azurerm_role_assignment" "kv_reader2" { + principal_id = var.player_object_id + role_definition_name = "Reader" + scope = azurerm_key_vault.ctf2.id +} + resource "azurerm_role_assignment" "kv_secrets_reader" { principal_id = var.player_object_id role_definition_name = "Key Vault Secrets User" From f691ccd05f8ea85f1367d9102e18f348c6a61984 Mon Sep 17 00:00:00 2001 From: Gerben Kleijn Date: Mon, 16 Feb 2026 11:50:24 -0700 Subject: [PATCH 4/6] fixed permission issues, added ability to enable/disable challenges --- .../challenges/Cloud Jumping/cloudjumping.tf | 20 ++++--- azure/challenges/Cloud Jumping/data/flag.txt | 2 +- .../image-inationcontinuation.tf | 2 +- .../Image-ination Station/data/Dockerfile | 2 +- azure/challenges/Not so secret/data/flag.txt | 2 +- azure/challenges/Permisery/permisery.tf | 2 +- azure/challenges/VM I Am/vmiam.tf | 2 +- azure/main.tf | 59 ++++++++++++------- azure/terraform.tfvars.example | 22 +++---- azure/variables.tf | 25 ++++++++ 10 files changed, 89 insertions(+), 49 deletions(-) diff --git a/azure/challenges/Cloud Jumping/cloudjumping.tf b/azure/challenges/Cloud Jumping/cloudjumping.tf index e817956..1db2f0c 100644 --- a/azure/challenges/Cloud Jumping/cloudjumping.tf +++ b/azure/challenges/Cloud Jumping/cloudjumping.tf @@ -18,11 +18,13 @@ locals { user_ip = chomp(data.http.current_ip.response_body) } +# password for read user resource "random_password" "read_user_password" { length = 16 special = true } +# store creds locally then later upload them to storage account resource "local_file" "credentials" { filename = "${path.module}/data/container/tmp.txt" content = <<-EOF @@ -31,6 +33,7 @@ resource "local_file" "credentials" { EOF } +# create read user and give them global reader resource "azuread_user" "read_user" { user_principal_name = "az.reader@${data.azuread_domains.domain.domains.0.domain_name}" display_name = "Azure Reader" @@ -95,18 +98,19 @@ resource "azurerm_storage_blob" "blob" { source = "${path.module}/data/container/${each.value}" } -resource "azurerm_role_assignment" "user_reader" { - scope = azurerm_resource_group.cloudjumping.id - role_definition_name = "Reader" - principal_id = var.player_object_id -} - +# give player permissions to read storage account and data resource "azurerm_role_assignment" "storage_blob_reader" { principal_id = var.player_object_id role_definition_name = "Storage Blob Data Reader" scope = azurerm_storage_account.sa.id } +resource "azurerm_role_assignment" "reader" { + principal_id = var.player_object_id + role_definition_name = "Reader" + scope = azurerm_storage_account.sa.id +} + /*---------------------------------------------*/ @@ -120,8 +124,9 @@ resource "azurerm_user_assigned_identity" "contributor_managed_identity" { location = azurerm_resource_group.cloudjumping.location } +# managed identity should have contributor role for cloudjumping resource group resource "azurerm_role_assignment" "contributor" { - scope = data.azurerm_subscription.current.id + scope = azurerm_resource_group.cloudjumping.id role_definition_name = "Contributor" principal_id = azurerm_user_assigned_identity.contributor_managed_identity.principal_id } @@ -133,6 +138,7 @@ resource "azurerm_role_assignment" "contributor" { // Create Linux VM with a managed identity ################################################# +# vm1 (jump-host) gets deployed from a template data "local_file" "jump_host_template" { filename = "${path.module}/data/jump-host-template.json" } diff --git a/azure/challenges/Cloud Jumping/data/flag.txt b/azure/challenges/Cloud Jumping/data/flag.txt index 9f2ef19..5a0104b 100644 --- a/azure/challenges/Cloud Jumping/data/flag.txt +++ b/azure/challenges/Cloud Jumping/data/flag.txt @@ -1 +1 @@ -FLAG{just_another_day_cloudsurfing} \ No newline at end of file +FLAG{cloudJumping:justAnotherDayCloudJumping} \ No newline at end of file diff --git a/azure/challenges/Image-ination Continuation/image-inationcontinuation.tf b/azure/challenges/Image-ination Continuation/image-inationcontinuation.tf index bb9800a..799b1f9 100644 --- a/azure/challenges/Image-ination Continuation/image-inationcontinuation.tf +++ b/azure/challenges/Image-ination Continuation/image-inationcontinuation.tf @@ -29,7 +29,7 @@ resource "azurerm_key_vault" "ctf" { # place the flag in the key vault resource "azurerm_key_vault_secret" "flag" { name = "flag" - value = "Flag{protect_those_service_principal_creds}" + value = "Flag{imageinationContinuation:protectThoseServicePrincipalCreds}" key_vault_id = azurerm_key_vault.ctf.id } diff --git a/azure/challenges/Image-ination Station/data/Dockerfile b/azure/challenges/Image-ination Station/data/Dockerfile index 4edb23f..8b2d626 100644 --- a/azure/challenges/Image-ination Station/data/Dockerfile +++ b/azure/challenges/Image-ination Station/data/Dockerfile @@ -1,6 +1,6 @@ FROM alpine:latest RUN adduser -D alice -RUN mkdir -p /home/alice && echo "FLAG{Interesting_stuff_can_be_hidden_in_image_files}" > /home/alice/flag.txt && chown -R alice:alice /home/alice +RUN mkdir -p /home/alice && echo "FLAG{imageinationStation:interestingStuffCanBeHiddenInImageFiles}" > /home/alice/flag.txt && chown -R alice:alice /home/alice COPY sp-creds.json /tmp/sp-creds.json RUN cat /tmp/sp-creds.json >> /home/alice/logic_app_creds.json RUN apk add --no-cache bash coreutils curl wget iputils busybox-extras procps diff --git a/azure/challenges/Not so secret/data/flag.txt b/azure/challenges/Not so secret/data/flag.txt index 1613a57..4da94e7 100644 --- a/azure/challenges/Not so secret/data/flag.txt +++ b/azure/challenges/Not so secret/data/flag.txt @@ -1 +1 @@ -FLAG{should_this_storage_blob_be_publicly_accessible} \ No newline at end of file +FLAG{notsosecret:shouldThisStorageBlobBePubliclyAccessible} \ No newline at end of file diff --git a/azure/challenges/Permisery/permisery.tf b/azure/challenges/Permisery/permisery.tf index cf287e2..d3b964e 100644 --- a/azure/challenges/Permisery/permisery.tf +++ b/azure/challenges/Permisery/permisery.tf @@ -46,7 +46,7 @@ resource "azurerm_key_vault" "ctf" { # put a flag in the key vault resource "azurerm_key_vault_secret" "flag" { name = "flag" - value = "FLAG{SSRF_in_the_cloud_is_always_fun}" + value = "FLAG{permisery:SSRFInTheCloudIsAlwaysFun}" key_vault_id = azurerm_key_vault.ctf.id depends_on = [azurerm_role_assignment.kv_admin] } diff --git a/azure/challenges/VM I Am/vmiam.tf b/azure/challenges/VM I Am/vmiam.tf index 72b8f5e..70c2e61 100644 --- a/azure/challenges/VM I Am/vmiam.tf +++ b/azure/challenges/VM I Am/vmiam.tf @@ -46,7 +46,7 @@ resource "azurerm_role_assignment" "terraform_admin_rbac" { # Secret(flag) resource "azurerm_key_vault_secret" "flag" { name = "ctf-flag" - value = "FLAG{keyvault_misconfigured_read}" + value = "FLAG{vmIAm:keyvaultMisconfiguredRead}" key_vault_id = azurerm_key_vault.ctf_kv.id depends_on = [ diff --git a/azure/main.tf b/azure/main.tf index 26f40e2..960dfb4 100644 --- a/azure/main.tf +++ b/azure/main.tf @@ -25,6 +25,8 @@ provider "azurerm" { subscription_id = var.subscription_id } +data "azurerm_client_config" "current" {} + # user password resource "random_password" "ctf_user_pw" { length = 14 @@ -42,6 +44,7 @@ resource "azuread_user" "ctf_user" { } module "challenge_notsosecret" { + count = var.notsosecret_enabled ? 1 : 0 source = "./challenges/Not so secret" azure_region = var.azure_region player_upn = azuread_user.ctf_user.user_principal_name @@ -49,6 +52,7 @@ module "challenge_notsosecret" { } module "challenge_permisery" { + count = var.permisery_enabled ? 1 : 0 source = "./challenges/Permisery" azure_region = var.azure_region player_upn = azuread_user.ctf_user.user_principal_name @@ -56,6 +60,7 @@ module "challenge_permisery" { } module "challenge_image-inationcontinuation" { + count = var.imageination_enabled ? 1 : 0 source = "./challenges/Image-ination Continuation" azure_region = var.azure_region player_upn = azuread_user.ctf_user.user_principal_name @@ -63,15 +68,17 @@ module "challenge_image-inationcontinuation" { } module "challenge_image-inationstation" { + count = var.imageination_enabled ? 1 : 0 source = "./challenges/Image-ination Station" azure_region = var.azure_region player_upn = azuread_user.ctf_user.user_principal_name player_object_id = azuread_user.ctf_user.object_id depends_on = [module.challenge_image-inationcontinuation] - depends_on_output = module.challenge_image-inationcontinuation.some_output #needed to make sure stuff finishes before other stuff + depends_on_output = module.challenge_image-inationcontinuation[0].some_output # needed to make sure stuff finishes before other stuff } module "challenge_vmiam" { + count = var.vmiam_enabled ? 1 : 0 source = "./challenges/VM I Am" azure_region = var.azure_region player_upn = azuread_user.ctf_user.user_principal_name @@ -79,35 +86,50 @@ module "challenge_vmiam" { } module "challenge_cloudjumping" { + count = var.cloudjumping_enabled ? 1 : 0 source = "./challenges/Cloud Jumping" azure_region = var.azure_region player_upn = azuread_user.ctf_user.user_principal_name player_object_id = azuread_user.ctf_user.object_id } +locals { + enabled_challenges = compact([ + var.notsosecret_enabled ? "Not So Secret (~$0.01/month)" : "", + var.permisery_enabled ? "Permisery (~$0/month)" : "", + var.imageination_enabled ? "Image-ination Challenges (~$5/month)" : "", + var.vmiam_enabled ? "VM I Am (~$15/month)" : "", + var.cloudjumping_enabled ? "Cloud Jumping (~$15/month)" : "" + ]) +} + output "Next_Steps" { - value = <<-EOT + value = < 0 ? join("\n| | ", local.enabled_challenges) : "None"} | +------------------------------------------------+ | +--------- @@ -130,11 +152,6 @@ locals { EOT } -output "credentials" { - value = local.credentials_text - sensitive = true -} - resource "local_file" "credentials" { filename = "credentials.txt" content = local.credentials_text diff --git a/azure/terraform.tfvars.example b/azure/terraform.tfvars.example index 5c27722..fbbcb4c 100644 --- a/azure/terraform.tfvars.example +++ b/azure/terraform.tfvars.example @@ -23,23 +23,15 @@ domain = "" # If you don't specify anything, the default behavior is to use https://icanhazip.com to pull your IP address # user_ip = "[YOUR_IP_ADDRESS]" -########################### -# Assume role Configuration -########################### - -# Nothing here - ############################ # Enabled/Disabled Challenges ############################ -# Low or No cost - Always on -# TBD +# enabled by default +notsosecret_enabled = true +permisery_enabled = true -# This challenges incur noticeable cost. Enable when needed -# TBD - -## Bastion host related challenges -## The following challenges all need `bastion_enabled = true` - -# TBD \ No newline at end of file +# disabled by default (cost) +imageination_enabled = false # about $5 per month / $0.17 per day +vmiam_enabled = false # about $15 per month / $0.50 per day +cloudjumping_enabled = false # about $15 per month / $0.50 per day \ No newline at end of file diff --git a/azure/variables.tf b/azure/variables.tf index 2ebb41b..aaaeb37 100644 --- a/azure/variables.tf +++ b/azure/variables.tf @@ -10,4 +10,29 @@ variable "subscription_id" { variable "domain" { type = string +} + +variable "notsosecret_enabled" { + type = bool + default = true +} + +variable "permisery_enabled" { + type = bool + default = true +} + +variable "imageination_enabled" { + type = bool + default = false +} + +variable "vmiam_enabled" { + type = bool + default = false +} + +variable "cloudjumping_enabled" { + type = bool + default = false } \ No newline at end of file From 97ce947dc3bac04f230b90861e4ee782c5ad81e0 Mon Sep 17 00:00:00 2001 From: Gerben Kleijn Date: Mon, 16 Feb 2026 13:26:23 -0700 Subject: [PATCH 5/6] reverted unintended changes --- aws/terraform.tfvars.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws/terraform.tfvars.example b/aws/terraform.tfvars.example index fa45b7f..0efeb28 100755 --- a/aws/terraform.tfvars.example +++ b/aws/terraform.tfvars.example @@ -36,7 +36,7 @@ aws_local_profile = "default" # Specify your IP address here to bre used with security groups (so that "public" challenges are only accessible to you) # If you don't specify anything, the default behavior is to use https://ifconfig.me to pull your IP address -user_ip = "72.217.56.164" +#user_ip = "[YOUR_IP_ADDRESS]" ###################### From b2941bc7b12956e3c61ec0cae70869a148e9c547 Mon Sep 17 00:00:00 2001 From: Gerben Kleijn Date: Mon, 16 Feb 2026 13:54:58 -0700 Subject: [PATCH 6/6] Minor changes to deployment output and files --- .../data/jump-host-template.json | 1 + .../image-inationcontinuation.tf | 4 + azure/main.tf | 116 +++++++++++------- 3 files changed, 76 insertions(+), 45 deletions(-) diff --git a/azure/challenges/Cloud Jumping/data/jump-host-template.json b/azure/challenges/Cloud Jumping/data/jump-host-template.json index e21ceeb..2361004 100644 --- a/azure/challenges/Cloud Jumping/data/jump-host-template.json +++ b/azure/challenges/Cloud Jumping/data/jump-host-template.json @@ -267,6 +267,7 @@ "storageProfile": { "osDisk": { "createOption": "FromImage", + "deleteOption": "Delete", "managedDisk": { "storageAccountType": "[variables('osDiskType')]" } diff --git a/azure/challenges/Image-ination Continuation/image-inationcontinuation.tf b/azure/challenges/Image-ination Continuation/image-inationcontinuation.tf index 799b1f9..110af74 100644 --- a/azure/challenges/Image-ination Continuation/image-inationcontinuation.tf +++ b/azure/challenges/Image-ination Continuation/image-inationcontinuation.tf @@ -31,6 +31,8 @@ resource "azurerm_key_vault_secret" "flag" { name = "flag" value = "Flag{imageinationContinuation:protectThoseServicePrincipalCreds}" key_vault_id = azurerm_key_vault.ctf.id + + depends_on = [azurerm_role_assignment.kv_admin] } # create an identity for the logic app @@ -117,6 +119,8 @@ resource "azurerm_role_assignment" "kv_admin" { scope = azurerm_key_vault.ctf.id } + + # get the logic app identity and store in a local file resource "null_resource" "get_logicapp_identity" { provisioner "local-exec" { diff --git a/azure/main.tf b/azure/main.tf index 960dfb4..7b7feed 100644 --- a/azure/main.tf +++ b/azure/main.tf @@ -94,55 +94,81 @@ module "challenge_cloudjumping" { } locals { - enabled_challenges = compact([ - var.notsosecret_enabled ? "Not So Secret (~$0.01/month)" : "", - var.permisery_enabled ? "Permisery (~$0/month)" : "", - var.imageination_enabled ? "Image-ination Challenges (~$5/month)" : "", - var.vmiam_enabled ? "VM I Am (~$15/month)" : "", - var.cloudjumping_enabled ? "Cloud Jumping (~$15/month)" : "" - ]) + challenge_catalog = [ + { + enabled = var.notsosecret_enabled + name = "Not So Secret" + cost = "~$0.01/month" + }, + { + enabled = var.permisery_enabled + name = "Permisery" + cost = "~$0/month" + }, + { + enabled = var.imageination_enabled + name = "Image-ination" + cost = "~$5/month" + }, + { + enabled = var.vmiam_enabled + name = "VM I Am" + cost = "~$15/month" + }, + { + enabled = var.cloudjumping_enabled + name = "Cloud Jumping" + cost = "~$15/month" + } + ] + + enabled_challenges = [ + for c in local.challenge_catalog : + format("| | %-31s | %-12s |", c.name, c.cost) + if c.enabled + ] } output "Next_Steps" { value = < 0 ? join("\n| | ", local.enabled_challenges) : "None"} - | +------------------------------------------------+ - | - +--------- - EOT ++--------- +| +| +---------------------------------------------------------------------------------------------+ +| | Deployment Information: | +| | | +| | CloudFoxable deployed to: Subscription ${data.azurerm_client_config.current.subscription_id}| +| | Tenant ${data.azurerm_client_config.current.tenant_id} | +| | Scoreboard URL: https://cloudfoxable.bishopfox.com | +| | CTF Starting User: Willem | +| | Credentials: cat credentials.txt | +| +---------------------------------------------------------------------------------------------+ +| +| Next steps: +| +| 1. Access the credentials for your CTF user: +| +| cat credentials.txt +| +| 2. Logout your admin user: +| +| az logout +| +| 3. Verify your CTF user's credentials are working: +| +| az login +| +| 3. Head back to https://cloudfoxable.bishopfox.com and complete the first Azure challenge! +| +| You'll need this: FLAG{congrats_you_set_up_Terraform_with_Azure} +| +| +---------------------------------+---------------+ +| | Currently Enabled Challenges | Cost/Month | +| +---------------------------------+---------------+ +${length(local.enabled_challenges) > 0 ? join("\n", local.enabled_challenges) : "| None | |"} +| +-------------------------------------------------+ +| ++--------- +EOT } locals {