Onboard Azure subscriptions and tenants with a Python script
Copy link

You can use a custom Python script (onboard.py) developed by Rapid7 to programmatically create and configure Azure resources required for Rapid7 to collect data from your environment. If you would prefer an alternative onboarding method, review Azure Overview & Support.

Prerequisites
Copy link

CLI and software:

  • Python 3.10 or greater
  • Azure CLI installed and configured (az command available)
  • OpenSSL (for certificate-based authentication)

General:

  • Azure permissions for:
    • Azure AD: Application registration creation and management
    • IAM: Role definitions and assignments at subscription or tenant scope
    • Microsoft Graph API: Read permissions for enhanced visibility
  • Access to one or more Azure subscriptions
  • (Optional) Management Group access for tenant-level onboarding
  • Cloud Security (InsightCloudSec) Domain or Organization Admin permissions
  • Knowledge of Azure concepts such as service principals, role-based access control (RBAC), and tenants
ℹ️

Not sure if you have the correct Azure permissions?

You can use the script to check your Azure permissions. Review Common script use cases for details.

Key script terminology
Copy link

Before you begin, review the core concepts used in Azure onboarding:

  • Service principal: An identity used by applications or automation tools to access Azure resources.
  • Application registration: The Azure AD configuration object that defines authentication and API access.
  • Role definition (RBAC): A set of permissions that can be assigned to identities at a defined scope. For more information on the default roles Rapid7 offers, visit Azure Overview & Support.
  • Role assignment: The association between a role and a principal at a given scope.
  • Scope: The level at which access applies:
    • Subscription Scope: Monitors a single Azure subscription
    • Tenant Scope: Monitors all subscriptions within an Azure AD tenant (requires Management Group access)
  • Microsoft Graph API permissions: Required permissions that allow Cloud Security (InsightCloudSec) to access directory and audit data.
  • Authentication methods: Defines how Cloud Security (InsightCloudSec) securely accesses Azure
    • Certificate: Self-signed X.509 certificate (recommended for production)
    • Password/Secret: Auto-generated client secret (simpler but less secure)

Download the script and connect accounts
Copy link

You can configure and download the script in the Cloud Security (InsightCloudSec) Add Cloud Account interface. Adjusting configuration details changes parameters inside the script, which affects role definitions, permissions, and deployment scope.

ℹ️

Need to adjust configuration details?

If you need a new configuration, Rapid7 recommends using the Add Cloud Account interface to generate and download a new script.

Connect a single Azure subscription

The onboarding script can create a service principal and assign roles to a single Azure subscription.

To generate the onboarding script:

  1. Log in to the Command Platform .
  2. Go to Data Connectors > Cloud Accounts.
  3. Click + Add Cloud.
  4. Select Microsoft Azure.
  5. Click Script.
  6. Select your Azure cloud environment (for example, Azure Commercial, Government, or China).
  7. Select Subscription.
  8. Select an authentication type:
    • API/Secret
    • Client Certificate (recommended)
  9. Click Generate & Download Script.

To run the script:

  1. Open a new tab and log in to the Azure portal .

  2. Click the Cloud Shell icon.

  3. Once the environment is finished loading, click Manage Files > Upload.

  4. Select the onboarding script from its downloaded location. The file is uploaded to /home/<name> by default.

  5. Recommended: run the script with the --read-only option to test your configuration, validate your permissions, and audit existing resources.

    python onboard.py --read-only --no-tenant-harvesting
  6. Run the script and follow the prompts. The script will not run with Python 2.

# Option 1: Basic interactive deployment python onboard.py # Option 2: Deploy with custom parameters python onboard.py \ --name "Rapid7 InsightCloudSec" \ --use-certificate \ --subscription-id <subscription-id> \ --no-tenant-harvesting \ --role 0

What happens:

  • The script validates Azure permissions
  • Creates an Azure AD application and service principal
  • Assigns a custom RBAC role at the subscription scope
  • Configures Microsoft Graph API permissions
  • Outputs credentials and deployment details

When the script is finished, copy the deployment details to a secure location.

Lastly, you’ll need to update Cloud Security (InsightCloudSec) with the deployment details.

To finish the onboarding process:

  1. Return to the Command Platform browser tab.
  2. Enter the Directory (Tenant) ID, Application (Client) ID, and Subscription ID for the subscription you are connecting.
  3. Enter the authentication details depending on the type you selected:
    1. API/Secret: Secret Key Value
    2. Client Certificate: PEM Certificate, Certificate Thumbprint
  4. Enter a Nickname for the Azure subscription. This is a unique value that can be used to search and filter across Cloud Security (InsightCloudSec).
  5. Click Connect Account.

Connect multiple subscriptions using management groups (tenant scope)

The onboarding script can configure tenant-level visibility across multiple subscriptions using management groups.

To generate the onboarding script:

  1. Log in to the Command Platform.
  2. Go to Data Connectors > Cloud Accounts.
  3. Click + Add Cloud.
  4. Select Microsoft Azure.
  5. Click Script.
  6. Select your Azure cloud environment (for example, Azure Commercial, Government, or China).
  7. Select Tenant/Root Management Group.
  8. Select an authentication type:
    • API/Secret
    • Client Certificate (recommended)
  9. Click Generate & Download Script.

To run the script:

  1. Open Azure Cloud Shell or a local terminal.

  2. Select the onboarding script from its downloaded location. The file is uploaded to /home/<name> by default.

  3. Recommended: run the script with the --read-only option to test your configuration, validate your permissions, and audit existing resources.

    python onboard.py --read-only --tenant-harvesting
  4. Run the script and follow the prompts. The script will not run with Python 2.

# Option 1: Basic interactive deployment python onboard.py --tenant-harvesting # Option 2: Deploy with custom parameters python onboard.py \ --name "Rapid7 InsightCloudSec" \ --use-certificate \ --tenant-harvesting \ --role 0

What happens:

The script reports on the status of the onboarding process:

  • The script detects tenant context
  • Creates a service principal
  • Creates or updates custom RBAC roles at tenant scope
  • Assigns roles across subscriptions
  • Enables organization-wide visibility

When the script is finished, copy the deployment details to a secure location.

Lastly, you’ll need to update Cloud Security (InsightCloudSec) with the deployment details.

To finish the onboarding process:

  1. Return to the Command Platform browser tab.
  2. Enter the Directory (Tenant) ID, Application (Client) ID, and Primary Subscription ID for the tenant you are connecting.
  3. Enter the authentication details depending on the type you selected:
    1. API/Secret: Secret Key Value
    2. Client Certificate: PEM Certificate, Certificate Thumbprint
  4. Enter a Nickname for the Azure tenant. This is a unique value that can be used to search and filter across Cloud Security (InsightCloudSec).
  5. Click Connect Account.

Script reference
Copy link

The onboarding script includes multiple options to customize or validate deployments. Use the help flag for the most up-to-date options:

python onboard.py --help
ℹ️

Many script options are pre-configured

Some options (like --use-certificate) may be pre-configured using environment variables (CHOSEN_ parameters) when generated from the platform.

Core script options

--help:

Display all available options.

python onboard.py --help

--read-only:

Run in read-only mode to validate configuration without making changes.

python onboard.py --read-only

--check-permissions:

Validate required Azure permissions before deployment.

python onboard.py --check-permissions

--verbose:

Enable detailed logging for troubleshooting.

python onboard.py --verbose

Script best practices

When running the script, use these best practices to ensure minimal friction:

  • Validate permissions before deployment.
  • Use read-only mode to test configurations.
  • Use certificate authentication for production environments.
  • Use tenant-level onboarding for centralized visibility.
  • Document deployment parameters for reuse.
  • Review role definitions before applying them.

Script security considerations

When connecting Rapid7 (or any product) to your Azure environment, you should always consider the following before deploying anything:

  • Review all RBAC roles to ensure least privilege.
  • Limit scope to only required subscriptions or tenants.
  • Regularly rotate credentials or certificates.
  • Monitor service principal activity in Azure AD logs.
  • Review Microsoft Graph API permissions granted during onboarding.

Common script use cases
Copy link

The most common use cases for the script (excluding onboarding) are as follows:

Check your Azure permissions

You may want to explicitly validate that your Azure credentials have the required permissions before attempting deployment or cleanup. Note that permission checks run automatically before every deployment unless --skip-permissions-check is provided.

To check your Azure permissions:

# Check deploy permissions python onboard.py --check-permissions # Check deploy permissions for tenant-level harvesting python onboard.py --check-permissions --tenant-harvesting # Check undeploy permissions python onboard.py --check-permissions --undeploy --name "My Service Principal"

How it works:

  1. Retrieves your current Azure identity
  2. Tests permissions against Azure Resource Manager API
  3. Reports results with detailed feedback on any missing permissions
    1. If this was an explicit permissions check, the script exits after showing results (does not proceed with deployment)
    2. If this was an automatic permissions check:
      • Passes: All permissions verified - proceeds with deployment
      • ⚠️ Fails: Missing permissions detected - warns but continues anyway
      • ℹ️ Skips: Suggest running with --check-permissions for detailed analysis if issues are detected
ℹ️

Don't have the required permissions?

See the Troubleshooting section for more details on how to prompt the correct person in your organization for the necessary connection details.

Enter read-only mode to prevent write operations

You may want to enable read-only mode to prevent all write operations (for example, role and principal creation) while allowing read-only Azure API calls for analysis. Read-only mode is useful for testing commands and validating configurations without making any changes.

python onboard.py --read-only --subscription-id <id>

Deploy non-interactively (automation)

You may want to deploy in an automated environment (for example, in a CI/CD pipeline or scripts).

To deploy non-interactively:

# Full non-interactive deployment with certificate python onboard.py \ --name "Rapid7 InsightCloudSec" \ --use-certificate \ --subscription-id <subscription-id> \ --tenant-harvesting \ --role 1 \ --non-interactive \ --quiet # With password authentication for simpler automation python onboard.py \ --name "Rapid7 ICS Prod" \ --no-certificate \ --subscription-id "$AZURE_SUBSCRIPTION_ID" \ --no-tenant-harvesting \ --role 0 \ --non-interactive

What happens:

  1. Validates credentials silently
  2. Script uses all provided parameters without prompts
  3. Creates service principal with specified authentication method
  4. Assigns specified role at appropriate scope
  5. Outputs credentials in parseable format
  6. Exits with appropriate status code

Azure DevOps example:

# azure-pipelines.yml steps: - task: AzureCLI@2 inputs: azureSubscription: 'Service Connection Name' scriptType: 'bash' scriptLocation: 'inlineScript' inlineScript: | python onboard.py \ --name "Rapid7 ICS $(Environment)" \ --use-certificate \ --subscription-id "$(SUBSCRIPTION_ID)" \ --tenant-harvesting \ --role 1 \ --non-interactive \ --quiet # Store output credentials in Key Vault az keyvault secret set \ --vault-name "$(KEY_VAULT_NAME)" \ --name "r7-ics-cert" \ --file rapid7_ics_cert.pem

GitHub Actions example:

# .github/workflows/azure-onboard.yml name: Deploy InsightCloudSec to Azure on: workflow_dispatch: inputs: environment: required: true type: choice options: - dev - staging - prod jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Azure Login uses: azure/login@v1 with: creds: ${{ secrets.AZURE_CREDENTIALS }} - name: Deploy InsightCloudSec run: | python onboard.py \ --name "Rapid7 ICS ${{ inputs.environment }}" \ --use-certificate \ --subscription-id "${{ secrets.AZURE_SUBSCRIPTION_ID }}" \ --role 1 \ --non-interactive

Download role definitions only

You may want to download the role definitions to review them before deployment.

To download all role definitions created by Rapid7:

# For subscriptions python onboard.py --download-roles-only <directory> # For tenants python onboard.py --download-roles-only <directory> --tenant-harvesting

All role definitions are downloaded as JSON from the Rapid7 content delivery network (CDN) and saved to the specified directory.

Update existing role

If a new Azure product is supported by Cloud Security (InsightCloudSec) or new permissions are required, you may want to update an existing role deployment with new policies or configuration.

To update an existing role:

# Update with change analysis python onboard.py --role <existing-role> --auto-update-roles

When you provide an existing role name to the onboarding script, it can automatically detect the existing role, analyze the changes necessary to update, and apply the changes.

Remove deployed resources

If you want to remove a principal and roles entirely, you can un-deploy the resources.

⚠️

Permanent operation

This operation permanently removes all resources associated with the connection.

To un-deploy onboarding artifacts:

# Delete the service principal and role assignments (but keep custom role definitions) python onboard.py --undeploy --role <role-to-remove> # Delete the service principal, role assignments, and custom role definitions python onboard.py --undeploy --role <test-role> --force-delete-all

List available roles

If you want to review available roles for onboarding, you can list them.

To list available roles:

python onboard.py --list-roles Available Role Templates: Role 0: Reader - Basic read-only access to Azure resources - Suitable for: Security posture assessment, compliance monitoring - Permissions: ~75 read actions Role 1: Reader Plus - Enhanced read permissions for deeper visibility - Suitable for: Vulnerability scanning, detailed inventory - Permissions: ~150 read actions Role 2: Power User - Read + limited write permissions - Suitable for: Automated remediation, configuration management - Permissions: ~200 read + 25 write actions

Advanced script use cases
Copy link

This section includes some niche, advanced use cases for the onboarding script:

Onboard multiple Azure AD tenants

When managing multiple Azure AD tenants:

# Login to specific tenant az login --tenant "tenant-id-1" # Deploy to first tenant python onboard.py --name "Rapid7 ICS Tenant1" --tenant-harvesting # Switch to second tenant az login --tenant "tenant-id-2" # Deploy to second tenant python onboard.py --name "Rapid7 ICS Tenant2" --tenant-harvesting

Manage credentials

The script generates self-signed certificates automatically, but you can also use existing certificates:

# Generate certificate externally openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 730 -nodes # The script will use its own certificate generation, but you can # modify the script to reference external certificates if needed

Certificate details:

  • Algorithm: RSA 4096-bit
  • Validity: 2 years (730 days)
  • Format: X.509 PEM
  • Storage: Local filesystem (handle securely!)

Troubleshooting
Copy link

What if the onboarding process fails?

  • Verify Azure CLI authentication (az login)
  • Ensure required permissions are assigned
  • Use --verbose for detailed logs
  • Run --check-permissions for diagnostics

If automatic permission checks fail, investigate with these commands:

# Check your current Azure identity az account show # List your role assignments az role assignment list --assignee "$(az ad signed-in-user show --query id -o tsv)" # Check specific permissions az role definition list --name "Owner" az role definition list --name "Contributor" # Test application registration permissions az ad app create --display-name "test-app" --sign-in-audience AzureADMyOrg az ad app delete --id "test-app-id"

What if I don’t have admin access in Azure?

As a non-admin user, you need to copy and send a message to an Azure admin user in your organization asking them to complete specific tasks and provide you with the information needed to complete onboarding.

⚠️

Non-admin users can only connect subscriptions

If you do not have Azure admin permissions, you can only onboard individual subscriptions. Azure admin users will need to onboard tenants.

  1. Log in to the Command Platform .
  2. Go to Data Connectors > Cloud Accounts.
  3. Click + Add Cloud.
  4. Click Microsoft Azure.
  5. Click Don’t have admin access?.
  6. Click Copy in the Microsoft Azure Admin Instructions text box and share them with the admin user.

When the admin has completed their steps and provided the information to you, you can now connect the account.

  1. Log in to the Command Platform .
  2. Go to Data Connectors > Cloud Accounts.
  3. Click + Add Cloud.
  4. Click Microsoft Azure.
  5. Enter the following information (provided by your admin):
    1. Select an Azure cloud environment.
    2. Enter a Nickname for the Azure subscription. This is a unique value that can be used to search and filter across Cloud Security (InsightCloudSec).
    3. Enter the Directory (Tenant) ID, Application (Client) ID, and Subscription ID for the subscription you are connecting.
    4. Select an authentication type:
      • API/Secret
      • Client Certificate (recommended)
    5. Enter the authentication details depending on the type you selected:
      1. API/Secret: Secret Key Value
      2. Client Certificate: PEM Certificate, Certificate Thumbprint
  6. Click Connect Account.

How do I turn on verbose logging?

The script has a debugging flag.

To use the --debug option:

python onboard.py --debug --role <role-name>

What if I’m getting a Failed to get Azure subscription information error?

This error is caused by the user not properly authenticating the Azure CLI or the Azure credentials expiring.

Solution:

# Check current authentication status az account show # Re-authenticate if needed az login # For service principal az login --service-principal \ --username "$APP_ID" \ --password "$PASSWORD" \ --tenant "$TENANT_ID" # For Azure Cloud Shell users: credentials should be automatic # If issues persist, try refreshing the session

What if I’m getting a Permission denied error?

This error is caused by the user having insufficient Azure permissions for required operations.

Solution:

Ensure your Azure user/role has:

  • Azure AD: Application.ReadWrite.All permission or Application Administrator role
  • IAM: User Access Administrator or Owner role at subscription or tenant scope
  • Microsoft Graph: Appropriate delegated or application permissions
# Check your role assignments az role assignment list --assignee "$(az ad signed-in-user show --query id -o tsv)" --all

What if I’m getting an Application registration name already exists error?

This error is caused by an existing application having the specified name in Azure Active Directory.

Solutions:

  1. Update existing application: Run script again with same name
  2. Use a different name:
    python onboard.py --name "Rapid7 ICS v2"
  3. Delete old application (if no longer needed):
    python onboard.py --undeploy --name "old-app-name"

What if I’m getting a Subscription not found error?

This error is caused by the user not having access to the specified subscription or the subscription doesn’t exist.

Solution:

# List available subscriptions az account list --output table # Set default subscription az account set --subscription "subscription-id" # Use correct subscription ID in script python onboard.py --subscription-id "correct-id"

What if I’m getting a Certificate generation fails error?

This error is caused by OpenSSL not being installed or not in PATH.

Solution:

# Check if OpenSSL is available openssl version # Install OpenSSL if missing (varies by OS) # Ubuntu/Debian: sudo apt-get install openssl # macOS: brew install openssl # Windows: # Download from https://slproweb.com/products/Win32OpenSSL.html # Alternative: Use password authentication python onboard.py --no-certificate

What if I’m getting a Management Group read access denied error?

This error is caused by the user not having permissions to read Management Groups.

Solutions:

  1. Request Management Group Reader role from Azure Administrator
  2. Use subscription-only scope instead:
    python onboard.py --no-tenant-harvesting
  3. Check current Management Group permissions:
    az account management-group list

What if the script is stuck or times out?

This error is often caused by network issues, Azure API throttling, or slow responses.

Solutions:

  1. Check network connectivity:
    az account show
  2. Run with verbose logging to see where it gets stuck:
    python onboard.py --verbose
  3. Retry after waiting (API throttling may resolve)
  4. Use Azure Cloud Shell for better connectivity