> For the complete documentation index, see [llms.txt](https://docs.fusion.vectra.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.fusion.vectra.ai/cloud-onboarding/gcp-cloud-onboarding/neto-onboarding-gcp.md).

# Vectra Terraform Cloud Onboarding for GCP Organizations

## Overview

The automation performs these functions for onboarding GCP to Vectra Fusion:

1. Deploy all the infrastructure required to integrate to Fusion to ingest VPC flow logs and/or Cloud DNS logs across multiple projects and folders in a GCP organization.
2. Enumerate GCP resources with IP addresses and meta-data associated with those resources and send to Vectra Fusion for context enrichmnet.
3. Monitor for VPC subnet changes and new projects, and trigger onboarding to Fusion new VPC flow logs and/or Cloud DNS logs that are in-scope.

It can also orchestrate VPC flow log and Cloud DNS log configurations, including:

4. Enable and configure VPC flow logging and Cloud DNS logging based on a policy you define at the organization, folder, or project level, with VPC and subnet subpolicy overrides.

You can choose to use this automation for only the Fusion onboarding of existing enabled logs, or for both the onboarding to Fusion and orchestration of flow and/or Cloud DNS logging across your whole organization, or in specific folders or projects, with VPC and subnet subpolicy overrides where needed.

## Architecture Diagrams

<figure><img src="/files/pHOQbYDzjDxm1TJRMbzl" alt=""><figcaption></figcaption></figure>

*Onboarding Automation Architecture Diagram Notes*

* The Cloud Functions have been consolidated into a single function (context function and its associated resources no longer exists separately)
* Cloud DNS, if enabled, has its own logging sink, pub/sub topic, subscription, and Fusion traffic source

## Deployment Components

This involves these main components:

### Terraform deployment

* `terraform/deployments/neto-onboard-gcp-full/` - Terraform to deploy resources for full deployment

Terraform will deploy the following resources to the project configured in the google provider:

* **Vectra Log Activator Cloud Function** - Orchestration function (see details in next section).

  This is deployed with the following resources:

  * Cloud Function
  * Storage Bucket for function source code
  * Service Account for the Cloud Function
  * IAM roles and permissions for the Cloud Function Service Account
  * Time sleep resource to handle dependencies and delays
* **Organization Cloud Assset Feed** - Triggers Cloud Function on change events in Projects or Folders through a message to the *Cloud Asset Pub/Sub topic*.
  * Organization Asset Feed
  * Service Account for asset feed
  * IAM roles and permissions for the Asset Feed Service Account
  * Pub/Sub topic for asset feed to trigger cloud function
  * Pub/Sub topic IAM binding for the service account
* **Flow Logs Pub/Sub** - For publishing and receiving VPC flow logs
  * Pub/Sub Topic for flow logs
  * Pub/Sub Subscription for flow logs
  * Pub/Sub IAM Members for publisher and subscriber roles
  * Project IAM Binding for Pub/Sub admin role
* **Cloud DNS Logs Pub/Sub** - For publishing and receiving Cloud DNS logs
  * Pub/Sub Topic for Cloud DNS logs
  * Pub/Sub Subscription for Cloud DNS logs
  * Pub/Sub IAM Members for publisher and subscriber roles
  * Project IAM Binding for Pub/Sub admin role
* **Metrics, Monitoring, and Notification Channel** - For monitoring the Cloud Function and alerting on errors
  * Logging Metric to count Cloud Function errors
  * Monitoring Alert Policy to define alert conditions and strategies
  * Monitoring Notification Channel to send email notifications
* **Secret Manager resources** - For storing and retrieving Vectra Fusion API key secret
  * Secret Manager Secrets for Vectra API secret (`netosecret`)
  * Secret Manager Secret Versions to store the actual secret value
  * Secret Manager IAM Members to grant access to the secret for the Cloud Function service account

### Cloud Function

#### `neto-logactivator` (GCP Cloud Run function `neto-acme-prod-logactivator`)

Triggers:

* Schedule (if `timer_enable=true`, based on schedule set in `timer_schedule`)
* Event triggers when changes occur to a project or folder
* Manually triggered by sending a message to the Pub/Sub topic (`scripts/run` will do this from command line)

1. Evaluate policy scope

* Identifies all the in-scope projects in the organization based on the scope policy you define. More details on defining scope is in the Scope Policy section below.

2. Create Vectra Fusion traffic source(s) if they do not exist

* If Flow log ingest is enabled (`ingest_flow=true`), creates a traffic source for the Pub/Sub topic subscription for all VPC flow logs.
* If Cloud DNS ingest is enabled (`ingest_dns=true`), creates a second traffic source for the Pub/Sub topic subscription for all Cloud DNS logs.
* Writes the label `neto_traffic_source` with value of your Fusion shortname to the orchestration project to indicate traffic sources have been created.

3. Onboard in-scope projects:
   * Creates a Cloud Logging Sink that routes flow logs to the Pub/Sub topic Vectra subscribes to, and a Cloud Logging Sink for Cloud DNS if enabled
   * Grants writer identity for the sink the `roles/pubsub.publisher` role to the Pub/Sub topic(s)
   * Writes the label `neto_account` with value of your Fusion shortname to the project to indicate it has been onboarded
4. Orchestrate logging in in-scope projects:
   * Enables flow logging for all the subnetworks in the project (if flow log orchestration is enabled)
   * Creates a Cloud DNS policy with DNS logging enabled for all the VPC in the project (if Cloud DNS orchestration is enabled, and no Cloud DNS policy already exists for the VPC)
5. Offboards out of scope projects previously onboarded
   * Identifies all projects out of scope with the `neto_account` label to offboard.
   * Removes the role bindings for the service account to the logging sink(s).
   * Deletes the logging sink(s).
   * Disables flow logs for subnets in the project (if `orchestrate_flow_logs=true`).
   * Disables Cloud DNS logging for VPC in the project (if `orchestrate_dns_logs=true`).
   * Removes the `neto_account` label to indicate its no longer onboarded.
6. Context enrichment
   * Enumerates all the compute Instances in in-scope projects, iterate through the interfaces, and add Vectra Fusion labels for these fields linked to the `networkIP` of each IP, skipping loopback, reserved, and multicast addresses:

If run with the `trigger_type` attribute set to `destroy`, the function will perform the offboarding of all projects, and then remove the Fusion traffic sources.

## Prerequisites

To simplify checking and configuring prerequisites, a set of scripts are provided in the `scripts/` directory that wrap the `gcloud` CLI.

See `scripts/README.md` for more details on the scripts and how to configure `gcloud` with the proper authentication (if you are not a `gcloud` expert and have these already setup).

{% stepper %}
{% step %}

### 1. Designate a project to deploy resources into

It is recommended you create a new GCP project for Terraform to deploy resources to, but you can reuse an existing project if you prefer. This project is referred to as the `orchestration project`.

The project needs the following APIs enabled:

| API Name                                 | Endpoint                              |
| ---------------------------------------- | ------------------------------------- |
| Cloud Asset API                          | `cloudasset.googleapis.com`           |
| Cloud Build API                          | `cloudbuild.googleapis.com`           |
| Cloud DNS API                            | `dns.googleapis.com`                  |
| Cloud Functions API                      | `cloudfunctions.googleapis.com`       |
| Cloud Monitoring API                     | `monitoring.googleapis.com`           |
| Cloud Pub/Sub API                        | `pubsub.googleapis.com`               |
| Cloud Resource Manager                   | `cloudresourcemanager.googleapis.com` |
| Cloud Run Admin API                      | `run.googleapis.com`                  |
| Cloud Scheduler API                      | `cloudscheduler.googleapis.com`       |
| Eventarc API                             | `eventarc.googleapis.com`             |
| Identity and Access Management (IAM) API | `iam.googleapis.com`                  |
| Network Management API                   | `networkmanagement.googleapis.com`    |
| Organization Policy API                  | `orgpolicy.googleapis.com`            |
| Secret Manager API                       | `secretmanager.googleapis.com`        |
| Service Usage API                        | `serviceusage.googleapis.com`         |

`scripts/prereq-apis plan <project-id>` will check if the required APIs are enabled, and if not provide you the command to run to enable them in the project.

This is the command to enable all required APIs (ensure you have set your current project to the orchestration project or specify `--project=orchestration-project-id`):

```sh
gcloud services enable \
  cloudasset.googleapis.com cloudbuild.googleapis.com cloudfunctions.googleapis.com \
  cloudresourcemanager.googleapis.com cloudscheduler.googleapis.com dns.googleapis.com \
  eventarc.googleapis.com iam.googleapis.com logging.googleapis.com \
  monitoring.googleapis.com networkmanagement.googleapis.com orgpolicy.googleapis.com \
  pubsub.googleapis.com run.googleapis.com secretmanager.googleapis.com
```

**Note:** After enabling the Cloud Asset API, you must make at least one API call to trigger the automatic creation of the Cloud Asset service account. This service account is required for the organization asset feed to function properly. Run this command to initialize it:

```sh
gcloud asset search-all-resources --scope=projects/<orchestration-project-id> --asset-types=compute.googleapis.com/Instance --limit=1
```

Wait 30-60 seconds after this command completes for the service account to propagate before running Terraform.
{% endstep %}

{% step %}

### 2. If you have GCP Organizational Policy Constraints

*Updating an organization policy requires the Organization Policy Administrator role (`roles/orgpolicy.policyAdmin`).*

If you have GCP organization policy constraints in place, you may be unable to deploy resources or execute actions, even if you have the appropriate permissions. If you receieve errors during the deployment or in the Cloud Function log indicating an organization policy is enforced, you will need to add or edit a rule for that policy to allow the action to take place.

See: <https://cloud.google.com/resource-manager/docs/organization-policy/creating-managing-policies>
{% endstep %}

{% step %}

### 3. If you have a Domain Restricted Sharing Organizational Policy Constraint

*Even if you have not set up any organization policy constraints, there may still be this default constraint in place.*

The *Domain Restricted Sharing* policy (`constraints/iam.allowedPolicyMemberDomains`) prevents you from granting a permission to a member on an external domain. Vectra's service account `sa-cloud@netography.iam.gserviceaccount.com` resides outside your domain, requiring a policy update to allow Vectra to subscribe to the Pub/Sub subscription where flow logs are published.

**This constraint is the default setting for all GCP organizations created on or after May 3, 2024.**

**Vectra account details**

| Field               | Value                                           |
| ------------------- | ----------------------------------------------- |
| Service Account     | `<sa-cloud@netography.iam.gserviceaccount.com>` |
| Customer ID         | `C04ddcbu8`                                     |
| Permission Required | Pub/Sub Subscriber (`roles/pubsub.publisher`)   |

If this policy restriction exists and you do not add a rule for this account, you will receive the following error when the automation attempts to grant this permission:

**IAM policy update failed - The ‘Domain Restricted Sharing’ organization policy (constraints/iam.allowedPolicyMemberDomains) is enforced.**

`scripts/prereq-domainrestricted plan` will check if the domain restricted sharing policy is in place and if it allows the Vectra customer ID.\
`scripts/prereq-domainrestricted apply` will add a rule to allow the Vectra customer ID to this policy.

*`scripts/prereq-domainrestricted` requires the `orgpolicy.googleapis.com` API in your orchestration project is enabled (you should have done this in the first pre-req step).*
{% endstep %}

{% step %}

### 4. Create a service account for the Terraform provider

It is recommended to create a service account in the project configured for the Terraform provider.

#### Terraform provider service account least privilege Organizational Level Roles

| Role Name                  | Role                                      | Description                             |
| -------------------------- | ----------------------------------------- | --------------------------------------- |
| Cloud Asset Owner          | `roles/cloudasset.owner`                  | Full control over Cloud Asset resources |
| DNS Admin                  | `roles/dns.admin`                         | Full control over DNS resources         |
| Logging Admin              | `roles/logging.admin`                     | Full control over logging resources     |
| Organization Administrator | `roles/resourcemanager.organizationAdmin` | Full control over Org-level resources   |
| Org Role Administrator     | `roles/iam.organizationRoleAdmin`         | Create the custom roles in org          |

#### Terraform provider service account least privilege Project Level Roles

| Role Name              | Role                                      | Description                                 |
| ---------------------- | ----------------------------------------- | ------------------------------------------- |
| Owner                  | `roles/owner`                             | Privileged access to project                |
| Cloud Functions Admin  | `roles/cloudfunctions.admin`              | Full control over Cloud Functions resources |
| Cloud Scheduler Admin  | `roles/cloudscheduler.admin`              | Full control over Cloud Scheduler resources |
| Logging Admin          | `roles/logging.admin`                     | Full control over logging resources         |
| Monitoring Admin       | `roles/monitoring.admin`                  | Full control over monitoring resources      |
| Project IAM Admin      | `roles/resourcemanager.projectIamAdmin`   | Full control over project IAM resources     |
| Pub/Sub Admin          | `roles/pubsub.admin`                      | Full control over Pub/Sub resources         |
| Secret Manager Admin   | `roles/secretmanager.admin`               | Full control over Secret Manager resources  |
| Service Account Admin  | `roles/iam.serviceAccountAdmin`           | Full control over service accounts          |
| Service Usage Consumer | `roles/serviceusage.serviceUsageConsumer` | Ability to use services in the project      |
| Storage Admin          | `roles/storage.admin`                     | Full control over storage resources         |

`scripts/prereq-terraform-sa plan` - review planned actions to create the service account and assign roles\
`scripts/prereq-terraform-sa apply` - create the service account and assign roles\
`scripts/prereq-terraform-sa verify` - check if the service account exists and has the required roles\
`scripts/prereq-terraform-sa keygen` - create a service account key and save it to a local file

You can also use `scripts/prereq-terraform-sa apply-token <user-email>` to grant a user permission to impersonate the service account if you will be using service account impersonation.
{% endstep %}

{% step %}

### 5. Create a default Cloud Asset Inventory Service Account in the Orchestration project

The default Cloud Asset Inventory Service Account must exist in the orchestration project or you will receive an error that looks like this when applying the Terraform:

```
Error applying IAM policy for pubsub topic "projects/neto-mycorp-dev-orch/topics/neto-mycorp-dev-asset-feed-topic": Error setting IAM policy for pubsub topic "projects/neto-mycorp-dev-orch/topics/neto-mycorp-dev-asset-feed-topic": googleapi: Error 400: Service account service-555555555@gcp-sa-cloudasset.iam.gserviceaccount.com does not exist.
```

`scripts/prereq-cloudasset create <project-id>` - create the service account in the project

You can also create the service account manually with the following command:

```sh
PROJECT=yourprojectid
gcloud beta services identity create --service=cloudasset.googleapis.com --project=$PROJECT
```

{% endstep %}

{% step %}

### 6. Vectra Fusion API key (`netosecret`)

You will need to create a Vectra Fusion API key. See: [API Keys](/settings/user-management/index.md)

This secret is stored in Google Secret Manager in the orchestration project as the `netosecret` secret. You will add it as part of the deployment steps below.

You should not store this value in your `tfvars` file directly.

Store and export it in your environment for using later in the deployment:

```sh
export NETOSECRET=your-api-key
```

On a Mac, you can copy it from your clipboard directly by running:

```sh
export NETOSECRET=$(pbpaste)
```

{% endstep %}

{% step %}

### 7. Vectra Fusion CLI tool (Optional)

It is helpful to use the neto CLI tool as part of deploying to validate its operation. This package is in the repo `/neto/` directory.

See \`../neto/README.md for more details

To install this into a Python virtual environment (recommended - this will ensure you don't have any conflicts, and allows you to run `neto` wheneveer you have activated this environment):\
From the root of repo directory `neto-onboarding/`, run:

```sh
python3 -m venv venv
source venv/bin/activate
cd neto
pip install .
neto --version
neto -h
```

To exit the virtual environment, run `deactivate`.\
To enter the virtual environment again, from repo root `neto-onboarding` run `source venv/bin/activate`.
{% endstep %}

{% step %}

### 8. Terraform 1.11 or newer and Basic terraform knowledge

Terraform 1.11 or newer is required to deploy the automation.

This automation has been built for engineers with basic familiarity using terraform.
{% endstep %}
{% endstepper %}

## GCP Regions

The orchestration functions in all regions available in your GCP organization. Unlike AWS and Azure, there is no per region handling for purposes of flow log orchestration.

## Scope Policy

The scope policy determines whether a project is in-scope for orchestration. See the [Log Activator Function](#terraformfunctionsneto-logactivator) for details of the actions taken for in-scope projects.

The scope policy is defined in JSON, containing a list of rules.

A rule has these values:

Each rule has a **type** (organization, folder, project), **action** (include or exclude), **members** (list of IDs or numbers), and an optional **subpolicy** section for VPC and subnet rules, and a **config** section for configuration parameters.

*The policy will ignore keys that are not applicable to it in rules outside of config, so adding comments to help you document your policy in unused keys such as `comment` can be helpful.*

```json
{
  "comment": "Sample GCP scope policy.",
  "tip": "Run 'neto policy validate --file scope-policy.json' to validate the policy after changing it.",
  "policy": [
    {
      "comment": "Rule to include everything in the organization.  This is the only rule needed for a simple deployment.",
      "format-help": "Use the number of the organization (eg 514213275881)",
      "type": "organization",
      "action": "include",
      "members": [
        "514213275881"
      ],
      "config": {
        "flowSampling": 1.0
      }
    },
    {
      "comment": "Rule to include all projects that are descendants of the folder(s) in members list",
      "format-help": "Use the number of the folder (eg 739546312018)",
      "type": "folder",
      "action": "include",
      "members": [
        "739546312018"
      ],
      "config": {
        "flowSampling": 0.9
      }
    },
    {
      "comment": "Rule to include specific projects.  Any config set here will override a folder or organization rule.",
      "format-help": "Use the ID of the project (eg my-project-id), not number or name.",
      "type": "project",
      "action": "include",
      "members": [
        "project-to-include-id",
        "project-to-include-id-2"
      ],
      "config": {
        "flowSampling": 1.0
      },
      "subpolicy": [
        {
          "comment": "Subpolicy rules apply to vpc or subnets within any project matching its parent rule.",
          "type": "subnet",
          "members": [
            "subnet-name-to-config-for-specific-regions"
          ],
          "comment-region": "If region is specified, the config will only apply to subnets in those regions.",
          "region": [
            "africa-south1",
            "asia-east1",
            "asia-east2"
          ],
          "config": {
            "flowSampling": 0.5
          }
        },
        {
          "comment": "This will apply to all subnets in regions not matching previous subpolicy rule.  Disables Cloud DNS logs for matching subnets",
          "type": "subnet",
          "members": [
            "subnet-name-to-config-for-all-regions"
          ],
          "config": {
            "flowSampling": 0.4,
            "dns": "disable"
          }
        },
        {
          "comment": "Excludes any vpc that match this subpolicy rule by having enable: false in config.",
          "format-help": "Use the vpc name.",
          "type": "vpc",
          "members": [
            "vpc-name-to-exclude"
          ],
          "config": {
            "enable": false
          }
        }
      ]
    }
  ]
}
```

Policy rules are always inherited, with the most closely scoped rule to the project having precedence (eg project rules take precedence over folder rules which take precedence over organization rules). Within the same type (eg multiple project rules or folder rules), the first rule that matches in the order they are listed in the JSON will be used.

### Valid `members` values

* `project`: `projectId` (`my-project`). The human-readable `name` can not be used, as it is not a unique identifier.
* `folder`: The numeric folder identifier (`name` omitting the leading `folders/` string). The human-readable folder `displayName` can not be used, as it is not a unique identifier.
* `organization`: The numeric organization identifier (`name` omitting the leading `organizations/` string). The human-readable organization `displayName` can not be used, as it is not a unique identifier.

**Note: In GCP, the `name` field is the human-readable string for a `project`, but the unique identifier for a `folder` or `organization`.**

### Policy config

You can modify flow log settings for each policy rule by adding a **config** section to the rule. If a config section is present, any values set take precedence over values set in tfvars. A config section in an `"action":"exclude"` rule will apply those settings when offboarding a project due to it no longer being in scope (if the project was never onboarded, the settings will never be used).

Within a config section, the supported keys are:

* `ignore` - If set to true, no flow log configuration will be modified. Use where another system is orchestrating flow log configurations to avoid conflicts.
* `enable` - If set to false, flow logs will be disabled for the matching entities.
* `disable` - If set to false, flow logs will NOT be disabled when offboarding the entity.
* `aggregationInterval`, `flowSampling`, `metadata`, `filterExpr` - Keys passed in the `logConfig` to GCP
* `sink_filter_flow`, `sink_filter_dns` - Cloud Logging Sink filter expression to use
* `dns` - Valid values are `enable`, `disable`, or `ignore`. This config setting is used if `orchestrate_dns` is set to `true` in tfvars to enable Cloud DNS logging orchestration. If set to `enable`, Cloud DNS logging will be enabled when onboarding the member. If set to `disable`, Cloud DNS logging will be disabled for the member. If set to `ignore`, Cloud DNS logging will not be modified by the orchestration. The `dns` config setting can be applied to an organization, folder, or project rule, and to a `vpc` or `subnet` subpolicy rule.
* `scope-policy.json.example` provides an example of the full policy template filled out.
* `scope-policy.json.template-full` provides a template for a more complex policy.
* `scope-policy.json.template-simple` provides a template for a simple policy.

Copy one to `scopy-policy.json` and edit.

## Deploying the automation

{% stepper %}
{% step %}

### 1. Apply the Terraform Project

* Clone the git repo
* Check all the pre-requisite steps above
* This terraform project is targeted towards a designated orchestration project in your GCP organiation
* From the root directory of this repository: `cd gcp/terraform/deployments/`
* Change the `backend.tf` file to the backend your organization uses
* Update the `providers.tf` with the project you are targeting and your preferred google provider authentication method.
* Copy `terraform.tfvars.template` to `terraform.tfvars` and define the appropriate variables.
* Copy `scope-policy.json.template-simple` to `scope-policy.json` and add a project to the scope (see Scope Policy config section above)
* Run `terraform init`
* Run `terraform apply` and accept the changes

The input variables and resources created are described in `terraform/deployments/README.md`

After completing the `terraform apply`, verify all the resources were deployed successfully.
{% endstep %}

{% step %}

### 2. Add Vectra API secret to Google Secret Manager

The Vectra API key `netosecret` is read from Google Secrets Manager in the project set in the Terraform provider, using the following secret id:

* `netosecret`

The values are set to `REPLACE_ME` by the Terraform deployment if the secret does not exist.

If this secret is stored in the `$NETOSECRET` environment variable (eg displayed when you `echo $NETOSECRET`), you can add it to Google Secret Manager by running:

```sh
printf $NETOSECRET |gcloud secrets versions add netosecret --data-file=-
```

If you prefer using the GCP Console, select the orchestration project, go to Secret Manager, and create a new version of the secret `netosecret` (check disable previous secrets):\
<https://console.cloud.google.com/security/secret-manager/secret/netosecret/>

**If you prefer to keep the API key in Terraform**

If you prefer to keep the API key in Terraform (although this is not as secure an approach as writing it directly to Secret Manager, you may have your own workflow for managing secrets):

1. Set and export it to the `TF_VAR_netosecret` environment variable before running `terraform apply`, or run `terraform apply -var netosecret=$NETOSECRET`
2. Edit `main-secrets.tf` and remove this block from `resource "google_secret_manager_secret_version" "netosecret"`

```
  lifecycle {
    ignore_changes = all
  }
```

Even if you use this approach, do not directly write the secret to the `tfvars` file or pass the secret directly on the command line as a string as these are not secure methods of storing and passing secrets.

*(This change will have Terraform apply the secret to Google Secret Manager any time you change it. Without removing the `ignore_changes` block, which is there to prevent Terraform from overwriting the value you manually set in Secret Manager in the recommended approach, Terraform will not keep the `netosecret` in tfvars in sync with the version in Secret Manager.)*
{% endstep %}

{% step %}

### 3. Trigger the Cloud Function to Run to Perform the Initial Onboarding

The Terraform deploys resources, but the Cloud Functions do most of the work. Cloud Functions will not execute until you manually trigger it or it runs on a schedule.

If you have a GCP organization that has less than 50 in-scope projects, simply run `scripts/run all` to run the complete function and it will handle all the steps of onboarding at once.

If you have a larger organization, or one with thousands of VPC subnets, you should onboard in steps. This is because the Google Function has a time limit of 9 minutes for each execution, and enabling all the components of the automation can extend beyond that time for the initial onboarding. The function is designed to pick up where it left off and resume onboarding if it times out, so it is expected and normal practice to have to trigger it multiple times during the first time onboarding of a large organization.

To onboard in steps, you have three options:

1. Expand the number of folders and projects in-scope through the scope policy, onboarding them in groups, and once they have completed onboarding and enabling, add the next set. This is a good general cloudops practice for ensuring that deployments that are across an organization can be validated in phases.
2. Trigger the function when first onboarding a new set of projects with `scripts/run -1`, `scripts/run -2`, `scripts-run -3`. This divides onboarding into enabling APIs (step 1), creating log sinks (step 2), and enabling flow logs (step 3).
3. If the function runs for 9 minutes before completing, it will stop at that point. To continue onboarding, simply trigger it again. It will verify the state of what it has already completed first, but these are fast operations, and then it will reach the point where it needs to continue to create/enable resources and it will pick up there.

```sh
Usage: ../../scripts/run <command> [options] [topic-name]
Triggers the Google Function to run

Commands:
  all                Full function run (onboarding, orchestration, context enrichment, and offboarding)
  onboard (or 1)     Onboarding: Enable APIs, logging sinks, add neto_account label to project
  orchestrate (or 2) Flow log orchestration in previously onboarded projects only (will not onboard new projects in-scope)
  context (or 3)     Context enrichment in previously onboarded projects only (will not onboard new projects in-scope)
  offboard (or 4)    Offboarding of out of scope projects (disable flow logs, remove log sinks, remove neto_account label; APIs remain enabled)
  destroy            Destroy all resources created by function (complete offboarding before a terraform destroy)
Options:
  -i, --index N      Index to start orchestration from (default: 1, first project in list); only applies to orchestration
  -c, --concurrency  Custom concurrency settings for execution in format "N,N,N" (gcp_concurrent_limit,gcp_connection_limit,gcp_thread_limit
  --skip-dns         Set ORCHESTRATE_DNS_LOGS=false to skip dns orchestration
  -u, --update-sinks Update log sink filters for all onboarded projects (default: only set logging sink filters when onboarding)
  -h, --help         Show this help message
```

**Trigger the Cloud Function with a Pub/Sub message**

You can also trigger the Log Activator Cloud Function to run by sending a message to the asset feed Pub/Sub topic created by the Terraform with an attribute `trigger_type` and value `manual`. The Pub/Sub topic name is constructed as `<prefix>-<customer>-<environment>-asset-feed-topic`. Review `scripts/run` to see how to construct the proper message.

#### Triggering the function in the GCP Console

You can also trigger the Log Activator Cloud Function to run in the GCP Console. Go to Pub/Sub > Topics, Select the asset feed topic in the orchestration project, then select the Messages tab, click Publish Message, click Add an Attribute, and enter key `trigger_type` and value `manual`. Review `scripts/run` to see how to construct additional attributes for the message.
{% endstep %}

{% step %}

### 4. Onboarding of New Projects and Subnetworks

Once the initial onboarding is complete:

1. Vectra Fusion will have 1 traffic source for the GCP Pub/Sub subscription in the project for flow logging, using one traffic source for all VPCs across all projects.
2. Vectra Fusion will have 1 traffic source for the GCP Pub/Sub subscription in the project for DNS logging, using one traffic source for all DNS logs across all projects.
3. Each in-scope project will have 2 new Cloud Logging Sinks, one for flow logs and one for DNS logs, that route logs to the Pub/Sub topic Vectra is subscribed to.
4. VPC flow logs will be enabled in all VPC subnetworks in the project (or however you configured the scope policy).
5. Cloud DNS logging policy will exist with all the VPCs enabled for logging in each project (if you enabled Cloud DNS logging in tfvars).
6. Context enrichment will have run in all in-scope projects, adding context labels to Fusion for addressable resources used by instances in the project.

Changes to in-scope projects, VPC, and subnetworks will be picked up, and any projects that have changed scope will be onboarded or offboarded, and any VPC and subnetworks that have changed or are new will be orchestartead during the next scheduled run of the cloud function.

If you want to change the scope, edit the scope policy (and/or edit the `terraform.tfvars` file to adjust any config settings), run `terraform apply` to deploy the changes, and trigger the cloud function again.
{% endstep %}

{% step %}

### 5. Scheduling the Cloud Function

Scheduling the `neto-logactivator` Cloud Function will ensure any changes in project scope, or new projects or subnets that may not have triggered or been successfully onboarded, will be identified and onboarded at the next scheduled execution.\
Enable Google Cloud Scheduler to trigger the function by setting the variables in the `terraform.tfvars` file:

```
timer_enable = true
timer_schedule = "0 0 * * *"   # every hour
```

{% endstep %}

{% step %}

### 6. Disable debug logging

Once the orchestration has fully run and is operating properly, you can disable debug logging (which is enabled by default to help assist in any troubleshooting during initial onboarding) by setting `debug_mode = false` in the `terraform.tfvars` file.
{% endstep %}
{% endstepper %}

### Offboarding a project

A project can be removed from scope in one of two ways:

1. Remove the project(s) from being in scope in the scope policy, by editing the policy and `terraform apply`
2. Move a project from an in-scope folder to an out of scope folder.

Trigger the *Log Activator* function to have the scope change take effect.

This will restore the project to its pre-orchestration state, **EXCEPT**:

1. If flow logs were enabled before the project was added to the scope, they will now be disabled after removing the project from the orchestration scope.
2. APIs enabled during onboarding are not disabled when offboarding.

If you do not want to disable flow logging when offboarding all projects, set `disable_flow_logs=false` in tfvars. If you not want to disable flow logging when offboarding a specific project, you can exclude that project from scope in the scope policy with a rule that has `"action": "exclude"` and a config section with the `"ignore": true` setting.

## Additional Configuration Options

### `context_list_scope`

Context enrichment gathers asset metadata using GCP's Cloud Asset Inventory. The `context_list_scope` variable determines how the Cloud Asset Inventory is called.

* `context_list_scope = "project"` - For organizations with a small proportion of the total GCP organizaion in-scope. This is the default setting. This will make 1 ListAssets call for each onboarded in-scope project.
* `context_list_scope = "organization"` - If you have hundreds of projects, or most of your GCP organization is in-scope, this is a faster/more efficient setting. This will make 1 ListAssets call for the whole organization, then filter the results by onboarded in-scope projects.

## Service Accounts, Roles, and Role Bindings

### Flow Logging Pub/Sub subscription role binding

| Roles                     | Binding                | Purposes                       |
| ------------------------- | ---------------------- | ------------------------------ |
| `roles/pubsub.subscriber` | Vectra service account | Allow Vectra to read flow logs |

### Org Asset Feed service account

| Roles                     | Binding                     | Purposes                          |
| ------------------------- | --------------------------- | --------------------------------- |
| `roles/pubsub.subscriber` | asset feed pub/sub topic    | Subscribe to Org Asset Feed topic |
| `roles/run.invoker`       | flow log activator function | Trigger function                  |

### Log Activator function service account

| Roles                                | Binding                  | Purpose                            |
| ------------------------------------ | ------------------------ | ---------------------------------- |
| `roles/pubsub.subscriber`            | orchestration project    | Read from asset feed Pub/Sub topic |
| `roles/storage.objectAdmin`          | function storage bucket  | Function configuration             |
| `roles/artifactregistry.writer`      | orchestration project    | Function configuration             |
| `roles/logging.logWriter`            | orchestration project    | Write function logs                |
| `roles/secretmanager.secretAccessor` | netography-app-key       | Read Fusion API key secret         |
| `roles/secretmanager.secretAccessor` | netography-shared-secret | Read Fusion API key secret         |
| LogActivator custom role             | GCP Organization         | Manage VPC flow logs               |

### Context Enrichment function service account

| Roles                                | Binding                  | Purpose                    |
| ------------------------------------ | ------------------------ | -------------------------- |
| `roles/pubsub.subscriber`            | orchestration project    | Trigger on a Pub/Sub topic |
| `roles/storage.objectAdmin`          | function storage bucket  | Function configuration     |
| `roles/artifactregistry.writer`      | orchestration project    | Function configuration     |
| `roles/logging.logWriter`            | orchestration project    | Write function logs        |
| `roles/secretmanager.secretAccessor` | netography-app-key       | Read Fusion API key secret |
| `roles/secretmanager.secretAccessor` | netography-shared-secret | Read Fusion API key secret |
| Context Enrich custom role           | GCP Organization         | Read asset information     |

### Cloud Asset Inventory default service account

| Roles                    | Binding                  | Purposes                           |
| ------------------------ | ------------------------ | ---------------------------------- |
| `roles/pubsub.publisher` | asset feed Pub/Sub topic | Publish messages to Pub/Sub topics |

### Custom Roles

The *Log Activator custom role* is bound to the *Log Activator function service account* for managing VPC flow logs across the in-scope projects in the organization

| Log Activator Custom Role Permission   | Description               | Purpose                                          |
| -------------------------------------- | ------------------------- | ------------------------------------------------ |
| `resourcemanager.projects.list`        | List projects             | Identify in-scope projects                       |
| `resourcemanager.projects.get`         | Get project details       | Identify in-scope projects                       |
| `resourcemanager.projects.updatet`     | Get project details       | Add neto\_onboard label to onboarded projects    |
| `resourcemanager.folders.get`          | Get folder details        | Identify in-scope projects                       |
| `resourcemanager.folders.list`         | List folders              | Identify in-scope projects                       |
| `cloudasset.assets.searchAllResources` | Search resources          | Identify out of scope logging sinks              |
| `compute.networks.list`                | List networks             | Identify VPC to configure Cloud DNS for          |
| `compute.subnetworks.list`             | List subnetworks          | Identify subnets to configure flow logs for      |
| `compute.subnetworks.get`              | Get subnetwork            | Retrieve existing flow log configurations        |
| `compute.subnetworks.update`           | Update subnetwork details | Enable flow logs                                 |
| `compute.regions.list`                 | List regions              | Enumerate subnets in a region                    |
| `dns.networks.bindPrivateaDNSPolicy`   | Bind DNS policy to VPC    | Enable Cloud DNS logging for VPC logging         |
| `dns.policies.create`                  | Create DNS policy         | Create Cloud DNS policy to enable logging        |
| `dns.policies.delete`                  | Delete DNS policy         | Delete Cloud DNS policy to disable logging       |
| `dns.policies.get`                     | Get DNS policy details    | Get current state of Cloud DNS policy            |
| `dns.policies.list`                    | List DNS policies         | Determine if Cloud DNS policy exists             |
| `dns.policies.update`                  | Update DNS policy         | Update Cloud DNS policy for logging              |
| `logging.logEntries.create`            | Create log entries        | Write function logs                              |
| `logging.sinks.create`                 | Create logging sinks      | Route flow logs to Pub/Sub topic                 |
| `logging.sinks.list`                   | List logging sinks        | Determine if sink needs to be created            |
| `logging.sinks.get`                    | Get logging sink details  | Get current state of logging sink config         |
| `logging.sinks.update`                 | Update logging sink       | Update logging sink config if needed             |
| `logging.sinks.delete`                 | Delete logging sink       | Remove logging sink during offboarding a project |
| `serviceusage.quotas.get`              | Get quotas                | Rate limit requests to within quota              |
| `serviceusage.services.enable`         | Enable services           | Enable logging API                               |
| `serviceusage.services.get`            | Get service details       | Determine if logging API enabled in project      |
| `serviceusage.services.list`           | List services             | Determine if logging API enabled in project      |
| `serviceusage.services.use`            | Use services              | Determine if logging API enabled in project      |

### Context Enrichment Labels

| Context Name   | GCP Field          | Example               |
| -------------- | ------------------ | --------------------- |
| `name`         | name               | myhost-vm             |
| `provider`     | "GCP"              | GCP                   |
| `entity`       | resource\_type     | instances             |
| `instancetype` | machineType        | e2-micro              |
| `az`           | zone               | us-west1-b            |
| `licenses`     | disks/licenses     | debian-12-bookworm    |
| `project`      | project            | neto-global-prod-orch |
| `network`      | interfaces/network | neto-vpc3             |
| `subnet`       | interfaces/subnet  | neto-vpc3-subnet1     |
| `externalip`   | interfaces/nat\_ip | 8.8.8.8               |

*Additional context labels for other GCP services are still being added to this function. Let us know if there are specific attributes and services that you'd like to see added.*

### Additional Procedures and Troubleshooting

#### Manually managing flow logs in all projects

In tfvars, set:

```bash
enable_flow_logs  = false
disable_flow_logs = false
```

In this case, the orchestration will do all of the onboarding to ingest flow logs from in scope projects that you enable outside of this automation or are already enabled, but the actual configuration of flow logging in the subnets is up to you.

#### Updating logging sink filters

You can filter the logs that are sent to Vectra by modifying the `sink_filter_flow` and `sink_filter_dns` variables in `terraform.tfvars` or in the `config` section of a scope policy rule. These filter expressions are directly passed to the GCP Cloud Logging Sink inclusion filter. See <https://cloud.google.com/logging/docs/export/configure_export_v2#filter-examples> for more information on how to write these expressions.

Changes to sink filters in tfvars and scope policy will only be applied when new projects are being onboarded by default. To update the filter for projects that are already onboarded, run `scripts/run --update-sinks all`. This will modify existing logging sinks to use the filter expression for each project, if it has been modified in tfvars or the scope policy.

For VPC flow logs, it is always preferable to modify the `vpc_logs_filter_expression` tfvars (`filterExpr` in the scope policy `config` section), as this will filter VPC logs before they are generated, reducing cost (filtering at the logging sink will still incur the cost to generate the log). Using `sink_filter_flow` is only needed if you are using the logs in multiple logging sinks, and want to filter the logs that are used by the logging sink that sends logs to Netography. Cloud DNS logging policies do not include a filter, so `sink_filter_dns` is the only way to filter DNS logs for a VPC.

*You can not directly set an exclusion filter for the logging sink, but inclusion filters can include `NOT` statements so anything you want to exclude you can accomplish with the inclusion filter.*

For example, if you wanted to exclude DNS queries for `.google.internal` domains for a set of projects, update the scope policy rule for those projects:

```json
{
  "policy": [
    {
      "type": "project",
      "action": "include",
      "members": [
        "my-project-id"
      ],
      "config": {
        "sink_filter_dns": "resource.type=\"dns_query\" AND NOT jsonPayload.queryName:\"google.internal\""
      }
    }
  ]
}
```

#### Warning: Unable to verify or enable services for project: ServiceUsage permission denied

This warning appears in the logs when the **Log Activator Function** checks if required APIs (`logging.googleapis.com`, `cloudasset.googleapis.com`, `dns.googleapis.com`) are enabled for an in-scope project. To perform these checks and enable the APIs requires the Service Usage API (`serviceusage.googleapis.com`) is already enabled in the orchestration project and monitored projects. This is enabled by default when creating a project in GCP through the GCP Console but other methods of creating projects may differ. If you receive this warning you have 2 options:

1. Enable the Service Usage API on the orchestration and in-scope project by going to the GCP Console, selecting the project, entering 'Service Usage API' in the search box, and then clicking **Enable**. You can't use gcloud services enable to do this as that also uses this API.
2. The Service Usage API is only used to check and enable the other APIs. If you have already enabled, or manually enable those 2 APIs in the in-scope project (`gcloud services enable logging cloudasset --project YOUR-PROJECT-ID`), the function will not be able to verify they are enabled but all other functionality will work as expected.

#### Cloud DNS policy and Cloud DNS logging (Error: Network cannot be bound to this policy because it is already bound to another policy.)

GCP enables Cloud DNS logging through the use of a Cloud DNS policy. The orchestration will create a new Cloud DNS policy and add the VPCs in in-scope projects to that policy if you have set `orchestrate_dns_logs = true` in tfvars.

This will NOT modify or delete an existing Cloud DNS policy you have in a project. If you already are using Cloud DNS and have existing policies in place (You can check this by running `gcloud dns policies list --project=PROJECT_ID`), it is up to you to manually enable logging in those policies (e.g. `gcloud dns policies update --enable-logging YOUR_DNS_POLICY --project=PROJECT_ID`) if it is not enabled.

The orchestration will create a Cloud DNS policy named `neto-dns-policy` (you can modify this value by setting `dns_policy_name` in tfvars) in each in-scope project, with logging enabled, and the VPC in that project bound to that policy. If you already have another Cloud DNS policy in the project that a VPC is bound to, you will receive an error:

`Network 'https://compute.googleapis.com/compute/v1/projects/your-project-id/global/networks/your-vpc-name' cannot be bound to this policy because it is already bound to another policy.`

To fix this error, you can either:

1. Disable the automation enabling Cloud DNS logging in total and only have it configured to ingest Cloud DNS logs you enable yourself by setting tfvars to `orchestrate_dns_logs = false` and `ingest_dns = true`.
2. Create a scope policy rule to ignore Cloud DNS logging for any project you have your own Cloud DNS policies in. Add a rule to match those projects, and in the config section of that rule add `"dns" : "ignore"`. See the scope policy config section above for more details.

NOte: The orchestration does not handle the case currently where you have some networks that are bound to an existing policy in a project and other networks that are not bound that you want to be orchestrated by the automation for logging. If this is a use case for your GCP environment, contact us to discuss handling this usage scenario.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.fusion.vectra.ai/cloud-onboarding/gcp-cloud-onboarding/neto-onboarding-gcp.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
