Permissions for onboarding GCP
This section describes the set of permissions that you grant to Illumio Cloud.
By participating in the BETA program for GCP features you agree that your company’s use of the BETA version of GCP features will be governed by Illumio’s Beta Terms and Conditions.
Permission Type | Permission Name | Notes |
---|---|---|
Read | roles/iam.securityReviewer (link lists all resources) | This role gives Illumio Cloud the permissions to read data or resources from your organization or project. This role allows the viewing of all resources, but does not allow modification. This role can be truncated to the following minimum resource permissions. (Limiting permissions to cloud services currently supported by Illumio Cloud):
Although Illumio Cloud does not currently support every resource listed in the full securityReviewer role, if you do not truncate the role, Illumio Cloud assigns all the resource permissions so that you don't have to update permissions each time Illumio supports additional resources. |
Read | roles/compute.viewer (link lists all resources) | This role gives Illumio Cloud the permissions to read compute resources from your organization or project. This role allows the viewing of all resources, but does not allow modification. The full role is required, so truncation is not supported. |
Read | roles/browser (link lists all resources) | Required for organization and folder onboarding. This role gives Illumio Cloud the permissions to read organization projects and folders. The full role is required, so truncation is not supported. |
Read | roles/cloudasset.viewer (link lists all resources) | This role gives Illumio Cloud the permissions to read cloud asset resources from your organization or project. This role allows the viewing of all resources, but does not allow modification. The full role is required, so truncation is not supported. |
Read Flows | IllumioPubSubFlowLogAccess | This custom role gives Illumio Cloud the permissions to read flows by creating and attaching subscriptions. The permission is also sought for offboarding flow access workflows. The full role is required, so truncation is not supported. This role assigns the following resource permissions:
|
Read Flows | IllumioPubSubAccessRole | This custom role gives Illumio Cloud the permissions to read flows by creating and attaching subscriptions. The permission is also sought for offboarding flow access workflows. This role assigns the following resource permissions:
|
Write | illumio_api_enable_role | This custom role gives Illumio Cloud the permissions to enable APIs. The full role is required, so truncation is not supported. This role assigns the following resource permissions:
|
Write | illumio_write_role | This custom role gives Illumio Cloud the permissions to modify data or resources in your organization or project. This role allows the modification of resources. Enable read-write mode from in the onboarding wizard to create the role. The full role is required, so truncation is not supported. This role assigns the following resource permissions:
|
Permissions script example
When you grant read and write permissions to Illumio Cloud, the gcp_onboarding_prod.sh script below creates roles and sets permissions. The script prompts you for permission to enable APIs. Enabling APIs is optional, but Illumio Cloud functionality is affected if you don't enable APIs.
Note
If billing is not enabled for your projects, Illumio Cloud cannot enable APIs.
#!/bin/bash #Constants RESOURCE_TYPE_PROJECT="project" RESOURCE_TYPE_ORGANIZATION="organization" RESOURCE_TYPE_FOLDER="folder" DEFAULT_ROLE_NAME="illumio_role_$(date +%s)" DEFAULT_SA_NAME="illumio-sa-$(date +%s)" DEFAULT_SA_DISPLAY_NAME="Illumio Service Account" DEFAULT_POST_URL="https://cloud.illum.io" PREDEFINED_ROLES="roles/iam.securityReviewer,roles/compute.viewer,roles/cloudasset.viewer" DEFAULT_WRITE_ROLE_NAME="illumio_write_role_$(date +%s)" WRITE_PERMISSIONS="compute.firewalls.create,compute.firewalls.delete,compute.firewalls.get,compute.firewalls.update,compute.networks.updatePolicy" DEFAULT_API_ENABLE_ROLE_NAME="illumio_api_enable_role_$(date +%s)" API_ENABLE_PERMISSION="serviceusage.services.enable,serviceusage.services.list,serviceusage.services.get" ILLUMIO_SA_EMAIL="[email protected]" GREEN='\033[32m' RESET='\033[0m' RED='\033[31m' # Resource tracking created_resources__service_accounts="" created_resources__roles="" RESOURCE_TYPE="$RESOURCE_TYPE_PROJECT" # using default resource type as object, based on if organization id is passed in arguments, it changes to "$RESOURCE_TYPE_ORGANIZATION" # Function to add a resource to the tracking list - these lists will be used to clean up resources in case of an error add_resource() { local resource_type=$1 local resource_value=$2 local var_name="created_resources__${resource_type}" if [[ -z "${!var_name}" ]]; then eval "$var_name=\"$resource_value\"" else eval "$var_name=\"${!var_name},$resource_value\"" fi } # Cleanup function for errors (triggered by trap) cleanup() { if [ "$1" == "0" ]; then return fi echo -e "${RED}Cleaning up resources...${RESET}" # Delete service accounts IFS=',' read -ra SAS <<< "${created_resources__service_accounts}" for sa in "${SAS[@]}"; do echo -e "${RED}Deleting service account: $sa${RESET}" if ! gcloud iam service-accounts delete "$sa" --quiet --project="$PROJECT_ID"; then echo -e "${RED}Failed to delete service account: $sa${RESET}" fi done # Delete roles IFS=',' read -ra ROLES <<< "${created_resources__roles}" for role in "${ROLES[@]}"; do echo -e "${RED}Deleting IAM role: $role${RESET}" if [ "$RESOURCE_TYPE" == "$RESOURCE_TYPE_ORGANIZATION" ]; then if ! gcloud iam roles delete "$role" --organization="$ORGANIZATION_ID" --quiet; then echo -e "${RED}Failed to delete IAM role: $role${RESET}" fi else if ! gcloud iam roles delete "$role" --project="$PROJECT_ID" --quiet; then echo -e "${RED}Failed to delete IAM role: $role${RESET}" fi fi done echo -e "${GREEN}DONE${RESET}" } # Error handling setup set -e trap 'cleanup $?' EXIT print_usage() { echo "Usage: $0 --project-id PROJECT_ID --auth-key AUTH_KEY --auth-secret AUTH_SECRET --tenant-id CS_TENANT_ID [--organization-id ORGANIZATION_ID] [--read-write] [--role-name ROLE_NAME] [--sa-name SA_NAME] [--sa-display-name SA_DISPLAY_NAME] [--illumio-sa-email ILLUMIO_SA_EMAIL] [--post-url POST_URL]" echo " --project-id PROJECT_ID Specify the GCP project ID (mandatory)" echo " --post-url POST_URL Specify the POST URL (optional)" echo " --role-name ROLE_NAME Specify the role name (optional)" echo " --sa-name SA_NAME Specify the service account name (optional)" echo " --sa-display-name SA_DISPLAY_NAME Specify the service account display name (optional)" echo " --illumio-sa-email ILLUMIO_SA_EMAIL Specify the Illumio service account email (optional)" echo " --auth-key AUTH_KEY Specify the authentication key for basic auth to Illumio endpoint (mandatory)" echo " --auth-secret AUTH_SECRET Specify the authentication secret for basic auth Illumio endpoint (mandatory)" echo " --tenant-id CS_TENANT_ID Specify the tenant ID for HTTP requests (mandatory)" echo " --organization-id ORGANIZATION_ID Specify the GCP organization ID (optional)" echo " --folder-id FOLDER_ID Specify the GCP folder ID (optional)" echo " --read-write Enable read-write mode (optional)" exit 1 } # Parse arguments READ_WRITE_MODE=false while [[ $# -gt 0 ]]; do case $1 in --project-id) PROJECT_ID="$2"; shift 2 ;; --post-url) POST_URL="$2"; shift 2 ;; --role-name) ROLE_NAME="$2"; shift 2 ;; --sa-name) SA_NAME="$2"; shift 2 ;; --sa-display-name) SA_DISPLAY_NAME="$2"; shift 2 ;; --illumio-sa-email) ILLUMIO_SA_EMAIL="$2"; shift 2 ;; --organization-id) ORGANIZATION_ID="$2"; shift 2 ;; --folder-id) FOLDER_ID="$2"; shift 2 ;; --read-write) READ_WRITE_MODE=true; shift ;; --auth-key) AUTH_KEY="$2"; shift 2 ;; --auth-secret) AUTH_SECRET="$2"; shift 2 ;; --tenant-id) CS_TENANT_ID="$2"; shift 2 ;; *) echo "Unknown option: $1"; print_usage ;; esac done # Validate mandatory parameters if [ -z "$PROJECT_ID" ] || [ -z "$AUTH_KEY" ] || [ -z "$AUTH_SECRET" ] || [ -z "$CS_TENANT_ID" ]; then # echo "$PROJECT_ID $AUTH_KEY $AUTH_SECRET $CS_TENANT_ID" echo "Error: Project id, auth key, secret and tenant id are mandatory." print_usage fi # Set default values if not provided ROLE_NAME="${ROLE_NAME:-$DEFAULT_ROLE_NAME}" SA_NAME="${SA_NAME:-$DEFAULT_SA_NAME}" SA_DISPLAY_NAME="${SA_DISPLAY_NAME:-$DEFAULT_SA_DISPLAY_NAME}" POST_URL="${POST_URL:-$DEFAULT_POST_URL}" # Validate PROJECT_ID if ! [[ "$PROJECT_ID" =~ ^[a-zA-Z][a-zA-Z0-9_-]*$ ]]; then echo -e "${RED}Error: Invalid PROJECT_ID. It must start with a letter and can only contain alphanumeric characters, hyphens, or underscores.${RESET}" exit 1 fi # Validate POST_URL if ! [[ "$POST_URL" =~ ^https?:// ]]; then echo -e "${RED}Error: Invalid POST_URL. It must start with http:// or https://.${RESET}" exit 1 fi # Validate ROLE_NAME if [ ${#ROLE_NAME} -gt 64 ]; then echo -e "${RED}Error: ROLE_NAME must not exceed 64 characters.${RESET}" exit 1 fi # Validate SA_NAME if [ ${#SA_NAME} -gt 30 ]; then echo -e "${RED}Error: SA_NAME must not exceed 30 characters.${RESET}" exit 1 fi # Validate SA_DISPLAY_NAME if [ ${#SA_DISPLAY_NAME} -gt 100 ]; then echo -e "${RED}Error: SA_DISPLAY_NAME must not exceed 100 characters.${RESET}" exit 1 fi # Validate ILLUMIO_SA_EMAIL if ! [[ "$ILLUMIO_SA_EMAIL" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9_-]+\.iam\.gserviceaccount\.com$ ]]; then echo -e "${RED}Error: Invalid ILLUMIO_SA_EMAIL. It must be a valid email address.${RESET}" exit 1 fi # Validate PROJECT_ID if ! [[ "$PROJECT_ID" =~ ^[a-zA-Z][a-zA-Z0-9_-]*$ ]]; then echo -e "${RED}Error: Invalid PROJECT_ID '$PROJECT_ID'. It must start with a letter and can only contain alphanumeric characters, hyphens, or underscores.${RESET}" exit 1 fi # Determine resource type based on folder ID or organization ID presence if [ -n "$FOLDER_ID" ] && [ -n "$ORGANIZATION_ID" ]; then RESOURCE_TYPE="$RESOURCE_TYPE_FOLDER" RESOURCE_ID="$FOLDER_ID" echo "Operating at folder level: $FOLDER_ID" # Validate folder ID format (typically numeric) if ! [[ "$FOLDER_ID" =~ ^[0-9]+$ ]]; then echo -e "${RED}Error: Invalid FOLDER_ID. It must be numeric.${RESET}" exit 1 fi # Validate organization ID format (typically numeric) # This is required for folder onboarding to create custom IAM role if ! [[ "$ORGANIZATION_ID" =~ ^[0-9]+$ ]]; then echo -e "${RED}Error: Invalid ORGANIZATION_ID. It must be numeric. Organization id is required to create custom IAM role for folder onboarding${RESET}" exit 1 fi elif [ -n "$ORGANIZATION_ID" ]; then RESOURCE_TYPE="$RESOURCE_TYPE_ORGANIZATION" RESOURCE_ID="$ORGANIZATION_ID" echo "Operating at organization level: $ORGANIZATION_ID" # Validate organization ID format (typically numeric) if ! [[ "$ORGANIZATION_ID" =~ ^[0-9]+$ ]]; then echo -e "${RED}Error: Invalid ORGANIZATION_ID. It must be numeric.${RESET}" exit 1 fi else RESOURCE_TYPE="$RESOURCE_TYPE_PROJECT" RESOURCE_ID="$PROJECT_ID" echo "Operating at project level: $PROJECT_ID" fi # READ_WRITE_MODE if $READ_WRITE_MODE; then echo "Read-write mode enabled." else echo "Read-only mode." fi # Function to set the active project set_project() { local project_id=$1 echo "Setting active project to $project_id..." gcloud config set project "$project_id" echo -e "${GREEN}DONE${RESET}" } # Function to create service account create_service_account() { local project_id=$1 local sa_name=$2 local sa_display_name=$3 echo "Creating service account..." gcloud iam service-accounts create "$sa_name" \ --display-name="$sa_display_name" \ --project="$project_id" \ --quiet #creating service account email using the service account name and project id local sa_email="${sa_name}@${project_id}.iam.gserviceaccount.com" echo "$sa_email" } # Function to create IAM role create_iam_role() { local resource_type=$1 local resource_id=$2 local role_name=$3 local permissions=$4 local organization_id=$5 echo "Creating custom IAM role..." if [ "$resource_type" == "$RESOURCE_TYPE_PROJECT" ]; then gcloud iam roles create "$role_name" \ --project="$resource_id" \ --title="$role_name" \ --description="Custom role for listing and getting storage and VPCs" \ --permissions="$permissions" \ --stage="GA" \ --quiet > /dev/null elif [ "$resource_type" == "$RESOURCE_TYPE_ORGANIZATION" ]; then gcloud iam roles create "$role_name" \ --organization="$resource_id" \ --title="$role_name" \ --description="Custom role for organization-level permissions" \ --permissions="$permissions" \ --stage="GA" \ --quiet > /dev/null elif [ "$resource_type" == "$RESOURCE_TYPE_FOLDER" ]; then # iam role could only be created at project/organization level, for folder onboarding creating it at organization level gcloud iam roles create "$role_name" \ --organization="$organization_id" \ --title="$role_name" \ --description="Custom role for folder-level permissions" \ --permissions="$permissions" \ --stage="GA" \ --quiet > /dev/null fi add_resource "roles" "$role_name" echo -e "${GREEN}DONE${RESET}" } # Function to bind IAM role to service account bind_role_to_service_account() { local resource_type=$1 local resource_id=$2 local sa_email=$3 local role_name=$4 local organization_id=$5 echo "Binding custom IAM role to service account..." if [ "$resource_type" == "$RESOURCE_TYPE_PROJECT" ]; then gcloud projects add-iam-policy-binding "$resource_id" \ --member="serviceAccount:$sa_email" \ --role="projects/$resource_id/roles/$role_name" \ --condition=None \ --quiet > /dev/null elif [ "$resource_type" == "$RESOURCE_TYPE_ORGANIZATION" ]; then gcloud organizations add-iam-policy-binding "$resource_id" \ --member="serviceAccount:$sa_email" \ --role="organizations/$resource_id/roles/$role_name" \ --condition=None \ --quiet > /dev/null elif [ "$resource_type" == "$RESOURCE_TYPE_FOLDER" ]; then gcloud resource-manager folders add-iam-policy-binding "$resource_id" \ --member="serviceAccount:$sa_email" \ --role="organizations/$organization_id/roles/$role_name" \ --condition=None \ --quiet > /dev/null fi echo -e "${GREEN}DONE${RESET}" } # Function to assign predefined role to service account assign_predefined_role() { local resource_type=$1 local resource_id=$2 local sa_email=$3 local role=$4 echo "Assigning predefined role $role to service account..." if [ "$resource_type" == "$RESOURCE_TYPE_PROJECT" ]; then gcloud projects add-iam-policy-binding "$resource_id" \ --member="serviceAccount:$sa_email" \ --role="$role" \ --condition=None \ --quiet > /dev/null elif [ "$resource_type" == "$RESOURCE_TYPE_ORGANIZATION" ]; then gcloud organizations add-iam-policy-binding "$resource_id" \ --member="serviceAccount:$sa_email" \ --role="$role"\ --condition=None \ --quiet > /dev/null elif [ "$resource_type" == "$RESOURCE_TYPE_FOLDER" ]; then gcloud resource-manager folders add-iam-policy-binding "$resource_id" \ --member="serviceAccount:$sa_email" \ --role="$role" \ --condition=None \ --quiet > /dev/null fi echo -e "${GREEN}DONE${RESET}" } # Function to enable impersonation permissions enable_impersonation_permissions() { local sa_email=$1 local project_id=$2 local illumio_sa_email=$3 echo "Configuring impersonation permissions..." gcloud iam service-accounts add-iam-policy-binding "$sa_email" \ --member="serviceAccount:$illumio_sa_email" \ --role="roles/iam.serviceAccountTokenCreator" \ --project="$project_id" \ --condition=None \ --quiet > /dev/null echo -e "${GREEN}DONE${RESET}" } send_data_to_endpoint() { local sa_email=$1 local resource_id=$2 local project_id=$3 local post_url=$4 local tenant_id=$5 local auth_key=$6 # Basic Authentication key local auth_secret=$7 # Basic Authentication secret local event=$8 local resource_type=$9 if [[ "$post_url" != *"proxy"* ]] || [[ "$post_url" == *"sunnyvale"* ]]; then post_url="$post_url/api/v1/integrations/cloud_credentials" fi # Determine onboarding_type based on resource_type local integration_type="" if [ "$resource_type" == "project" ]; then integration_type="GcpProject" elif [ "$resource_type" == "folder" ]; then integration_type="GcpFolder" elif [ "$resource_type" == "organization" ]; then integration_type="GcpOrganization" else echo "Error: Invalid resource_type provided." exit 1 fi echo "Sending resource ID, service account email, and project ID to $post_url" # Perform the HTTP POST request with Basic Authentication and custom headers response=$(curl -s -w "\n%{http_code}" -X POST \ -H "Content-Type: application/json" \ -H "Authorization: Basic $(echo -n "$auth_key:$auth_secret" | base64 | tr -d '\n')" \ -H "X-Tenant-Id: $tenant_id" \ -d "{\"sa_email\":\"$sa_email\",\"gcp_resource_id\":\"$resource_id\",\"project_csp_id\":\"$project_id\",\"type\":\"$event\",\"integration_type\":\"$integration_type\"}" \ "$post_url") # Extract the response body and status code body=$(echo "$response" | sed '$d') # Remove last line (status code) status_code=$(echo "$response" | tail -n1) # Extract last line (status code) # Check the HTTP status code if [ "$status_code" -ge 200 ] && [ "$status_code" -lt 300 ]; then echo "POST request successful. Response:" echo "$body" else echo "Error: POST request failed with status code $status_code. Response:" echo "$body" exit 1 # Trigger cleanup via ERR trap if there's an error. fi } # Function to check if gcloud CLI is available check_gcloud_availability() { if ! command -v gcloud &> /dev/null; then echo -e "${RED}Error: gcloud CLI is not available. Please install and configure it before running this script.${RESET}" exit 1 fi echo "gcloud CLI is available. Proceeding with the script." } # Function to enable specific APIs for a project enable_apis_for_project() { local project_id=$1 echo "Enabling APIs (iamcredentials.googleapis.com, cloudresourcemanager.googleapis.com) for project $project_id..." if ! gcloud services enable iamcredentials.googleapis.com cloudresourcemanager.googleapis.com --project="$project_id" --quiet; then echo -e "${RED}Failed to enable required APIs for project $project_id.${RESET}" exit 1 fi echo -e "${GREEN}DONE${RESET}" } # Main execution sequence main() { check_gcloud_availability if [ "$RESOURCE_TYPE" == "$RESOURCE_TYPE_PROJECT" ]; then set_project "$PROJECT_ID" fi # TODO: Check user permissions before proceeding SA_EMAIL=$(create_service_account "$PROJECT_ID" "$SA_NAME" "$SA_DISPLAY_NAME" | tail -n 1) # doing add_resource here for service account because we are using a pipe (| tail -n 1) when calling the function, which creates a subshell. # Variables modified in subshells do not propagate back to the parent shell, hence the added service account was not visible in cleanup function add_resource "service_accounts" "$SA_EMAIL" # Prompt user for consent to enable APIs for Illumio-supported resources echo "Do you allow Illumio to enable APIs for supported resources at the time of ingestion? (y/N)" read -r consent if [[ "$consent" == "y" || "$consent" == "Y" ]]; then echo "User consented to enable APIs for Illumio-supported resources." create_iam_role "$RESOURCE_TYPE" "$RESOURCE_ID" "$DEFAULT_API_ENABLE_ROLE_NAME" "$API_ENABLE_PERMISSION" "$ORGANIZATION_ID" bind_role_to_service_account "$RESOURCE_TYPE" "$RESOURCE_ID" "$SA_EMAIL" "$DEFAULT_API_ENABLE_ROLE_NAME" "$ORGANIZATION_ID" else echo "User did not consent to enable APIs for Illumio-supported resources." fi # Convert the comma-separated list into an array and loop through it IFS=',' read -ra ROLES_ARRAY <<< "$PREDEFINED_ROLES" for role in "${ROLES_ARRAY[@]}"; do assign_predefined_role "$RESOURCE_TYPE" "$RESOURCE_ID" "$SA_EMAIL" "$role" done enable_impersonation_permissions "$SA_EMAIL" "$PROJECT_ID" "$ILLUMIO_SA_EMAIL" # required to list projects under the organization or folder if [ "$RESOURCE_TYPE" == "$RESOURCE_TYPE_ORGANIZATION" ] || [ "$RESOURCE_TYPE" == "$RESOURCE_TYPE_FOLDER" ]; then assign_predefined_role "$RESOURCE_TYPE" "$RESOURCE_ID" "$SA_EMAIL" "roles/browser" fi # Check if READ_WRITE_MODE is true to create and bind IAM role with WRITE_PERMISSIONS if $READ_WRITE_MODE; then echo "Read-write mode is enabled. Creating IAM role with write permissions..." create_iam_role "$RESOURCE_TYPE" "$RESOURCE_ID" "$DEFAULT_WRITE_ROLE_NAME" "$WRITE_PERMISSIONS" "$ORGANIZATION_ID" bind_role_to_service_account "$RESOURCE_TYPE" "$RESOURCE_ID" "$SA_EMAIL" "$DEFAULT_WRITE_ROLE_NAME" "$ORGANIZATION_ID" fi # Enable APIs for the project to allow impersonation and cloudresourcemanager to read child resources enable_apis_for_project "$PROJECT_ID" send_data_to_endpoint "$SA_EMAIL" "$RESOURCE_ID" "$PROJECT_ID" "$POST_URL" "$CS_TENANT_ID" "$AUTH_KEY" "$AUTH_SECRET" "GCPRole" "$RESOURCE_TYPE" } main echo -e "${GREEN}Script executed successfully.${RESET}"#!/bin/bash #Constants RESOURCE_TYPE_PROJECT="project" RESOURCE_TYPE_ORGANIZATION="organization" RESOURCE_TYPE_FOLDER="folder" DEFAULT_ROLE_NAME="illumio_role_$(date +%s)" DEFAULT_SA_NAME="illumio-sa-$(date +%s)" DEFAULT_SA_DISPLAY_NAME="Illumio Service Account" DEFAULT_POST_URL="https://cloud.illum.io" PREDEFINED_ROLES="roles/iam.securityReviewer,roles/compute.viewer,roles/cloudasset.viewer" DEFAULT_WRITE_ROLE_NAME="illumio_write_role_$(date +%s)" WRITE_PERMISSIONS="compute.firewalls.create,compute.firewalls.delete,compute.firewalls.get,compute.firewalls.update,compute.networks.updatePolicy" DEFAULT_API_ENABLE_ROLE_NAME="illumio_api_enable_role_$(date +%s)" API_ENABLE_PERMISSION="serviceusage.services.enable,serviceusage.services.list,serviceusage.services.get" # Resource tracking created_resources__service_accounts="" created_resources__roles="" RESOURCE_TYPE="$RESOURCE_TYPE_PROJECT" # using default resource type as object, based on if organization id is passed in arguments, it changes to "$RESOURCE_TYPE_ORGANIZATION" # Function to add a resource to the tracking list - these lists will be used to clean up resources in case of an error add_resource() { local resource_type=$1 local resource_value=$2 local var_name="created_resources__${resource_type}" if [[ -z "${!var_name}" ]]; then eval "$var_name=\"$resource_value\"" else eval "$var_name=\"${!var_name},$resource_value\"" fi } # Cleanup function for errors (triggered by trap) cleanup() { if [ "$1" == "0" ]; then return fi echo "Cleaning up resources..." # Delete service accounts IFS=',' read -ra SAS <<< "${created_resources__service_accounts}" for sa in "${SAS[@]}"; do echo "Deleting service account: $sa" gcloud iam service-accounts delete "$sa" --quiet --project="$PROJECT_ID" || true done # Delete roles IFS=',' read -ra ROLES <<< "${created_resources__roles}" for role in "${ROLES[@]}"; do echo "Deleting IAM role: $role" if [ "$RESOURCE_TYPE" == "$RESOURCE_TYPE_ORGANIZATION" ]; then gcloud iam roles delete "$role" --organization="$ORGANIZATION_ID" --quiet || true else gcloud iam roles delete "$role" --project="$PROJECT_ID" --quiet || true fi done } # Error handling setup set -e trap 'cleanup $?' EXIT ILLUMIO_SA_EMAIL="[email protected]" print_usage() { echo "Usage: $0 --project-id PROJECT_ID --auth-key AUTH_KEY --auth-secret AUTH_SECRET --tenant-id CS_TENANT_ID [--organization-id ORGANIZATION_ID] [--read-write] [--role-name ROLE_NAME] [--sa-name SA_NAME] [--sa-display-name SA_DISPLAY_NAME] [--illumio-sa-email ILLUMIO_SA_EMAIL] [--post-url POST_URL]" echo " --project-id PROJECT_ID Specify the GCP project ID (mandatory)" echo " --post-url POST_URL Specify the POST URL (optional)" echo " --role-name ROLE_NAME Specify the role name (optional)" echo " --sa-name SA_NAME Specify the service account name (optional)" echo " --sa-display-name SA_DISPLAY_NAME Specify the service account display name (optional)" echo " --illumio-sa-email ILLUMIO_SA_EMAIL Specify the Illumio service account email (optional)" echo " --auth-key AUTH_KEY Specify the authentication key for basic auth to Illumio endpoint (mandatory)" echo " --auth-secret AUTH_SECRET Specify the authentication secret for basic auth Illumio endpoint (mandatory)" echo " --tenant-id CS_TENANT_ID Specify the tenant ID for HTTP requests (mandatory)" echo " --organization-id ORGANIZATION_ID Specify the GCP organization ID (optional)" echo " --folder-id FOLDER_ID Specify the GCP folder ID (optional)" echo " --read-write Enable read-write mode (optional)" exit 1 } # Parse arguments READ_WRITE_MODE=false while [[ $# -gt 0 ]]; do case $1 in --project-id) PROJECT_ID="$2"; shift 2 ;; --post-url) POST_URL="$2"; shift 2 ;; --role-name) ROLE_NAME="$2"; shift 2 ;; --sa-name) SA_NAME="$2"; shift 2 ;; --sa-display-name) SA_DISPLAY_NAME="$2"; shift 2 ;; --illumio-sa-email) ILLUMIO_SA_EMAIL="$2"; shift 2 ;; --organization-id) ORGANIZATION_ID="$2"; shift 2 ;; --folder-id) FOLDER_ID="$2"; shift 2 ;; --read-write) READ_WRITE_MODE=true; shift ;; --auth-key) AUTH_KEY="$2"; shift 2 ;; --auth-secret) AUTH_SECRET="$2"; shift 2 ;; --tenant-id) CS_TENANT_ID="$2"; shift 2 ;; *) echo "Unknown option: $1"; print_usage ;; esac done # Validate mandatory parameters if [ -z "$PROJECT_ID" ] || [ -z "$AUTH_KEY" ] || [ -z "$AUTH_SECRET" ] || [ -z "$CS_TENANT_ID" ]; then # echo "$PROJECT_ID $AUTH_KEY $AUTH_SECRET $CS_TENANT_ID" echo "Error: Project id, auth key, secret and tenant id are mandatory." print_usage fi # Set default values if not provided ROLE_NAME="${ROLE_NAME:-$DEFAULT_ROLE_NAME}" SA_NAME="${SA_NAME:-$DEFAULT_SA_NAME}" SA_DISPLAY_NAME="${SA_DISPLAY_NAME:-$DEFAULT_SA_DISPLAY_NAME}" POST_URL="${POST_URL:-$DEFAULT_POST_URL}" # Validate PROJECT_ID if ! [[ "$PROJECT_ID" =~ ^[a-zA-Z][a-zA-Z0-9_-]*$ ]]; then echo "Error: Invalid PROJECT_ID. It must start with a letter and can only contain alphanumeric characters, hyphens, or underscores." exit 1 fi # Validate POST_URL if ! [[ "$POST_URL" =~ ^https?:// ]]; then echo "Error: Invalid POST_URL. It must start with http:// or https://." exit 1 fi # Validate ROLE_NAME if [ ${#ROLE_NAME} -gt 64 ]; then echo "Error: ROLE_NAME must not exceed 64 characters." exit 1 fi # Validate SA_NAME if [ ${#SA_NAME} -gt 30 ]; then echo "Error: SA_NAME must not exceed 30 characters." exit 1 fi # Validate SA_DISPLAY_NAME if [ ${#SA_DISPLAY_NAME} -gt 100 ]; then echo "Error: SA_DISPLAY_NAME must not exceed 100 characters." exit 1 fi # Validate ILLUMIO_SA_EMAIL if ! [[ "$ILLUMIO_SA_EMAIL" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9_-]+\.iam\.gserviceaccount\.com$ ]]; then echo "Error: Invalid ILLUMIO_SA_EMAIL. It must be a valid email address." exit 1 fi # Validate PROJECT_ID if [ ${#PROJECT_ID} -lt 6 ] || [ ${#PROJECT_ID} -gt 30 ]; then echo "Error: PROJECT_ID must be between 6 to 30 characters." exit 1 fi # Determine resource type based on folder ID or organization ID presence if [ -n "$FOLDER_ID" ] && [ -n "$ORGANIZATION_ID" ]; then RESOURCE_TYPE="$RESOURCE_TYPE_FOLDER" RESOURCE_ID="$FOLDER_ID" echo "Operating at folder level: $FOLDER_ID" # Validate folder ID format (typically numeric) if ! [[ "$FOLDER_ID" =~ ^[0-9]+$ ]]; then echo "Error: Invalid FOLDER_ID. It must be numeric." exit 1 fi # Validate organization ID format (typically numeric) # This is required for folder onboarding to create custom IAM role if ! [[ "$ORGANIZATION_ID" =~ ^[0-9]+$ ]]; then echo "Error: Invalid ORGANIZATION_ID. It must be numeric. Organization id is required to create custom IAM role for folder onboarding" exit 1 fi elif [ -n "$ORGANIZATION_ID" ]; then RESOURCE_TYPE="$RESOURCE_TYPE_ORGANIZATION" RESOURCE_ID="$ORGANIZATION_ID" echo "Operating at organization level: $ORGANIZATION_ID" # Validate organization ID format (typically numeric) if ! [[ "$ORGANIZATION_ID" =~ ^[0-9]+$ ]]; then echo "Error: Invalid ORGANIZATION_ID. It must be numeric." exit 1 fi else RESOURCE_TYPE="$RESOURCE_TYPE_PROJECT" RESOURCE_ID="$PROJECT_ID" echo "Operating at project level: $PROJECT_ID" fi # READ_WRITE_MODE if $READ_WRITE_MODE; then echo "Read-write mode enabled." else echo "Read-only mode." fi # Function to set the active project set_project() { local project_id=$1 echo "Setting active project to $project_id..." gcloud config set project "$project_id" } # Function to create service account create_service_account() { local project_id=$1 local sa_name=$2 local sa_display_name=$3 echo "Creating service account..." gcloud iam service-accounts create "$sa_name" \ --display-name="$sa_display_name" \ --project="$project_id" \ --quiet #creating service account email using the service account name and project id local sa_email="${sa_name}@${project_id}.iam.gserviceaccount.com" echo "$sa_email" } # Function to create IAM role create_iam_role() { local resource_type=$1 local resource_id=$2 local role_name=$3 local permissions=$4 local organization_id=$5 echo "Creating custom IAM role..." if [ "$resource_type" == "$RESOURCE_TYPE_PROJECT" ]; then gcloud iam roles create "$role_name" \ --project="$resource_id" \ --title="$role_name" \ --description="Custom role for listing and getting storage and VPCs" \ --permissions="$permissions" \ --stage="GA" elif [ "$resource_type" == "$RESOURCE_TYPE_ORGANIZATION" ]; then gcloud iam roles create "$role_name" \ --organization="$resource_id" \ --title="$role_name" \ --description="Custom role for organization-level permissions" \ --permissions="$permissions" \ --stage="GA" elif [ "$resource_type" == "$RESOURCE_TYPE_FOLDER" ]; then # iam role could only be created at project/organization level, for folder onboarding creating it at organization level gcloud iam roles create "$role_name" \ --organization="$organization_id" \ --title="$role_name" \ --description="Custom role for folder-level permissions" \ --permissions="$permissions" \ --stage="GA" fi add_resource "roles" "$role_name" } # Function to bind IAM role to service account bind_role_to_service_account() { local resource_type=$1 local resource_id=$2 local sa_email=$3 local role_name=$4 local organization_id=$5 echo "Binding custom IAM role to service account..." if [ "$resource_type" == "$RESOURCE_TYPE_PROJECT" ]; then gcloud projects add-iam-policy-binding "$resource_id" \ --member="serviceAccount:$sa_email" \ --role="projects/$resource_id/roles/$role_name" \ --condition=None \ --quiet elif [ "$resource_type" == "$RESOURCE_TYPE_ORGANIZATION" ]; then gcloud organizations add-iam-policy-binding "$resource_id" \ --member="serviceAccount:$sa_email" \ --role="organizations/$resource_id/roles/$role_name" \ --condition=None \ --quiet elif [ "$resource_type" == "$RESOURCE_TYPE_FOLDER" ]; then gcloud resource-manager folders add-iam-policy-binding "$resource_id" \ --member="serviceAccount:$sa_email" \ --role="organizations/$organization_id/roles/$role_name" \ --condition=None \ --quiet fi } # Function to assign predefined role to service account assign_predefined_role() { local resource_type=$1 local resource_id=$2 local sa_email=$3 local role=$4 echo "Assigning predefined role $role to service account..." if [ "$resource_type" == "$RESOURCE_TYPE_PROJECT" ]; then gcloud projects add-iam-policy-binding "$resource_id" \ --member="serviceAccount:$sa_email" \ --role="$role" \ --condition=None \ --quiet elif [ "$resource_type" == "$RESOURCE_TYPE_ORGANIZATION" ]; then gcloud organizations add-iam-policy-binding "$resource_id" \ --member="serviceAccount:$sa_email" \ --role="$role"\ --condition=None \ --quiet elif [ "$resource_type" == "$RESOURCE_TYPE_FOLDER" ]; then gcloud resource-manager folders add-iam-policy-binding "$resource_id" \ --member="serviceAccount:$sa_email" \ --role="$role" \ --condition=None \ --quiet fi } # Function to enable impersonation permissions enable_impersonation_permissions() { local sa_email=$1 local project_id=$2 local illumio_sa_email=$3 echo "Configuring impersonation permissions..." gcloud iam service-accounts add-iam-policy-binding "$sa_email" \ --member="serviceAccount:$illumio_sa_email" \ --role="roles/iam.serviceAccountTokenCreator" \ --project="$project_id" \ --condition=None \ --quiet } send_data_to_endpoint() { local sa_email=$1 local resource_id=$2 local project_id=$3 local post_url=$4 local tenant_id=$5 local auth_key=$6 # Basic Authentication key local auth_secret=$7 # Basic Authentication secret local event=$8 local resource_type=$9 if [[ "$post_url" != *"proxy"* ]] || [[ "$post_url" == *"sunnyvale"* ]]; then post_url="$post_url/api/v1/integrations/cloud_credentials" fi # Determine onboarding_type based on resource_type local integration_type="" if [ "$resource_type" == "project" ]; then integration_type="GcpProject" elif [ "$resource_type" == "folder" ]; then integration_type="GcpFolder" elif [ "$resource_type" == "organization" ]; then integration_type="GcpOrganization" else echo "Error: Invalid resource_type provided." exit 1 fi echo "Sending resource ID, service account email, and project ID to $post_url" # Perform the HTTP POST request with Basic Authentication and custom headers response=$(curl -s -w "\n%{http_code}" -X POST \ -H "Content-Type: application/json" \ -H "Authorization: Basic $(echo -n "$auth_key:$auth_secret" | base64 | tr -d '\n')" \ -H "X-Tenant-Id: $tenant_id" \ -d "{\"sa_email\":\"$sa_email\",\"gcp_resource_id\":\"$resource_id\",\"project_csp_id\":\"$project_id\",\"type\":\"$event\",\"integration_type\":\"$integration_type\"}" \ "$post_url") # Extract the response body and status code body=$(echo "$response" | sed '$d') # Remove last line (status code) status_code=$(echo "$response" | tail -n1) # Extract last line (status code) # Check the HTTP status code if [ "$status_code" -ge 200 ] && [ "$status_code" -lt 300 ]; then echo "POST request successful. Response:" echo "$body" else echo "Error: POST request failed with status code $status_code. Response:" echo "$body" exit 1 # Trigger cleanup via ERR trap if there's an error. fi } # Function to check if gcloud CLI is available check_gcloud_availability() { if ! command -v gcloud &> /dev/null; then echo "Error: gcloud CLI is not available. Please install and configure it before running this script." exit 1 fi echo "gcloud CLI is available. Proceeding with the script." } # Main execution sequence main() { check_gcloud_availability if [ "$RESOURCE_TYPE" == "$RESOURCE_TYPE_PROJECT" ]; then set_project "$PROJECT_ID" fi # TODO: Check user permissions before proceeding SA_EMAIL=$(create_service_account "$PROJECT_ID" "$SA_NAME" "$SA_DISPLAY_NAME" | tail -n 1) # doing add_resource here for service account because we are using a pipe (| tail -n 1) when calling the function, which creates a subshell. # Variables modified in subshells do not propagate back to the parent shell, hence the added service account was not visible in cleanup function add_resource "service_accounts" "$SA_EMAIL" # Prompt user for consent to enable APIs for Illumio-supported resources echo "Do you want to allow Illumio to enable APIs for supported resources? (y/N)" read -r consent if [[ "$consent" == "y" || "$consent" == "Y" ]]; then echo "User consented to enable APIs for Illumio-supported resources." create_iam_role "$RESOURCE_TYPE" "$RESOURCE_ID" "$DEFAULT_API_ENABLE_ROLE_NAME" "$API_ENABLE_PERMISSION" "$ORGANIZATION_ID" bind_role_to_service_account "$RESOURCE_TYPE" "$RESOURCE_ID" "$SA_EMAIL" "$DEFAULT_API_ENABLE_ROLE_NAME" "$ORGANIZATION_ID" else echo "User did not consent to enable APIs for Illumio-supported resources." fi # Convert the comma-separated list into an array and loop through it IFS=',' read -ra ROLES_ARRAY <<< "$PREDEFINED_ROLES" for role in "${ROLES_ARRAY[@]}"; do assign_predefined_role "$RESOURCE_TYPE" "$RESOURCE_ID" "$SA_EMAIL" "$role" done enable_impersonation_permissions "$SA_EMAIL" "$PROJECT_ID" "$ILLUMIO_SA_EMAIL" # required to list projects under the organization or folder if [ "$RESOURCE_TYPE" == "$RESOURCE_TYPE_ORGANIZATION" ] || [ "$RESOURCE_TYPE" == "$RESOURCE_TYPE_FOLDER" ]; then assign_predefined_role "$RESOURCE_TYPE" "$RESOURCE_ID" "$SA_EMAIL" "roles/browser" fi # Check if READ_WRITE_MODE is true to create and bind IAM role with WRITE_PERMISSIONS if $READ_WRITE_MODE; then echo "Read-write mode is enabled. Creating IAM role with write permissions..." create_iam_role "$RESOURCE_TYPE" "$RESOURCE_ID" "$DEFAULT_WRITE_ROLE_NAME" "$WRITE_PERMISSIONS" "$ORGANIZATION_ID" bind_role_to_service_account "$RESOURCE_TYPE" "$RESOURCE_ID" "$SA_EMAIL" "$DEFAULT_WRITE_ROLE_NAME" "$ORGANIZATION_ID" fi send_data_to_endpoint "$SA_EMAIL" "$RESOURCE_ID" "$PROJECT_ID" "$POST_URL" "$CS_TENANT_ID" "$AUTH_KEY" "$AUTH_SECRET" "GCPRole" "$RESOURCE_TYPE" } main echo "Script executed successfully."
Flow log support
Illumio Cloud supports VPC and firewall flow logs.