This Terraform module provides an easy way to configure Aqua Security’s CSPM and agentless solutions on Azure.
It creates the necessary resources, such as service accounts, roles, and permissions, to enable seamless integration with Aqua’s platform.
- Pre-requisites
- IAM roles and discovery flags
- Usage
- Examples
- Continuous Management Group Onboarding and Offboarding
- Using Existing Network
- Using Existing Service Principal
Before using this module, ensure that you have the following:
- Terraform version
1.6.4or later. azureCLI installed and configured.Python3+ installed.- Aqua Security account API credentials.
- Leverage the Aqua platform to generate the local variables required by the module.
- Important: Replace
<aqua_api_key>and<aqua_api_secret>with your generated API credentials. - Get from Azure console your Tenant ID.
- Run
az login --tenant <tenant_id>to set your tenant. - Only for single subscription --> run
az account set --subscription <subscription_name>to set azure cli context. - Run
terraform initto initialize the module. - Run
terraform applyto create the resources.
Here's an example of how to use this module:
module "aqua_azure_onboarding" {
source = "aquasecurity/onboarding/azure"
onboarding_type = "single-subscription"
aqua_bucket_name = "aqua-bucket-name"
aqua_cspm_url = "aqua-cspm-url"
aqua_volscan_api_url = "aqua-volscan-api-url"
aqua_volscan_api_token = "aqua-volscan-api-token"
aqua_volscan_resource_group_location = "westus2"
aqua_volscan_scan_locations = ["australiaeast", "australiasoutheast"]
aqua_cspm_group_id = "cspm-group-id"
aqua_configuration_id = "aqua-configuration-id"
aqua_autoconnect_url = "aqua-autoconnect-url"
aqua_api_key = "aqua-api-key"
aqua_api_secret = "aqua-api-secret"
aqua_custom_tags = { aqua = "true" }
registry_scanning_deployment = true
serverless_scanning_deployment = true
volume_scanning_deployment = true
base_cspm = false
}module "aqua_azure_onboarding" {
source = "aquasecurity/onboarding/azure"
onboarding_type = "management-group"
aqua_bucket_name = "aqua-bucket-name"
management_group_id = "management-group-id"
aqua_cspm_url = "aqua-cspm-url"
aqua_volscan_api_url = "aqua-volscan-api-url"
aqua_volscan_api_token = "aqua-volscan-api-token"
aqua_volscan_resource_group_location = "westus2"
aqua_volscan_scan_locations = ["australiaeast", "australiasoutheast"]
aqua_cspm_group_id = "cspm-group-id"
aqua_configuration_id = "aqua-configuration-id"
aqua_autoconnect_url = "aqua-autoconnect-url"
aqua_api_key = "aqua-api-key"
aqua_api_secret = "aqua-api-secret"
aqua_custom_tags = { aqua = "true" }
registry_scanning_deployment = true
serverless_scanning_deployment = true
volume_scanning_deployment = true
base_cspm = false
}To automate and simplify the process of onboarding new subscriptions and offboarding deprecated subscriptions from an existing management group onto Aqua, incorporate this Terraform module into a CI/CD pipeline or set up scheduled Terraform apply runs. Upon every run of the pipeline / scheduled runs, Aqua will re-validate the state and onboard / offboard the delta subscriptions.
- Integrate this Terraform module onto your CI/CD pipeline.
- Configure the pipeline to trigger a Terraform plan and apply whenever a subscription is added or removed.
- Automate the process by scheduling regular Terraform apply runs using a cron job or a CI/CD scheduling mechanism
- This GitHub Actions workflow automates onboarding and offboarding of Azure management group subscriptions. It can run on a schedule or be triggered manually. The workflow checks out the code, installs Terraform, logs into Azure, and executes terraform apply to apply the latest configuration changes.
name: Azure Continuous Onboarding
on:
workflow_dispatch:
inputs:
run:
description: 'Run terraform apply'
required: true
type: boolean
schedule:
- cron: '30 20 * * *'
permissions:
id-token: write
contents: read
jobs:
terraform-apply:
if: ${{ github.event_name == 'schedule' || github.event.inputs.run == 'true' }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{ vars.TF_VERSION }}
- name: Azure login
uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Run Terraform Init
run: terraform init
- name: Run Terraform Apply
run: terraform apply -auto-approveIf you prefer to use existing networking instead of Aqua provisioning new ones,
you can do so by setting create_network = false in the module's input variables.
In this case, you will need to create the network per subscription,
prior to onboarding, the following resources with the following naming convention:
- Resource group:
- Name
'aqua-agentless-scanner' - Tag
aqua-agentless-scanner:true
- Name
- Security group (per each chosen scan location):
- Name
<resource-group-name>-<region>. E.g.,aqua-agentless-scanner-centralus - Tag
aqua-agentless-scanner:true
- Name
- Virtual network (per each chosen scan location):
- Name
<resource-group-name>-<region>. E.g.,aqua-agentless-scanner-centralus - Tag
aqua-agentless-scanner:true
- Name
- Subnet (attached to the virtual network):
- Name
<resource-group-name>. E.g.,aqua-agentless-scanner
- Name
If you prefer to use an existing service principal instead of Aqua provisioning a new one,
you can do so by setting create_service_principal = false in the module's input variables.
In this case, you will need to create the service principal and application prior to onboarding, using the following configuration:
- Application Name:
- Management group:
aqua-cspm-scanner-<tenant_id>-<management_group_id> - Single subscription:
aqua-cspm-scanner-<subscription_id>
- Management group:
- Application Password:
- Description:
rbac - End date: Aqua recommends
17520hor more
- Description:
- Service Principal:
- ID:
<Application ID>or<Object ID>of the associated application
- ID:
# Creating a service principal for 30 years (this also creates an application)
az ad sp create-for-rbac --only-show-errors --name aqua-cspm-scanner-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --years 30 --output json
# Output
{
"appId": "<appId>",
"displayName": "<displayName>",
"password": "<password>",
"tenant": "<tenant>"
}
# Show service principal to fetch the id (service_principal_object_id)
az ad sp show --id <appId> | jq .id
# Output
"<id>"Supply the service principal object id, application id, and application password in the module's input variables.
For example:
module "aqua_azure_onboarding" {
# (unchanged)
create_service_principal = false # Set to false to skip service principal creation
service_principal_object_id = "<service-principal-object>" # Referencing service principal object ID created prior to onboarding
application_id = "<application-id>" # Referencing application ID created prior to onboarding
application_password = "<application-password>" # Referencing application password created prior to onboarding
# (unchanged)
}| Name | Version |
|---|---|
| terraform | >= 1.6.4 |
| azuread | ~>2.47.0 |
| azurerm | ~>3.95.0 |
| external | ~>2.3.3 |
| http | ~>3.4.2 |
| Name | Version |
|---|---|
| azuread | ~>2.47.0 |
| azurerm | ~>3.95.0 |
| Name | Source | Version |
|---|---|---|
| application | ./modules/application | n/a |
| iam | ./modules/iam | n/a |
| management_group | ./modules/management_group | n/a |
| subscription | ./modules/subscription | n/a |
| Name | Type |
|---|---|
| azuread_client_config.current | data source |
| azurerm_management_group.current | data source |
| azurerm_subscription.current | data source |
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| application_id | Application ID - represented by the Service principal client ID associated with the application (in case that var.create_service_principal is false) | string |
"" |
no |
| application_password | Application password (in case that var.create_service_principal is false) | string |
"" |
no |
| aqua_api_key | Aqua API key | string |
n/a | yes |
| aqua_api_secret | Aqua API secret key | string |
n/a | yes |
| aqua_autoconnect_url | Aqua AutoConnect URL | string |
n/a | yes |
| aqua_bucket_name | Aqua Bucket Name | string |
n/a | yes |
| aqua_configuration_id | Aqua configuration ID | string |
n/a | yes |
| aqua_cspm_group_id | CSPM group ID | string |
n/a | yes |
| aqua_cspm_role_name | Aqua AutoConnect Scanner Role Name - The default value will be calculated as 'Aqua_Auto_Discovery_Scanner_Role_<subscription_id>' | string |
"" |
no |
| aqua_cspm_url | Aqua CSPM url | string |
n/a | yes |
| aqua_custom_tags | Client additional resource tags | map(string) |
{} |
no |
| aqua_event_subscriptions_name | Aqua volume scanning Event Subscriptions Name | string |
"aqua-agentless-scanner" |
no |
| aqua_network_security_group_name | Aqua volume scanning Network Security Group Name | string |
"aqua-agentless-scanner" |
no |
| aqua_registry_scanner_role_name | Custom Azure role name for registry scanning; empty uses default Aqua_Registry_Scanner_Role_<suffix> |
string |
"" |
no |
| aqua_serverless_scanner_role_name | Custom Azure role name for serverless scanning; empty uses default Aqua_Serverless_Scanner_Role_<suffix> |
string |
"" |
no |
| aqua_subnet_name | Aqua volume scanning Subnet Name | string |
"aqua-agentless-scanner" |
no |
| aqua_system_topics_name | Aqua volume scanning Event Grid System Topic Name | string |
"aqua-agentless-scanner" |
no |
| aqua_virtual_network_name | Aqua volume scanning Virtual Network Name | string |
"aqua-agentless-scanner" |
no |
| aqua_volscan_api_token | Aqua volume scanning API token | string |
n/a | yes |
| aqua_volscan_api_url | Aqua Event Subscription webhook URL | string |
n/a | yes |
| aqua_volscan_resource_group_location | Aqua volume scanning Resource Group Location | string |
"eastus" |
no |
| aqua_volscan_resource_group_name | Aqua volume scanning Resource Group Name | string |
"aqua-agentless-scanner" |
no |
| aqua_volscan_scan_locations | List of Azure locations to scan - by default, all regions are selected | list(string) |
[ |
no |
| create_network | Toggle to create network resources | bool |
true |
no |
| create_service_principal | Toggle to create service principal | bool |
true |
no |
| management_group_id | Aqua Management Group ID - Relevant when onboarding_type is management-group | string |
"" |
no |
| onboarding_type | The type of onboarding. Valid values are 'single-subscription' or 'management-group' onboarding types | string |
n/a | yes |
| registry_scanning_deployment | Defines whether resources related to registry scanning will be created | bool |
true |
no |
| serverless_scanning_deployment | Defines whether resources related to serverless scanning will be created | bool |
true |
no |
| volume_scanning_deployment | Defines whether resources related to volume (agentless) scanning will be created | bool |
true |
no |
| service_principal_object_id | Service principal object ID associated with the application (in case that var.create_service_principal is false) | string |
"" |
no |
| show_outputs | Toggle to show summary outputs after deployment | bool |
false |
no |
| Name | Description |
|---|---|
| application_id | Application ID |
| aqua_agentless_scanner_delete_role_definition_id | The ID of the created Aqua agentless delete role definition |
| aqua_agentless_scanner_role_definition_id | The ID of the created Aqua agentless role definition, or null if volume_scanning_deployment is false (or if show_outputs is false) |
| aqua_connected_subscriptions | Aqua connected subscriptions |
| aqua_cspm_scanner_role_definition_id | The ID of the created Aqua CSPM role definition |
| aqua_registry_scanner_role_definition_id | The ID of the registry scanner role definition, or null if registry_scanning_deployment is false |
| aqua_serverless_scanner_role_definition_id | The ID of the serverless scanner role definition, or null if serverless_scanning_deployment is false |
| aqua_volscan_resource_group_name | Aqua volume scanning Resource Group Name |
| eventgrid_id | EventGrid ID |
| management_group_name | Management Group name |
| management_group_subscriptions | Management group subscription list |
| offboard_subscription_results | Offboard status |
| offboard_subscriptions | Offboard subscriptions |
| onboard_subscriptions | Subscriptions to be onboarded |
| resource_group_id | Resource Group ID |
| security_groups_names | Security Groups names |
| subscription_id | Subscription ID |
| virtual_networks_names | Virtual Networks names |