Onboard GCP projects and organizations with a Python script
Copy link

You can use a custom Python script (onboard.py) to programmatically create and configure GCP resources required for Rapid7 to collect data from your environment. The script automates service account creation, IAM role configuration, and permission assignments. If you would prefer an alternative onboarding method, review GCP Overview & Support.

Prerequisites
Copy link

CLI and software:

  • Python 3.10 or greater
  • GCP CLI installed and configured (gcloud command available)

General:

  • Appropriate GCP permissions:
    • Project scope:
      • Owner role or Editor, Project IAM Admin, and Service Account Admin roles
    • Organization scope:
      • Organization Admin role or Organization Viewer, Project IAM Admin, and Service Account Admin roles
  • Access to one or more GCP projects
  • Cloud Security (InsightCloudSec) Domain or Organization Admin permissions
  • Cloud Security (InsightCloudSec) administrative permissions
ℹ️

Not sure if you have the correct GCP permissions?

You can use the script to check your GCP 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 Account: A service account is a special type of Google account intended to represent a non-human user that needs to authenticate and be authorized to access data in Google APIs.
  • IAM Custom Roles: Custom IAM roles allow you to bundle one or more supported permissions to meet your specific needs. Unlike predefined roles, custom roles are defined at the organization or project level.
  • Role Assignment Scope:
    • Project: Monitors a single GCP project
    • Organization: Monitors all projects within a GCP organization
  • JSON Key Files: Service account authentication uses JSON key files that contain credentials. These keys should be stored securely and rotated regularly.

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 GCP project

The onboarding script can create a service account with credentials and assign permissions and roles to a single GCP project.

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 Google Cloud Platform.
  5. Click Script.
  6. Select Project.
  7. Click Generate & Download Script.

To run the script:

  1. Open a new tab and log in to the GCP console .

  2. Click the Activate Cloud Shell icon.

  3. Once the environment is finished loading, click More (…) > 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-organization-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 \ --service-account-name r7icsharvester \ --service-account-display-name Rapid7 InsightCloudSec \ --role-id Rapid7ICSHarvester \ --project-id <project-id> \ --no-organization-harvesting

What happens:

  • Validates GCP permissions
  • Creates a service account
  • Creates and assigns a custom IAM role at the project level
  • Generates a JSON key file for authentication

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 API Credentials and Project ID for the project you are connecting.
  3. Optionally, enter the Email Delegation (if configured).
  4. Enter a Nickname for the project. This is a unique value that can be used to search and filter across Cloud Security (InsightCloudSec).
  5. Click Connect Account.

Connect multiple projects using organizations (organization scope)

The onboarding script can configure organization-level visibility across multiple projects using organizations.

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 Google Cloud Platform.
  5. Click Script.
  6. Select Organization.
  7. Click Generate & Download Script.

To run the script:

  1. Open a new tab and log in to the GCP console .

  2. Click the Activate Cloud Shell icon.

  3. Once the environment is finished loading, click More (…) > 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 --organization-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 \ --service-account-name r7icsharvester \ --service-account-display-name Rapid7 InsightCloudSec \ --role-id Rapid7ICSHarvester \ --project-id <project-id> \ --organization-harvesting

What happens:

  • Detects organization context
  • Creates a service account in a host project
  • Creates a custom IAM role at the organization level
  • Assigns permissions across projects
  • Generates a JSON key file

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 API Credentials and Project ID for the organization you are connecting.
  3. Optionally, enter the Email Delegation (if configured).
  4. Enter a Nickname for the project. 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 --organization-harvesting) 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:

  • Check permissions first before attempting deployments using --check-permissions
  • Test with --read-only mode when working with new configurations
  • Use descriptive names that include environment or purpose (for example, “r7ics-prod”)
  • Store JSON keys securely in Secret Manager or equivalent secure storage
  • Rotate keys regularly (recommended: every 90 days)
  • Use organization scope only when multi-project visibility is required
  • Document service accounts for future reference and auditing
  • Monitor service account usage through Cloud Logging
  • Use separate service accounts for different environments (dev, staging, prod)
  • Enable audit logging to track service account activity

Script security considerations

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

  • Grant only the minimum permissions required for monitoring
  • Store JSON keys in secure vaults, never in code repositories or public locations
  • Replace service account keys periodically (recommended: every 90 days)
  • Monitor service account activity in Cloud Logging and Cloud Audit Logs
  • Use project-only scope unless organization-wide visibility is explicitly required
  • Restrict who can create and manage service accounts using IAM policies
  • Minimize the number of active keys per service account (delete unused keys)
  • Consider using Workload Identity Federation instead of key files when possible
  • Run deployment from trusted networks (Cloud Shell recommended)
  • Periodically audit custom role permissions and remove unnecessary access

Common script use cases
Copy link

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

Check your GCP permissions

You may want to explicitly validate that your GCP 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 --project-id my-project # Check deploy permissions for tenant-level harvesting python onboard.py --check-permissions --tenant-harvesting # Check undeploy permissions python onboard.py --check-permissions --undeploy

How it works:

  1. Script validates your gcloud CLI credentials are configured
  2. Tests permissions for service account management
  3. Tests permissions for custom role creation
  4. Tests permissions for IAM policy binding at required scope
  5. Provides clear feedback on missing permissions with guidance
    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 validate your configuration and parameters without making any changes to GCP.

# Test complete deployment configuration python onboard.py \ --read-only \ --service-account-name "test-account" \ --project-id "test-project" \ --organization-harvesting # Test undeploy operation python onboard.py --read-only --undeploy --service-account-name "existing-account"

What happens:

  1. Script simulates all operations without executing writes
  2. Shows what would be created/modified/deleted
  3. Validates all parameters and configurations
  4. Reports any issues that would occur
  5. Exits without making any changes

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 project scope python onboard.py \ --service-account-name "r7icsharvester" \ --project-id "my-gcp-project" \ --no-organization-harvesting \ --non-interactive \ --quiet # With organization-level harvesting python onboard.py \ --service-account-name "r7ics-org" \ --project-id "org-admin-project" \ --organization-harvesting \ --non-interactive \ --verbose

What happens:

  1. Automatic permission check validates credentials silently
  2. Script uses all provided parameters without prompts
  3. Creates service account with specified configuration
  4. Creates custom role with required permissions
  5. Assigns role at appropriate scope
  6. Generates JSON key file
  7. Exits with appropriate status code

Update existing service account

Update role permissions for an existing service account.

To update roles only:

# Update role permissions without prompting python onboard.py \ --service-account-name "r7icsharvester" \ --project-id "my-project" \ --update-role-permissions \ --auto-update-roles # Update to add organization-level harvesting python onboard.py \ --service-account-name "r7icsharvester" \ --project-id "my-project" \ --organization-harvesting \ --update-role-permissions \ --auto-update-roles

What happens:

  1. Script detects existing service account
  2. Compares current role permissions with latest template
  3. Updates role definition if different
  4. Re-assigns roles at new scope if needed
  5. Preserves existing JSON keys (doesn’t generate new ones)

Clean up resources

You may want to remove service account and role assignments when no longer needed. However, custom role definitions are not deleted to prevent disrupting other service accounts that might use them.

⚠️

This action is permanent

Undeploying a service account permanently deletes the account and any associated keys.

To undeploy a service account:

# Check undeploy permissions first python onboard.py --check-permissions --undeploy # Test undeploy with read-only mode python onboard.py --read-only --undeploy --service-account-name "r7icsharvester" # Perform actual undeploy python onboard.py --undeploy --service-account-name "r7icsharvester" # Non-interactive undeploy python onboard.py \ --undeploy \ --service-account-name "old-service-account" \ --project-id "my-project" \ --non-interactive

What happens:

  1. Automatic permission check validates you can delete resources
  2. Script locates service account by name
  3. Removes all IAM policy bindings
  4. Deletes all JSON keys associated with service account
  5. Deletes service account
  6. Preserves custom role definitions (can be reused)
  7. Confirms deletion

Multi-environment deployment

You may want to deploy separate service accounts for development, staging, and production environments.

Example:

# Development environment (single project) python onboard.py \ --service-account-name "r7ics-dev" \ --service-account-display-name "R7 ICS Development" \ --project-id "$DEV_PROJECT_ID" \ --no-organization-harvesting \ --key-filename "dev_key.json" \ --non-interactive # Staging environment (single project) python onboard.py \ --service-account-name "r7ics-staging" \ --service-account-display-name "R7 ICS Staging" \ --project-id "$STAGING_PROJECT_ID" \ --no-organization-harvesting \ --key-filename "staging_key.json" \ --non-interactive # Production environment (organization-wide) python onboard.py \ --service-account-name "r7ics-prod" \ --service-account-display-name "R7 ICS Production" \ --project-id "$PROD_PROJECT_ID" \ --organization-harvesting \ --key-filename "prod_key.json" \ --non-interactive

Service account key rotation

You may want to rotate service account keys for security compliance.

Example:

# Step 1: Verify existing service account works gcloud auth activate-service-account --key-file old_key.json gcloud projects list # Test access # Step 2: Generate new key by re-running deployment # (This creates a new key while preserving the service account) python onboard.py \ --service-account-name "r7icsharvester" \ --project-id "my-project" \ --key-filename "new_key.json" \ --non-interactive

Advanced Usage
Copy link

Working with Multiple Organizations

When managing multiple GCP organizations:

# Set active organization and project gcloud config set project project-in-org-1 gcloud organizations list gcloud config set organization ORG_ID_1 # Deploy to first organization python onboard.py \ --service-account-name "r7ics-org1" \ --organization-harvesting # Switch to second organization gcloud config set project project-in-org-2 gcloud config set organization ORG_ID_2 # Deploy to second organization python onboard.py \ --service-account-name "r7ics-org2" \ --organization-harvesting

Custom role permission management

The script creates a custom role with specific permissions, but you can modify the permissions as needed.

To modify permissions:

# View current role permissions gcloud iam roles describe Rapid7ICSCustomRole --project my-project # Update role with additional permissions gcloud iam roles update Rapid7ICSCustomRole \ --project my-project \ --add-permissions compute.instances.list,storage.buckets.list # Or use the script's update feature python onboard.py --update-role-permissions --auto-update-roles

Service account impersonation

For added security, you can use service account impersonation instead of key files:

# Grant your user account Service Account Token Creator role gcloud iam service-accounts add-iam-policy-binding \ r7icsharvester@my-project.iam.gserviceaccount.com \ --member="user:your-email@example.com" \ --role="roles/iam.serviceAccountTokenCreator" # Use impersonation instead of key file gcloud config set auth/impersonate_service_account \ r7icsharvester@my-project.iam.gserviceaccount.com # Test access gcloud projects list

Automating with CI/CD pipelines

Cloud Build example:

# cloudbuild.yaml steps: - name: 'gcr.io/cloud-builders/gcloud' entrypoint: 'bash' args: - '-c' - | python onboard.py \ --service-account-name "r7ics-${_ENVIRONMENT}" \ --project-id "${PROJECT_ID}" \ --organization-harvesting \ --key-filename "key_${_ENVIRONMENT}.json" \ --non-interactive # Store key in Secret Manager gcloud secrets create r7ics-key-${_ENVIRONMENT} \ --data-file="key_${_ENVIRONMENT}.json" \ --project="${PROJECT_ID}" substitutions: _ENVIRONMENT: 'prod'

GitHub Actions example:

# .github/workflows/gcp-onboard.yml name: Deploy InsightCloudSec to GCP 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: Authenticate to Google Cloud uses: google-github-actions/auth@v1 with: credentials_json: ${{ secrets.GCP_CREDENTIALS }} - name: Set up Cloud SDK uses: google-github-actions/setup-gcloud@v1 - name: Deploy InsightCloudSec run: | python onboard.py \ --service-account-name "r7ics-${{ inputs.environment }}" \ --project-id "${{ secrets.GCP_PROJECT_ID }}" \ --key-filename "${{ inputs.environment }}_key.json" \ --non-interactive

Terraform integration

You can also manage the service account with Terraform for infrastructure-as-code:

# terraform/main.tf resource "google_service_account" "r7ics" { account_id = "r7icsharvester" display_name = "Rapid7 InsightCloudSec Harvester" description = "Rapid7 InsightCloudSec harvester service account" project = var.project_id } resource "google_project_iam_custom_role" "r7ics_role" { role_id = "Rapid7ICSCustomRole" title = "Rapid7 ICS Custom Role" description = "Custom role for Rapid7 InsightCloudSec monitoring" project = var.project_id permissions = [ # Add required permissions here "compute.instances.list", "storage.buckets.list", # ... more permissions ] } resource "google_project_iam_member" "r7ics_binding" { project = var.project_id role = google_project_iam_custom_role.r7ics_role.id member = "serviceAccount:${google_service_account.r7ics.email}" } resource "google_service_account_key" "r7ics_key" { service_account_id = google_service_account.r7ics.name }

Troubleshooting
Copy link

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

As a non-admin user, you need to copy and send a message to a GCP 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 projects

If you do not have GCP admin permissions, you can only onboard individual projects. GCP admin users will need to onboard organizations.

  1. Log in to the Command Platform .
  2. Go to Data Connectors > Cloud Accounts.
  3. Click + Add Cloud.
  4. Click Google Cloud Platform.
  5. Click Don’t have admin access?.
  6. Click Copy in the Google Cloud Platform 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 Google Cloud Platform.
  5. Enter the following information (provided by your admin):
    1. Enter the API Credentials and Project ID for the project you are connecting.
    2. Optionally, enter the Email Delegation (if configured).
    3. Enter a Nickname for the project. This is a unique value that can be used to search and filter across Cloud Security (InsightCloudSec).
  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 GCP account information error?

This error is caused by the user not properly authenticating the gcloud CLI or the project is not set.

Solution:

# Check current authentication status gcloud auth list gcloud config get-value project # Re-authenticate if needed gcloud auth login # Set default project gcloud config set project PROJECT_ID # For Cloud Shell users: credentials should be automatic # If issues persist, try refreshing the session ```issues persist, try refreshing the session

What if I’m getting a Permission denied error?

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

Solution:

Ensure your GCP user/account has appropriate roles:

For Project Scope:

# Check your project-level roles gcloud projects get-iam-policy PROJECT_ID \ --flatten="bindings[].members" \ --filter="bindings.members:user:YOUR_EMAIL" # Required roles (choose one): # - roles/owner, OR # - roles/editor + roles/iam.projectIamAdmin + roles/iam.serviceAccountAdmin

For Organization Scope:

# Check your organization-level roles gcloud organizations get-iam-policy ORG_ID \ --flatten="bindings[].members" \ --filter="bindings.members:user:YOUR_EMAIL" # Required roles (choose one): # - roles/resourcemanager.organizationAdmin, OR # - roles/resourcemanager.organizationViewer + roles/iam.projectIamAdmin + # roles/iam.serviceAccountAdmin

What if I’m getting a Service account name already exists error?

This error is caused by an existing service account having the specified name in the project.

Solutions:

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

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

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

Solution:

# List available projects gcloud projects list # Verify project exists and you have access gcloud projects describe PROJECT_ID # Use correct project ID in script python onboard.py --project-id "correct-project-id"

What if I’m getting a Custom role limit exceeded error?

This error is caused by GCP-enforced limits on custom roles per project and organization.

Solutions:

  1. Delete unused custom roles:
    # List custom roles gcloud iam roles list --project PROJECT_ID # Delete unused role gcloud iam roles delete ROLE_ID --project PROJECT_ID
  2. Modify script to reuse existing role
  3. Request quota increase by contacting Google Cloud Support

What if I’m getting an Organization not found error?

This error is caused by the specificed project not being part of an organization or not having the Organization Viewer role.

Solutions:

  1. Verify organization exists:
    gcloud organizations list
  2. Check if project is in organization:
    gcloud projects describe PROJECT_ID --format="value(parent)"
  3. Use project-only scope if no organization:
    python onboard.py --no-organization-harvesting
  4. Request Organization Viewer role from GCP Administrator

What if I’m getting an API not enabled error?

This error is caused by the required GCP APIs not being enabled in the project.

Solution:

# Enable required APIs gcloud services enable iam.googleapis.com gcloud services enable cloudresourcemanager.googleapis.com gcloud services enable compute.googleapis.com gcloud services enable storage.googleapis.com # Or enable all at once gcloud services enable \ iam.googleapis.com \ cloudresourcemanager.googleapis.com \ compute.googleapis.com \ storage.googleapis.com # List currently enabled services gcloud services list --enabled

What if the script is stuck or times out?

This error is often caused by network issues, API rate limiting, or slow responses.

Solutions:

  1. Check network connectivity:
    gcloud projects list
  2. Run with verbose logging to see where it gets stuck:
    python onboard.py --verbose
  3. Retry after waiting (API rate limiting may resolve)
  4. Use Cloud Shell for better connectivity and performance