# Shared Security Resources

This stage sets up an area dedicated to hosting security resources and configurations which impact the whole organization, or are shared across the hierarchy to other projects and teams.

Like other modern FAST stage, the resource design is defined here via YAML configuration files and implemented via factories to provide maximum flexibility. A sample reference design compatible with legacy FAST is provided in an initial dataset, and can be used as-is or used as a basis for customizations.

The following diagram illustrates the high-level design of resources implemented in the default dataset:

<p align="center">
  <img src="diagram.png" alt="Security diagram">
</p>

<!-- BEGIN TOC -->
- [Quickstart](#quickstart)
  - [Factory data set](#factory-data-set)
  - [Defaults file](#defaults-file)
  - [Terraform vars configuration](#terraform-vars-configuration)
  - [Linking FAST output files](#linking-fast-output-files)
  - [Terraform init/apply cycle](#terraform-initapply-cycle)
- [Design overview and choices](#design-overview-and-choices)
  - [Cloud KMS](#cloud-kms)
  - [Certificate Authority Service (CAS)](#certificate-authority-service-cas)
- [Files](#files)
- [Variables](#variables)
- [Outputs](#outputs)
<!-- END TOC -->

## Quickstart

This stage is designed to be applied after stage 0, but as any other FAST stage it can also be used in isolation, provided the required prerequisites are met. This section details the FAST usage, where prerequisited are already in place.

The high-level flow for running this stage is:

- check the **factory data set** and do any necessary edits to match your configuration (number of projects, names, KMS keys, CAs, etc.)
- populate the **defaults file** with attributes matching your configuration
- define a simple tfvars file if your dataset is in a non-standard path, and/or you want local output files (recommended for initial setups)
- bring in or link the prerequisite files generated by the previous stage
- run `terraform init` and `apply`

### Factory data set

The default dataset provides two projects, each rooted in a separate folder. I does not define any KMS or CAS resources.

If a different folder or project configuration is needed copy the full dataset to a different path to avoid accidental changes from upstream, then add or remove files in `data/folders` and `data/projects`.

A simple KMS keyrin is provided in `keyrings` folder, use it as an example if more are needed. For CAS too a sample configuration is already present, but the Certificate Authorities factory is disabled by default. If CAS is needed define the `factories_config.certificate_authorities` variable attribute in your tfvars and set it to the path of the relevant data folder (`data/certificate-authorities` by default) as shown in this snippet.

```hcl
factories_config = {
  certificate_authorities = "data/certificate-authorities"
}
```

### Defaults file

Configurations defaults are stored in the `defaults.yaml` file in the selected dataset. Relocating the defaults file is good practice to avoid accindetal changes from upstream, this is done via the `factories_config.default` variable attribute.

Once a suitable place has been found for the file, edit it to match the desired configuration. Several pieces of information coming from the previous stage (prefix, billing account, etc.) are pre-populated in the project defaults so they don't need to be explicitly set. If some of them need to be overridden, the attributes in `projects.overrides` take precedence as shown in this annotated sample.

```yaml
context:
  # external definitions can be set here and used in context from YAML files
  # locations.primary is used by the default dataset, and should be defined
  locations:
    primary: europe-west1
    secondary: europe-west3
# defaults and overrides common to security projects should go here
# defining storage_location is required
projects:
  defaults:
    storage_location: eu
  # overrides are optional, and can be used to override some FAST defaults
  overrides:
    # don't do this unless you have a good reason :
    prefix: foo-0
```

### Terraform vars configuration

A tfvars file allows you to control paths for the project factories data, and to enable local output files generation. This example shows how to override all the factory paths while also enabling the CAS factory, and how to enable output files.

```hcl
factories_config = {
  certificate_authorities = "/some/path/data/certificate-authorities"
  defaults                = "/some/path/data/defaults.yaml"
  folders                 = "/some/path/data/folders"
  keyrings                = "/some/path/data/keyrings"
  projects                = "/some/path/data/projects"
}
outputs_location = "~/fast-config"
```

### Linking FAST output files

If you enabled local output files in the previous stage, run this command replacing the example path with the one for your output files.

```bash
../fast-links.sh ~/fast-config

# File linking commands for security stage

# provider file
ln -s ~/fast-config/providers/2-security-providers.tf ./

# input files from other stages
ln -s ~/fast-config/tfvars/0-globals.auto.tfvars.json ./
ln -s ~/fast-config/tfvars/0-org-setup.auto.tfvars.json ./

# conventional location for this stage terraform.tfvars (manually managed)
ln -s ~/fast-config/2-security.auto.tfvars ./
```

If you have no local output files, check the previous state's outputs for the name of your GCS outputs bucket and replace it in the example below.

```bash
../fast-links.sh gs://myprefix-prod-iac-org-0-iac-outputs

# File linking commands for security stage

# provider file
gcloud storage cp gs://myprefix-prod-iac-org-0-iac-outputs/providers/2-security-providers.tf ./

# input files from other stages
gcloud storage cp gs://myprefix-prod-iac-org-0-iac-outputs/tfvars/0-globals.auto.tfvars.json ./
gcloud storage cp gs://myprefix-prod-iac-org-0-iac-outputs/tfvars/0-org-setup.auto.tfvars.json ./

# conventional location for this stage terraform.tfvars (manually managed)
gcloud storage cp gs://myprefix-prod-iac-org-0-iac-outputs/2-security.auto.tfvars ./
```

Once you have one of the above outputs, copy/paste it in your terminal from within this stage's folder.

Note that the last command in both outputs is optional: this is our recommended best practice to centrally store the tfvars file you created for this stage. If this convention works for you, move the tfvars file created in the previous steps to the path shown in the output, then run the command.

### Terraform init/apply cycle

Once everything is set up, simply run the usual `init`/`apply` cycle.

```bash
terraform init
terraform apply
```

## Design overview and choices

Project-level security resources are grouped into one project per environment. This setup matches requirements we frequently observe in real life and provides enough separation without needlessly complicating operations.

Cloud KMS is configured and designed mainly to encrypt GCP resources with a [Customer-managed encryption key](https://cloud.google.com/kms/docs/cmek) but it may be used to create cryptokeys used to [encrypt application data](https://cloud.google.com/kms/docs/encrypting-application-data) and other uses.

A single [Certificate Authority Service](https://cloud.google.com/security/products/certificate-authority-service?hl=en) pool and CA are configured by default, but the setup can be easily extended to support multiple resources in any environment.

IAM for day to day operations is already assigned at the folder level to the security team by the previous stage, but more granularity can be added here to grant control of separate services across environments to different actors.

### Cloud KMS

A reference Cloud KMS implementation is part of this stage, to provide a simple way of managing centralized keys, that are then shared and consumed widely across the organization to enable customer-managed encryption. The implementation is also easy to clone and modify to support other services like Secret Manager.

The Cloud KMS configuration allows defining keys by name (typically matching the downstream service that uses them) in different locations. It then takes care internally of provisioning the relevant keyrings and creating keys in the appropriate location.

IAM roles on keys can be configured at the logical level for all locations where a logical key is created. Their management can also be delegated via [delegated role grants](https://cloud.google.com/iam/docs/setting-limits-on-granting-roles) exposed through a simple variable, to allow other identities to set IAM policies on keys. This is particularly useful in setups like project factories, making it possible to configure IAM bindings during project creation for team groups or service agent accounts (compute, storage, etc.).

### Certificate Authority Service (CAS)

A reference Certificate Authority Services (CAS) is also part of this stage, allowing creation of any number of CA pools and authorities. To create custom CAS, the relevant factory variable needs to be configured first as explained above.

<!-- TFDOC OPTS files:1 show_extra:1 exclude:2-security-providers.tf -->
<!-- BEGIN TFDOC -->
## Files

| name | description | modules | resources |
|---|---|---|---|
| [factory-cas.tf](./factory-cas.tf) | None | <code>certificate-authority-service</code> |  |
| [factory-keyrings.tf](./factory-keyrings.tf) | None | <code>kms</code> |  |
| [factory-projects.tf](./factory-projects.tf) | None | <code>project-factory</code> |  |
| [main.tf](./main.tf) | Module-level locals and resources. |  |  |
| [outputs.tf](./outputs.tf) | Module outputs. |  | <code>google_storage_bucket_object</code> · <code>local_file</code> |
| [variables-fast.tf](./variables-fast.tf) | None |  |  |
| [variables.tf](./variables.tf) | Module variables. |  |  |

## Variables

| name | description | type | required | default | producer |
|---|---|:---:|:---:|:---:|:---:|
| [billing_account](variables-fast.tf#L17) | Billing account id. | <code title="object&#40;&#123;&#10;  id &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ |  | <code>0-org-setup</code> |
| [prefix](variables-fast.tf#L57) | Prefix used for resources that need unique names. Use a maximum of 9 chars for organizations, and 11 chars for tenants. | <code>string</code> | ✓ |  | <code>0-org-setup</code> |
| [context](variables.tf#L17) | Context-specific interpolations. | <code title="object&#40;&#123;&#10;  condition_vars    &#61; optional&#40;map&#40;map&#40;string&#41;&#41;, &#123;&#125;&#41;&#10;  email_addresses   &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10;  custom_roles      &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10;  folder_ids        &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10;  iam_principals    &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10;  locations         &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10;  project_ids       &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10;  storage_buckets   &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10;  tag_keys          &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10;  tag_values        &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10;  vpc_sc_perimeters &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> |  | <code>&#123;&#125;</code> |  |
| [custom_roles](variables-fast.tf#L25) | Custom roles defined at the org level, in key => id format. | <code>map&#40;string&#41;</code> |  | <code>&#123;&#125;</code> | <code>0-org-setup</code> |
| [factories_config](variables.tf#L36) | Configuration for the resource factories or external data. | <code title="object&#40;&#123;&#10;  certificate_authorities &#61; optional&#40;string&#41; &#35; &#34;data&#47;certificate-authorities&#34;&#10;  defaults                &#61; optional&#40;string, &#34;data&#47;defaults.yaml&#34;&#41;&#10;  folders                 &#61; optional&#40;string, &#34;data&#47;folders&#34;&#41;&#10;  keyrings                &#61; optional&#40;string, &#34;data&#47;keyrings&#34;&#41;&#10;  projects                &#61; optional&#40;string, &#34;data&#47;projects&#34;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> |  | <code>&#123;&#125;</code> |  |
| [folder_ids](variables-fast.tf#L33) | Folders created in the bootstrap stage. | <code>map&#40;string&#41;</code> |  | <code>&#123;&#125;</code> | <code>0-org-setup</code> |
| [iam_principals](variables-fast.tf#L41) | IAM-format principals. | <code>map&#40;string&#41;</code> |  | <code>&#123;&#125;</code> | <code>0-org-setup</code> |
| [perimeters](variables-fast.tf#L49) | Optional VPC-SC perimeter ids. | <code>map&#40;string&#41;</code> |  | <code>&#123;&#125;</code> | <code>1-vpcsc</code> |
| [project_ids](variables-fast.tf#L67) | Projects created in the bootstrap stage. | <code>map&#40;string&#41;</code> |  | <code>&#123;&#125;</code> | <code>0-org-setup</code> |
| [service_accounts](variables-fast.tf#L75) | Service accounts created in the bootstrap stage. | <code>map&#40;string&#41;</code> |  | <code>&#123;&#125;</code> | <code>0-org-setup</code> |
| [storage_buckets](variables-fast.tf#L83) | Storage buckets created in the bootstrap stage. | <code>map&#40;string&#41;</code> |  | <code>&#123;&#125;</code> | <code>0-org-setup</code> |
| [tag_keys](variables-fast.tf#L91) | FAST-managed resource manager tag keys. | <code>map&#40;string&#41;</code> |  | <code>&#123;&#125;</code> | <code>0-org-setup</code> |
| [tag_values](variables-fast.tf#L99) | FAST-managed resource manager tag values. | <code>map&#40;string&#41;</code> |  | <code>&#123;&#125;</code> | <code>0-org-setup</code> |
| [universe](variables-fast.tf#L107) | GCP universe where to deploy projects. The prefix will be prepended to the project id. | <code title="object&#40;&#123;&#10;  domain                         &#61; string&#10;  prefix                         &#61; string&#10;  forced_jit_service_identities  &#61; optional&#40;list&#40;string&#41;, &#91;&#93;&#41;&#10;  unavailable_services           &#61; optional&#40;list&#40;string&#41;, &#91;&#93;&#41;&#10;  unavailable_service_identities &#61; optional&#40;list&#40;string&#41;, &#91;&#93;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> |  | <code>null</code> | <code>0-org-setup</code> |

## Outputs

| name | description | sensitive | consumers |
|---|---|:---:|---|
| [ca_pools](outputs.tf#L64) | Certificate Authority Service pools and CAs. |  |  |
| [kms_keys_ids](outputs.tf#L69) | KMS keys IDs. |  |  |
| [tfvars](outputs.tf#L74) | Terraform variable files for the following stages. | ✓ |  |
<!-- END TFDOC -->
