Skip to main content

Service Account

The DiscrimiNAT requires different permissions to work effectively across differing setups.

The most basic of the setups is a single project with only VM instances to protect within the same project. The permissions for this are included with our Deployment Manager template and Terraform modules as allowed scopes on the DiscrimiNAT instances.

For the rest, and if you'd rather manage the service account with discrete permissions, the following should come in handy.

TL;DR​

For all features and topologies enabled,

  1. Create an IAM service account, in a host project, for use by DiscrimiNAT instances.
  2. Create an organisation-level IAM Role with the following permissions.
  3. Create a folder-level† (or organisation-level) IAM binding granting the above IAM Role to the Principal of the above service account.
caution

† The chosen folder should contain the host project and all service projects either directly or through subfolders.

logging.logEntries.create
compute.firewalls.list
compute.instances.list
compute.addresses.list
compute.addresses.use
compute.subnetworks.useExternalIp
compute.instances.addAccessConfig
compute.projects.get
vpcaccess.connectors.list
compute.subnetworks.get
container.clusters.list
roles/monitoring.metricWriter
tip

roles/monitoring.metricWriter is the Google predefined Monitoring Metric Writer role. It can be associated with the service account as a whole.

LOGGING​

The DiscrimiNAT automatically logs config & flow events to StackDriver. The following permission allows its instances to log at logName="projects/<google-cloud project name>/logs/discriminat-config" and logName="projects/<google-cloud project name>/logs/discriminat-flow".

logging.logEntries.create

ALLOWLIST CONFIG​

To form a complete picture of the VM instances in the VPC and their associated Firewall Rules, the DiscrimiNAT needs read access to these resources.

compute.firewalls.list
compute.instances.list

SHARED VPC​

In addition to the above, to discover VM instances in service projects, the following permission is required. See the Shared VPC page for more information.

compute.projects.get

SERVERLESS VPC ACCESS CONNECTORS​

In addition to the above, the following will be required to form a complete picture of any Serverless VPC Access Connectors.

If permissions for Shared VPC are included, then any Serverless VPC Access Connectors defined in service projects will also be picked up.

vpcaccess.connectors.list
compute.subnetworks.get

See the Serverless VPC Access Connectors page for more information.

CLOUD COMPOSER v2 GKE CLUSTERS​

A Composer v2 environment's cluster is an Autopilot mode VPC-native Google Kubernetes Engine cluster. Network Tags to it, however, can be applied at the time of the Composer environment's creation. Add the following permissions to the service account's role to allow the DiscrimiNAT to apply corresponding Firewall Rules to the clusters' subnets.

container.clusters.list
compute.subnetworks.get

EXTERNAL IPs​

If a Public IP is not found attached to a DiscrimiNAT instance, it will look for any allocated but unassociated External IPs that have a label-key named discriminat – the value which should be set to the value of the variable custom_deployment_id of the Terraform module, if that was set, else anything but blank. One of such External IPs will be attempted to be associated with itself then.

tip

This allows you to have a stable set of static IPs to share with your partners, who may wish to allowlist/whitelist them.

Private Google Access enabled on the subnet DiscrimiNAT is deployed in is needed for this mechanism to work though – since making the association needs access to the Compute API. In the google_network example, this is demonstrated by setting subnet_private_access = true.

compute.addresses.list
compute.addresses.use
compute.subnetworks.useExternalIp
compute.instances.addAccessConfig

OPS AGENT​

The DiscrimiNAT comes with Google's Ops Agent pre-installed. Should you require detailed metrics on the operating system's performance and utilisation, such as memory and load average, the permissions granted by the Monitoring Metric Writer role would be required.

roles/monitoring.metricWriter
tip

roles/monitoring.metricWriter is the Google predefined Monitoring Metric Writer role. It can be associated with the service account as a whole.

TERRAFORM​

If using Terraform, a new variable from v2.3 onwards has been introduced to let the user override the service account used by DiscrimiNAT instances. This is the custom_service_account_email variable and if left unset, defaults to the default compute engine service account with limited scopes of compute-rw, logging-write and monitoring-write. If set to the Principal of any service account, assigns that service account to the instances and changes the scope to cloud-platform.

Sample code to create a Service Account, the IAM Role and an IAM Binding for a simple, single Project only deployment​

variable "project_id" {
type = string
description = "Project ID for the Service Account to reside in. Think about the actual Project the DiscrimiNAT Firewall will be deployed in (where the VPC Network will be.) You must have privileges to create a new Service Account in this Project."
}

resource "google_project_iam_custom_role" "discriminat" {
role_id = "DiscrimiNAT"
title = "DiscrimiNAT Firewall Role"
description = "Permissions needed for DiscrimiNAT Firewall to read metadata from VMs, Subnetworks, Firewall Rules, etc., write Logs & Metrics, and attach an External IP to itself. See upstream docs for full details: https://chasersystems.com/docs/discriminat/gcp/service-account/"
permissions = ["logging.logEntries.create", "compute.firewalls.list", "compute.instances.list", "compute.addresses.list", "compute.addresses.use", "compute.subnetworks.useExternalIp", "compute.instances.addAccessConfig", "compute.projects.get", "vpcaccess.connectors.list", "compute.subnetworks.get", "container.clusters.list"]
}

resource "google_service_account" "discriminat" {
account_id = "discriminat"
display_name = "DiscrimiNAT Firewall Service Account"
description = "For DiscrimiNAT Firewall. See upstream docs for full details: https://chasersystems.com/docs/discriminat/gcp/service-account/"
}

resource "google_project_iam_member" "discriminat_custom_role" {
project = var.project_id
role = google_project_iam_custom_role.discriminat.id
member = "serviceAccount:${google_service_account.discriminat.email}"
}

resource "google_project_iam_member" "discriminat_metric_writer" {
project = var.project_id
role = "roles/monitoring.metricWriter"
member = "serviceAccount:${google_service_account.discriminat.email}"
}

output "discriminat_service_account_email" {
value = google_service_account.discriminat.email
}

Sample code to create a Service Account, the IAM Role and an IAM Binding for a complex, Shared VPC deployment with Projects in a Folder​

variable "project_id" {
type = string
description = "Project ID for the Service Account to reside in. Think about the actual Project the DiscrimiNAT Firewall will be deployed in (where the VPC Network will be.) You must have privileges to create a new Service Account in this Project."
}

variable "folder_id" {
type = string
description = "The numeric Folder ID that is hierarchically high enough to contain the Host Project and all Service Projects connected to the VPC Network this particular DiscrimiNAT deployment will filter outbound traffic for. You must have privileges to create an IAM Binding at this level."
}

variable "org_id" {
type = string
description = "The numeric Organization ID to create the Role in. You must have privileges to create a Role at this level."
}

resource "google_organization_iam_custom_role" "discriminat" {
role_id = "DiscrimiNAT"
title = "DiscrimiNAT Firewall Role"
description = "Permissions needed for DiscrimiNAT Firewall to read metadata from VMs, Subnetworks, Firewall Rules, etc., write Logs & Metrics, and attach an External IP to itself. See upstream docs for full details: https://chasersystems.com/docs/discriminat/gcp/service-account/"
permissions = ["logging.logEntries.create", "compute.firewalls.list", "compute.instances.list", "compute.addresses.list", "compute.addresses.use", "compute.subnetworks.useExternalIp", "compute.instances.addAccessConfig", "compute.projects.get", "vpcaccess.connectors.list", "compute.subnetworks.get", "container.clusters.list"]
org_id = var.org_id
}

resource "google_service_account" "discriminat" {
account_id = "discriminat"
display_name = "DiscrimiNAT Firewall Service Account"
description = "For DiscrimiNAT Firewall. See upstream docs for full details: https://chasersystems.com/docs/discriminat/gcp/service-account/"
project = var.project_id
}

resource "google_folder_iam_member" "discriminat_custom_role" {
folder = var.folder_id
role = google_organization_iam_custom_role.discriminat.id
member = "serviceAccount:${google_service_account.discriminat.email}"
}

resource "google_folder_iam_member" "discriminat_metric_writer" {
folder = var.folder_id
role = "roles/monitoring.metricWriter"
member = "serviceAccount:${google_service_account.discriminat.email}"
}

output "discriminat_service_account_email" {
value = google_service_account.discriminat.email
}

FAQ​

Does DiscrimiNAT work without a custom service account?​

Yes. It can work with the default compute engine service account with limited scopes of compute-rw, logging-write and monitoring-write, if Shared VPC and Serverless VPC Access Connectors support is not required.

Can the service account be changed on-the-fly?​

Our usual deployment patterns encapsulate the instances in a Managed Instance Group (MIG). Any change is applied to the MIG template, which then does need to restart the instances in order to change the service account. If deployed behind an Internal Load Balancer (ILB), there will be near-zero downtime while the instances roll-over. If routed to directly, there will be a minute or two's interruption.