diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8d8f6fc8b..740842358 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + workflow: rules: - when: never # This rule will always prevent the pipeline from running until we have a properly configured and registered runner instance. diff --git a/.tflint.hcl b/.tflint.hcl index 16198b068..32ca27d95 100644 --- a/.tflint.hcl +++ b/.tflint.hcl @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/GEMINI.md b/GEMINI.md index 27fc8be96..bb172ab2d 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -1,3 +1,19 @@ + + # gemini.md - AI Assistant Guidelines for Stellar Engine ## Project Overview diff --git a/README.md b/README.md index 18464abc9..f4631c4d6 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,19 @@ + + ## Introduction Stellar Engine is a fork of the Google Cloud Foundation Fabric (CFF) repository, aimed at providing Infrastructure as Code (IaC) for Google Cloud Platform (GCP) customers who need to create a landing zone environment with the Assured Workload overlays. In addition to the IaC, there is [documentation available](docs/path-to-authorization.md) for both the DISA FedRAMP High (FRH), DoD Impact Level 4 (IL4) and DoD Impact Level (IL5) compliance regimes that provide a mapping of National Institute of Standards and Technology (NIST) 800-53r5 controls to enable projects that leverage the Stellar Engine codebase to accelerate the speed at which an Authorization to Operate (ATO) can be attained. diff --git a/automation/allow_bq.sh b/automation/allow_bq.sh new file mode 100644 index 000000000..55297ea3a --- /dev/null +++ b/automation/allow_bq.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#### Use this script at your own risk. The author assumes no responsibility for any damages or losses incurred through its use. + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +cd "${SCRIPT_DIR}" || exit + +# shellcheck source=automation/config.env.sample +source "${SCRIPT_DIR}"/config.env + + +# Mapping abbreviations +if [[ ${COMPLIANCE_REGIME} == "FEDRAMP_HIGH" ]]; then + COMPLIANCE_REGIME="FRH" +elif [[ ${COMPLIANCE_REGIME} == "FEDRAMP_MODERATE" ]]; then + COMPLIANCE_REGIME="FRM" +fi + +aw_folder=$(gcloud resource-manager folders list --folder="${TOP_LEVEL_FOLDER_ID}" --filter="display_name:${COMPLIANCE_REGIME}-${PREFIX}" --format="value(ID)") +echo 'constraint: constraints/gcp.restrictServiceUsage' > tmp_aw_policy.yaml + +gcloud resource-manager org-policies describe constraints/gcp.restrictServiceUsage --folder="${aw_folder}" --format='yaml(listPolicy.allowedValues)' >> tmp_aw_policy.yaml +{ + echo " - bigquery.googleapis.com" + echo " - bigqueryconnection.googleapis.com" + echo " - bigquerydatapolicy.googleapis.com" + echo " - bigquerydatatransfer.googleapis.com" + echo " - bigquerymigration.googleapis.com" + echo " - bigqueryreservation.googleapis.com" + echo " - bigquerystorage.googleapis.com" + +} >> tmp_aw_policy.yaml + +gcloud resource-manager org-policies set-policy tmp_aw_policy.yaml --folder="${aw_folder}" \ No newline at end of file diff --git a/automation/allow_compliance_apis.sh b/automation/allow_compliance_apis.sh new file mode 100644 index 000000000..2b1e05dbc --- /dev/null +++ b/automation/allow_compliance_apis.sh @@ -0,0 +1,66 @@ +#!/bin/bash +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +cd "${SCRIPT_DIR}" || exit + +compliance_LIST="${SCRIPT_DIR}/allowed_apis.yaml" +LZ_EXCEPTIONS="${SCRIPT_DIR}/lz_exceptions.yaml" +PLAN_FILE="tfplan" + +echo "-------------------------------------------------------" +echo "Running compliance IL5 + COA2 API Cross-Check..." +echo "-------------------------------------------------------" + +if [[ ! -f "$compliance_LIST" ]]; then + echo "[ERROR] compliance list not found at $compliance_LIST" + exit 1 +fi + +if [[ ! -f "$LZ_EXCEPTIONS" ]]; then + echo "[ERROR] LZ Exceptions list not found at $LZ_EXCEPTIONS" + exit 1 +fi + +ALLOWED_compliance=$(yq eval '.allowed_apis[]' "$compliance_LIST") +ALLOWED_COA2=$(yq eval '.COA2[]' "$LZ_EXCEPTIONS") + +ALLOWED_APIS=$(echo -e "${ALLOWED_compliance}\n${ALLOWED_COA2}" | sort -u | sed '/^null$/d') + +cd "${SCRIPT_DIR}/../fast/stages-aw/1-assured-workload" || exit 1 +if [[ ! -f "$PLAN_FILE" ]]; then + echo "Creating temporary plan for validation..." + terraform plan -out="$PLAN_FILE" > /dev/null +fi + +REQUESTED_APIS=$(terraform show -json "$PLAN_FILE" | jq -r '.resource_changes[]? | select(.type == "google_project_service") | .change.after.service' | sort -u) +MISSING_APIS="" + +for api in $REQUESTED_APIS; do + if ! echo "$ALLOWED_APIS" | grep -qx "$api"; then + echo "[!] VIOLATION: '$api' is NOT in the compliance approved list or COA2 exceptions." + MISSING_APIS+="$api " + fi +done + +if [[ -n "$MISSING_APIS" ]]; then + echo -e "\n[ERROR] compliance COMPLIANCE FAILURE" + echo "The following APIs are requested in code but missing from approved lists:" + for missing in $MISSING_APIS; do echo " - $missing"; done + exit 1 +else + echo "compliance/COA2 Cross-Check Passed: All requested services are authorized." + exit 0 +fi diff --git a/automation/allowed_apis.yaml b/automation/allowed_apis.yaml new file mode 100644 index 000000000..ba6d318c0 --- /dev/null +++ b/automation/allowed_apis.yaml @@ -0,0 +1,48 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#testing purposes API's that already match existing list in the org. +allowed_apis: + - artifactregistry.googleapis.com + - bigquery.googleapis.com + - bigquerydatatransfer.googleapis.com + - privateca.googleapis.com + - cloudbuild.googleapis.com + - composer.googleapis.com + - datafusion.googleapis.com + - dns.googleapis.com + - cloudidentity.googleapis.com + - cloudkms.googleapis.com + - logging.googleapis.com + - monitoring.googleapis.com + - run.googleapis.com + - spanner.googleapis.com + - sqladmin.googleapis.com + - storage.googleapis.com + - cloudtasks.googleapis.com + - vision.googleapis.com + - workstations.googleapis.com + - compute.googleapis.com + - dataflow.googleapis.com + - dataproc.googleapis.com + - eventarc.googleapis.com + - gkehub.googleapis.com + - container.googleapis.com + - iam.googleapis.com + - redis.googleapis.com + - pubsub.googleapis.com + - secretmanager.googleapis.com + - dlp.googleapis.com + - speech.googleapis.com + - datapipelines.googleapis.com diff --git a/automation/clean.sh b/automation/clean.sh new file mode 100644 index 000000000..554f6e0a6 --- /dev/null +++ b/automation/clean.sh @@ -0,0 +1,81 @@ +#!/bin/bash +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#### This script is an experimental state, and is designed to help clean environments +#### Use this script at your own risk. The author assumes no responsibility for any damages or losses incurred through its use. + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +# shellcheck source=automation/config.env.sample +source "${SCRIPT_DIR}"/config.env + +# Tags +parent_tag_name=$(gcloud resource-manager tags keys list \ + --parent=organizations/"${ORGANIZATION_ID}" \ + --format="value(name)") + +child_tag_name=$(gcloud resource-manager tags values list \ + --parent="${parent_tag_name}" \ + --format="value(name)") + +gcloud resource-manager tags values delete "$child_tag_name" +gcloud resource-manager tags keys delete "$parent_tag_name" + +# Custom Org Roles +declare -a custom_org_roles=() +while IFS= read -r role_name; do + custom_org_roles+=("$role_name") +done < <(gcloud iam roles list \ + --organization="${ORGANIZATION_ID}" \ + --filter='name~^organizations/' \ + --format='value(name)' | awk -F'/' '{print $NF}' 2>/dev/null) + +for i in "${custom_org_roles[@]}"; do + gcloud iam roles delete --organization="${ORGANIZATION_ID}" "$i" +done + +# Log Sinks +gcloud logging sinks delete "empty-audit-logs" --organization="$ORGANIZATION_ID" +gcloud logging sinks delete "workspace-audit-logs" --organization="$ORGANIZATION_ID" +gcloud logging sinks delete "vpc-sc" --organization="$ORGANIZATION_ID" +gcloud logging sinks delete "audit-logs" --organization="$ORGANIZATION_ID" + +# Org Roles +gcloud iam roles delete gcveNetworkAdmin --organization="$ORGANIZATION_ID" +gcloud iam roles delete storageViewer --organization="$ORGANIZATION_ID" +gcloud iam roles delete organizationIamAdmin --organization="$ORGANIZATION_ID" +gcloud iam roles delete tenantNetworkAdmin --organization="$ORGANIZATION_ID" +gcloud iam roles delete tagViewer --organization="$ORGANIZATION_ID" +gcloud iam roles delete serviceProjectNetworkAdmin --organization="$ORGANIZATION_ID" +gcloud iam roles delete organizationAdminViewer --organization="$ORGANIZATION_ID" + +# Org Policies +gcloud resource-manager org-policies delete --organization="$ORGANIZATION_ID" constraints/clouddeploy.disableServiceLabelGeneration +gcloud resource-manager org-policies delete --organization="$ORGANIZATION_ID" constraints/cloudfunctions.requireVPCConnector +gcloud resource-manager org-policies delete --organization="$ORGANIZATION_ID" constraints/compute.disableAllIpv6 +gcloud resource-manager org-policies delete --organization="$ORGANIZATION_ID" constraints/compute.disableHybridCloudIpv6 +gcloud resource-manager org-policies delete --organization="$ORGANIZATION_ID" constraints/compute.disableInternetNetworkEndpointGroup +gcloud resource-manager org-policies delete --organization="$ORGANIZATION_ID" constraints/compute.disableSshInBrowser +gcloud resource-manager org-policies delete --organization="$ORGANIZATION_ID" constraints/compute.disableVpcExternalIpv6 +gcloud resource-manager org-policies delete --organization="$ORGANIZATION_ID" constraints/compute.disableVpcInternalIpv6 +gcloud resource-manager org-policies delete --organization="$ORGANIZATION_ID" constraints/compute.requireOsLogin +gcloud resource-manager org-policies delete --organization="$ORGANIZATION_ID" constraints/essentialcontacts.disableProjectSecurityContacts +gcloud resource-manager org-policies delete --organization="$ORGANIZATION_ID" constraints/firestore.requireP4SAforImportExport +gcloud resource-manager org-policies delete --organization="$ORGANIZATION_ID" constraints/gcp.detailedAuditLoggingMode +gcloud resource-manager org-policies delete --organization="$ORGANIZATION_ID" constraints/gcp.disableCloudLogging +gcloud resource-manager org-policies delete --organization="$ORGANIZATION_ID" constraints/iam.disableServiceAccountCreation +gcloud resource-manager org-policies delete --organization="$ORGANIZATION_ID" constraints/iap.requireGlobalIapWebDisabled +gcloud resource-manager org-policies delete --organization="$ORGANIZATION_ID" constraints/iap.requireRegionalIapWebDisabled +gcloud resource-manager org-policies delete --organization="$ORGANIZATION_ID" constraints/compute.requireOsLogin \ No newline at end of file diff --git a/automation/compliance_exceptions.yaml b/automation/compliance_exceptions.yaml new file mode 100644 index 000000000..3e801ebce --- /dev/null +++ b/automation/compliance_exceptions.yaml @@ -0,0 +1,43 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# lz_exceptions.yaml +# Combined list of Category 1 and Category 2 API exceptions for LZ Infrastructure +# These APIs are authorized for use in Core LZ projects only. +COA2: +# Category 1: IL5 Authorized / compliance Catalog Update Pending +#category_1_exceptions: + - accesscontextmanager.googleapis.com + - cloudasset.googleapis.com + - cloudbilling.googleapis.com + - networkconnectivity.googleapis.com + - servicedirectory.googleapis.com +# Category 2: Management/Enabling APIs Not Listed in compliance Catalog +# category_2_exceptions: + - assuredworkloads.googleapis.com + - bigqueryreservation.googleapis.com + - bigquerystorage.googleapis.com + - billingbudgets.googleapis.com + - cloudquotas.googleapis.com + - cloudresourcemanager.googleapis.com + - essentialcontacts.googleapis.com + - iamcredentials.googleapis.com + - iap.googleapis.com + - networksecurity.googleapis.com + - orgpolicy.googleapis.com + - servicenetworking.googleapis.com + - serviceusage.googleapis.com + - stackdriver.googleapis.com + - storage-component.googleapis.com + - sts.googleapis.com \ No newline at end of file diff --git a/automation/config.env.sample b/automation/config.env.sample new file mode 100644 index 000000000..d659afd06 --- /dev/null +++ b/automation/config.env.sample @@ -0,0 +1,56 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +BILLING_ACCOUNT=012345-67890-12345 +BOOTSTRAP_PROJECT_ID=bootstrap-project +COMPLIANCE_REGIME=IL5 +DIRECTORY_CUSTOMER_ID=012345678 +DEPLOYER_EMAIL_ADDRESS=user@example.com +FULLY_QUALIFIED_DOMAIN_NAME=example.com +LOGGING_ALERTS_EMAIL_ADDRESS=user@example.com +ORGANIZATION_ID=012345678912 +PREFIX=pre +REGIONS=us-east4 +AW_REGION=us +TENANT_ENVIRONMENTS=dev,prod +EXTERNAL_DIRECTORY_CUSTOMER_IDS= +EXTERNAL_ORGANIZATION_IDS= +TOP_LEVEL_FOLDER_NAME= +TOP_LEVEL_FOLDER_ID= +# Following are for Workload Identity Federation via GitLab (Leave blank if not using) +# Ex: google-cloud/army-example-lz +CI_PROJECT_PATH= +# URL of gitlab instance +GITLAB_URL= +# run --> curl -s https://GITLAB_DOMAIN/oauth/discovery/keys +# If that doesn't work run --> curl -s https://GITLAB_DOMAIN/-/jwks +# Leave blank if not using on the army network +JWKS_KEY= +# Group naming: +TF_VAR_gcp_organization_admins_group=gcp-organization-admins +TF_VAR_gcp_billing_admins_group=gcp-billing-admins +TF_VAR_gcp_vpc_network_admins_group=gcp-vpc-network-admins +TF_VAR_gcp_hybrid_connectivity_admins_group=gcp-hybrid-connectivity-admins +TF_VAR_gcp_logging_monitoring_admins_group=gcp-logging-monitoring-admins +TF_VAR_gcp_logging_monitoring_viewers_group=gcp-logging-monitoring-viewers +TF_VAR_gcp_security_admins_group=gcp-security-admins +TF_VAR_gcp_developers_group=gcp-developers +TF_VAR_gcp_devops_group=gcp-devops + +# Determines whether to create pubsub sink in Stage-1 +APPLY_TIER_1_PUBSUB_SINK=true + +# Determines requested network quota in Stage-3, defaults to 15 in variables +NETWORK_QUOTA_PREFERRED_VALUE=50 +TENANT_CI_PROJECT_PATH= diff --git a/automation/delete_projects_and_folders.sh b/automation/delete_projects_and_folders.sh new file mode 100644 index 000000000..ea1341290 --- /dev/null +++ b/automation/delete_projects_and_folders.sh @@ -0,0 +1,190 @@ +#!/bin/bash +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Exit immediately if a command exits with a non-zero status. +set -euo pipefail + +# --- Configuration --- +DRY_RUN=false +GCLOUD_QUIET_FLAG="" # Will be set to "--quiet" if the corresponding flag is passed + +# --- Function Definitions --- + +# Function to print usage instructions +usage() { + echo "Usage: $0 [OPTIONS] " + echo "Recursively deletes all folders and projects within a GCP Organization." + echo "" + echo "Arguments:" + echo " ORGANIZATION_ID The numeric ID of the GCP Organization (e.g., 123456789012)." + echo "" + echo "Options:" + echo " --dry-run Show what would be deleted without actually deleting anything." + echo " --quiet Pass the '--quiet' flag to 'gcloud' delete commands to suppress their prompts." + echo " --help Display this help and exit." + exit 1 +} + +# Recursive function to delete a folder and its contents +delete_folder_recursively() { + local folder_id="$1" + echo "" + echo "--- Processing Folder ID: $folder_id ---" + + # 1. Delete all projects inside the current folder + echo "-> Searching for projects in folder $folder_id..." + # The '|| true' prevents the script from exiting if no projects are found + local project_ids + project_ids=$(gcloud projects list \ + --filter="parent.id=$folder_id AND parent.type=folder" \ + --format="value(projectId)" || true) + + if [[ -n "$project_ids" ]]; then + for project_id in $project_ids; do + if [ "$DRY_RUN" = false ]; then + echo "Deleting project: $project_id" + # The $GCLOUD_QUIET_FLAG variable is used here + gcloud projects delete "$project_id" $GCLOUD_QUIET_FLAG + else + echo "DRY RUN: Would delete project '$project_id'." + fi + done + else + echo "No projects found in folder $folder_id." + fi + + # 2. Recursively delete all sub-folders + echo "-> Searching for sub-folders in folder $folder_id..." + # The '|| true' prevents the script from exiting if no sub-folders are found + local sub_folder_ids + sub_folder_ids=$(gcloud resource-manager folders list \ + --folder="$folder_id" \ + --format="value(ID)" || true) + + if [[ -n "$sub_folder_ids" ]]; then + for sub_folder_id in $sub_folder_ids; do + # Recursive call for each sub-folder + delete_folder_recursively "$sub_folder_id" + done + else + echo "No sub-folders found in folder $folder_id." + fi + + # 3. Delete the (now empty) current folder + if [ "$DRY_RUN" = false ]; then + echo "-> Deleting folder itself: $folder_id" + # The $GCLOUD_QUIET_FLAG variable is used here + gcloud resource-manager folders delete "$folder_id" $GCLOUD_QUIET_FLAG + else + echo "-> DRY RUN: Would delete folder '$folder_id'." + fi + echo "--- Finished Processing Folder ID: $folder_id ---" +} + + +# --- Main Script Logic --- + +# Check for gcloud command +if ! command -v gcloud &> /dev/null; then + echo "ERROR: 'gcloud' command not found. Please install and configure the Google Cloud SDK." + exit 1 +fi + +# Robust argument parsing +POSITIONAL_ARGS=() +while [[ $# -gt 0 ]]; do + case $1 in + --dry-run) + DRY_RUN=true + shift # past argument + ;; + --quiet) + GCLOUD_QUIET_FLAG="--quiet" + shift # past argument + ;; + --help) + usage + ;; + -*) # Unknown option + echo "Error: Unknown option $1" + usage + ;; + *) # Positional argument + POSITIONAL_ARGS+=("$1") + shift + ;; + esac +done +set -- "${POSITIONAL_ARGS[@]}" # Restore positional parameters + +# Check for ORGANIZATION_ID +if [[ $# -ne 1 ]]; then + echo "Error: Missing ORGANIZATION_ID." + usage +fi +ORG_ID="$1" + +# Validate ORG_ID is a number +if ! [[ "$ORG_ID" =~ ^[0-9]+$ ]]; then + echo "Error: ORGANIZATION_ID must be a numeric value." + usage +fi + +# Main warning and confirmation prompt +echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" +echo "!!! W A R N I N G !!!" +echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" +echo "This is a destructive action, intended to clean up " +echo "A GCP ORG for DELETION" +echo "Common causes of failure are firewall associations" +echo "for shared VPC in the Networking Folders" +echo "----------------------------------------------------------------" +echo "This script will PERMANENTLY delete all folders and all projects" +echo "under the organization with ID: $ORG_ID." +echo "This action CANNOT be undone." +echo "" + +if [ "$DRY_RUN" = true ]; then + echo "✅ DRY RUN MODE ENABLED. NO RESOURCES WILL BE DELETED." +else + # Prompt for confirmation unless in dry-run mode + read -r -p "To confirm this destructive action, type the organization ID ($ORG_ID) again: " confirmation + if [[ "$confirmation" != "$ORG_ID" ]]; then + echo "Confirmation failed. Exiting without making changes." + exit 0 + fi +fi + +echo "" +echo "Starting process for Organization ID: $ORG_ID" + +# Get top-level folders in the organization +echo "Fetching top-level folders..." +top_level_folders=$(gcloud resource-manager folders list \ + --organization="$ORG_ID" \ + --format="value(ID)" || true) + +if [[ -z "$top_level_folders" ]]; then + echo "No folders found in organization $ORG_ID. Nothing to do." + exit 0 +fi + +# Loop through top-level folders and start the recursive deletion +for folder_id in $top_level_folders; do + delete_folder_recursively "$folder_id" +done + +echo "" +echo "✅ Script completed." \ No newline at end of file diff --git a/automation/migrate-tenants.sh b/automation/migrate-tenants.sh new file mode 100644 index 000000000..bd2db82d3 --- /dev/null +++ b/automation/migrate-tenants.sh @@ -0,0 +1,135 @@ +#!/bin/bash +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This is a temporary script to migrate tenants from a single tenants.yml to the tenants directory. +# This script will only need to be ran once. + +# Exit immediately if a command exits with a non-zero status +set -e + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +compliance_regime_mapping() { + case "${1}" in + "COMPLIANCE_REGIME_UNSPECIFIED") echo "cru" ;; + "IL2") echo "il2" ;; + "IL4") echo "il4" ;; + "IL5") echo "il5" ;; + "FEDRAMP_HIGH") echo "frh" ;; + "FEDRAMP_MODERATE") echo "frm" ;; + *) echo "${1}" | tr '[:upper:]' '[:lower:]' ;; + esac +} + +# ========================================== +# CONFIGURATION & INITIALIZATION +# ========================================== + +# shellcheck source=automation/config.env.sample +if [ -f "$SCRIPT_DIR/config.env" ]; then + source "$SCRIPT_DIR"/config.env +else + echo "Error: config.env not found at $SCRIPT_DIR/config.env" + exit 1 +fi + +COMPLIANCE_REGIME_ABBREVIATION=$(compliance_regime_mapping "${COMPLIANCE_REGIME}") +TENANTS_BUCKET="gs://${PREFIX}-${COMPLIANCE_REGIME_ABBREVIATION}-prod-iac-core-tenants/tenant-config" + +OLD_TENANTS_FILE="${SCRIPT_DIR}/../tenants.yml" +TENANTS_DIR="${SCRIPT_DIR}/../tenants" + +# Ensure the local output directory exists +mkdir -p "$TENANTS_DIR" + +# ========================================== +# STEP 1: Pull the legacy tenants.yml +# ========================================== +echo "Downloading legacy tenants.yml from GCS..." +if ! gcloud storage cp "$TENANTS_BUCKET/tenants.yml" "$OLD_TENANTS_FILE" 2>/dev/null; then + echo "Error: Could not find or download tenants.yml from $TENANTS_BUCKET/tenants.yml" + exit 1 +fi + +if [ ! -s "$OLD_TENANTS_FILE" ]; then + echo "Error: The downloaded tenants.yml file is empty." + exit 1 +fi + +# ========================================== +# STEP 2: Parse and Split Tenants +# ========================================== +# Count how many tenants exist in the array +TOTAL_TENANTS=$(yq '.tenants | length' "$OLD_TENANTS_FILE") + +if [ "$TOTAL_TENANTS" -eq 0 ] || [ "$TOTAL_TENANTS" == "null" ]; then + echo "No tenants found in the legacy file to migrate." + exit 0 +fi + +echo "Found $TOTAL_TENANTS tenants to migrate. Processing..." +echo "------------------------------------------------" + +for (( idx=0; idx "$TEN_FILE" + chmod 444 "$TEN_FILE" + + # ========================================== + # STEP 3: Push individual file to GCS + # ========================================== + echo " -> Uploading ${TEN_NAME}.yml to GCS..." + gcloud storage cp "$TEN_FILE" "$TENANTS_BUCKET/${TEN_NAME}.yml" +done + +echo "------------------------------------------------" +echo "Success! Cleaned up and split $TOTAL_TENANTS tenants into individual files." + +# ========================================== +# STEP 4: Remove Legacy artifacts +# ========================================== +echo "------------------------------------------------" +echo "[!] Migration processing is complete." +read -r -p "Would you like to permanently delete the legacy tenants.yml file from GCS and local storage? (y/N): " CONFIRM + +if [[ "$CONFIRM" =~ ^[Yy](es)?$ ]]; then + echo "Cleaning up legacy artifacts..." + + echo " -> Removing legacy tenants.yml from GCS..." + gcloud storage rm "$TENANTS_BUCKET/tenants.yml" + + echo " -> Removing legacy tenants.yml locally..." + rm -f "$OLD_TENANTS_FILE" + + echo "------------------------------------------------" + echo "Success! Split $TOTAL_TENANTS tenants into individual files and uploaded them." + echo "The legacy tenants.yml file has been completely deleted from both GCS and your local drive." +else + echo "------------------------------------------------" + echo "Success! Split $TOTAL_TENANTS tenants into individual files and uploaded them." + echo "[*] Cleanup skipped. The legacy tenants.yml files have been left intact on GCS and locally." +fi \ No newline at end of file diff --git a/automation/restore.sh b/automation/restore.sh new file mode 100644 index 000000000..f67fe4ec9 --- /dev/null +++ b/automation/restore.sh @@ -0,0 +1,76 @@ +#!/bin/bash +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#### This script is an experimental state, and is designed to help restore environment where the prefix has not been changed +#### It is currently best used via copy-and-paste of commands as needed (after sourcing config.env) +#### You may still need to change the name of custom org policies in the yaml files for a successful deployment +#### Use this script at your own risk. The author assumes no responsibility for any damages or losses incurred through its use. + +# Source config.env to get TENANT_ENVIRONMENTS +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) +# shellcheck source=automation/config.env.sample +source "$SCRIPT_DIR"/config.env + +terraform import "module.organization.google_org_policy_policy.default[\"{}\"]" + +# Undelete projects for each tenant environment +IFS=',' read -r -a ENV_ARRAY <<< "$TENANT_ENVIRONMENTS" +for ENV_NAME in "${ENV_ARRAY[@]}"; do + ENV_NAME=$(echo "$ENV_NAME" | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]') # Ensure lowercase + gcloud projects undelete "${PREFIX}"-"${ENV_NAME}"-net-host +done + +# Give projects time to be undeleted +sleep 60 + +# Re-enable billing for each tenant environment +for ENV_NAME in "${ENV_ARRAY[@]}"; do + ENV_NAME=$(echo "$ENV_NAME" | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]') # Ensure lowercase + gcloud alpha billing projects link "${PREFIX}"-"${ENV_NAME}"-net-host --billing-account "${BILLING_ACCOUNT}" +done + +if promptUser "Stage 2 - Networking"; then + # Choose networking paradigm + echo "Please type \"1\", \"2\", or \"3\" below that corresponds to the network paradigm you want: " + echo "1) IL2/FedRAMP Moderate" + echo "2) FedRAMP High" + echo "3) IL4/IL5" + read -r choice + + ########### IL2/FedRAMP Moderate ########### + if [ "$choice" == 1 ]; then + echo "This stage is still under development." + + ########### FedRAMP High ########### + elif [ "$choice" == 2 ]; then + cd "${SCRIPT_DIR}"/../fast/stages-aw/2-networking-a-fedramp-high || exit + + ########### IL4/IL5 ########### + elif [ "$choice" == 3 ]; then + cd "${SCRIPT_DIR}"/../fast/stages-aw/2-networking-b-il5-ngfw || exit + fi +fi + +# Import projects for each tenant environment +for ENV_NAME in "${ENV_ARRAY[@]}"; do + ENV_NAME=$(echo "$ENV_NAME" | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]') # Ensure lowercase + terraform import "module.env-spoke-projects[\"${ENV_NAME}\"].google_project.project[0]" "${PREFIX}"-"${ENV_NAME}"-net-host +done + +# KMS +gcloud kms keys versions restore 1 --location="${REGIONS}" --keyring='vdss-keyring' --key=default --project="${PREFIX}"-net-vdss-host +gcloud kms keys versions enable 1 --location="${REGIONS}" --keyring=vdss-keyring --key=default --project="${PREFIX}"-net-vdss-host +terraform import 'module.kms.google_kms_key_ring.default[0]' projects/"${PREFIX}"-net-vdss-host/locations/"${REGIONS}"/keyRings/vdss-keyring +terraform import 'module.kms.google_kms_crypto_key.default["default"]' projects/"${PREFIX}"-net-vdss-host/locations/"${REGIONS}"/keyRings/vdss-keyring/cryptoKeys/default diff --git a/automation/shared-services-deploy.sh b/automation/shared-services-deploy.sh new file mode 100644 index 000000000..a4a8c056b --- /dev/null +++ b/automation/shared-services-deploy.sh @@ -0,0 +1,675 @@ +#!/bin/bash +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#### Shared Services Deploy Script +#### Deploys shared-services stage resources (e.g., BCAP) independently of stellar-deploy.sh. +#### Prerequisites: Stages 0-5 must already be deployed via stellar-deploy.sh. + +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) +cd "${SCRIPT_DIR}" || exit + +# --- Helper Functions (from stellar-deploy.sh) --- + +cleanup() { + local resourceFile=${1} + local statusFile=${2} + if [[ -f $resourceFile ]]; then + rm "$resourceFile" + fi + if [[ -f $statusFile ]]; then + rm "$statusFile" + fi +} + +tfRun() { + local tf_cmd="$1" + local resources_file="$2" + local status_file="$3" + + if [[ ! -d $SCRIPT_DIR/tmp ]]; then + mkdir -p "${SCRIPT_DIR}"/tmp + fi + + local cmd="terraform $tf_cmd" + + eval "$cmd" 2>&1| tee >(sed 's/\x1b\[[0-9;]*[a-zA-Z]//g' >> "$resources_file") + local tf_exit_code=${PIPESTATUS[0]} + echo "$tf_exit_code" > "$status_file" +} + +errorChecking() { + local tf_cmd="$1" + local resource_file="$2" + local status_file="$3" + + local upper_cmd="" + upper_cmd=$(upper "${tf_cmd%% *}") + + while [[ $(cat "$statusFile") -ne 0 ]]; do + echo -e "\n--- ${upper_cmd} FAILED ---" + if grep -q "BigQuery service account: googleapi: Error 403: Request is disallowed by organization's constraints/gcp.restrictServiceUsage constraint" "$resource_file"; then + echo -e "\n--- ${upper_cmd} FAILED WITH BQ USAGE CONSTRAINT ERROR ---" + if promptUser "Would you like to update the Assured Workloads folder to allow BigQuery and Cloud KMS?"; then + ("${SCRIPT_DIR}/allow_bq.sh") + sleep 120 + fi + return 1 + fi + if promptUser "Would you like to see what the terraform errors are?"; then + awk '/[Ee]rror/{p=1;print;next} p' "$resource_file" + fi + if promptUser "Do you want to re-run 'terraform ${tf_cmd}' now?"; then + echo "Initiating manual 'terraform ${tf_cmd}'..." + tfRun "$tf_cmd" "$resource_file" "$status_file" + else + echo "Skipping 'terraform ${tf_cmd}'." + return 1 + fi + done + cleanup "$resource_file" "$status_file" +} + +runTerraformCommand() { + local tf_cmd="$1" + local resource_file="$2" + local status_file="$3" + + tfRun "$tf_cmd" "$resource_file" "$status_file" + + if [[ -f "$status_file" ]] && [[ $(cat "$status_file") -ne 0 ]]; then + errorChecking "$tf_cmd" "$resource_file" "$status_file" + else + cleanup "$resource_file" "$status_file" + fi +} + +upper() { + if [[ -n "$1" ]]; then + echo "${1}" | tr '[:lower:]' '[:upper:]' + fi + return 0 +} + +compliance_regime_mapping() { + case "${1}" in + "COMPLIANCE_REGIME_UNSPECIFIED") + echo "cru" + ;; + "IL2") + echo "il2" + ;; + "IL4") + echo "il4" + ;; + "IL5") + echo "il5" + ;; + "FEDRAMP_HIGH") + echo "frh" + ;; + "FEDRAMP_MODERATE") + echo "frm" + ;; + *) + echo "${1}" | tr '[:upper:]' '[:lower:]' + ;; + esac +} + +promptUser() { + echo -e "\n${1} Type 's' to skip, or 'c' to continue'." + read -r choice + if [[ "$choice" == "s" ]]; then + return 255 # Won't run command + else + shift + for i in "$@"; do + eval "$i" + done + fi +} + +# --- Configuration --- + +if [[ ! -f "${SCRIPT_DIR}/config.env" ]]; then + echo "ERROR: config.env not found in ${SCRIPT_DIR}." + echo "Please ensure stages 0-5 have been deployed via stellar-deploy.sh first." + echo "Copy config.env.sample to config.env and configure it for your deployment." + exit 1 +fi + +# shellcheck source=automation/config.env.sample +source "${SCRIPT_DIR}/config.env" +IFS=',' read -r -a REGIONS_ARRAY <<< "$REGIONS" + +COMPLIANCE_REGIME_ABBREVIATION=$(compliance_regime_mapping "${COMPLIANCE_REGIME}") +GCS_BUCKET="gs://${PREFIX}-${COMPLIANCE_REGIME_ABBREVIATION}-prod-iac-core-outputs" +BCAP_DIR="${SCRIPT_DIR}/../fast/stages-aw/shared-services/bcap" +NTP_DIR="${SCRIPT_DIR}/../fast/stages-aw/shared-services/ntp" +DNS_DIR="${SCRIPT_DIR}/../fast/stages-aw/shared-services/dns" +SMTP_DIR="${SCRIPT_DIR}/../fast/stages-aw/shared-services/smtp" +AD_DIR="${SCRIPT_DIR}/../fast/stages-aw/shared-services/ad" + +# --- Shared Services - BCAP Deployment --- + +echo -e "\n#######################################################" +echo " Shared Services - BCAP Deployment" +echo "#######################################################" +echo "" +echo "This script deploys the Boundary Cloud Access Point (BCAP) infrastructure." +echo "Prerequisites: Stages 0-2 must already be deployed via stellar-deploy.sh." + +if promptUser "Shared Services - BCAP -"; then + cd "${BCAP_DIR}" || exit + + resourceFile="${SCRIPT_DIR}/tmp/shared-services-bcap_tf_resources_$$" + statusFile="${SCRIPT_DIR}/tmp/shared-services-bcap_tf_status_$$" + + if promptUser "Would you like to pull the remote tfvars files created in Stage 3?" "${cmd[@]}"; then + gcloud storage cp "${GCS_BUCKET}/tfvars/3-networking-shared-services.auto.tfvars.json" ./ + fi + + if promptUser "Would you like to pull the shared-services providers file from GCS?"; then + gcloud storage cp "${GCS_BUCKET}/providers/shared-services-providers.tf" ./ + fi + + REGIONS_CONFIG=$(printf '%s", "' "${REGIONS_ARRAY[@]}" | sed 's/", "$//') + REGIONS_CONFIG="[\"$REGIONS_CONFIG\"]" + + if promptUser "Would you to generate a new tfvars file?"; then + yq -o=json '.' data/config.yml > terraform.tfvars.json + jq '.bcap' 3-networking-shared-services.auto.tfvars.json > networking-bcap.auto.tfvars.json + fi + + if promptUser "Would you like to perform the terraform init?"; then + runTerraformCommand "init -backend-config=prefix=bcap" "$resourceFile" "$statusFile" + fi + + if promptUser "Would you like to perform a terraform plan?"; then + runTerraformCommand "plan" "$resourceFile" "$statusFile" + fi + + if promptUser "Would you like to perform the terraform apply?"; then + runTerraformCommand "apply" "$resourceFile" "$statusFile" + fi + + echo "" + echo "Congratulations, you have completed the BCAP deployment!" + echo "" + echo "Post-Apply Steps:" + echo " 1. Retrieve pairing keys: terraform output -json pairing_keys" + echo " 2. Provide pairing keys to the BCAP provider (DISA/Google BCAP Team)" + echo " 3. Once attachments are active, configure BGP peering on Cloud Routers" + echo "" +fi + +# --- Shared Services - NTP Relay Deployment --- + +echo -e "\n#######################################################" +echo " Shared Services - NTP Relay Deployment" +echo "#######################################################" +echo "" +echo "This script deploys STIG-compliant NTP relay VMs that sync to USNO." +echo "Prerequisites: Stages 0-2 must already be deployed via stellar-deploy.sh." + +if promptUser "Shared Services - NTP Relay -"; then + cd "${NTP_DIR}" || exit + + resourceFile="${SCRIPT_DIR}/tmp/shared-services-ntp_tf_resources_$$" + statusFile="${SCRIPT_DIR}/tmp/shared-services-ntp_tf_status_$$" + + cmd=( + "gcloud storage cp ${GCS_BUCKET}/tfvars/1-assured-workload.auto.tfvars.json ./" + "gcloud storage cp ${GCS_BUCKET}/tfvars/3-networking-shared-services.auto.tfvars.json ./" + ) + promptUser "Would you like to pull the remote tfvars files created in Stage 1 and Stage 3?" "${cmd[@]}" + + if promptUser "Would you like to pull the shared-services providers file from GCS?"; then + gcloud storage cp "${GCS_BUCKET}/providers/shared-services-providers.tf" ./ + fi + + if promptUser "Would you to generate a new tfvars file?"; then + yq -o=json '.' data/config.yml > ntp-config.auto.tfvars.json + cat <ntp-global.auto.tfvars +prefix = "${PREFIX}" +EOF + fi + + if promptUser "Would you like to perform the terraform init?"; then + runTerraformCommand "init -backend-config=prefix=ntp" "$resourceFile" "$statusFile" + fi + + if promptUser "Would you like to perform a terraform plan?"; then + runTerraformCommand "plan" "$resourceFile" "$statusFile" + fi + + if promptUser "Would you like to perform the terraform apply?"; then + runTerraformCommand "apply" "$resourceFile" "$statusFile" + fi + + echo "" + echo "Congratulations, you have completed the NTP Relay deployment!" + echo "" + echo "Post-Apply Steps:" + echo " 1. Retrieve relay IP: terraform output relay_ip" + echo " 2. Relay IP has been published to GCS at:" + echo " ${GCS_BUCKET}/tfvars/shared-services-ntp.auto.tfvars.json" + echo " 3. Configure spoke VMs' /etc/chrony.conf to point at the relay IPs:" + echo " server iburst maxpoll 6" + echo " 4. Remove any metadata.google.internal or pool.ntp.org NTP sources" + echo "" +fi + +# --- Shared Services - DNS Deployment --- + +echo -e "\n#######################################################" +echo " Shared Services - DNS Deployment" +echo "#######################################################" +echo "" +echo "This script deploys IL5-compliant DNS forwarding zones that route" +echo "domain-specific queries to the Army DNS resolver in Azure via VPN." +echo "Prerequisites: Stages 0-3 and 3-vpn must already be deployed." + +if promptUser "Shared Services - DNS -"; then + cd "${DNS_DIR}" || exit + + resourceFile="${SCRIPT_DIR}/tmp/shared-services-dns_tf_resources_$$" + statusFile="${SCRIPT_DIR}/tmp/shared-services-dns_tf_status_$$" + + cmd=( + "gcloud storage cp ${GCS_BUCKET}/tfvars/1-assured-workload.auto.tfvars.json ./" + "gcloud storage cp ${GCS_BUCKET}/tfvars/3-networking-shared-services.auto.tfvars.json ./" + ) + promptUser "Would you like to pull the remote tfvars files created in Stage 1 and Stage 3?" "${cmd[@]}" + + if promptUser "Would you like to pull the shared-services providers file from GCS?"; then + gcloud storage cp "${GCS_BUCKET}/providers/shared-services-providers.tf" ./ + fi + + if promptUser "Would you to generate a new tfvars file?"; then + yq -o=json '.' data/config.yml > dns-config.auto.tfvars.json + cat <dns-global.auto.tfvars +prefix = "${PREFIX}" +EOF + fi + + if promptUser "Would you like to perform the terraform init?"; then + runTerraformCommand "init -backend-config=prefix=dns" "$resourceFile" "$statusFile" + fi + + if promptUser "Would you like to perform a terraform plan?"; then + runTerraformCommand "plan" "$resourceFile" "$statusFile" + fi + + if promptUser "Would you like to perform the terraform apply?"; then + runTerraformCommand "apply" "$resourceFile" "$statusFile" + fi + + echo "" + echo "Congratulations, you have completed the DNS deployment!" + echo "" + echo "Post-Apply Steps:" + echo " 1. Forwarding zone info has been published to GCS at:" + echo " ${GCS_BUCKET}/tfvars/shared-services-dns.auto.tfvars.json" + echo " 2. Verify forwarding from a GCP VM:" + echo " dig test.army.mil @35.199.192.0" + echo " 3. Verify internal DNS still works:" + echo " dig vm-name.us-east4-a.c.project.internal" + echo "" +fi +# --- Shared Services - SMTP Relay Deployment --- + +echo -e "\n#######################################################" +echo " Shared Services - SMTP Relay Deployment" +echo "#######################################################" +echo "" +echo "This script deploys a STIG-compliant Postfix SMTP relay (smarthost)" +echo "that relays all outbound email through the DISA EESG via BCAP." +echo "Prerequisites: Stages 0-3 must already be deployed via stellar-deploy.sh." + +if promptUser "Shared Services - SMTP Relay -"; then + cd "${SMTP_DIR}" || exit + + resourceFile="${SCRIPT_DIR}/tmp/shared-services-smtp_tf_resources_$$" + statusFile="${SCRIPT_DIR}/tmp/shared-services-smtp_tf_status_$$" + + cmd=( + "gcloud storage cp ${GCS_BUCKET}/tfvars/1-assured-workload.auto.tfvars.json ./" + "gcloud storage cp ${GCS_BUCKET}/tfvars/3-networking-shared-services.auto.tfvars.json ./" + ) + promptUser "Would you like to pull the remote tfvars files created in Stage 1 and Stage 3?" "${cmd[@]}" + + if promptUser "Would you like to pull the shared-services providers file from GCS?"; then + gcloud storage cp "${GCS_BUCKET}/providers/shared-services-providers.tf" ./ + fi + + if promptUser "Would you to generate a new tfvars file?"; then + yq -o=json '.' data/config.yml > smtp-config.auto.tfvars.json + # Override encryption_key with the SMTP-specific KMS key from the shared-services output. + # The shared-services tfvars exports encryption_key (NTP) and smtp_encryption_key (SMTP). + jq -n --arg key "$(jq -r '.smtp_encryption_key' 3-networking-shared-services.auto.tfvars.json)" \ + '{encryption_key: $key}' > smtp-encryption.auto.tfvars.json + cat <smtp-global.auto.tfvars +prefix = "${PREFIX}" +EOF + fi + + if promptUser "Would you like to perform the terraform init?"; then + runTerraformCommand "init -backend-config=prefix=smtp" "$resourceFile" "$statusFile" + fi + + if promptUser "Would you like to perform a terraform plan?"; then + runTerraformCommand "plan" "$resourceFile" "$statusFile" + fi + + if promptUser "Would you like to perform the terraform apply?"; then + runTerraformCommand "apply" "$resourceFile" "$statusFile" + fi + + echo "" + echo "Congratulations, you have completed the SMTP Relay deployment!" + echo "" + echo "Post-Apply Steps:" + echo " 1. Retrieve relay IP: terraform output relay_ip" + echo " 2. Relay IP has been published to GCS at:" + echo " ${GCS_BUCKET}/tfvars/shared-services-smtp.auto.tfvars.json" + echo " 3. Configure spoke applications to relay mail through:" + echo " SMTP_HOST= SMTP_PORT=25" + echo " 4. Verify from a spoke VM: telnet 25" + echo "" +fi + +# --- Shared Services - SMTP Relay Deployment --- + +echo -e "\n#######################################################" +echo " Shared Services - SMTP Relay Deployment" +echo "#######################################################" +echo "" +echo "This script deploys a STIG-compliant Postfix SMTP relay (smarthost)" +echo "that relays all outbound email through the DISA EESG via BCAP." +echo "Prerequisites: Stages 0-3 must already be deployed via stellar-deploy.sh." + +if promptUser "Shared Services - SMTP Relay -"; then + cd "${SMTP_DIR}" || exit + + resourceFile="${SCRIPT_DIR}/tmp/shared-services-smtp_tf_resources_$$" + statusFile="${SCRIPT_DIR}/tmp/shared-services-smtp_tf_status_$$" + + cmd=( + "gcloud storage cp ${GCS_BUCKET}/tfvars/1-assured-workload.auto.tfvars.json ./" + "gcloud storage cp ${GCS_BUCKET}/tfvars/3-networking-shared-services.auto.tfvars.json ./" + ) + promptUser "Would you like to pull the remote tfvars files created in Stage 1 and Stage 3?" "${cmd[@]}" + + if promptUser "Would you like to pull the shared-services providers file from GCS?"; then + gcloud storage cp "${GCS_BUCKET}/providers/shared-services-providers.tf" ./ + fi + + if promptUser "Would you to generate a new tfvars file?"; then + yq -o=json '.' data/config.yml > smtp-config.auto.tfvars.json + # Override encryption_key with the SMTP-specific KMS key from the shared-services output. + # The shared-services tfvars exports encryption_key (NTP) and smtp_encryption_key (SMTP). + jq -n --arg key "$(jq -r '.smtp_encryption_key' 3-networking-shared-services.auto.tfvars.json)" \ + '{encryption_key: $key}' > smtp-encryption.auto.tfvars.json + cat <smtp-global.auto.tfvars +prefix = "${PREFIX}" +EOF + fi + + if promptUser "Would you like to perform the terraform init?"; then + runTerraformCommand "init -backend-config=prefix=smtp" "$resourceFile" "$statusFile" + fi + + if promptUser "Would you like to perform a terraform plan?"; then + runTerraformCommand "plan" "$resourceFile" "$statusFile" + fi + + if promptUser "Would you like to perform the terraform apply?"; then + runTerraformCommand "apply" "$resourceFile" "$statusFile" + fi + + echo "" + echo "Congratulations, you have completed the SMTP Relay deployment!" + echo "" + echo "Post-Apply Steps:" + echo " 1. Retrieve relay IP: terraform output relay_ip" + echo " 2. Relay IP has been published to GCS at:" + echo " ${GCS_BUCKET}/tfvars/shared-services-smtp.auto.tfvars.json" + echo " 3. Configure spoke applications to relay mail through:" + echo " SMTP_HOST= SMTP_PORT=25" + echo " 4. Verify from a spoke VM: telnet 25" + echo "" +fi + +# --- Shared Services - Active Directory Domain Controller Deployment --- + +echo -e "\n#######################################################" +echo " Shared Services - Active Directory Domain Controller Deployment" +echo "#######################################################" +echo "" +echo "This script deploys a STIG-compliant Active Directory Domain Controller" +echo "that replicates from the the Domain Controllers in Azure." +echo "Prerequisites: Stages 0-3 must already be deployed via stellar-deploy.sh." + +if promptUser "Shared Services - Active Directory -"; then + cd "${AD_DIR}" || exit + + resourceFile="${SCRIPT_DIR}/tmp/shared-services-ad_tf_resources_$$" + statusFile="${SCRIPT_DIR}/tmp/shared-services-ad_tf_status_$$" + + cmd=( + "gcloud storage cp ${GCS_BUCKET}/tfvars/1-assured-workload.auto.tfvars.json ./" + "gcloud storage cp ${GCS_BUCKET}/tfvars/3-networking-shared-services.auto.tfvars.json ./" + ) + promptUser "Would you like to pull the remote tfvars files created in Stage 1 and Stage 3?" "${cmd[@]}" + + if promptUser "Would you like to pull the shared-services providers file from GCS?"; then + gcloud storage cp "${GCS_BUCKET}/providers/shared-services-providers.tf" ./ + fi + + if promptUser "Would you to generate a new tfvars file?"; then + yq -o=json '.' data/config.yml > ad-config.auto.tfvars.json + cat <ad-global.auto.tfvars +prefix = "${PREFIX}" +EOF + fi + + if promptUser "Would you like to perform the terraform init?"; then + runTerraformCommand "init -backend-config=prefix=ad" "$resourceFile" "$statusFile" + fi + + if promptUser "Would you like to perform a terraform plan?"; then + runTerraformCommand "plan" "$resourceFile" "$statusFile" + fi + + if promptUser "Would you like to perform the terraform apply?"; then + runTerraformCommand "apply" "$resourceFile" "$statusFile" + fi + + echo "" + echo "Congratulations, you have completed the Active Directory Domain Controller deployment!" + echo "" + echo "1. Hand off networking to Palo Alto / Security Team" + echo " Provide the provisioned GCP DC IPs above to the firewall administrators." + echo " Request ingress/egress policy mapping to authorize AD traffic to/from Azure." + echo "" + echo "2. Stage Google Cloud Subnet in Azure Active Directory" + echo " Coordinated with the Azure AD identity team to open 'dssite.msc'." + echo " Map the GCP Subnet CIDR block directly to a new" + echo " Active Directory Site object (e.g., 'GCP-Region-Shared-Services')." + echo "" + echo "3. Execute Active Directory Replica Promotion" + echo " RDP to the newly provisioned Windows instances using approved secure access." + echo " Verify the local NTP clock is actively syncing against NTP Server." + echo " Run the AD replica promotion wizard or utilize the Offline Domain Join (.blob)" + echo " file generated by the primary forest authorities." + echo "" + echo "4. Verify Replication Health with Azure" + echo " From an administrative PowerShell terminal on the new GCP DCs, run:" + echo " > repadmin /showrepl" + echo " Verify all inbound neighbor statuses return SUCCESS." + echo "=========================================================================" + echo "" +fi + +# --- Shared Services - ACAS (Assured Compliance Assessment Solution) Deployment --- + +echo -e "\n#######################################################" +echo " Shared Services - ACAS Deployment" +echo "#######################################################" +echo "" +echo "This script deploys the ACAS solution (Image Factory, Nessus Scanner, and SecurityCenter)." +echo "Prerequisites: Stages 0-3 must already be deployed via stellar-deploy.sh." + +if promptUser "Shared Services - ACAS -"; then + ACAS_DIR="${SCRIPT_DIR}/../fast/stages-aw/shared-services/acas" + + # -------------------------------------------------------- + # A. ACAS Image Factory + # -------------------------------------------------------- + if promptUser "Deploy ACAS Component [1/3]: Image Factory?"; then + cd "${ACAS_DIR}/image-factory" || exit + + resourceFile="${SCRIPT_DIR}/tmp/shared-services-acas-factory_tf_resources_$$" + statusFile="${SCRIPT_DIR}/tmp/shared-services-acas-factory_tf_status_$$" + + cmd=( + "gcloud storage cp ${GCS_BUCKET}/tfvars/1-assured-workload.auto.tfvars.json ./" + "gcloud storage cp ${GCS_BUCKET}/tfvars/3-networking-shared-services.auto.tfvars.json ./" + "gcloud storage cp ${GCS_BUCKET}/providers/shared-services-providers.tf ./" + ) + promptUser "Pull remote tfvars and providers from GCS?" "${cmd[@]}" + + if promptUser "Generate local tfvars file from centralized config.yml?"; then + yq -o=json '.image_factory' "${ACAS_DIR}/data/config.yml" > acas-factory.auto.tfvars.json + cat <acas-global.auto.tfvars +prefix = "${PREFIX}" +EOF + fi + + if promptUser "Pull ACAS RPM packages from GCS staging?"; then + mkdir -p rpms + # RPM Ingestion Check + if ! gcloud storage ls "${GCS_BUCKET}/acas-staging/*.rpm" &>/dev/null; then + echo -e "\n=========================================================================" + echo -e " [!] CONFIGURATION ERROR: No ACAS RPMs found in GCS staging!" + echo -e "=========================================================================" + echo " Path Checked: ${GCS_BUCKET}/acas-staging/" + echo "" + echo " Please download the RHEL8 RPMs from the DoD Patch Repository:" + echo " -> https://patches.csd.disa.mil (CAC required)" + echo "" + echo " Then upload them to your GCS outputs bucket using this command:" + echo " $ gcloud storage cp *.rpm ${GCS_BUCKET}/acas-staging/" + echo "" + echo " For detailed instructions, refer to: " + echo " fast/stages-aw/shared-services/acas/README.md" + echo "=========================================================================" + exit 1 + fi + gcloud storage cp "${GCS_BUCKET}/acas-staging/*.rpm" ./rpms/ + fi + + if promptUser "Perform terraform init?"; then + runTerraformCommand "init -backend-config=prefix=acas-factory" "$resourceFile" "$statusFile" + fi + if promptUser "Perform terraform plan?"; then + runTerraformCommand "plan" "$resourceFile" "$statusFile" + fi + if promptUser "Perform terraform apply?"; then + runTerraformCommand "apply" "$resourceFile" "$statusFile" + fi + fi + + # -------------------------------------------------------- + # B. ACAS Nessus Scanner + # -------------------------------------------------------- + if [[ $(yq '.scanner_deployment.enable' "${ACAS_DIR}/data/config.yml") == "true" ]]; then + if promptUser "Deploy ACAS Component [2/3]: Nessus Scanner VM(s)?"; then + cd "${ACAS_DIR}/scanner" || exit + + resourceFile="${SCRIPT_DIR}/tmp/shared-services-acas-scanner_tf_resources_$$" + statusFile="${SCRIPT_DIR}/tmp/shared-services-acas-scanner_tf_status_$$" + + cmd=( + "gcloud storage cp ${GCS_BUCKET}/tfvars/1-assured-workload.auto.tfvars.json ./" + "gcloud storage cp ${GCS_BUCKET}/tfvars/3-networking-shared-services.auto.tfvars.json ./" + "gcloud storage cp ${GCS_BUCKET}/providers/shared-services-providers.tf ./" + ) + promptUser "Pull remote tfvars and providers from GCS?" "${cmd[@]}" + + if promptUser "Generate local tfvars file from centralized config.yml?"; then + yq -o=json '.scanner_deployment' "${ACAS_DIR}/data/config.yml" | jq 'del(.enable)' > acas-scanner.auto.tfvars.json + cat <acas-global.auto.tfvars +prefix = "${PREFIX}" +EOF + fi + + if promptUser "Perform terraform init?"; then + runTerraformCommand "init -backend-config=prefix=acas-scanner" "$resourceFile" "$statusFile" + fi + if promptUser "Perform terraform plan?"; then + runTerraformCommand "plan" "$resourceFile" "$statusFile" + fi + if promptUser "Perform terraform apply?"; then + runTerraformCommand "apply" "$resourceFile" "$statusFile" + fi + fi + else + echo -e "\n--- ACAS Scanner Deployment is disabled in config.yml. Skipping. ---" + fi + + # -------------------------------------------------------- + # C. ACAS SecurityCenter + # -------------------------------------------------------- + if [[ $(yq '.securitycenter_deployment.enable' "${ACAS_DIR}/data/config.yml") == "true" ]]; then + if promptUser "Deploy ACAS Component [3/3]: SecurityCenter VM?"; then + cd "${ACAS_DIR}/securitycenter" || exit + + resourceFile="${SCRIPT_DIR}/tmp/shared-services-acas-sc_tf_resources_$$" + statusFile="${SCRIPT_DIR}/tmp/shared-services-acas-sc_tf_status_$$" + + cmd=( + "gcloud storage cp ${GCS_BUCKET}/tfvars/1-assured-workload.auto.tfvars.json ./" + "gcloud storage cp ${GCS_BUCKET}/tfvars/3-networking-shared-services.auto.tfvars.json ./" + "gcloud storage cp ${GCS_BUCKET}/providers/shared-services-providers.tf ./" + ) + promptUser "Pull remote tfvars and providers from GCS?" "${cmd[@]}" + + if promptUser "Generate local tfvars file from centralized config.yml?"; then + yq -o=json '.securitycenter_deployment' "${ACAS_DIR}/data/config.yml" | jq 'del(.enable)' > acas-sc.auto.tfvars.json + cat <acas-global.auto.tfvars +prefix = "${PREFIX}" +EOF + fi + + if promptUser "Perform terraform init?"; then + runTerraformCommand "init -backend-config=prefix=acas-sc" "$resourceFile" "$statusFile" + fi + if promptUser "Perform terraform plan?"; then + runTerraformCommand "plan" "$resourceFile" "$statusFile" + fi + if promptUser "Perform terraform apply?"; then + runTerraformCommand "apply" "$resourceFile" "$statusFile" + fi + fi + else + echo -e "\n--- ACAS SecurityCenter Deployment is disabled in config.yml. Skipping. ---" + fi + + echo "" + echo "Congratulations, you have completed the ACAS Shared Service deployment!" + echo "" +fi \ No newline at end of file diff --git a/automation/stellar-deploy.sh b/automation/stellar-deploy.sh new file mode 100644 index 000000000..1f3500aa5 --- /dev/null +++ b/automation/stellar-deploy.sh @@ -0,0 +1,998 @@ +#!/bin/bash +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#### Use this script at your own risk. The author assumes no responsibility for any damages or losses incurred through its use. + +GCP_ROLES=( + "roles/resourcemanager.organizationAdmin:roles/resourcemanager.folderAdmin:roles/resourcemanager.projectCreator:roles/billing.user:roles/iam.organizationRoleAdmin:roles/orgpolicy.policyAdmin:roles/securitycenter.admin:roles/cloudsupport.admin:roles/pubsub.admin:roles/cloudkms.admin" + "roles/billing.admin:roles/billing.creator:roles/resourcemanager.organizationViewer" + "roles/compute.networkAdmin:roles/compute.xpnAdmin:roles/compute.securityAdmin:roles/resourcemanager.folderViewer" + "roles/compute.networkAdmin:roles/resourcemanager.folderViewer" + "roles/logging.admin:roles/monitoring.admin:roles/pubsub.admin" + "roles/logging.viewer:roles/monitoring.viewer" + "roles/orgpolicy.policyAdmin:roles/iam.securityAdmin:roles/iam.securityReviewer:roles/iam.serviceAccountCreator:roles/iam.organizationRoleViewer:roles/securitycenter.admin:roles/resourcemanager.folderIamAdmin:roles/logging.privateLogViewer:roles/logging.configWriter:roles/container.viewer:roles/compute.viewer:roles/logging.admin:roles/monitoring.admin:roles/cloudkms.admin" + "" + "roles/resourcemanager.folderViewer" +) + +GCP_DESCRIPTIONS=( + "Organization administrators have access to administer all resources belonging to the organization." + "Billing administrators are responsible for setting up billing accounts and monitoring their usage." + "Network administrators are responsible for creating VPC networks, subnets, and firewall rules." + "Hybrid Connectivity administrators are responsible for creating network devices such as Cloud VPN instances and cloud routers." + "Logging-monitoring administrators have access to all features of Logging and Cloud Monitoring." + "Logging-monitoring viewers have read-only access to a defined subset of both ingested logs and monitoring data." + "Security administrators are responsible for establishing and managing security policies for the entire organization, including access management and organization constraint policies." + "Developers are responsible for designing, coding, and testing applications." + "DevOps practitioners create or manage end-to-end pipelines that support continuous integration and delivery, monitoring, and system provisioning." +) + +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) + +if [ -n "$1" ]; then + if [ ! -f "$1" ]; then + echo "Error: The configuration file '$1' does not exist." >&2 + exit 1 + fi + CONFIG_FILE="$(realpath "$1")" +else + CONFIG_FILE="$SCRIPT_DIR/config.env" +fi + +echo Running deploy with configuration at path: "${CONFIG_FILE}" +echo "#######################################################" + +cd "${SCRIPT_DIR}" || exit + +# Allows us to decide when this array is populated if we are using environment variables +populateGroups() { + GCP_GROUPS=( + "${TF_VAR_gcp_organization_admins_group:-gcp-organization-admins}" + "${TF_VAR_gcp_billing_admins_group:-gcp-billing-admins}" + "${TF_VAR_gcp_vpc_network_admins_group:-gcp-vpc-network-admins}" + "${TF_VAR_gcp_hybrid_connectivity_admins_group:-gcp-hybrid-connectivity-admins}" + "${TF_VAR_gcp_logging_monitoring_admins_group:-gcp-logging-monitoring-admins}" + "${TF_VAR_gcp_logging_monitoring_viewers_group:-gcp-logging-monitoring-viewers}" + "${TF_VAR_gcp_security_admins_group:-gcp-security-admins}" + "${TF_VAR_gcp_developers_group:-gcp-developers}" + "${TF_VAR_gcp_devops_group:-gcp-devops}" + ) +} + +cleanup() { + local resourceFile=${1} + local statusFile=${2} + if [[ -f $resourceFile ]]; then + rm "$resourceFile" + fi + if [[ -f $statusFile ]]; then + rm "$statusFile" + fi +} + +tfRun() { + local tf_cmd="$1" + local resources_file="$2" + local status_file="$3" + + if [[ ! -d $SCRIPT_DIR/tmp ]]; then + mkdir -p "${SCRIPT_DIR}"/tmp + fi + + local cmd="terraform $tf_cmd" + + eval "$cmd" 2>&1| tee >(sed 's/\x1b\[[0-9;]*[a-zA-Z]//g' >> "$resources_file") + local tf_exit_code=${PIPESTATUS[0]} + echo "$tf_exit_code" > "$status_file" +} + +errorChecking() { + local tf_cmd="$1" + local resource_file="$2" + local status_file="$3" + + local upper_cmd="" + upper_cmd=$(upper "${tf_cmd%% *}") + + while [[ $(cat "$statusFile") -ne 0 ]]; do + echo -e "\n--- ${upper_cmd} FAILED ---" + if grep -q "BigQuery service account: googleapi: Error 403: Request is disallowed by organization's constraints/gcp.restrictServiceUsage constraint" "$resource_file"; then + echo -e "\n--- ${upper_cmd} FAILED WITH BQ USAGE CONSTRAINT ERROR ---" + if promptUser "Would you like to update the Assured Workloads folder to allow BigQuery and Cloud KMS?"; then + ("${SCRIPT_DIR}/allow_bq.sh") + sleep 120 + fi + return 1 + fi + if promptUser "Would you like to see what the terraform errors are?"; then + awk '/[Ee]rror/{p=1;print;next} p' "$resource_file" + fi + if promptUser "Do you want to re-run 'terraform ${tf_cmd}' now?"; then + echo "Initiating manual 'terraform ${tf_cmd}'..." + tfRun "$tf_cmd" "$resource_file" "$status_file" + else + echo "Skipping 'terraform ${tf_cmd}'." + return 1 + fi + done + cleanup "$resource_file" "$status_file" +} + +runTerraformCommand() { + local tf_cmd="$1" + local resource_file="$2" + local status_file="$3" + + tfRun "$tf_cmd" "$resource_file" "$status_file" + + if [[ -f "$status_file" ]] && [[ $(cat "$status_file") -ne 0 ]]; then + errorChecking "$tf_cmd" "$resource_file" "$status_file" + else + cleanup "$resource_file" "$status_file" + fi +} + +automateGroupsAdminAccess() { + local TEMP_DIR="${SCRIPT_DIR}/tmp" + if [[ ! -d $TEMP_DIR ]]; then + mkdir -p "${TEMP_DIR}" + fi + POLICY_JSON="${TEMP_DIR}/policy.json" + gcloud organizations get-iam-policy "$ORGANIZATION_ID" --format=json > "$POLICY_JSON" + CURRENT_GROUPS_RAW=$(gcloud identity groups search --customer "$DIRECTORY_CUSTOMER_ID" --labels "cloudidentity.googleapis.com/groups.discussion_forum" --format 'value(groups.groupKey.id)') + CURRENT_GROUPS=$(echo "$CURRENT_GROUPS_RAW" | tr ';' ' ') + GROUP_SLEEP_FLAG=false + for i in "${!GCP_GROUPS[@]}"; do + group="${GCP_GROUPS[$i]}"@"$FULLY_QUALIFIED_DOMAIN_NAME" + if ! echo "$CURRENT_GROUPS" | grep -q -w "$group"; then + echo "Creating group ${group}" + gcloud identity groups create "$group" --display-name="${GCP_GROUPS[$i]}" --organization "$ORGANIZATION_ID" --description "${GCP_DESCRIPTIONS[$i]}" + GROUP_SLEEP_FLAG=true + fi + done + if [[ $GROUP_SLEEP_FLAG == true ]]; then + echo "Sleeping for 30s to allow groups to propagate in GCP" + sleep 30 + fi + for i in "${!GCP_GROUPS[@]}"; do + group="${GCP_GROUPS[$i]}"@"$FULLY_QUALIFIED_DOMAIN_NAME" + if [[ "${GCP_ROLES[$i]}" ]]; then + IFS=':' read -ra ROLES_ARRAY <<< "${GCP_ROLES[$i]}" + echo "Assigning roles to group: $GROUP_NAME" + for role in "${ROLES_ARRAY[@]}"; do + jq --arg role "$role" --arg member "group:$group" ' + .bindings |= + ( + if any(.[]; .role == $role) then + map( + if .role ==$role and (.members | index($member) | not) then + .members += [$member] + else + . + end + ) + else + . + [ {"role": $role, "members": [$member]} ] + end + ) + ' "$POLICY_JSON" > temp.json && mv temp.json "$POLICY_JSON" + done + unset IFS + fi + done + gcloud organizations set-iam-policy "$ORGANIZATION_ID" "$POLICY_JSON" + rm -rf "$TEMP_DIR" +} + +upper() { + if [[ -n "$1" ]]; then + echo "${1}" | tr '[:lower:]' '[:upper:]' + fi + return 0 +} + +compliance_regime_mapping() { + case "${1}" in + "COMPLIANCE_REGIME_UNSPECIFIED") + echo "cru" + ;; + "IL2") + echo "il2" + ;; + "IL4") + echo "il4" + ;; + "IL5") + echo "il5" + ;; + "FEDRAMP_HIGH") + echo "frh" + ;; + "FEDRAMP_MODERATE") + echo "frm" + ;; + *) + echo "${1}" | tr '[:upper:]' '[:lower:]' + ;; + esac +} + +promptUser() { + echo -e "\n${1} Type 's' to skip, or 'c' to continue'." + read -r choice + if [[ "$choice" == "s" ]]; then + return 255 # Won't run command + else + shift + for i in "$@"; do + eval "$i" + done + fi +} + + +############ Prerequisites ############ +echo "Welcome to the Secure Cloud Landing Zone automated deployment! +This is designed for the initial deployment. For a redeployment, please make sure you change the prefix and run the delete.sh script prior to redeployment. + +If you do not have a large enough quota for your billing projects, follow the below link: +https://support.google.com/code/contact/billing_quota_increase + +Also, please make sure you have Super Admin privileges - if not, please contact your oganization administrator." + +echo -e "\n#######################################################" +echo "#######################################################" +echo "#######################################################" + +if promptUser "Prerequisites -"; then + # Authentication + promptUser 'Would you like to (re)authenticate with Google Cloud?' "gcloud auth login; gcloud auth application-default login" + + # Set variables + if [ ! -f "$CONFIG_FILE" ] || promptUser "Would you like to overwrite your .env file?"; then + gcloud organizations list + + read -r -p "Enter your billing account: " BILLING_ACCOUNT + read -r -p "Enter your bootstrap project ID: " BOOTSTRAP_PROJECT_ID + read -r -p "Enter the compliance regime: " COMPLIANCE_REGIME + read -r -p "Enter your directory customer ID : " DIRECTORY_CUSTOMER_ID + read -r -p "Enter your deployer email address: " DEPLOYER_EMAIL_ADDRESS + read -r -p "Enter your fully qualified domain name: " FULLY_QUALIFIED_DOMAIN_NAME + read -r -p "Enter your logging alerts email address: " LOGGING_ALERTS_EMAIL_ADDRESS + read -r -p "Enter your organization ID: " ORGANIZATION_ID + read -r -p "Enter your prefix (6 chars or less): " PREFIX + read -r -p "Enter your regions: " REGIONS + read -r -p "Enter your Assured Workload region: " AW_REGION + read -r -p "Enter your tenant environment(s) (dev,prod): " TENANT_ENVIRONMENTS + read -r -p "Enter your external Directory Customer IDs (comma-separated, or blank): " EXTERNAL_DIRECTORY_CUSTOMER_IDS + read -r -p "Enter your external Organization IDs (comma-separated, or blank): " EXTERNAL_ORGANIZATION_IDS + read -r -p "Enter the top level folder name: " TOP_LEVEL_FOLDER_NAME + read -r -p "Enter the top level folder ID: " TOP_LEVEL_FOLDER_ID + read -r -p "Enter the project path in gitlab for Workload Identity Federation (leave blank if not using): " CI_PROJECT_PATH + read -r -p "Enter the branch name in gitlab where Workload Identity Federation will authenticate from (leave blank if not using): " CI_COMMIT_BRANCH + read -r -p "Enter the GitLab URL if using Workload Identity Federation excluding trailing forward slash (leave blank if not using): " GITLAB_URL + read -r -p "Enter the JWKS (JSON Web Key Set) for GitLab-to-GCP authentication. Note: This is only required if operating on the secure Army network: " JWKS_KEY + + read -r -p "Enter the group name for gcp_organization_admins [default: gcp-organization-admins]: " TF_VAR_gcp_organization_admins_group + TF_VAR_gcp_organization_admins_group=${TF_VAR_gcp_organization_admins_group:-gcp-organization-admins} + read -r -p "Enter the group name for gcp_billing_admins [default: gcp-billing-admins]: " TF_VAR_gcp_billing_admins_group + TF_VAR_gcp_billing_admins_group=${TF_VAR_gcp_billing_admins_group:-gcp-billing-admins} + read -r -p "Enter the group name for gcp_vpc_network_admins [default: gcp-vpc-network-admins]: " TF_VAR_gcp_vpc_network_admins_group + TF_VAR_gcp_vpc_network_admins_group=${TF_VAR_gcp_vpc_network_admins_group:-gcp-vpc-network-admins} + read -r -p "Enter the group name for gcp_hybrid_connectivity_admins [default: gcp-hybrid-connectivity-admins]: " TF_VAR_gcp_hybrid_connectivity_admins_group + TF_VAR_gcp_hybrid_connectivity_admins_group=${TF_VAR_gcp_hybrid_connectivity_admins_group:-gcp-hybrid-connectivity-admins} + read -r -p "Enter the group name for gcp_logging_monitoring_admins [default: gcp-logging-monitoring-admins]: " TF_VAR_gcp_logging_monitoring_admins_group + TF_VAR_gcp_logging_monitoring_admins_group=${TF_VAR_gcp_logging_monitoring_admins_group:-gcp-logging-monitoring-admins} + read -r -p "Enter the group name for gcp_logging_monitoring_viewers [default: gcp-logging-monitoring-viewers]: " TF_VAR_gcp_logging_monitoring_viewers_group + TF_VAR_gcp_logging_monitoring_viewers_group=${TF_VAR_gcp_logging_monitoring_viewers_group:-gcp-logging-monitoring-viewers} + read -r -p "Enter the group name for gcp_security_admins [default: gcp-security-admins]: " TF_VAR_gcp_security_admins_group + TF_VAR_gcp_security_admins_group=${TF_VAR_gcp_security_admins_group:-gcp-security-admins} + read -r -p "Enter the group name for gcp_developers [default: gcp-developers]: " TF_VAR_gcp_developers_group + TF_VAR_gcp_developers_group=${TF_VAR_gcp_developers_group:-gcp-developers} + read -r -p "Enter the group name for gcp_devops [default: gcp-devops]: " TF_VAR_gcp_devops_group + TF_VAR_gcp_devops_group=${TF_VAR_gcp_devops_group:-gcp-devops} + + echo "--- Configuration Summary ---" + echo "billing-account: $BILLING_ACCOUNT" + echo "bootstrap-project-id: $BOOTSTRAP_PROJECT_ID" + echo "compliance-regime: $COMPLIANCE_REGIME" + echo "directory-customer-id: $DIRECTORY_CUSTOMER_ID" + echo "deployer-email-address: $DEPLOYER_EMAIL_ADDRESS" + echo "fully-qualified-domain-name: $FULLY_QUALIFIED_DOMAIN_NAME" + echo "logging-alerts-email-address: $LOGGING_ALERTS_EMAIL_ADDRESS" + echo "organization-id: $ORGANIZATION_ID" + echo "prefix: $PREFIX" + echo "regions: $REGIONS" + echo "aw-region: $AW_REGION" + echo "tenant-environments: $TENANT_ENVIRONMENTS" + echo "external-directory-customer-ids: $EXTERNAL_DIRECTORY_CUSTOMER_IDS" + echo "external-organization-ids: $EXTERNAL_ORGANIZATION_IDS" + echo "top-level-folder-name: $TOP_LEVEL_FOLDER_NAME" + echo "top-level-folder-id: $TOP_LEVEL_FOLDER_ID" + echo "ci-project-path: $CI_PROJECT_PATH" + echo "ci-commit-branch: $CI_COMMIT_BRANCH" + echo "gitlab-url: $GITLAB_URL" + echo "jwks-key: $JWKS_KEY" + echo "gcp-organization-admins: $TF_VAR_gcp_organization_admins_group" + echo "gcp-billing-admins: $TF_VAR_gcp_billing_admins_group" + echo "gcp-vpc-network-admins: $TF_VAR_gcp_vpc_network_admins_group" + echo "gcp-hybrid-connectivity-admins: $TF_VAR_gcp_hybrid_connectivity_admins_group" + echo "gcp-logging-monitoring-admins: $TF_VAR_gcp_logging_monitoring_admins_group" + echo "gcp-logging-monitoring-viewers: $TF_VAR_gcp_logging_monitoring_viewers_group" + echo "gcp-security-admins: $TF_VAR_gcp_security_admins_group" + echo "gcp-developers: $TF_VAR_gcp_developers_group" + echo "gcp-devops: $TF_VAR_gcp_devops_group" + + + { + echo "BILLING_ACCOUNT=$BILLING_ACCOUNT" + echo "BOOTSTRAP_PROJECT_ID=$BOOTSTRAP_PROJECT_ID" + echo "COMPLIANCE_REGIME=$COMPLIANCE_REGIME" + echo "DIRECTORY_CUSTOMER_ID=$DIRECTORY_CUSTOMER_ID" + echo "DEPLOYER_EMAIL_ADDRESS=$DEPLOYER_EMAIL_ADDRESS" + echo "FULLY_QUALIFIED_DOMAIN_NAME=$FULLY_QUALIFIED_DOMAIN_NAME" + echo "LOGGING_ALERTS_EMAIL_ADDRESS=$LOGGING_ALERTS_EMAIL_ADDRESS" + echo "ORGANIZATION_ID=$ORGANIZATION_ID" + echo "PREFIX=$PREFIX" + echo "REGIONS=$REGIONS" + echo "AW_REGION=$AW_REGION" + echo "TENANT_ENVIRONMENTS=$TENANT_ENVIRONMENTS" + echo "EXTERNAL_DIRECTORY_CUSTOMER_IDS=$EXTERNAL_DIRECTORY_CUSTOMER_IDS" + echo "EXTERNAL_ORGANIZATION_IDS=$EXTERNAL_ORGANIZATION_IDS" + echo "TOP_LEVEL_FOLDER_NAME=$TOP_LEVEL_FOLDER_NAME" + echo "TOP_LEVEL_FOLDER_ID=$TOP_LEVEL_FOLDER_ID" + echo "CI_PROJECT_PATH=$CI_PROJECT_PATH" + echo "CI_COMMIT_BRANCH=$CI_COMMIT_BRANCH" + echo "GITLAB_URL=$GITLAB_URL" + echo "JWKS_KEY=$JWKS_KEY" + echo "TF_VAR_gcp_organization_admins_group=$TF_VAR_gcp_organization_admins_group" + echo "TF_VAR_gcp_billing_admins_group=$TF_VAR_gcp_billing_admins_group" + echo "TF_VAR_gcp_vpc_network_admins_group=$TF_VAR_gcp_vpc_network_admins_group" + echo "TF_VAR_gcp_hybrid_connectivity_admins_group=$TF_VAR_gcp_hybrid_connectivity_admins_group" + echo "TF_VAR_gcp_logging_monitoring_admins_group=$TF_VAR_gcp_logging_monitoring_admins_group" + echo "TF_VAR_gcp_logging_monitoring_viewers_group=$TF_VAR_gcp_logging_monitoring_viewers_group" + echo "TF_VAR_gcp_security_admins_group=$TF_VAR_gcp_security_admins_group" + echo "TF_VAR_gcp_developers_group=$TF_VAR_gcp_developers_group" + echo "TF_VAR_gcp_devops_group=$TF_VAR_gcp_devops_group" + } >"$CONFIG_FILE" + else + # shellcheck source=automation/config.env.sample + source "$CONFIG_FILE" + echo "------------------------------------------------------------------" + basename "$CONFIG_FILE" + cat "$CONFIG_FILE" + echo -e "\n------------------------------------------------------------------" + echo "If the above does not look correct your .env file may be wrong!" + fi + + echo -e "\n--- Compliance List Verification ---" + if promptUser "Are the .yaml files accurately reflecting the compliance catalog?"; then + sync_compliance_lists() { + local target_dir=$1 + mkdir -p "${target_dir}" + echo "[SYNC] Copying compliance lists to ${target_dir}..." + cp "${SCRIPT_DIR}/allowed_apis.yaml" "${target_dir}/" + cp "${SCRIPT_DIR}/lz_exceptions.yaml" "${target_dir}/" + chmod 444 "${target_dir}/allowed_apis.yaml" + chmod 444 "${target_dir}/lz_exceptions.yaml" + } + + sync_compliance_lists "${SCRIPT_DIR}/../fast/stages-aw/1-assured-workload/data" + sync_compliance_lists "${SCRIPT_DIR}/../fast/stages-aw/3-networking/data" + + echo "[SUCCESS] Compliance lists synced and locked (Read-Only)." + fi + # -------------------------------------------- + + # Set Bootstrap Project + echo -e "\nChecking to make sure the bootstrap project exists" + bootstrap_state=$(gcloud projects describe "${BOOTSTRAP_PROJECT_ID}" --format 'value(lifecycleState)' 2>/dev/null) + bootstrap_status=$? + if [[ "$bootstrap_status" -ne 0 ]]; then + if promptUser "Project '${BOOTSTRAP_PROJECT_ID}' does not exist. Would you like to create it and set it to the default project?"; then + gcloud projects create "${BOOTSTRAP_PROJECT_ID}" --folder="${TOP_LEVEL_FOLDER_ID}" + gcloud config set project "${BOOTSTRAP_PROJECT_ID}" + fi + elif [[ "${bootstrap_state}" == "DELETE_REQUESTED" ]]; then + if promptUser "Project '${BOOTSTRAP_PROJECT_ID}' is pending deletion. Would you like to re-enable it and set it to the default project?"; then + gcloud projects undelete "${BOOTSTRAP_PROJECT_ID}" + gcloud config set project "${BOOTSTRAP_PROJECT_ID}" + fi + elif [[ "${bootstrap_state}" != "ACTIVE" ]]; then + echo "Project '${BOOTSTRAP_PROJECT_ID}' exists but is in non-active state: ${bootstrap_state}. This can be caused by the project still being in a provisioning state or by the lifecycleStatus not having been set yet." + else + promptUser "Would you like to set the bootstrap project as the default project?" "gcloud config set project ${BOOTSTRAP_PROJECT_ID}" + fi + + # setIAM + promptUser "Would you like to set your IAM permissions?" "\"${SCRIPT_DIR}/../fast/stages-aw/0-organization-bootstrap/setIAM.sh\" ${DEPLOYER_EMAIL_ADDRESS} ${ORGANIZATION_ID}" + + # enable Services + promptUser "Would you like to enable all Google Cloud Services?" "\"${SCRIPT_DIR}/../fast/stages-aw/0-organization-bootstrap/enableServices.sh\" ${DEPLOYER_EMAIL_ADDRESS} ${ORGANIZATION_ID}" + + if promptUser "Would you like to link the billing account to the bootstrap project?"; then + gcloud billing projects link "${BOOTSTRAP_PROJECT_ID}" --billing-account="${BILLING_ACCOUNT}" + fi + + # Groups and Admin setup + populateGroups + if promptUser "Would you like to create the Users and Groups and set up Administrative access?"; then + automateGroupsAdminAccess + fi + + echo -e "\nPlease follow the link below (if you have not yet done so) to enable access transparency for your organization" + echo "https://console.cloud.google.com/iam-admin/settings?invt=AbuKFg&organizationId=${ORGANIZATION_ID}" + echo "Press any key when complete to go to the next step." + read -r -n 1 -s -p "" + + echo -e "\nCongratulations, you have finished the prerequisites!" + +else + + # shellcheck source=automation/config.env.sample + source "$CONFIG_FILE" + populateGroups + echo "------------------------------------------------------------------" + basename "$CONFIG_FILE" + cat "$CONFIG_FILE" + echo -e "\n------------------------------------------------------------------" + echo -e "If the above does not look correct your configuration file may be wrong!\n" +fi + +# Mapping abbreviations +COMPLIANCE_REGIME_ABBREVIATION=$(compliance_regime_mapping "${COMPLIANCE_REGIME}") + +# Convert REGIONS from a string to an array +IFS=',' read -r -a REGIONS_ARRAY <<< "$REGIONS" +REGIONS_CONFIG=$(printf '%s", "' "${REGIONS_ARRAY[@]}" | sed 's/", "$//') +REGIONS_CONFIG="[\"$REGIONS_CONFIG\"]" + +########### Stage 0 - Organization ########### +echo -e "\n#######################################################" +echo "#######################################################" +echo "#######################################################" + +if promptUser "Stage 0 - Organization Bootstrap -"; then + cd "${SCRIPT_DIR}"/../fast/stages-aw/0-organization-bootstrap || exit + resourceFile="${SCRIPT_DIR}/tmp/0-organization-bootstrap_tf_resources_$$" + statusFile="${SCRIPT_DIR}/tmp/0-organization-bootstrap_tf_status_$$" + + TOP_LEVEL_FOLDER_NAME_LOWER=$(echo "$TOP_LEVEL_FOLDER_NAME" | tr '[:upper:]' '[:lower:]') + # Check for remote Terraform state for organization + GCS_SOURCE_URL="gs://${TOP_LEVEL_FOLDER_NAME_LOWER}-prod-iac-core/terraform/state/default.tfstate" + SKIP_STAGE=false + + # # Check if the state exists in GCS + echo "Checking for file existence in Cloud Storage: ${GCS_SOURCE_URL}" + if gcloud storage ls "${GCS_SOURCE_URL}" &>/dev/null; then + echo "Skipping stage as the remote state is already present" + SKIP_STAGE=true + fi + + if [ "$SKIP_STAGE" = false ]; then + # Confirm billing account privileges + echo "Please make sure you have billing account admin privileges, and billing is enabled on the bootstrap project." + echo "Press any key to confirm, and go to the next step." + read -r -n 1 -s -p "" + + if promptUser "Would you to generate a new tfvars file?"; then + # Organization Policy: Allowed Policy Member Domains + if [ -z "$EXTERNAL_DIRECTORY_CUSTOMER_IDS" ]; then + # No External Customer Directory IDs + allowed_policy_member_domains_config="[]" + else + # Trim and Format Member Domains + allowed_policy_member_domains_config="[\"$(echo "$EXTERNAL_DIRECTORY_CUSTOMER_IDS" | tr -d '[:space:]' | sed 's/,/\", \"/g')\"]" + fi + + # Organization Policy: Access Boundaries + if [ -z "$EXTERNAL_ORGANIZATION_IDS" ]; then + # No External Organization IDs + allowed_access_boundaries_config="[]" + else + # Trim and Format Access Boundaries + allowed_access_boundaries_config="[\"$(echo "$EXTERNAL_ORGANIZATION_IDS" | tr -d '[:space:]' | sed 's/,/\", \"/g')\"]" + fi + GROUPS_BLOCK="" + + # Check each variable and append to our string if it exists + [ -n "${TF_VAR_gcp_billing_admins_group}" ] && GROUPS_BLOCK="${GROUPS_BLOCK} gcp-billing-admins = \"${TF_VAR_gcp_billing_admins_group}\"\n" + [ -n "${TF_VAR_gcp_devops_group}" ] && GROUPS_BLOCK="${GROUPS_BLOCK} gcp-devops = \"${TF_VAR_gcp_devops_group}\"\n" + [ -n "${TF_VAR_gcp_vpc_network_admins_group}" ] && GROUPS_BLOCK="${GROUPS_BLOCK} gcp-vpc-network-admins = \"${TF_VAR_gcp_vpc_network_admins_group}\"\n" + [ -n "${TF_VAR_gcp_organization_admins_group}" ] && GROUPS_BLOCK="${GROUPS_BLOCK} gcp-organization-admins = \"${TF_VAR_gcp_organization_admins_group}\"\n" + [ -n "${TF_VAR_gcp_security_admins_group}" ] && GROUPS_BLOCK="${GROUPS_BLOCK} gcp-security-admins = \"${TF_VAR_gcp_security_admins_group}\"\n" + [ -n "${TF_VAR_gcp_devops_group}" ] && GROUPS_BLOCK="${GROUPS_BLOCK} gcp-support = \"${TF_VAR_gcp_devops_group}\"\n" + + # Wrap it in the Terraform object syntax, interpreting the \n newlines safely + # If GROUPS_BLOCK is entirely empty, this outputs a clean "groups = {}" + if [ -n "$GROUPS_BLOCK" ]; then + GROUPS_OUTPUT=$(printf "{\n%b}" "$GROUPS_BLOCK") + else + GROUPS_OUTPUT="{}" + fi + + cat <terraform.tfvars +assured_workloads = { + regime = "${COMPLIANCE_REGIME}" # "IL4, IL5, FEDRAMP_HIGH, etc... if you wish to not use assured_workloads, set this value to COMPLIANCE_REGIME_UNSPECIFIED" + location = "${AW_REGION}" +} + +billing_account = { + id = "${BILLING_ACCOUNT}" +} + +bootstrap_project = "${BOOTSTRAP_PROJECT_ID}" + +groups = ${GROUPS_OUTPUT} + +# locations for GCS, BigQuery, KMS, and logging buckets created here +locations = { + bq = "$(echo "$REGIONS_CONFIG" | jq -r '.[0]')" + gcs = ${REGIONS_CONFIG} + logging = ${REGIONS_CONFIG} + pubsub = ${REGIONS_CONFIG} + kms = ${REGIONS_CONFIG} +} + +# use \`gcloud organizations list\` +organization = { + domain = "${FULLY_QUALIFIED_DOMAIN_NAME}" + id = "${ORGANIZATION_ID}" + customer_id = "${DIRECTORY_CUSTOMER_ID}" +} + +org_policies_config = { + import_defaults = false # No policies to import as of 27 SEP 2024 + constraints = { + allowed_policy_member_domains = ${allowed_policy_member_domains_config} # Additional externally allowed customer_ids + allowed_access_boundaries = ${allowed_access_boundaries_config} # Additional externally allowed organization_ids + } +} + +top_level_folder = { + name = "${TOP_LEVEL_FOLDER_NAME}" + id = "${TOP_LEVEL_FOLDER_ID}" +} +EOF + fi + + if promptUser "Would you like to ensure essential APIs are enabled for the folder context?"; then + echo "Enabling APIs for project: ${TOP_LEVEL_FOLDER_NAME}..." + + apis=( + "cloudbilling.googleapis.com" + "iam.googleapis.com" + "billingbudgets.googleapis.com" + "kmsinventory.googleapis.com" + "cloudkms.googleapis.com" + "assuredworkloads.googleapis.com" + "orgpolicy.googleapis.com" + "cloudresourcemanager.googleapis.com" + ) + + for api in "${apis[@]}"; do + echo "Activating $api for Folder: ${TOP_LEVEL_FOLDER_ID}..." + gcloud beta services enable "$api" --folder="${TOP_LEVEL_FOLDER_ID}" + done + + echo "Waiting for API propagation (120s)..." + sleep 120 + fi + + # Create temporary providers.tf + if [ ! -f "0-organization-bootstrap-providers.tf" ] || promptUser "Would you like to generate your initial providers.tf?"; then + cp providers.tf.tmp 0-organization-bootstrap-providers.tf + fi + + if promptUser "Would you like to perform the initial terraform init?"; then + runTerraformCommand "init" "$resourceFile" "$statusFile" + fi + + if promptUser "Would you like to perform the terraform apply?"; then + runTerraformCommand "apply" "$resourceFile" "$statusFile" + fi + + + # Update Providers + cmd=("gcloud storage cp gs://${TOP_LEVEL_FOLDER_NAME_LOWER}-org-iac-bootstrap/providers/0-organization-bootstrap-providers.tf ./") + promptUser "Would you like to update your providers file?" "${cmd[@]}" # Pass the array elements + + # Migrate State + if promptUser "Would you like to migrate to the remote state to ${TOP_LEVEL_FOLDER_NAME_LOWER}-org-iac?"; then + runTerraformCommand "init --migrate-state" "$resourceFile" "$statusFile" + fi + + echo "Congratulations, you have completed Stage 0!" + fi +fi + + + +########### Stage 1 - Assured Workload ############ +echo -e "\n#######################################################" +echo "#######################################################" +echo "#######################################################" + +if promptUser "Stage 1 - Assured Workload -"; then + cd "${SCRIPT_DIR}"/../fast/stages-aw/1-assured-workload || exit + resourceFile="${SCRIPT_DIR}/tmp/1-assured-workload_tf_resources_$$" + statusFile="${SCRIPT_DIR}/tmp/1-assured-workload_tf_status_$$" + + # # Set file paths for tfvars file + # GCS_SOURCE_URL="gs://${PREFIX}-prod-iac-core-inputs-0/stage-1/stage-1-inputs.auto.tfvars.json" + # LOCAL_DEST_PATH="./stage-1-inputs.auto.tfvars.json" + + # # Check if the file exists in GCS + # echo "Checking for file existence in Cloud Storage: ${GCS_SOURCE_URL}" + # if gcloud storage ls "${GCS_SOURCE_URL}" &>/dev/null; then + # cmd=("gcloud storage cp ${GCS_SOURCE_URL} ${LOCAL_DEST_PATH}") + # promptUser "Would you like to download your tfvars file for stage-1 from ${PREFIX}-prod-iac-core-inputs-0/stage-1?" "${cmd[@]}" + # fi + + # Generate TF Vars - This will NOT work indented + if promptUser "Would you to generate a new tfvars file?"; then + GROUPS_BLOCK="" + + # Check each variable and append to our string if it exists + [ -n "${TF_VAR_gcp_billing_admins_group}" ] && GROUPS_BLOCK="${GROUPS_BLOCK} gcp-billing-admins = \"${TF_VAR_gcp_billing_admins_group}\"\n" + [ -n "${TF_VAR_gcp_devops_group}" ] && GROUPS_BLOCK="${GROUPS_BLOCK} gcp-devops = \"${TF_VAR_gcp_devops_group}\"\n" + [ -n "${TF_VAR_gcp_vpc_network_admins_group}" ] && GROUPS_BLOCK="${GROUPS_BLOCK} gcp-vpc-network-admins = \"${TF_VAR_gcp_vpc_network_admins_group}\"\n" + [ -n "${TF_VAR_gcp_organization_admins_group}" ] && GROUPS_BLOCK="${GROUPS_BLOCK} gcp-organization-admins = \"${TF_VAR_gcp_organization_admins_group}\"\n" + [ -n "${TF_VAR_gcp_security_admins_group}" ] && GROUPS_BLOCK="${GROUPS_BLOCK} gcp-security-admins = \"${TF_VAR_gcp_security_admins_group}\"\n" + [ -n "${TF_VAR_gcp_devops_group}" ] && GROUPS_BLOCK="${GROUPS_BLOCK} gcp-support = \"${TF_VAR_gcp_devops_group}\"\n" + + # Wrap it in the Terraform object syntax, interpreting the \n newlines safely + # If GROUPS_BLOCK is entirely empty, this outputs a clean "groups = {}" + if [ -n "$GROUPS_BLOCK" ]; then + GROUPS_OUTPUT=$(printf "{\n%b}" "$GROUPS_BLOCK") + else + GROUPS_OUTPUT="{}" + fi + cat <terraform.tfvars +billing_account = { + id = "${BILLING_ACCOUNT}" +} + +groups = ${GROUPS_OUTPUT} + +# locations for GCS, BigQuery, KMS, and logging buckets created here +locations = { + bq = "$(echo "$REGIONS_CONFIG" | jq -r '.[0]')" + gcs = ${REGIONS_CONFIG} + logging = ${REGIONS_CONFIG} + pubsub = ${REGIONS_CONFIG} + kms = ${REGIONS_CONFIG} +} + +# use \`gcloud organizations list\` +organization = { + domain = "${FULLY_QUALIFIED_DOMAIN_NAME}" + id = "${ORGANIZATION_ID}" + customer_id = "${DIRECTORY_CUSTOMER_ID}" +} + +outputs_location = "~/fast-config" + +# use something unique and no longer than 9 characters +prefix = "${PREFIX}" + +fast_features = { + envs = true +} + +assured_workloads = { + regime = "${COMPLIANCE_REGIME}" # "IL4, IL5, FEDRAMP_HIGH, etc... if you wish to not use assured_workloads, set this value to COMPLIANCE_REGIME_UNSPECIFIED" + location = "${AW_REGION}" +} + +bootstrap_project = "${BOOTSTRAP_PROJECT_ID}" + +alert_email = "${LOGGING_ALERTS_EMAIL_ADDRESS}" + +top_level_folder = { + name = "${TOP_LEVEL_FOLDER_NAME}" + id = "${TOP_LEVEL_FOLDER_ID}" +} +EOF + + if [ -n "${APPLY_TIER_1_PUBSUB_SINK}" ]; then + echo "apply_tier_1_pubsub_sink = ${APPLY_TIER_1_PUBSUB_SINK}" >> terraform.tfvars + fi + + if [[ -n "$CI_PROJECT_PATH" && -n "$GITLAB_URL" ]]; then + export CI_PROJECT_PATH GITLAB_URL TENANT_CI_PROJECT_PATH + jq -n ' + .workload_identity_providers["gitlab-fed"] = { + "issuer": "gitlab", + "attribute_condition": "attribute.project_path == \"\(env.CI_PROJECT_PATH)\"", + "custom_settings": { + "issuer_uri": env.GITLAB_URL, + "audiences": [env.GITLAB_URL], + "jwks_json": env.JWKS_KEY + } + } | + .cicd_repositories.bootstrap = { + "name": env.CI_PROJECT_PATH, + "type": "gitlab", + "identity_provider": "gitlab-fed" + } | + .cicd_repositories.resman = { + "name": env.CI_PROJECT_PATH, + "type": "gitlab", + "identity_provider": "gitlab-fed" + } | + + if (env.TENANT_CI_PROJECT_PATH != null and env.TENANT_CI_PROJECT_PATH != "") then + .workload_identity_providers["gitlab-tenants"] = { + "issuer": "gitlab", + "attribute_condition": "attribute.project_path == \"\(env.TENANT_CI_PROJECT_PATH)\"", + "custom_settings": { + "issuer_uri": env.GITLAB_URL, + "audiences": [env.GITLAB_URL], + "jwks_json": env.JWKS_KEY + } + } | + .cicd_repositories.tenant = { + "name": env.TENANT_CI_PROJECT_PATH, + "type": "gitlab", + "identity_provider": "gitlab-tenants" + } + else + .cicd_repositories.tenant = { + "name": env.CI_PROJECT_PATH, + "type": "gitlab", + "identity_provider": "gitlab-fed" + } + end + ' > identity-providers.auto.tfvars.json + fi + fi + + # Create temporary providers.tf + if [ ! -f "1-assured-workload-providers.tf" ] || promptUser "Would you like to generate your initial providers.tf?"; then + cp providers.tf.tmp 1-assured-workload-providers.tf + fi + + if promptUser "Would you like to perform the initial terraform init?"; then + runTerraformCommand "init" "$resourceFile" "$statusFile" + fi + + if promptUser "Do you want to cross reference with the compliance and LZ Exception lists to ensure compliance?"; then + echo "Verifying project-level API allowlists against compliance and LZ Exception catalogs" + if ! bash "${SCRIPT_DIR}/allow_compliance_apis.sh"; then + echo "[ERROR] Exiting deployment: Unauthorized APIs detected in Terraform Plan." + exit 1 + fi + echo "[SUCCESS] Cross-check passed. Proceeding with Tiered Enforcement (COA 2)." + fi + + # Terraform Apply #1 + if promptUser "Would you like to run the first terraform apply with the bootstrap user?"; then + runTerraformCommand "apply -var bootstrap_user=${DEPLOYER_EMAIL_ADDRESS}" "$resourceFile" "$statusFile" + fi + + # Terraform Apply #2 + if promptUser "Would you like to run the second terraform apply with the bootstrap user?"; then + runTerraformCommand "apply -var bootstrap_user=${DEPLOYER_EMAIL_ADDRESS}" "$resourceFile" "$statusFile" + fi + + export PROJ="automation-project" + RAW_PROJ_NAME=$(yq '.projects[] | select(.name == env(PROJ)) | .project_name' "${SCRIPT_DIR}"/../project-config.yml) + PROJ_NAME="${RAW_PROJ_NAME///$PREFIX}" + PROJ_NAME="${PROJ_NAME///$COMPLIANCE_REGIME_ABBREVIATION}" + cmd=("gcloud config set project ${PROJ_NAME}") + promptUser "Would you like to set the default project to ${PROJ_NAME}" "${cmd[@]}" + + # Update Providers + cmd=("gcloud storage cp gs://${PREFIX}-${COMPLIANCE_REGIME_ABBREVIATION}-prod-iac-core-outputs/providers/1-assured-workload-providers.tf ./") + promptUser "Would you like to update your providers file?" "${cmd[@]}" # Pass the array elements + + # Migrate State + if promptUser "Would you like to migrate to the remote state to ${PROJ_NAME}?"; then + runTerraformCommand "init --migrate-state" "$resourceFile" "$statusFile" + fi + + # Terraform Apply #3 + if promptUser "Would you like to run the third terraform apply (without the bootstrap user)?"; then + runTerraformCommand "apply" "$resourceFile" "$statusFile" + fi + echo "Congratulations, you have completed Stage 1!" +fi + +########### Stage 2 - Resman ############ +echo -e "\n#######################################################" +echo "#######################################################" +echo "#######################################################" + +if promptUser "Stage 2 - Resource Manager -"; then + cd "${SCRIPT_DIR}"/../fast/stages-aw/2-resman || exit + resourceFile="${SCRIPT_DIR}/tmp/2-resman_tf_resources_$$" + statusFile="${SCRIPT_DIR}/tmp/2-resman_tf_status_$$" + + export PROJ="automation-project" + RAW_PROJ_NAME=$(yq '.projects[] | select(.name == env(PROJ)) | .project_name' "${SCRIPT_DIR}"/../project-config.yml) + PROJ_NAME="${RAW_PROJ_NAME///$PREFIX}" + PROJ_NAME="${PROJ_NAME///$COMPLIANCE_REGIME_ABBREVIATION}" + + ## Set file paths for tfvars file + # GCS_SOURCE_URL="gs://${PREFIX}-prod-iac-core-inputs-0/stage-2/stage-2-inputs.auto.tfvars.json" + # LOCAL_DEST_PATH="./stage-1-inputs.auto.tfvars.json" + + # # Check if the file exists in GCS + # echo "Checking for file existence in Cloud Storage: ${GCS_SOURCE_URL}" + # if gcloud storage ls "${GCS_SOURCE_URL}" &>/dev/null; then + # cmd=("gcloud storage cp ${GCS_SOURCE_URL} ${LOCAL_DEST_PATH}") + # promptUser "Would you like to download your tfvars file for stage-2 from ${PREFIX}-prod-iac-core-inputs-0/stage-2?" "${cmd[@]}" + # fi + + # Generate new tfvars - this will not work indented + if promptUser "Would you like to generate a new 2-resman tfvars?"; then # Tenant Loop Logic + # Tenant Environment Configuration ---" + tenant_environments_config="" + IFS=',' read -r -a ENV_ARRAY <<< "$TENANT_ENVIRONMENTS" + for ENV_NAME in "${ENV_ARRAY[@]}"; do + ENV_NAME=$(echo "$ENV_NAME" | tr -d '[:space:]') + + tenant_environments_config+=" + ${ENV_NAME} = { + admin = \"${TF_VAR_gcp_organization_admins_group:-gcp-organization-admins}@${FULLY_QUALIFIED_DOMAIN_NAME}\" + }," + done + # Remove the trailing comma + if [[ -n "$tenant_environments_config" ]]; then + tenant_environments_config="${tenant_environments_config%,*}" + fi + + cat <terraform.tfvars +fast_features = { + envs = true +} + +tenant_environments = { +${tenant_environments_config:1} +} +EOF + + if [[ -n "$CI_PROJECT_PATH" && -n "$GITLAB_URL" ]]; then + cat <>terraform.tfvars + +cicd_repositories = { + networking = { + name = "${CI_PROJECT_PATH}" + type = "gitlab" + identity_provider = "gitlab-fed" + } + security = { + name = "${CI_PROJECT_PATH}" + type = "gitlab" + identity_provider = "gitlab-fed" + } + shared_services = { + name = "${CI_PROJECT_PATH}" + type = "gitlab" + identity_provider = "gitlab-fed" + } +} +EOF + fi + fi + + # Copy remote tfvars + cmd=( + "gcloud storage cp gs://${PREFIX}-${COMPLIANCE_REGIME_ABBREVIATION}-prod-iac-core-outputs/providers/2-resman-providers.tf ./" + "gcloud storage cp gs://${PREFIX}-${COMPLIANCE_REGIME_ABBREVIATION}-prod-iac-core-outputs/tfvars/1-globals.auto.tfvars.json ./" + "gcloud storage cp gs://${PREFIX}-${COMPLIANCE_REGIME_ABBREVIATION}-prod-iac-core-outputs/tfvars/1-assured-workload.auto.tfvars.json ./" + ) + promptUser "Would you like to pull the remote tfvars files created in Stage 1?" "${cmd[@]}" + + if promptUser "Would you like to perform the terraform init?"; then + runTerraformCommand "init" "$resourceFile" "$statusFile" + fi + + if promptUser "Would you like to perform the terraform apply?"; then + runTerraformCommand "apply" "$resourceFile" "$statusFile" + fi + + echo "Congratulations, you have completed Stage 2!" +fi + +########### Stage 3 - Networking ############ +echo -e "\n#######################################################" +echo "#######################################################" +echo "#######################################################" + +if promptUser "Stage 3 - Networking -"; then + cd "${SCRIPT_DIR}"/../fast/stages-aw/3-networking || exit + # Add external billing account + export PROJ="automation-project" + RAW_PROJ_NAME=$(yq '.projects[] | select(.name == env(PROJ)) | .project_name' "${SCRIPT_DIR}"/../project-config.yml) + PROJ_NAME="${RAW_PROJ_NAME///$PREFIX}" + PROJ_NAME="${PROJ_NAME///$COMPLIANCE_REGIME_ABBREVIATION}" + + resourceFile="${SCRIPT_DIR}/tmp/3-networking-ngfw_tf_resources_$$" + statusFile="${SCRIPT_DIR}/tmp/3-networking-ngfw_tf_status_$$" + + # cmd=("./pre-redeploy.sh") + # promptUser "If this is a redeployment (<30 days), would you like to run the redeploy script?" "${cmd[@]}" + + if promptUser "Would you like to pull the remote tfvars files created in Stages 1 and 2?"; then + gcloud storage cp gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-outputs/providers/3-networking-providers.tf ./ + gcloud storage cp gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-outputs/tfvars/1-globals.auto.tfvars.json ./ + gcloud storage cp gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-outputs/tfvars/1-assured-workload.auto.tfvars.json ./ + gcloud storage cp gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-outputs/tfvars/2-resman.auto.tfvars.json ./ + fi + + if [ -n "${NETWORK_QUOTA_PREFERRED_VALUE}" ]; then + echo "network_quota_preferred_value = ${NETWORK_QUOTA_PREFERRED_VALUE}" >> terraform.tfvars + fi + + if promptUser "Would you like to perform the terraform init?"; then + runTerraformCommand "init" "$resourceFile" "$statusFile" + fi + + if promptUser "Would you like to perform the targeted terraform apply?"; then + runTerraformCommand "apply \ + -target=google_cloud_quotas_quota_preference.network_quota \ + -target=google_project_iam_custom_role.ngfw-custom-role \ + -target=local_file.generated_ingress_rule" "$resourceFile" "$statusFile" + fi + + if promptUser "Would you like to perform the full terraform apply?"; then + runTerraformCommand "apply" "$resourceFile" "$statusFile" + fi + + echo "Congratulations, you have completed Stage 3!" +fi + +########### Stage 4 - Security ############ +echo -e "\n#######################################################" +echo "#######################################################" +echo "#######################################################" + +if promptUser "Stage 4 - Security -"; then + cd "${SCRIPT_DIR}"/../fast/stages-aw/4-security || exit + resourceFile="${SCRIPT_DIR}/tmp/4-security_tf_resources_$$" + statusFile="${SCRIPT_DIR}/tmp/4-security_tf_status_$$" + + # Add external billing account + export PROJ="automation-project" + RAW_PROJ_NAME=$(yq '.projects[] | select(.name == env(PROJ)) | .project_name' "${SCRIPT_DIR}"/../project-config.yml) + PROJ_NAME="${RAW_PROJ_NAME///$PREFIX}" + PROJ_NAME="${PROJ_NAME///$COMPLIANCE_REGIME_ABBREVIATION}" + + if promptUser "Would you like to pull the remote tfvars files created in Stages 1 and 2?"; then + gcloud storage cp gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-outputs/providers/4-security-providers.tf ./ + gcloud storage cp gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-outputs/tfvars/1-globals.auto.tfvars.json ./ + gcloud storage cp gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-outputs/tfvars/1-assured-workload.auto.tfvars.json ./ + gcloud storage cp gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-outputs/tfvars/2-resman.auto.tfvars.json ./ + fi + + if promptUser "Would you like to perform the terraform init?"; then + runTerraformCommand "init" "$resourceFile" "$statusFile" + fi + + if promptUser "Would you like to perform the terraform apply?"; then + runTerraformCommand "apply" "$resourceFile" "$statusFile" + fi + + promptUser "Would you like to run the lockdown script?" "./sa_lockdown.sh" + + # promptUser "Would you like to delete the bootstrap project?" "./delete_gcp_project.sh --project-id=${BOOTSTRAP_PROJECT_ID}" + + echo "Congratulations, you have finished Stage 4! Please see the SBPG linked below for further hardening." + echo 'https://docs.google.com/document/d/1bkPg-Uj6cf6_w1IHPCTZ66SC0fVWz9pUfTZy9v6hcr0/' +fi + +m -rf "${SCRIPT_DIR}"/tmp \ No newline at end of file diff --git a/automation/stellar-destroy.sh b/automation/stellar-destroy.sh new file mode 100644 index 000000000..c7a72957c --- /dev/null +++ b/automation/stellar-destroy.sh @@ -0,0 +1,473 @@ +#!/bin/bash +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#### Use this script at your own risk. The author assumes no responsibility for any damages or losses incurred through its use. + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +cd "${SCRIPT_DIR}" || exit + +promptUser() { + echo -e "\n${1} Type 's' to skip, or 'c' to continue'." + read -r choice + if [[ "$choice" == "s" ]]; then + return 255 # Won't run command + else + shift + for i in "$@"; do + eval "$i" + done + fi +} + +compliance_regime_mapping() { + case "${1}" in + "COMPLIANCE_REGIME_UNSPECIFIED") + echo "cru" + ;; + "IL2") + echo "il2" + ;; + "IL4") + echo "il4" + ;; + "IL5") + echo "il5" + ;; + "FEDRAMP_HIGH") + echo "frh" + ;; + "FEDRAMP_MODERATE") + echo "frm" + ;; + *) + echo "${1}" | tr '[:upper:]' '[:lower:]' + ;; + esac +} + +############ Prerequisites ############ +echo "Welcome to the Secure Cloud Landing Zone automated destruction!" + +if ! promptUser "This script will delete your entire environment, and all local .terraform dirs. Proceed with caution."; then exit; fi + +promptUser 'Would you like to authenticate with Google Cloud?' "gcloud auth login; gcloud auth application-default login" + +echo -e "\n#######################################################" +echo "#######################################################" +echo "#######################################################" + +if promptUser "Prerequisites -"; then + + # Pull Config File + if promptUser "Would you like to use an existing config file from a Google Storage Bucket?"; then + + echo -e "\nSearching for existing config.env files in GCS buckets..." + config_files=() + while IFS= read -r line; do + config_files+=("$line") + done < <( + for project in $(gcloud projects list --format="value(projectId)"); do + gcloud storage ls --project="$project" "gs://*-iac-core-config*/config.env" 2>/dev/null + done + ) + + if [ ${#config_files[@]} -eq 0 ]; then + echo "No existing config.env files found in any accessible GCS buckets." + else + echo -e "\nThe following config files were found:" + for i in "${!config_files[@]}"; do + printf "%s) %s\n" "$((i+1))" "${config_files[$i]#"gs://"}" + done + + echo "" + read -r -p "Please select the config file to use: " choice + + if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -le ${#config_files[@]} ]; then + selected_index=$((choice-1)) + GCS_SOURCE_URL="${config_files[$selected_index]}" + display_path="${GCS_SOURCE_URL#"gs://"}" + echo "You selected: $display_path" + promptUser "Would you like to copy $display_path to $SCRIPT_DIR/config.env ?" "gcloud storage cp \"$GCS_SOURCE_URL\" \"$SCRIPT_DIR/config.env\"" + else + echo "Invalid selection. Please try again." + fi + fi + fi + + # Set variables + if [ ! -f "$SCRIPT_DIR"/config.env ] || promptUser "Would you like to overwrite your config.env file?"; then + gcloud organizations list + + read -r -p "Enter your billing account: " BILLING_ACCOUNT + read -r -p "Enter your bootstrap project ID: " BOOTSTRAP_PROJECT_ID + read -r -p "Enter the compliance regime: " COMPLIANCE_REGIME + read -r -p "Enter your directory customer ID : " DIRECTORY_CUSTOMER_ID + read -r -p "Enter your deployer email address: " DEPLOYER_EMAIL_ADDRESS + read -r -p "Enter your fully qualified domain name: " FULLY_QUALIFIED_DOMAIN_NAME + read -r -p "Enter your logging alerts email address: " LOGGING_ALERTS_EMAIL_ADDRESS + read -r -p "Enter your organization ID: " ORGANIZATION_ID + read -r -p "Enter your prefix (6 chars or less): " PREFIX + read -r -p "Enter your regions: " REGIONS + read -r -p "Enter your Assured Workload region: " AW_REGION + read -r -p "Enter your tenant environment(s) (dev,prod): " TENANT_ENVIRONMENTS + read -r -p "Enter your external Directory Customer IDs (comma-separated, or blank): " EXTERNAL_DIRECTORY_CUSTOMER_IDS + read -r -p "Enter your external Organization IDs (comma-separated, or blank): " EXTERNAL_ORGANIZATION_IDS + read -r -p "Enter the top level folder name: " TOP_LEVEL_FOLDER_NAME + read -r -p "Enter the top level folder ID: " TOP_LEVEL_FOLDER_ID + read -r -p "Enter the project path in gitlab for Workload Identity Federation (leave blank if not using): " CI_PROJECT_PATH + read -r -p "Enter the branch name in gitlab where Workload Identity Federation will authenticate from (leave blank if not using): " CI_COMMIT_BRANCH + read -r -p "Enter the GitLab URL if using Workload Identity Federation excluding trailing forward slash (leave blank if not using): " GITLAB_URL + read -r -p "Enter the JWKS (JSON Web Key Set) for GitLab-to-GCP authentication. Note: This is only required if operating on the secure Army network: " JWKS_KEY + + echo "--- Configuration Summary ---" + echo "billing-account: $BILLING_ACCOUNT" + echo "bootstrap-project-id: $BOOTSTRAP_PROJECT_ID" + echo "compliance-regime: $COMPLIANCE_REGIME" + echo "directory-customer-id: $DIRECTORY_CUSTOMER_ID" + echo "deployer-email-address: $DEPLOYER_EMAIL_ADDRESS" + echo "fully-qualified-domain-name: $FULLY_QUALIFIED_DOMAIN_NAME" + echo "logging-alerts-email-address: $LOGGING_ALERTS_EMAIL_ADDRESS" + echo "organization-id: $ORGANIZATION_ID" + echo "prefix: $PREFIX" + echo "regions: $REGIONS" + echo "aw-region: $AW_REGION" + echo "tenant-environments: $TENANT_ENVIRONMENTS" + echo "external-directory-customer-ids: $EXTERNAL_DIRECTORY_CUSTOMER_IDS" + echo "external-organization-ids: $EXTERNAL_ORGANIZATION_IDS" + echo "top-level-folder-name: $TOP_LEVEL_FOLDER_NAME" + echo "top-level-folder-id: $TOP_LEVEL_FOLDER_ID" + echo "ci-project-path: $CI_PROJECT_PATH" + echo "ci-commit-branch: $CI_COMMIT_BRANCH" + echo "gitlab-url: $GITLAB_URL" + echo "jwks-key: $JWKS_KEY" + + { + echo "BILLING_ACCOUNT=$BILLING_ACCOUNT" + echo "BOOTSTRAP_PROJECT_ID=$BOOTSTRAP_PROJECT_ID" + echo "COMPLIANCE_REGIME=$COMPLIANCE_REGIME" + echo "DIRECTORY_CUSTOMER_ID=$DIRECTORY_CUSTOMER_ID" + echo "DEPLOYER_EMAIL_ADDRESS=$DEPLOYER_EMAIL_ADDRESS" + echo "FULLY_QUALIFIED_DOMAIN_NAME=$FULLY_QUALIFIED_DOMAIN_NAME" + echo "LOGGING_ALERTS_EMAIL_ADDRESS=$LOGGING_ALERTS_EMAIL_ADDRESS" + echo "ORGANIZATION_ID=$ORGANIZATION_ID" + echo "PREFIX=$PREFIX" + echo "REGIONS=$REGIONS" + echo "AW_REGION=$AW_REGION" + echo "TENANT_ENVIRONMENTS=$TENANT_ENVIRONMENTS" + echo "EXTERNAL_DIRECTORY_CUSTOMER_IDS=$EXTERNAL_DIRECTORY_CUSTOMER_IDS" + echo "EXTERNAL_ORGANIZATION_IDS=$EXTERNAL_ORGANIZATION_IDS" + echo "TOP_LEVEL_FOLDER_NAME=$TOP_LEVEL_FOLDER_NAME" + echo "TOP_LEVEL_FOLDER_ID=$TOP_LEVEL_FOLDER_ID" + echo "CI_PROJECT_PATH=$CI_PROJECT_PATH" + echo "CI_COMMIT_BRANCH=$CI_COMMIT_BRANCH" + echo "GITLAB_URL=$GITLAB_URL" + echo "JWKS_KEY=$JWKS_KEY" + } > "$SCRIPT_DIR"/config.env + else + # shellcheck source=automation/config.env.sample + source "$SCRIPT_DIR"/config.env + echo "------------------------------------------------------------------" + echo "config.env" + cat config.env + echo -e "\n------------------------------------------------------------------" + echo "If the above does not look correct your config.env may be wrong!" + fi + + # Mapping abbreviations + COMPLIANCE_REGIME_ABBREVIATION=$(compliance_regime_mapping "${COMPLIANCE_REGIME}") + + export PROJ="automation-project" + RAW_PROJ_NAME=$(yq '.projects[] | select(.name == env(PROJ)) | .project_name' ../project-config.yml) + PROJ_NAME="${RAW_PROJ_NAME///$PREFIX}" + PROJ_NAME="${PROJ_NAME///$COMPLIANCE_REGIME_ABBREVIATION}" + promptUser "Would you like to set your default project to ${PROJ_NAME}?" "gcloud config set project ${PROJ_NAME}" + + # if promptUser "Would you to set your IAM permissions?"; then + # "${SCRIPT_DIR}"/../fast/stages-aw/0-organization-bootstrap/setIam.sh "${DEPLOYER_EMAIL_ADDRESS}" "${ORGANIZATION_ID}" + # fi + + if promptUser "Would you like to disable org policies to allow for deletion?"; then + # gcloud org-policies delete-custom-constraint custom.kmsRotation"${PREFIX}" --organization="${ORGANIZATION_ID}" + gcloud resource-manager org-policies disable-enforce compute.requireOsLogin --folder="${TOP_LEVEL_FOLDER_ID}" + echo "Sleeping for 60 seconds to allow disabling policies to take effect" + sleep 60 + fi +else + # shellcheck source=automation/config.env.sample + source "$SCRIPT_DIR"/config.env + echo "------------------------------------------------------------------" + echo "${SCRIPT_DIR}/config.env" + cat "${SCRIPT_DIR}"/config.env + echo -e "\n------------------------------------------------------------------" + echo "If the above does not look correct your config.env may be wrong!" + + COMPLIANCE_REGIME_ABBREVIATION=$(compliance_regime_mapping "${COMPLIANCE_REGIME}") +fi + +# Convert REGIONS from a string to an array +IFS=',' read -r -a REGIONS_ARRAY <<< "$REGIONS" +REGIONS_CONFIG=$(printf '%s", "' "${REGIONS_ARRAY[@]}" | sed 's/", "$//') +REGIONS_CONFIG="[\"$REGIONS_CONFIG\"]" + +########### Stage 4 - Security ############ +echo -e "\n#######################################################" +echo "#######################################################" +echo "#######################################################" + +if promptUser "Stage 4 - Security"; then + cd "${SCRIPT_DIR}"/../fast/stages-aw/4-security || exit + + # if promptUser "Would you like to restore your bootstrap project if it was deleted?"; then + # gcloud projects undelete "${BOOTSTRAP_PROJECT_ID}" + # sleep 60 + # gcloud billing projects link "${BOOTSTRAP_PROJECT_ID}" --billing-account="${BILLING_ACCOUNT}" + # fi + + if promptUser "Would you like to pull the remote tfvars files created in Stages 0 and 1?"; then + gcloud storage cp gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-outputs/providers/4-security-providers.tf ./ + gcloud storage cp gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-outputs/tfvars/1-globals.auto.tfvars.json ./ + gcloud storage cp gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-outputs/tfvars/1-assured-workload.auto.tfvars.json ./ + gcloud storage cp gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-outputs/tfvars/2-resman.auto.tfvars.json ./ + fi + + if promptUser "Would you like to re-enable disabled Service Accounts?"; then + ./sa_lockdown.sh --enable + sleep 30 + fi + + promptUser "Would you like to perform the terraform init?" "terraform init" + promptUser "Would you like to run terraform destroy?" "terraform destroy" + promptUser "Would you like to delete your .terraform dir?" "rm -r .terraform" + + export PROJ="automation-project" + RAW_PROJ_NAME=$(yq '.projects[] | select(.name == env(PROJ)) | .project_name' "${SCRIPT_DIR}"/../project-config.yml) + PROJ_NAME="${RAW_PROJ_NAME///$PREFIX}" + PROJ_NAME="${PROJ_NAME///$COMPLIANCE_REGIME_ABBREVIATION}" +fi + +########## Stage 3 - Networking ############ +echo -e "\n#######################################################" +echo "#######################################################" +echo "#######################################################" + +if promptUser "Stage 3 - Networking"; then + + cd "${SCRIPT_DIR}"/../fast/stages-aw/3-networking || exit + + if promptUser "Would you like to pull the remote tfvars files created in Stages 0 and 1?"; then + gcloud storage cp gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-outputs/providers/3-networking-providers.tf ./ + gcloud storage cp gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-outputs/tfvars/1-globals.auto.tfvars.json ./ + gcloud storage cp gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-outputs/tfvars/1-assured-workload.auto.tfvars.json ./ + gcloud storage cp gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-outputs/tfvars/2-resman.auto.tfvars.json ./ + gcloud storage cp gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-outputs/tfvars/3-networking.auto.tfvars.json ./ # TESTING + fi + + promptUser "Would you like to perform the terraform init?" "terraform init" + promptUser "Would you like to generate your hierarchical-ingress-rules.yml file?" "terraform apply -target=local_file.generated_ingress_rule" + promptUser "Would you like to run terraform destroy?" "terraform destroy" + promptUser "If you receive a peering error, would you like to rerun terraform destroy?" "terraform destroy" + promptUser "Would you like to delete your .terraform dir?" "rm -r .terraform" + + export PROJ="automation-project" + RAW_PROJ_NAME=$(yq '.projects[] | select(.name == env(PROJ)) | .project_name' "${SCRIPT_DIR}"/../project-config.yml) + PROJ_NAME="${RAW_PROJ_NAME///$PREFIX}" + PROJ_NAME="${PROJ_NAME///$COMPLIANCE_REGIME_ABBREVIATION}" +fi + + +########### Stage 2 - Resman ############ +echo -e "\n#######################################################" +echo "#######################################################" +echo "#######################################################" + +if promptUser "Stage 2 - Resource Manager"; then # Left Here + cd "${SCRIPT_DIR}"/../fast/stages-aw/2-resman || exit + + if promptUser "Would you like to pull the remote tfvars files created in Stage 0?"; then + gcloud storage cp gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-outputs/providers/2-resman-providers.tf ./ + gcloud storage cp gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-outputs/tfvars/1-globals.auto.tfvars.json ./ + gcloud storage cp gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-outputs/tfvars/1-assured-workload.auto.tfvars.json ./ + gcloud storage cp gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-outputs/tfvars/2-resman.auto.tfvars.json ./ ### TESTING - Find something similar for networking deletion + fi + + promptUser "Would you like to perform the terraform init?" "terraform init" + + if promptUser "Would you like to remove all storage buckets?"; then + terraform state rm "module.branch-security-gcs.google_storage_bucket.bucket[0]" \ + "module.branch-network-gcs.google_storage_bucket.bucket[0]" + sleep 2 + + gcloud storage rm -r gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-resman-sec + gcloud storage rm -r gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-resman-net-0 + fi + promptUser "Would you like to run terraform destroy?" "terraform destroy -lock=false" + + # if promptUser "If you received an error for TagValues, would you like to delete all child tags?"; then + # read -r -p "Please enter the TagValue from the above error - numbers only" TAG + # gcloud resource-manager tags values delete tagValues/"${TAG}" + # terraform destroy + # fi + + promptUser "Would you like to delete your .terraform dir?" "rm -r .terraform" +fi + +########### Stage 1 - Assured Workload ############ +echo -e "\n#######################################################" +echo "#######################################################" +echo "#######################################################" + + +if promptUser "Stage 1 - Assured Workload"; then + cd "${SCRIPT_DIR}"/../fast/stages-aw/1-assured-workload || exit + + if promptUser "Would you like to pull the remote tfvars files created in Stage 1?"; then + gcloud storage cp gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-outputs/providers/1-assured-workload-providers.tf ./ + gcloud storage cp gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-inputs/stage-1/stage-1-inputs.auto.tfvars.json ./ + fi + + if promptUser "Would you like to set the bootstrap project as your default project?"; then + gcloud config set project "${BOOTSTRAP_PROJECT_ID}" + fi + + if promptUser "Would you like to copy the remote state to your local device, revert your providers, and migrate to the local state?"; then + gcloud storage cp gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-bootstrap/default.tfstate ./terraform.tfstate + cp providers.tf.tmp 1-assured-workload-providers.tf + terraform init -migrate-state + fi + + if promptUser "Would you to set your IAM permissions?"; then + "${SCRIPT_DIR}"/../fast/stages-aw/0-organization-bootstrap/setIam.sh "${DEPLOYER_EMAIL_ADDRESS}" "${ORGANIZATION_ID}" + fi + + if promptUser "Would you like to delete storage buckets?"; then + terraform state rm 'module.automation-tf-bootstrap-gcs.google_storage_bucket.bucket[0]' \ + 'module.automation-tf-output-gcs.google_storage_bucket.bucket[0]' \ + 'module.automation-tf-resman-gcs.google_storage_bucket.bucket[0]' \ + 'module.automation-tf-inputs-gcs.google_storage_bucket.bucket[0]' \ + 'module.automation-tf-config-gcs[0].google_storage_bucket.bucket[0]' \ + 'module.automation-tf-tenant-gcs.google_storage_bucket.bucket[0]' + sleep 2 + + gcloud storage rm -r gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-outputs + gcloud storage rm -r gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-bootstrap + gcloud storage rm -r gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-inputs + gcloud storage rm -r gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-config-0 + gcloud storage rm -r gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-config + gcloud storage rm -r gs://"${PREFIX}"-"${COMPLIANCE_REGIME_ABBREVIATION}"-prod-iac-core-tenants + fi + + if promptUser "Would you like to run terraform destroy?"; then + terraform destroy -var bootstrap_user="$(gcloud config list --format 'value(core.account)')" + fi + + if promptUser "Did you receive any errors deleting projects or Assured Workloads resources?"; then + "${SCRIPT_DIR}"/../fast/stages-aw/0-organization-bootstrap/setIam.sh "${DEPLOYER_EMAIL_ADDRESS}" "${ORGANIZATION_ID}" + sleep 60 + terraform destroy + fi + + ### Keeping the below in for reference + # if promptUser "Did you receive any errors deleting projects"; then + # "${SCRIPT_DIR}"/../fast/stages-aw/0-organization-bootstrap/setIam.sh "${DEPLOYER_EMAIL_ADDRESS}" "${ORGANIZATION_ID}" + # gcloud projects delete "${PREFIX}"-prod-audit-logs-0 + # gcloud projects delete "${PREFIX}"-prod-iac-core-0 + # fi + + # if promptUser "Did you receive any errors deleting Assured Workloads?"; then + # "${SCRIPT_DIR}"/../fast/stages-aw/0-organization-bootstrap/setIam.sh "${DEPLOYER_EMAIL_ADDRESS}" "${ORGANIZATION_ID}" + + # aw_folder=$(gcloud resource-manager folders list --organization="${ORGANIZATION_ID}" | grep stellar-engine-"${PREFIX}" | awk '{print $3}') + # common_folder=$(gcloud resource-manager folders list --folder="${aw_folder}" --format='value(ID)') + # aw_environment=$(gcloud assured workloads list \ + # --organization="${ORGANIZATION_ID}" \ + # --location=us-east4 \ + # --format='value(name)' 2>/dev/null) + + # gcloud resource-manager folders delete "${common_folder}" + # gcloud resource-manager folders delete "${aw_folder}" + # echo 'Waiting 2 minutes to ensure child folders and projects are properly deleted, then deleting the Assured Workloads Environment' + # sleep 120 + # gcloud assured workloads delete "${aw_environment}" + # fi + + if promptUser "Would you like to delete your .terraform dir?"; then + rm -r .terraform + fi + + if promptUser "Would you like to delete your .tfstate?"; then + rm terraform.tfstate* + fi +fi + +########### Stage 0 - Organization ############ +echo -e "\n#######################################################" +echo "#######################################################" +echo "#######################################################" + + +if promptUser "Stage 0 - Organization -"; then + cd "${SCRIPT_DIR}"/../fast/stages-aw/0-organization-bootstrap || exit + + # Check for remaining AW folders + echo "Checking for other Assured Workloads in the folder ${TOP_LEVEL_FOLDER_ID}" + AW_COUNT=$(gcloud resource-manager folders list --folder="${TOP_LEVEL_FOLDER_ID}" --format="value(display_name)" | grep -Ec "CRU-|FRH-|IL2-|IL4-|IL5-") + + if [[ "$AW_COUNT" -gt 0 ]]; then + echo "There are still other Assured Workload folders deployed to this organization. Please run this script against the remaining Assured Workloads those before running this step." + exit + fi + TOP_LEVEL_FOLDER_NAME_LOWER=$(echo "$TOP_LEVEL_FOLDER_NAME" | tr '[:upper:]' '[:lower:]') + if promptUser "Would you like to pull the remote providers file created in Stage 0 and initialize the remote bucket?"; then + gcloud storage cp gs://"${TOP_LEVEL_FOLDER_NAME_LOWER}"-org-iac-bootstrap/tfvars/stage-0-inputs.auto.tfvars.json ./ + gcloud storage cp gs://"${TOP_LEVEL_FOLDER_NAME_LOWER}"-org-iac-bootstrap/providers/0-organization-bootstrap-providers.tf ./ + terraform init + fi + + if promptUser "Would you like to copy the remote state to your local device, revert your providers, and migrate to the local state?"; then + gcloud storage cp gs://"${TOP_LEVEL_FOLDER_NAME_LOWER}"-org-iac/terraform/state/default.tfstate ./terraform.tfstate + cp providers.tf.tmp 0-organization-bootstrap-providers.tf + terraform init -migrate-state + fi + + + if promptUser "Would you like to delete storage buckets?"; then + terraform state rm 'module.lz-logs-bootstrap-gcs.google_storage_bucket.bucket[0]' \ + 'module.lz-logs-state-gcs.google_storage_bucket.bucket[0]' + sleep 2 + + gcloud storage rm -r gs://"${TOP_LEVEL_FOLDER_NAME_LOWER}"-org-iac-bootstrap + gcloud storage rm -r gs://"${TOP_LEVEL_FOLDER_NAME_LOWER}"-org-iac + fi + + if promptUser "Would you like to run terraform destroy?"; then + terraform destroy + fi +fi + +if promptUser "Would you like re-enable compute.requireOsLogin?"; then + gcloud resource-manager org-policies enable-enforce compute.requireOsLogin --organization="${ORGANIZATION_ID}" +fi + +if promptUser "Would you like to remove your gcloud configuration?"; then + gcloud auth revoke "${DEPLOYER_EMAIL_ADDRESS}" +fi + +echo -e "\nCongratulations! You have deleted your environment. Please run clean.sh if you are still running into issues." + +# TODO - Remove user permissions +# Keep these +# Organization Policy Administrator +# Organization Role Administrator +# Service Account Admin diff --git a/blueprints/README.md b/blueprints/README.md index 80b61b0ac..d29a0c83f 100644 --- a/blueprints/README.md +++ b/blueprints/README.md @@ -1,3 +1,19 @@ + + # Terraform End-to-End Blueprints for Google Cloud This repository contains Terraform Blueprints for Google Cloud, designed to accelerate the deployment of various Google Cloud services. The table below provides a comprehensive list of available blueprints, indicating their applicability for FedRAMP High (FRH) and/or Impact Level 5 (IL5) compliance regimes. Each blueprint name links directly to its respective folder containing detailed documentation and Terraform code. diff --git a/blueprints/fedramp-high/access-context-manager/README.md b/blueprints/fedramp-high/access-context-manager/README.md index ece9a5db8..5e19da848 100644 --- a/blueprints/fedramp-high/access-context-manager/README.md +++ b/blueprints/fedramp-high/access-context-manager/README.md @@ -1,3 +1,19 @@ + + # Access Control Manager diff --git a/blueprints/fedramp-high/access-context-manager/main.tf b/blueprints/fedramp-high/access-context-manager/main.tf index 2add1e2cb..322c1ea75 100644 --- a/blueprints/fedramp-high/access-context-manager/main.tf +++ b/blueprints/fedramp-high/access-context-manager/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ module "access_context_manager" { source = "../../../modules/access-context-manager" diff --git a/blueprints/fedramp-high/access-context-manager/outputs.tf b/blueprints/fedramp-high/access-context-manager/outputs.tf index 0c946e571..7171d3f54 100644 --- a/blueprints/fedramp-high/access-context-manager/outputs.tf +++ b/blueprints/fedramp-high/access-context-manager/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "access_levels" { description = "The list of created access levels with their details." diff --git a/blueprints/fedramp-high/access-context-manager/provider.tf b/blueprints/fedramp-high/access-context-manager/provider.tf index 5b34969e1..d59c5acd9 100644 --- a/blueprints/fedramp-high/access-context-manager/provider.tf +++ b/blueprints/fedramp-high/access-context-manager/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/fedramp-high/access-context-manager/terraform.tfvars.sample b/blueprints/fedramp-high/access-context-manager/terraform.tfvars.sample index 780ca49f9..08af349ce 100644 --- a/blueprints/fedramp-high/access-context-manager/terraform.tfvars.sample +++ b/blueprints/fedramp-high/access-context-manager/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + organization_id = "1234567890" domain = "your-company.com" region = "us-central1" diff --git a/blueprints/fedramp-high/access-context-manager/variables.tf b/blueprints/fedramp-high/access-context-manager/variables.tf index ec4673fdb..8090ff552 100644 --- a/blueprints/fedramp-high/access-context-manager/variables.tf +++ b/blueprints/fedramp-high/access-context-manager/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "access_levels" { description = "List of access levels to create. Each access level is a map containing 'name', 'description', and 'conditions'." diff --git a/blueprints/fedramp-high/app-engine/README.md b/blueprints/fedramp-high/app-engine/README.md index 7342bfa1d..d028a6bd7 100644 --- a/blueprints/fedramp-high/app-engine/README.md +++ b/blueprints/fedramp-high/app-engine/README.md @@ -1,3 +1,19 @@ + + # App Engine diff --git a/blueprints/fedramp-high/app-engine/main.tf b/blueprints/fedramp-high/app-engine/main.tf index e23125405..86841414c 100644 --- a/blueprints/fedramp-high/app-engine/main.tf +++ b/blueprints/fedramp-high/app-engine/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ module "app-engine" { source = "../../../modules/app-engine" diff --git a/blueprints/fedramp-high/app-engine/outputs.tf b/blueprints/fedramp-high/app-engine/outputs.tf index 6d215b57e..90eaada9d 100644 --- a/blueprints/fedramp-high/app-engine/outputs.tf +++ b/blueprints/fedramp-high/app-engine/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "app_id" { value = module.app-engine.app_id diff --git a/blueprints/fedramp-high/app-engine/provider.tf b/blueprints/fedramp-high/app-engine/provider.tf index 1883e0d73..ee0f59cb7 100644 --- a/blueprints/fedramp-high/app-engine/provider.tf +++ b/blueprints/fedramp-high/app-engine/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/fedramp-high/app-engine/terraform.tfvars.sample b/blueprints/fedramp-high/app-engine/terraform.tfvars.sample index d610db218..a9044d4c1 100644 --- a/blueprints/fedramp-high/app-engine/terraform.tfvars.sample +++ b/blueprints/fedramp-high/app-engine/terraform.tfvars.sample @@ -1,2 +1,18 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-xxxx-main-0" region = "us-east4" \ No newline at end of file diff --git a/blueprints/fedramp-high/app-engine/variables.tf b/blueprints/fedramp-high/app-engine/variables.tf index 9e012568a..5b9b2b20a 100644 --- a/blueprints/fedramp-high/app-engine/variables.tf +++ b/blueprints/fedramp-high/app-engine/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "main_project_id" { description = "Main project ID." diff --git a/blueprints/fedramp-high/beyondcorp/README.md b/blueprints/fedramp-high/beyondcorp/README.md index 68948c987..34f9f5558 100644 --- a/blueprints/fedramp-high/beyondcorp/README.md +++ b/blueprints/fedramp-high/beyondcorp/README.md @@ -1,3 +1,19 @@ + + ## Introduction to BeyondCorp BeyondCorp is Google Cloud's zero-trust network security framework, enabling secure access to applications and resources without relying on traditional VPNs. diff --git a/blueprints/fedramp-high/beyondcorp/main.tf b/blueprints/fedramp-high/beyondcorp/main.tf index 6b2030239..a7097a2a5 100644 --- a/blueprints/fedramp-high/beyondcorp/main.tf +++ b/blueprints/fedramp-high/beyondcorp/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ module "beyondcorp" { source = "../../../modules/beyondcorp" diff --git a/blueprints/fedramp-high/beyondcorp/outputs.tf b/blueprints/fedramp-high/beyondcorp/outputs.tf index 2b0212f81..464e45071 100644 --- a/blueprints/fedramp-high/beyondcorp/outputs.tf +++ b/blueprints/fedramp-high/beyondcorp/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "endpoint_name" { description = "Name of the endpoint that was created." diff --git a/blueprints/fedramp-high/beyondcorp/provider.tf b/blueprints/fedramp-high/beyondcorp/provider.tf index 9d85cb3aa..72ff648d7 100644 --- a/blueprints/fedramp-high/beyondcorp/provider.tf +++ b/blueprints/fedramp-high/beyondcorp/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/fedramp-high/beyondcorp/terraform.tfvars.sample b/blueprints/fedramp-high/beyondcorp/terraform.tfvars.sample index 3276be368..48bd1ffcb 100644 --- a/blueprints/fedramp-high/beyondcorp/terraform.tfvars.sample +++ b/blueprints/fedramp-high/beyondcorp/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + organization_id = "xxxxxxxxxxxx" main_project_id = "xxxx-xxxx-xxxx-main-0" diff --git a/blueprints/fedramp-high/beyondcorp/variables.tf b/blueprints/fedramp-high/beyondcorp/variables.tf index 9e6e9233d..f7b127f86 100644 --- a/blueprints/fedramp-high/beyondcorp/variables.tf +++ b/blueprints/fedramp-high/beyondcorp/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "endpoint_name" { description = "Name for endpoint." diff --git a/blueprints/fedramp-high/bigtable/README.md b/blueprints/fedramp-high/bigtable/README.md index 1c9990c70..3ecbc77ea 100644 --- a/blueprints/fedramp-high/bigtable/README.md +++ b/blueprints/fedramp-high/bigtable/README.md @@ -1,3 +1,19 @@ + + # Bigtable diff --git a/blueprints/fedramp-high/bigtable/main.tf b/blueprints/fedramp-high/bigtable/main.tf index d90016770..11fdb84b3 100644 --- a/blueprints/fedramp-high/bigtable/main.tf +++ b/blueprints/fedramp-high/bigtable/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ data "google_project" "project" {} diff --git a/blueprints/fedramp-high/bigtable/outputs.tf b/blueprints/fedramp-high/bigtable/outputs.tf index 144ca9aac..37c9cfcc7 100644 --- a/blueprints/fedramp-high/bigtable/outputs.tf +++ b/blueprints/fedramp-high/bigtable/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "bigtable_service_identity_email" { description = "The email of the Bigtable Service Identity." diff --git a/blueprints/fedramp-high/bigtable/provider.tf b/blueprints/fedramp-high/bigtable/provider.tf index b1661f133..bfba739c4 100644 --- a/blueprints/fedramp-high/bigtable/provider.tf +++ b/blueprints/fedramp-high/bigtable/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/fedramp-high/bigtable/terraform.tfvars.sample b/blueprints/fedramp-high/bigtable/terraform.tfvars.sample index 2854f4772..ef2d7e332 100644 --- a/blueprints/fedramp-high/bigtable/terraform.tfvars.sample +++ b/blueprints/fedramp-high/bigtable/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-xxxx-main-0" core_project_id = "xxxx-xxxx-xxxx-iac-core-0" diff --git a/blueprints/fedramp-high/bigtable/variables.tf b/blueprints/fedramp-high/bigtable/variables.tf index fad46aee2..da706d95b 100644 --- a/blueprints/fedramp-high/bigtable/variables.tf +++ b/blueprints/fedramp-high/bigtable/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "auto_delete" { description = "Persistent Disk auto delete options." diff --git a/blueprints/fedramp-high/cloud-armor/README.md b/blueprints/fedramp-high/cloud-armor/README.md index 6b9499eb4..e74da59e7 100644 --- a/blueprints/fedramp-high/cloud-armor/README.md +++ b/blueprints/fedramp-high/cloud-armor/README.md @@ -1,3 +1,19 @@ + + # Google Cloud Armor diff --git a/blueprints/fedramp-high/cloud-armor/main.tf b/blueprints/fedramp-high/cloud-armor/main.tf index b180baec7..3f7750042 100644 --- a/blueprints/fedramp-high/cloud-armor/main.tf +++ b/blueprints/fedramp-high/cloud-armor/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { file = yamldecode(file(var.rules_file)) diff --git a/blueprints/fedramp-high/cloud-armor/outputs.tf b/blueprints/fedramp-high/cloud-armor/outputs.tf index b681c0e7b..9ed6370fa 100644 --- a/blueprints/fedramp-high/cloud-armor/outputs.tf +++ b/blueprints/fedramp-high/cloud-armor/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "policies" { description = "All created policy resources." value = google_compute_region_security_policy.policy diff --git a/blueprints/fedramp-high/cloud-armor/provider.tf b/blueprints/fedramp-high/cloud-armor/provider.tf index e8f900b4f..96e6d0614 100644 --- a/blueprints/fedramp-high/cloud-armor/provider.tf +++ b/blueprints/fedramp-high/cloud-armor/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/fedramp-high/cloud-armor/rules.yaml b/blueprints/fedramp-high/cloud-armor/rules.yaml index 89c00ffa9..f02583a99 100644 --- a/blueprints/fedramp-high/cloud-armor/rules.yaml +++ b/blueprints/fedramp-high/cloud-armor/rules.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + gitlab-waf-policy: #Policy name description: WAF Policy tested for protecting GitLab for FEDRAMP High compliance rules: #List of rules in order of priority diff --git a/blueprints/fedramp-high/cloud-armor/terraform.tfvars.sample b/blueprints/fedramp-high/cloud-armor/terraform.tfvars.sample index 22434ba54..88df87890 100644 --- a/blueprints/fedramp-high/cloud-armor/terraform.tfvars.sample +++ b/blueprints/fedramp-high/cloud-armor/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-xxxx-main-0" region = "us-east4" rules_file = "rules.yaml" \ No newline at end of file diff --git a/blueprints/fedramp-high/cloud-armor/variables.tf b/blueprints/fedramp-high/cloud-armor/variables.tf index 33cb04d94..e9fb880d6 100644 --- a/blueprints/fedramp-high/cloud-armor/variables.tf +++ b/blueprints/fedramp-high/cloud-armor/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "main_project_id" { description = "Main project ID for Cloud Armor policies." diff --git a/blueprints/fedramp-high/cloud-composer-environment/README.md b/blueprints/fedramp-high/cloud-composer-environment/README.md index 3d32718cb..f2bc3ecc7 100644 --- a/blueprints/fedramp-high/cloud-composer-environment/README.md +++ b/blueprints/fedramp-high/cloud-composer-environment/README.md @@ -1,3 +1,19 @@ + + # Cloud Composer diff --git a/blueprints/fedramp-high/cloud-composer-environment/iam.tf b/blueprints/fedramp-high/cloud-composer-environment/iam.tf index 5880f16c2..42fcf10c4 100644 --- a/blueprints/fedramp-high/cloud-composer-environment/iam.tf +++ b/blueprints/fedramp-high/cloud-composer-environment/iam.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ resource "google_project_iam_member" "composer_worker" { project = var.main_project_id diff --git a/blueprints/fedramp-high/cloud-composer-environment/main.tf b/blueprints/fedramp-high/cloud-composer-environment/main.tf index 4262b04ef..27d1b1486 100644 --- a/blueprints/fedramp-high/cloud-composer-environment/main.tf +++ b/blueprints/fedramp-high/cloud-composer-environment/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ data "google_project" "current" { project_id = var.main_project_id diff --git a/blueprints/fedramp-high/cloud-composer-environment/outputs.tf b/blueprints/fedramp-high/cloud-composer-environment/outputs.tf index 9a896f6cc..9ce4d3675 100644 --- a/blueprints/fedramp-high/cloud-composer-environment/outputs.tf +++ b/blueprints/fedramp-high/cloud-composer-environment/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "airflow_uri" { value = google_composer_environment.main.config[0].airflow_uri diff --git a/blueprints/fedramp-high/cloud-composer-environment/provider.tf b/blueprints/fedramp-high/cloud-composer-environment/provider.tf index d155278b8..e58e2e590 100644 --- a/blueprints/fedramp-high/cloud-composer-environment/provider.tf +++ b/blueprints/fedramp-high/cloud-composer-environment/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/fedramp-high/cloud-composer-environment/terraform.tfvars.sample b/blueprints/fedramp-high/cloud-composer-environment/terraform.tfvars.sample index 358b9831e..87feef010 100644 --- a/blueprints/fedramp-high/cloud-composer-environment/terraform.tfvars.sample +++ b/blueprints/fedramp-high/cloud-composer-environment/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-xxxx-main-0" network_project_id = "xxxx-xxxx-net-host" diff --git a/blueprints/fedramp-high/cloud-composer-environment/variables.tf b/blueprints/fedramp-high/cloud-composer-environment/variables.tf index f40713a6f..11770bfa1 100644 --- a/blueprints/fedramp-high/cloud-composer-environment/variables.tf +++ b/blueprints/fedramp-high/cloud-composer-environment/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "composer_env_name" { diff --git a/blueprints/fedramp-high/cloud-functions/README.md b/blueprints/fedramp-high/cloud-functions/README.md index bca93362f..8f47b807a 100644 --- a/blueprints/fedramp-high/cloud-functions/README.md +++ b/blueprints/fedramp-high/cloud-functions/README.md @@ -1,3 +1,19 @@ + + # Cloud Functions This blueprint deploys a 2nd Generation Cloud Function. The Cloud Function Module and resource do not have the ability to set the binary authorization to default, so the only way around this is to deploy the cloud function with the gcloud command. diff --git a/blueprints/fedramp-high/cloud-functions/main.tf b/blueprints/fedramp-high/cloud-functions/main.tf index e1bcc8b8d..96987e484 100644 --- a/blueprints/fedramp-high/cloud-functions/main.tf +++ b/blueprints/fedramp-high/cloud-functions/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ data "google_project" "current" { project_id = var.main_project_id diff --git a/blueprints/fedramp-high/cloud-functions/outputs.tf b/blueprints/fedramp-high/cloud-functions/outputs.tf index a27fdf15d..5aba05bab 100644 --- a/blueprints/fedramp-high/cloud-functions/outputs.tf +++ b/blueprints/fedramp-high/cloud-functions/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "artifact_registry_iam_member" { description = "IAM member assigned to roles/artifactregistry.createOnPushWriter." diff --git a/blueprints/fedramp-high/cloud-functions/provider.tf b/blueprints/fedramp-high/cloud-functions/provider.tf index 570abf718..8c273e482 100644 --- a/blueprints/fedramp-high/cloud-functions/provider.tf +++ b/blueprints/fedramp-high/cloud-functions/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/fedramp-high/cloud-functions/terraform.tfvars.sample b/blueprints/fedramp-high/cloud-functions/terraform.tfvars.sample index 4f3be833d..be7f00848 100644 --- a/blueprints/fedramp-high/cloud-functions/terraform.tfvars.sample +++ b/blueprints/fedramp-high/cloud-functions/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-xxxx-main-0" function_name = "function-name-00" diff --git a/blueprints/fedramp-high/cloud-functions/variables.tf b/blueprints/fedramp-high/cloud-functions/variables.tf index 9186fed2f..1d9bac421 100644 --- a/blueprints/fedramp-high/cloud-functions/variables.tf +++ b/blueprints/fedramp-high/cloud-functions/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "artifact_registry_name" { description = "Name of the Artifact Registry being deployed." diff --git a/blueprints/fedramp-high/cloud-ids/README.md b/blueprints/fedramp-high/cloud-ids/README.md index 023e4d8da..de89fa43d 100644 --- a/blueprints/fedramp-high/cloud-ids/README.md +++ b/blueprints/fedramp-high/cloud-ids/README.md @@ -1,3 +1,19 @@ + + # Cloud IDS diff --git a/blueprints/fedramp-high/cloud-ids/main.tf b/blueprints/fedramp-high/cloud-ids/main.tf index 348c94ff6..9e01cb994 100644 --- a/blueprints/fedramp-high/cloud-ids/main.tf +++ b/blueprints/fedramp-high/cloud-ids/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ resource "google_project_service" "net-host-services" { project = var.network_project_id diff --git a/blueprints/fedramp-high/cloud-ids/outputs.tf b/blueprints/fedramp-high/cloud-ids/outputs.tf index 078eb456e..078819416 100644 --- a/blueprints/fedramp-high/cloud-ids/outputs.tf +++ b/blueprints/fedramp-high/cloud-ids/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "ids_name" { description = "The name of the Cloud IDS instance." diff --git a/blueprints/fedramp-high/cloud-ids/providers.tf b/blueprints/fedramp-high/cloud-ids/providers.tf index 19ba596d1..87f84d295 100644 --- a/blueprints/fedramp-high/cloud-ids/providers.tf +++ b/blueprints/fedramp-high/cloud-ids/providers.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/fedramp-high/cloud-ids/terraform.tfvars.sample b/blueprints/fedramp-high/cloud-ids/terraform.tfvars.sample index d3a742657..b1bd692ff 100644 --- a/blueprints/fedramp-high/cloud-ids/terraform.tfvars.sample +++ b/blueprints/fedramp-high/cloud-ids/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-xxxx-main-0" network_project_id = "xxxx-xxxx-net-host" diff --git a/blueprints/fedramp-high/cloud-ids/variables.tf b/blueprints/fedramp-high/cloud-ids/variables.tf index 2eccdd933..30a18ece6 100644 --- a/blueprints/fedramp-high/cloud-ids/variables.tf +++ b/blueprints/fedramp-high/cloud-ids/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "ids_name" { description = "Name for IDS." diff --git a/blueprints/fedramp-high/cloud-run/README.md b/blueprints/fedramp-high/cloud-run/README.md index 55991e849..65fe9b00e 100644 --- a/blueprints/fedramp-high/cloud-run/README.md +++ b/blueprints/fedramp-high/cloud-run/README.md @@ -1,3 +1,19 @@ + + # Cloud Run diff --git a/blueprints/fedramp-high/cloud-run/main.tf b/blueprints/fedramp-high/cloud-run/main.tf index 9cade1cc1..9b8dfb3b6 100644 --- a/blueprints/fedramp-high/cloud-run/main.tf +++ b/blueprints/fedramp-high/cloud-run/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ data "google_project" "project" { project_id = var.main_project_id diff --git a/blueprints/fedramp-high/cloud-run/outputs.tf b/blueprints/fedramp-high/cloud-run/outputs.tf index 8b9bca30e..2ddef8116 100644 --- a/blueprints/fedramp-high/cloud-run/outputs.tf +++ b/blueprints/fedramp-high/cloud-run/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "cloud_run" { description = "Cloud Run Service that was created." diff --git a/blueprints/fedramp-high/cloud-run/provider.tf b/blueprints/fedramp-high/cloud-run/provider.tf index 2176c32b6..6dcabd4fb 100644 --- a/blueprints/fedramp-high/cloud-run/provider.tf +++ b/blueprints/fedramp-high/cloud-run/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">=1.0.0" diff --git a/blueprints/fedramp-high/cloud-run/terraform.tfvars.sample b/blueprints/fedramp-high/cloud-run/terraform.tfvars.sample index e687650da..503384363 100644 --- a/blueprints/fedramp-high/cloud-run/terraform.tfvars.sample +++ b/blueprints/fedramp-high/cloud-run/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-xxxx-main-0" core_project_id = "xxxx-xxxx-xxxx-iac-core-0" diff --git a/blueprints/fedramp-high/cloud-run/variables.tf b/blueprints/fedramp-high/cloud-run/variables.tf index 7553695ee..69af884d4 100644 --- a/blueprints/fedramp-high/cloud-run/variables.tf +++ b/blueprints/fedramp-high/cloud-run/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "binary_authorization_mode" { description = "Binary Authorization mode for the Cloud Run service." diff --git a/blueprints/fedramp-high/cloud-scheduler-job/README.md b/blueprints/fedramp-high/cloud-scheduler-job/README.md index 290dcd5f2..6150a32a0 100644 --- a/blueprints/fedramp-high/cloud-scheduler-job/README.md +++ b/blueprints/fedramp-high/cloud-scheduler-job/README.md @@ -1,3 +1,19 @@ + + # Cloud Scheduler Job Blueprint This blueprint schedules a cron job to publish messages to an *existing* Google Cloud Pub/Sub topic. diff --git a/blueprints/fedramp-high/cloud-scheduler-job/main.tf b/blueprints/fedramp-high/cloud-scheduler-job/main.tf index d5722a9cd..8f15dce93 100644 --- a/blueprints/fedramp-high/cloud-scheduler-job/main.tf +++ b/blueprints/fedramp-high/cloud-scheduler-job/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ data "google_project" "current" { project_id = var.main_project_id diff --git a/blueprints/fedramp-high/cloud-scheduler-job/outputs.tf b/blueprints/fedramp-high/cloud-scheduler-job/outputs.tf index 1aee02ad3..33d704f0f 100644 --- a/blueprints/fedramp-high/cloud-scheduler-job/outputs.tf +++ b/blueprints/fedramp-high/cloud-scheduler-job/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "id" { description = "Job ID." diff --git a/blueprints/fedramp-high/cloud-scheduler-job/provider.tf b/blueprints/fedramp-high/cloud-scheduler-job/provider.tf index 5a8b3340b..59626538e 100644 --- a/blueprints/fedramp-high/cloud-scheduler-job/provider.tf +++ b/blueprints/fedramp-high/cloud-scheduler-job/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/fedramp-high/cloud-scheduler-job/terraform.tfvars.sample b/blueprints/fedramp-high/cloud-scheduler-job/terraform.tfvars.sample index 3884aba6a..628f94e54 100644 --- a/blueprints/fedramp-high/cloud-scheduler-job/terraform.tfvars.sample +++ b/blueprints/fedramp-high/cloud-scheduler-job/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-main-0" # The Google Cloud Project ID where the Cloud Scheduler job will be created. name = "cloud-scheduler-job-name-00" # Name of the Cloud Scheduler job. diff --git a/blueprints/fedramp-high/cloud-scheduler-job/variables.tf b/blueprints/fedramp-high/cloud-scheduler-job/variables.tf index 21e233050..50f4e58d3 100644 --- a/blueprints/fedramp-high/cloud-scheduler-job/variables.tf +++ b/blueprints/fedramp-high/cloud-scheduler-job/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "data" { description = "The base64-encoded data to be sent as the Pub/Sub message payload." diff --git a/blueprints/fedramp-high/cloud-spanner/README.md b/blueprints/fedramp-high/cloud-spanner/README.md index 6660afdc0..d1346c565 100644 --- a/blueprints/fedramp-high/cloud-spanner/README.md +++ b/blueprints/fedramp-high/cloud-spanner/README.md @@ -1,3 +1,19 @@ + + # Cloud Spanner - [Introduction to Cloud Spanner](#introduction-to-cloud-spanner) diff --git a/blueprints/fedramp-high/cloud-spanner/main.tf b/blueprints/fedramp-high/cloud-spanner/main.tf index 19deed3bb..b3894353f 100644 --- a/blueprints/fedramp-high/cloud-spanner/main.tf +++ b/blueprints/fedramp-high/cloud-spanner/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ resource "google_project_service" "spanner_api" { project = var.main_project_id diff --git a/blueprints/fedramp-high/cloud-spanner/outputs.tf b/blueprints/fedramp-high/cloud-spanner/outputs.tf index c6acd03b4..0f43ddbfe 100644 --- a/blueprints/fedramp-high/cloud-spanner/outputs.tf +++ b/blueprints/fedramp-high/cloud-spanner/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "instance" { description = "Cloud spanner instance." diff --git a/blueprints/fedramp-high/cloud-spanner/provider.tf b/blueprints/fedramp-high/cloud-spanner/provider.tf index 1883e0d73..ee0f59cb7 100644 --- a/blueprints/fedramp-high/cloud-spanner/provider.tf +++ b/blueprints/fedramp-high/cloud-spanner/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/fedramp-high/cloud-spanner/terraform.tfvars.sample b/blueprints/fedramp-high/cloud-spanner/terraform.tfvars.sample index cd0c09181..14d49a229 100644 --- a/blueprints/fedramp-high/cloud-spanner/terraform.tfvars.sample +++ b/blueprints/fedramp-high/cloud-spanner/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-xxxx-main-0" instance_name = "cloud-spanner-instance-name-00" diff --git a/blueprints/fedramp-high/cloud-spanner/variables.tf b/blueprints/fedramp-high/cloud-spanner/variables.tf index be4b9faff..17fd6cfee 100644 --- a/blueprints/fedramp-high/cloud-spanner/variables.tf +++ b/blueprints/fedramp-high/cloud-spanner/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "config_name" { description = "Cloud spanner instance config name." diff --git a/blueprints/fedramp-high/cloud-translation/README.md b/blueprints/fedramp-high/cloud-translation/README.md index 0b35b771a..7d50dfe94 100644 --- a/blueprints/fedramp-high/cloud-translation/README.md +++ b/blueprints/fedramp-high/cloud-translation/README.md @@ -1,3 +1,19 @@ + + # Cloud Translation diff --git a/blueprints/fedramp-high/cloud-translation/code/example.yaml b/blueprints/fedramp-high/cloud-translation/code/example.yaml index 4e2608617..3c9cc4848 100644 --- a/blueprints/fedramp-high/cloud-translation/code/example.yaml +++ b/blueprints/fedramp-high/cloud-translation/code/example.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + main: steps: - init: diff --git a/blueprints/fedramp-high/cloud-translation/main.tf b/blueprints/fedramp-high/cloud-translation/main.tf index 01055407f..5fc00801c 100644 --- a/blueprints/fedramp-high/cloud-translation/main.tf +++ b/blueprints/fedramp-high/cloud-translation/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Enable the API service resource "google_project_service" "translate" { diff --git a/blueprints/fedramp-high/cloud-translation/outputs.tf b/blueprints/fedramp-high/cloud-translation/outputs.tf index f55489a13..f510566c7 100644 --- a/blueprints/fedramp-high/cloud-translation/outputs.tf +++ b/blueprints/fedramp-high/cloud-translation/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "input_bucket" { description = "Bucket that takes documents as input." diff --git a/blueprints/fedramp-high/cloud-translation/provider.tf b/blueprints/fedramp-high/cloud-translation/provider.tf index 4a580dc98..fd3388782 100644 --- a/blueprints/fedramp-high/cloud-translation/provider.tf +++ b/blueprints/fedramp-high/cloud-translation/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/fedramp-high/cloud-translation/terraform.tfvars.sample b/blueprints/fedramp-high/cloud-translation/terraform.tfvars.sample index d321cd193..06efd569c 100644 --- a/blueprints/fedramp-high/cloud-translation/terraform.tfvars.sample +++ b/blueprints/fedramp-high/cloud-translation/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-main-0" region = "us-east4" diff --git a/blueprints/fedramp-high/cloud-translation/variables.tf b/blueprints/fedramp-high/cloud-translation/variables.tf index 0af22aa25..7472d1f46 100644 --- a/blueprints/fedramp-high/cloud-translation/variables.tf +++ b/blueprints/fedramp-high/cloud-translation/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "deletion_protection" { description = "Deletion proteciton." diff --git a/blueprints/fedramp-high/cloud-workstations/README.md b/blueprints/fedramp-high/cloud-workstations/README.md index 538eb9353..acc61fed8 100644 --- a/blueprints/fedramp-high/cloud-workstations/README.md +++ b/blueprints/fedramp-high/cloud-workstations/README.md @@ -1,3 +1,19 @@ + + # Cloud Workstations Blueprint This blueprint demonstrates how to create Workstations on Google Cloud Platform (GCP) with Customer-Managed Encryption Keys (CMEK) using Cloud KMS. diff --git a/blueprints/fedramp-high/cloud-workstations/iam.tf b/blueprints/fedramp-high/cloud-workstations/iam.tf index 0fcbd459c..381f5184c 100644 --- a/blueprints/fedramp-high/cloud-workstations/iam.tf +++ b/blueprints/fedramp-high/cloud-workstations/iam.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ resource "google_service_account" "workstation_config_key_user" { project = var.main_project_id diff --git a/blueprints/fedramp-high/cloud-workstations/main.tf b/blueprints/fedramp-high/cloud-workstations/main.tf index c6933ed46..289832b8b 100644 --- a/blueprints/fedramp-high/cloud-workstations/main.tf +++ b/blueprints/fedramp-high/cloud-workstations/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ locals { landing_project = var.network_project_id == null ? var.main_project_id : var.network_project_id diff --git a/blueprints/fedramp-high/cloud-workstations/outputs.tf b/blueprints/fedramp-high/cloud-workstations/outputs.tf index e8a385728..a0f5206d9 100644 --- a/blueprints/fedramp-high/cloud-workstations/outputs.tf +++ b/blueprints/fedramp-high/cloud-workstations/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "workstation_cluster" { description = "The cluster that was created to host the workstations." diff --git a/blueprints/fedramp-high/cloud-workstations/provider.tf b/blueprints/fedramp-high/cloud-workstations/provider.tf index 4b3f8df3f..97e0ea2c1 100644 --- a/blueprints/fedramp-high/cloud-workstations/provider.tf +++ b/blueprints/fedramp-high/cloud-workstations/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/fedramp-high/cloud-workstations/terraform.tfvars.sample b/blueprints/fedramp-high/cloud-workstations/terraform.tfvars.sample index 14506df58..e0b219500 100644 --- a/blueprints/fedramp-high/cloud-workstations/terraform.tfvars.sample +++ b/blueprints/fedramp-high/cloud-workstations/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-main-0" core_project_id = "xxxx-xxxx-iac-core-0" network_project_id = "xxxx-xxxx-net-host" diff --git a/blueprints/fedramp-high/cloud-workstations/variables.tf b/blueprints/fedramp-high/cloud-workstations/variables.tf index 2422bb42e..4acf30e23 100644 --- a/blueprints/fedramp-high/cloud-workstations/variables.tf +++ b/blueprints/fedramp-high/cloud-workstations/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "cluster_id" { description = "The ID of the workstation cluster." diff --git a/blueprints/fedramp-high/cnap/README.md b/blueprints/fedramp-high/cnap/README.md index dcea70f84..9c014ae91 100644 --- a/blueprints/fedramp-high/cnap/README.md +++ b/blueprints/fedramp-high/cnap/README.md @@ -1,3 +1,19 @@ + + # Cloud Native Access Point This blueprint bootstraps a minimal environment using the concepts for a Cloud Native Access Point and BeyondCorp. For more information about the CNAP, please see the [Department of Defence Cloud Native Access Point Reference Design](https://dodcio.defense.gov/Portals/0/Documents/Library/CNAP_RefDesign_v1.0.pdf). diff --git a/blueprints/fedramp-high/cnap/access_policy.tf b/blueprints/fedramp-high/cnap/access_policy.tf index 7b0ebbb93..8621da93e 100644 --- a/blueprints/fedramp-high/cnap/access_policy.tf +++ b/blueprints/fedramp-high/cnap/access_policy.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ resource "google_access_context_manager_access_levels" "access-levels" { parent = "accessPolicies/${var.access_policy_number}" diff --git a/blueprints/fedramp-high/cnap/cloud_armor.tf b/blueprints/fedramp-high/cnap/cloud_armor.tf index cf8439401..8fda64635 100644 --- a/blueprints/fedramp-high/cnap/cloud_armor.tf +++ b/blueprints/fedramp-high/cnap/cloud_armor.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ locals { waf = yamldecode(file("data/cloudarmor.yaml")) diff --git a/blueprints/fedramp-high/cnap/cloud_ids.tf b/blueprints/fedramp-high/cnap/cloud_ids.tf index 77feae4ad..26ed1bb02 100644 --- a/blueprints/fedramp-high/cnap/cloud_ids.tf +++ b/blueprints/fedramp-high/cnap/cloud_ids.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - module "cloud_ids" { source = "../../../modules/intrusion-detection-system" project = var.network_project_id diff --git a/blueprints/fedramp-high/cnap/cloud_run.tf b/blueprints/fedramp-high/cnap/cloud_run.tf index 546ad16e8..5aa8fcbdc 100644 --- a/blueprints/fedramp-high/cnap/cloud_run.tf +++ b/blueprints/fedramp-high/cnap/cloud_run.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # These Cloud Run services are meant to represent real applications deployed behind the CNAP # This isn't mean to imply that *only* Cloud Run applications can be hosted behind the CNAP diff --git a/blueprints/fedramp-high/cnap/compute_engine.tf b/blueprints/fedramp-high/cnap/compute_engine.tf index 51155a7b9..e7ae3744e 100644 --- a/blueprints/fedramp-high/cnap/compute_engine.tf +++ b/blueprints/fedramp-high/cnap/compute_engine.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - data "google_compute_default_service_account" "default" { project = data.google_project.project.project_id } diff --git a/blueprints/fedramp-high/cnap/data/cloudarmor.yaml b/blueprints/fedramp-high/cnap/data/cloudarmor.yaml index 0475fdd52..dc6ebbc45 100644 --- a/blueprints/fedramp-high/cnap/data/cloudarmor.yaml +++ b/blueprints/fedramp-high/cnap/data/cloudarmor.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + basic_rules: #Rules called basic_rules xss: expression: "xss-v33-stable" # Preconfigured rule name diff --git a/blueprints/fedramp-high/cnap/data/cloudrun.yaml b/blueprints/fedramp-high/cnap/data/cloudrun.yaml index c0b9e37c1..2380f17a3 100644 --- a/blueprints/fedramp-high/cnap/data/cloudrun.yaml +++ b/blueprints/fedramp-high/cnap/data/cloudrun.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + easy: cloud_run_image: "us-docker.pkg.dev/cloudrun/container/hello" members: diff --git a/blueprints/fedramp-high/cnap/data/compute-engine.yaml b/blueprints/fedramp-high/cnap/data/compute-engine.yaml index 0aa00d48b..0381a5005 100644 --- a/blueprints/fedramp-high/cnap/data/compute-engine.yaml +++ b/blueprints/fedramp-high/cnap/data/compute-engine.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + # Terraform will puke if you try to have it parse an empty yaml file --- easy-vm: diff --git a/blueprints/fedramp-high/cnap/iap.tf b/blueprints/fedramp-high/cnap/iap.tf index 06e55b686..bdaf5c42a 100644 --- a/blueprints/fedramp-high/cnap/iap.tf +++ b/blueprints/fedramp-high/cnap/iap.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ resource "google_project_service" "project_service" { diff --git a/blueprints/fedramp-high/cnap/load_balancer.tf b/blueprints/fedramp-high/cnap/load_balancer.tf index ce21bca41..802cc7be3 100644 --- a/blueprints/fedramp-high/cnap/load_balancer.tf +++ b/blueprints/fedramp-high/cnap/load_balancer.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ locals { cr_backends = { for key, _ in try(local.cloud_runs, {}) : key => diff --git a/blueprints/fedramp-high/cnap/main.tf b/blueprints/fedramp-high/cnap/main.tf index 92e3e9d0b..2f7365127 100644 --- a/blueprints/fedramp-high/cnap/main.tf +++ b/blueprints/fedramp-high/cnap/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ locals { diff --git a/blueprints/fedramp-high/cnap/org_policy.tf b/blueprints/fedramp-high/cnap/org_policy.tf index 26c65cfbc..caed7c531 100644 --- a/blueprints/fedramp-high/cnap/org_policy.tf +++ b/blueprints/fedramp-high/cnap/org_policy.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ resource "google_org_policy_policy" "allow_external_lb" { name = "projects/${data.google_project.landing_project.number}/policies/compute.restrictLoadBalancerCreationForTypes" diff --git a/blueprints/fedramp-high/cnap/provider.tf b/blueprints/fedramp-high/cnap/provider.tf index 10a7f0fe3..5fd92d421 100644 --- a/blueprints/fedramp-high/cnap/provider.tf +++ b/blueprints/fedramp-high/cnap/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/fedramp-high/cnap/terraform.tfvars.sample b/blueprints/fedramp-high/cnap/terraform.tfvars.sample index d99a16bc9..620fa9273 100644 --- a/blueprints/fedramp-high/cnap/terraform.tfvars.sample +++ b/blueprints/fedramp-high/cnap/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + domain = "xxxx.example.com" main_project_id = "xxxx-xxxx-xxxx-main-0" diff --git a/blueprints/fedramp-high/cnap/variables.tf b/blueprints/fedramp-high/cnap/variables.tf index ab5df3ff5..0aa10fa22 100644 --- a/blueprints/fedramp-high/cnap/variables.tf +++ b/blueprints/fedramp-high/cnap/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "access_policy_number" { description = "There can only be one Access Policy per GCP Org. Use gcloud access-context-manager policies list --organization to list it." type = number diff --git a/blueprints/fedramp-high/datafusion/README.md b/blueprints/fedramp-high/datafusion/README.md index 8709b0f84..53636e69c 100644 --- a/blueprints/fedramp-high/datafusion/README.md +++ b/blueprints/fedramp-high/datafusion/README.md @@ -1,3 +1,19 @@ + + # Data Fusion diff --git a/blueprints/fedramp-high/datafusion/iam.tf b/blueprints/fedramp-high/datafusion/iam.tf index a71d6dd05..163d4457b 100644 --- a/blueprints/fedramp-high/datafusion/iam.tf +++ b/blueprints/fedramp-high/datafusion/iam.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ resource "google_service_account" "datafusion_sa" { project = var.main_project_id diff --git a/blueprints/fedramp-high/datafusion/main.tf b/blueprints/fedramp-high/datafusion/main.tf index 73433756f..b487ecf69 100644 --- a/blueprints/fedramp-high/datafusion/main.tf +++ b/blueprints/fedramp-high/datafusion/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ data "google_project" "project" { project_id = var.main_project_id diff --git a/blueprints/fedramp-high/datafusion/outputs.tf b/blueprints/fedramp-high/datafusion/outputs.tf index 9e7fde70c..52b6a4042 100644 --- a/blueprints/fedramp-high/datafusion/outputs.tf +++ b/blueprints/fedramp-high/datafusion/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "id" { description = "Fully qualified instance id." diff --git a/blueprints/fedramp-high/datafusion/provider.tf b/blueprints/fedramp-high/datafusion/provider.tf index e17e7b392..c7bf3b90f 100644 --- a/blueprints/fedramp-high/datafusion/provider.tf +++ b/blueprints/fedramp-high/datafusion/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/fedramp-high/datafusion/terraform.tfvars.sample b/blueprints/fedramp-high/datafusion/terraform.tfvars.sample index 5a94820ac..3ef39d559 100644 --- a/blueprints/fedramp-high/datafusion/terraform.tfvars.sample +++ b/blueprints/fedramp-high/datafusion/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-xxxx-main-0" core_project_id = "xxxx-xxxx-xxxx-iac-core-0" network_project_id = "xxxx-xxxx-net-host" diff --git a/blueprints/fedramp-high/datafusion/variables.tf b/blueprints/fedramp-high/datafusion/variables.tf index 4ad55cb8b..1a5c6de62 100644 --- a/blueprints/fedramp-high/datafusion/variables.tf +++ b/blueprints/fedramp-high/datafusion/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "core_project_id" { description = "Core project ID." diff --git a/blueprints/fedramp-high/dataproc-cluster/README.md b/blueprints/fedramp-high/dataproc-cluster/README.md index 069bdcb6e..e828607cf 100644 --- a/blueprints/fedramp-high/dataproc-cluster/README.md +++ b/blueprints/fedramp-high/dataproc-cluster/README.md @@ -1,3 +1,19 @@ + + Copyright 2023 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/blueprints/fedramp-high/dataproc-cluster/iam.tf b/blueprints/fedramp-high/dataproc-cluster/iam.tf index 3bd6f9534..02ce80e6f 100644 --- a/blueprints/fedramp-high/dataproc-cluster/iam.tf +++ b/blueprints/fedramp-high/dataproc-cluster/iam.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ resource "google_project_iam_member" "worker" { project = var.main_project_id diff --git a/blueprints/fedramp-high/dataproc-cluster/main.tf b/blueprints/fedramp-high/dataproc-cluster/main.tf index 36035e2bb..1e2211990 100644 --- a/blueprints/fedramp-high/dataproc-cluster/main.tf +++ b/blueprints/fedramp-high/dataproc-cluster/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - data "google_project" "current" { project_id = var.main_project_id } diff --git a/blueprints/fedramp-high/dataproc-cluster/outputs.tf b/blueprints/fedramp-high/dataproc-cluster/outputs.tf index f441c94c1..c41b0a1df 100644 --- a/blueprints/fedramp-high/dataproc-cluster/outputs.tf +++ b/blueprints/fedramp-high/dataproc-cluster/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "dataproc_bucket" { description = "GCS Bucket for DataProc." diff --git a/blueprints/fedramp-high/dataproc-cluster/provider.tf b/blueprints/fedramp-high/dataproc-cluster/provider.tf index 6e485bd7b..54ffe5959 100644 --- a/blueprints/fedramp-high/dataproc-cluster/provider.tf +++ b/blueprints/fedramp-high/dataproc-cluster/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">=1.0.0" diff --git a/blueprints/fedramp-high/dataproc-cluster/terraform.tfvars.sample b/blueprints/fedramp-high/dataproc-cluster/terraform.tfvars.sample index fd7f68bb6..a63dfd2ac 100644 --- a/blueprints/fedramp-high/dataproc-cluster/terraform.tfvars.sample +++ b/blueprints/fedramp-high/dataproc-cluster/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-xxxx-main-0" core_project_id = "xxxx-xxxx-xxxx-iac-core-0" network_project_id = "xxxx-xxxx-net-host" diff --git a/blueprints/fedramp-high/dataproc-cluster/variables.tf b/blueprints/fedramp-high/dataproc-cluster/variables.tf index 14c81fa29..0e3ce5ed3 100644 --- a/blueprints/fedramp-high/dataproc-cluster/variables.tf +++ b/blueprints/fedramp-high/dataproc-cluster/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "core_project_id" { description = "The ID of the iac core project where the KMS key is." type = string diff --git a/blueprints/fedramp-high/datastore/README.md b/blueprints/fedramp-high/datastore/README.md index 2dd6ee84b..d686d40bf 100644 --- a/blueprints/fedramp-high/datastore/README.md +++ b/blueprints/fedramp-high/datastore/README.md @@ -1,3 +1,19 @@ + + # Datastore Blueprint diff --git a/blueprints/fedramp-high/datastore/index.yaml b/blueprints/fedramp-high/datastore/index.yaml index d76e88945..0087a3f40 100644 --- a/blueprints/fedramp-high/datastore/index.yaml +++ b/blueprints/fedramp-high/datastore/index.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + indexes: - kind: Task diff --git a/blueprints/fedramp-high/datastore/main.tf b/blueprints/fedramp-high/datastore/main.tf index 439267640..6fafce3ed 100644 --- a/blueprints/fedramp-high/datastore/main.tf +++ b/blueprints/fedramp-high/datastore/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ resource "google_project_service" "datastore_api" { project = var.main_project_id diff --git a/blueprints/fedramp-high/datastore/provider.tf b/blueprints/fedramp-high/datastore/provider.tf index 2014efec8..a176e5d5a 100644 --- a/blueprints/fedramp-high/datastore/provider.tf +++ b/blueprints/fedramp-high/datastore/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/fedramp-high/datastore/terraform.tfvars.sample b/blueprints/fedramp-high/datastore/terraform.tfvars.sample index d610db218..a9044d4c1 100644 --- a/blueprints/fedramp-high/datastore/terraform.tfvars.sample +++ b/blueprints/fedramp-high/datastore/terraform.tfvars.sample @@ -1,2 +1,18 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-xxxx-main-0" region = "us-east4" \ No newline at end of file diff --git a/blueprints/fedramp-high/datastore/variables.tf b/blueprints/fedramp-high/datastore/variables.tf index 5302b5e87..b9abf030b 100644 --- a/blueprints/fedramp-high/datastore/variables.tf +++ b/blueprints/fedramp-high/datastore/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "main_project_id" { description = "The ID of your project. This project must contain an app engine instance." diff --git a/blueprints/fedramp-high/document-ai/README.md b/blueprints/fedramp-high/document-ai/README.md index 9c5315514..5ead3f315 100644 --- a/blueprints/fedramp-high/document-ai/README.md +++ b/blueprints/fedramp-high/document-ai/README.md @@ -1,3 +1,19 @@ + + # Document AI diff --git a/blueprints/fedramp-high/document-ai/code/example.yaml b/blueprints/fedramp-high/document-ai/code/example.yaml index 3ac295d9d..0c9a4ee22 100644 --- a/blueprints/fedramp-high/document-ai/code/example.yaml +++ b/blueprints/fedramp-high/document-ai/code/example.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + main: steps: - start: diff --git a/blueprints/fedramp-high/document-ai/iam.tf b/blueprints/fedramp-high/document-ai/iam.tf index 05c3f6f2e..60edb03fd 100644 --- a/blueprints/fedramp-high/document-ai/iam.tf +++ b/blueprints/fedramp-high/document-ai/iam.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ resource "google_service_account" "workflow_sa" { account_id = "docai-workflow-sa" diff --git a/blueprints/fedramp-high/document-ai/main.tf b/blueprints/fedramp-high/document-ai/main.tf index de2b2cd8d..0e3227cfa 100644 --- a/blueprints/fedramp-high/document-ai/main.tf +++ b/blueprints/fedramp-high/document-ai/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Enable the API service resource "google_project_service" "documentai" { diff --git a/blueprints/fedramp-high/document-ai/outputs.tf b/blueprints/fedramp-high/document-ai/outputs.tf index f89959784..2e0097923 100644 --- a/blueprints/fedramp-high/document-ai/outputs.tf +++ b/blueprints/fedramp-high/document-ai/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "id" { description = "Document AI processor id." diff --git a/blueprints/fedramp-high/document-ai/provider.tf b/blueprints/fedramp-high/document-ai/provider.tf index 4a580dc98..fd3388782 100644 --- a/blueprints/fedramp-high/document-ai/provider.tf +++ b/blueprints/fedramp-high/document-ai/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/fedramp-high/document-ai/terraform.tfvars.sample b/blueprints/fedramp-high/document-ai/terraform.tfvars.sample index 6eb0b7fa4..18f9b3b2a 100644 --- a/blueprints/fedramp-high/document-ai/terraform.tfvars.sample +++ b/blueprints/fedramp-high/document-ai/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-xxxx-main-0" name = "document-ai-processor-name-00" diff --git a/blueprints/fedramp-high/document-ai/variables.tf b/blueprints/fedramp-high/document-ai/variables.tf index f8b89eb3e..733ccf14b 100644 --- a/blueprints/fedramp-high/document-ai/variables.tf +++ b/blueprints/fedramp-high/document-ai/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "deletion_protection" { description = "Deletion proteciton." diff --git a/blueprints/fedramp-high/firestore/README.md b/blueprints/fedramp-high/firestore/README.md index 63397f463..ff6a3eb99 100644 --- a/blueprints/fedramp-high/firestore/README.md +++ b/blueprints/fedramp-high/firestore/README.md @@ -1,3 +1,19 @@ + + # Firestore diff --git a/blueprints/fedramp-high/firestore/main.tf b/blueprints/fedramp-high/firestore/main.tf index a42ac67c6..7fc1d8f36 100644 --- a/blueprints/fedramp-high/firestore/main.tf +++ b/blueprints/fedramp-high/firestore/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ resource "google_project_service" "datastore_api" { project = var.main_project_id diff --git a/blueprints/fedramp-high/firestore/outputs.tf b/blueprints/fedramp-high/firestore/outputs.tf index 2a11ae15d..a01c89f3c 100644 --- a/blueprints/fedramp-high/firestore/outputs.tf +++ b/blueprints/fedramp-high/firestore/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "firestore_earliest_version_time" { value = module.firestore.firestore_database.earliest_version_time diff --git a/blueprints/fedramp-high/firestore/provider.tf b/blueprints/fedramp-high/firestore/provider.tf index 139d6d95d..d978e880d 100644 --- a/blueprints/fedramp-high/firestore/provider.tf +++ b/blueprints/fedramp-high/firestore/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/fedramp-high/firestore/terraform.tfvars.sample b/blueprints/fedramp-high/firestore/terraform.tfvars.sample index 0852a0742..ba612247d 100644 --- a/blueprints/fedramp-high/firestore/terraform.tfvars.sample +++ b/blueprints/fedramp-high/firestore/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-xxxx-main-0" firestore_database_name = "firestore-database-00" diff --git a/blueprints/fedramp-high/firestore/variables.tf b/blueprints/fedramp-high/firestore/variables.tf index 160d15f06..3ca468a99 100644 --- a/blueprints/fedramp-high/firestore/variables.tf +++ b/blueprints/fedramp-high/firestore/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "backup_schedule" { description = "The Backup schedule - select daily or weekly in your tfvars." diff --git a/blueprints/fedramp-high/gemini-enterprise/README.md b/blueprints/fedramp-high/gemini-enterprise/README.md index 6ed805d99..4f4f9c89b 100644 --- a/blueprints/fedramp-high/gemini-enterprise/README.md +++ b/blueprints/fedramp-high/gemini-enterprise/README.md @@ -1,3 +1,19 @@ + + # Gemini Enterprise for FedRAMP High - Comprehensive Documentation **Version:** 1.2.0 diff --git a/blueprints/fedramp-high/gemini-enterprise/analytics/Dockerfile b/blueprints/fedramp-high/gemini-enterprise/analytics/Dockerfile index 1af08c50f..ed3f6c120 100644 --- a/blueprints/fedramp-high/gemini-enterprise/analytics/Dockerfile +++ b/blueprints/fedramp-high/gemini-enterprise/analytics/Dockerfile @@ -1,3 +1,17 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # Use a hardened base image (e.g., Iron Bank or Google Distroless) FROM python:3.11-slim @@ -10,4 +24,6 @@ COPY . . # Expose port 8080 for Cloud Run EXPOSE 8080 -CMD ["streamlit", "run", "app.py", "--server.port=8080", "--server.address=0.0.0.0"] \ No newline at end of file +CMD ["streamlit", "run", "app.py", "--server.port=8080", "--server.address=0.0.0.0"] +# Run as non-root user for security +USER 10001 diff --git a/blueprints/fedramp-high/gemini-enterprise/analytics/README.md b/blueprints/fedramp-high/gemini-enterprise/analytics/README.md index 32c98be77..daaa4c2c4 100644 --- a/blueprints/fedramp-high/gemini-enterprise/analytics/README.md +++ b/blueprints/fedramp-high/gemini-enterprise/analytics/README.md @@ -1,3 +1,19 @@ + + # Gemini Enterprise Usage Analytics Dashboard This directory contains a Streamlit application designed to visualize usage analytics for Gemini Enterprise (via Discovery Engine) by querying audit logs stored in BigQuery. diff --git a/blueprints/fedramp-high/gemini-enterprise/analytics/app.py b/blueprints/fedramp-high/gemini-enterprise/analytics/app.py index ab8b4a133..0a84a68da 100644 --- a/blueprints/fedramp-high/gemini-enterprise/analytics/app.py +++ b/blueprints/fedramp-high/gemini-enterprise/analytics/app.py @@ -1,3 +1,17 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import streamlit as st import plotly.express as px from google.cloud import bigquery diff --git a/blueprints/fedramp-high/gemini-enterprise/deploy.sh b/blueprints/fedramp-high/gemini-enterprise/deploy.sh index 9bf05aa33..9b3a98086 100755 --- a/blueprints/fedramp-high/gemini-enterprise/deploy.sh +++ b/blueprints/fedramp-high/gemini-enterprise/deploy.sh @@ -1,4 +1,18 @@ #!/bin/bash +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + set -e # Ensure gem4gov can be found in the python path diff --git a/blueprints/fedramp-high/gemini-enterprise/gem4gov-cli/README.md b/blueprints/fedramp-high/gemini-enterprise/gem4gov-cli/README.md index 45627d80b..9d44949b1 100644 --- a/blueprints/fedramp-high/gemini-enterprise/gem4gov-cli/README.md +++ b/blueprints/fedramp-high/gemini-enterprise/gem4gov-cli/README.md @@ -1,3 +1,19 @@ + + # gem4gov `gem4gov` is a command-line tool designed to streamline the onboarding process for government customers to Gemini for Government. This tool automates the setup and configuration of the necessary Google Cloud components, ensuring a smooth and efficient deployment. diff --git a/blueprints/fedramp-high/gemini-enterprise/gem4gov-cli/auth.py b/blueprints/fedramp-high/gemini-enterprise/gem4gov-cli/auth.py index 7c10684f1..139fe70f8 100644 --- a/blueprints/fedramp-high/gemini-enterprise/gem4gov-cli/auth.py +++ b/blueprints/fedramp-high/gemini-enterprise/gem4gov-cli/auth.py @@ -1,4 +1,4 @@ -# Copyright 2026 Google Inc. +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + import click import google.auth from googleapiclient.discovery import build diff --git a/blueprints/fedramp-high/gemini-enterprise/gem4gov-cli/data_stores.py b/blueprints/fedramp-high/gemini-enterprise/gem4gov-cli/data_stores.py index 2739848c6..92a9238bb 100644 --- a/blueprints/fedramp-high/gemini-enterprise/gem4gov-cli/data_stores.py +++ b/blueprints/fedramp-high/gemini-enterprise/gem4gov-cli/data_stores.py @@ -1,4 +1,4 @@ -# Copyright 2026 Google Inc. +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + import click import json from googleapiclient.errors import HttpError diff --git a/blueprints/fedramp-high/gemini-enterprise/gem4gov-cli/engine_features.yaml b/blueprints/fedramp-high/gemini-enterprise/gem4gov-cli/engine_features.yaml index 351b94741..18421ab78 100644 --- a/blueprints/fedramp-high/gemini-enterprise/gem4gov-cli/engine_features.yaml +++ b/blueprints/fedramp-high/gemini-enterprise/gem4gov-cli/engine_features.yaml @@ -1,4 +1,4 @@ -# Copyright 2026 Google Inc. +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + # Features for the search engine # See https://cloud.google.com/generative-ai-app-builder/docs/reference/rest/v1alpha/projects.locations.collections.engines#features features: diff --git a/blueprints/fedramp-high/gemini-enterprise/gem4gov-cli/gem4gov.py b/blueprints/fedramp-high/gemini-enterprise/gem4gov-cli/gem4gov.py index 88b0226fc..908a4cc53 100644 --- a/blueprints/fedramp-high/gemini-enterprise/gem4gov-cli/gem4gov.py +++ b/blueprints/fedramp-high/gemini-enterprise/gem4gov-cli/gem4gov.py @@ -1,4 +1,4 @@ -# Copyright 2026 Google Inc. +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + import sys import click import google.auth diff --git a/blueprints/fedramp-high/gemini-enterprise/gem4gov-cli/setup.py b/blueprints/fedramp-high/gemini-enterprise/gem4gov-cli/setup.py index e82adeaec..a0a442f2d 100644 --- a/blueprints/fedramp-high/gemini-enterprise/gem4gov-cli/setup.py +++ b/blueprints/fedramp-high/gemini-enterprise/gem4gov-cli/setup.py @@ -1,4 +1,4 @@ -# Copyright 2026 Google Inc. +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + from setuptools import setup, find_packages setup( diff --git a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/access_policy.tf b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/access_policy.tf index c23561be3..4e749136e 100644 --- a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/access_policy.tf +++ b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/access_policy.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Access level for allowlisted source IP ranges resource "google_access_context_manager_access_level" "ip_based_access" { diff --git a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/analytics.tf b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/analytics.tf index b15fbf141..12392ec52 100644 --- a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/analytics.tf +++ b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/analytics.tf @@ -1,16 +1,18 @@ -# Copyright 2026 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ resource "google_project_iam_audit_config" "discovery_engine_audit" { count = var.enable_analytics ? 1 : 0 diff --git a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/cloudarmor.tf b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/cloudarmor.tf index 4bd820156..41c1a05fd 100644 --- a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/cloudarmor.tf +++ b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/cloudarmor.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ locals { waf = yamldecode(file("data/cloudarmor.yaml")) diff --git a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/cmek.tf b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/cmek.tf index ceba27071..d57ba868b 100644 --- a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/cmek.tf +++ b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/cmek.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ locals { # Final CMEK Key ID - Only explicitly set if we are enabling Data Store CMEK diff --git a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/data/cloudarmor.yaml b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/data/cloudarmor.yaml index f271fff03..59926d968 100644 --- a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/data/cloudarmor.yaml +++ b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/data/cloudarmor.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + basic_rules: sqli: expression: "sqli-v33-stable" diff --git a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/discovery-engine.tf b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/discovery-engine.tf index 5ebab61e1..c3b67f8d1 100644 --- a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/discovery-engine.tf +++ b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/discovery-engine.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ locals { gcs_lifecycle_age = 30 diff --git a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/iam.tf b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/iam.tf index fbb6989e3..2bbb231f6 100644 --- a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/iam.tf +++ b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/iam.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # ----------------------------------------------------------------------------- # IAM ROLE ASSIGNMENTS diff --git a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/load_balancer.tf b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/load_balancer.tf index 8ff9923ea..ffd01d1d7 100644 --- a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/load_balancer.tf +++ b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/load_balancer.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ locals { load_balancing_scheme = var.deployment_type == "internal" ? "INTERNAL_MANAGED" : "EXTERNAL_MANAGED" diff --git a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/main.tf b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/main.tf index 03200889d..b5449abfe 100644 --- a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/main.tf +++ b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ ## Data Variables + Enabling APIs ## diff --git a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/network.tf b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/network.tf index 22328d50c..bd5ca55e3 100644 --- a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/network.tf +++ b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/network.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # ---------------------------------------------------------------------------- # # Networking Resources # diff --git a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/outputs.tf b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/outputs.tf index b25d6549f..1bd759a49 100644 --- a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/outputs.tf +++ b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "admin_group" { value = var.admin_group diff --git a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/provider.tf b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/provider.tf index 003d35631..d9bd6e074 100644 --- a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/provider.tf +++ b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/state.tf b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/state.tf index fa25bbd22..bc2f72778 100644 --- a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/state.tf +++ b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/state.tf @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + data "google_storage_bucket" "terraform_state" { name = var.terraform_state_bucket } diff --git a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/terraform.tfvars.sample b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/terraform.tfvars.sample index c8e951a03..a4dfd479b 100644 --- a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/terraform.tfvars.sample +++ b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/terraform.tfvars.sample @@ -1,16 +1,19 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "prefx-main-xxx-x" prefix = "prefx" diff --git a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/variables.tf b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/variables.tf index 101692e3a..ec18b0ef4 100644 --- a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/variables.tf +++ b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-0/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "environment" { description = "The environment identifier (e.g. prod, dev, staging)." type = string diff --git a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-1/load_balancer.tf b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-1/load_balancer.tf index 05075f763..fefa9988f 100644 --- a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-1/load_balancer.tf +++ b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-1/load_balancer.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Data source to read Stage 0 state data "terraform_remote_state" "stage_0" { diff --git a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-1/provider.tf b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-1/provider.tf index 8066dcb9c..35a459f55 100644 --- a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-1/provider.tf +++ b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-1/provider.tf @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + terraform { backend "gcs" {} required_providers { diff --git a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-1/terraform.tfvars.sample b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-1/terraform.tfvars.sample index 57d72389b..d61f748cb 100644 --- a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-1/terraform.tfvars.sample +++ b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-1/terraform.tfvars.sample @@ -1,16 +1,19 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + # Stage 0 State Bucket (Required for remote state access) stage_0_state_bucket = "sedev-gemini-enterprise-tf-state-sedev-test-mike-iac-core-0" diff --git a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-1/variables.tf b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-1/variables.tf index 18098d670..3b46d9f55 100644 --- a/blueprints/fedramp-high/gemini-enterprise/gemini-stage-1/variables.tf +++ b/blueprints/fedramp-high/gemini-enterprise/gemini-stage-1/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "stage_0_state_bucket" { description = "The name of the GCS bucket used for Stage 0 Terraform state." diff --git a/blueprints/fedramp-high/gitlab/README.md b/blueprints/fedramp-high/gitlab/README.md index 02137b30e..643e1e9c7 100644 --- a/blueprints/fedramp-high/gitlab/README.md +++ b/blueprints/fedramp-high/gitlab/README.md @@ -1,3 +1,19 @@ + + # GitLab Blueprint This blueprint will deploy all the required infrastructure to host a GitLab instance that can support 40 RPS. diff --git a/blueprints/fedramp-high/gitlab/images/Backend 443.png b/blueprints/fedramp-high/gitlab/images/Backend 443.png new file mode 100644 index 000000000..386e8753b Binary files /dev/null and b/blueprints/fedramp-high/gitlab/images/Backend 443.png differ diff --git a/blueprints/fedramp-high/gitlab/images/DNS Auth Creation.png b/blueprints/fedramp-high/gitlab/images/DNS Auth Creation.png new file mode 100644 index 000000000..25b213831 Binary files /dev/null and b/blueprints/fedramp-high/gitlab/images/DNS Auth Creation.png differ diff --git a/blueprints/fedramp-high/gitlab/images/DNS CNAME Creation.png b/blueprints/fedramp-high/gitlab/images/DNS CNAME Creation.png new file mode 100644 index 000000000..a537db252 Binary files /dev/null and b/blueprints/fedramp-high/gitlab/images/DNS CNAME Creation.png differ diff --git a/blueprints/fedramp-high/gitlab/images/Healthcheck 443.png b/blueprints/fedramp-high/gitlab/images/Healthcheck 443.png new file mode 100644 index 000000000..a0ceae25f Binary files /dev/null and b/blueprints/fedramp-high/gitlab/images/Healthcheck 443.png differ diff --git a/blueprints/fedramp-high/gitlab/images/IAP.png b/blueprints/fedramp-high/gitlab/images/IAP.png new file mode 100644 index 000000000..d6253651f Binary files /dev/null and b/blueprints/fedramp-high/gitlab/images/IAP.png differ diff --git a/blueprints/fedramp-high/gitlab/images/VPC-subnets.png b/blueprints/fedramp-high/gitlab/images/VPC-subnets.png new file mode 100644 index 000000000..bbd058819 Binary files /dev/null and b/blueprints/fedramp-high/gitlab/images/VPC-subnets.png differ diff --git a/blueprints/fedramp-high/gitlab/images/frontend certificate.png b/blueprints/fedramp-high/gitlab/images/frontend certificate.png new file mode 100644 index 000000000..b56fe7bce Binary files /dev/null and b/blueprints/fedramp-high/gitlab/images/frontend certificate.png differ diff --git a/blueprints/fedramp-high/gitlab/images/instance runner .png b/blueprints/fedramp-high/gitlab/images/instance runner .png new file mode 100644 index 000000000..274930925 Binary files /dev/null and b/blueprints/fedramp-high/gitlab/images/instance runner .png differ diff --git a/blueprints/fedramp-high/gitlab/images/instance-linux.png b/blueprints/fedramp-high/gitlab/images/instance-linux.png new file mode 100644 index 000000000..2f33bcf96 Binary files /dev/null and b/blueprints/fedramp-high/gitlab/images/instance-linux.png differ diff --git a/blueprints/fedramp-high/gitlab/images/linux platform.png b/blueprints/fedramp-high/gitlab/images/linux platform.png new file mode 100644 index 000000000..c73f12adf Binary files /dev/null and b/blueprints/fedramp-high/gitlab/images/linux platform.png differ diff --git a/blueprints/fedramp-high/gitlab/images/sucessful gitlab launch.png b/blueprints/fedramp-high/gitlab/images/sucessful gitlab launch.png new file mode 100644 index 000000000..d810457bf Binary files /dev/null and b/blueprints/fedramp-high/gitlab/images/sucessful gitlab launch.png differ diff --git a/blueprints/fedramp-high/gitlab/images/terraform.tfvars.png b/blueprints/fedramp-high/gitlab/images/terraform.tfvars.png new file mode 100644 index 000000000..9bbbcb33f Binary files /dev/null and b/blueprints/fedramp-high/gitlab/images/terraform.tfvars.png differ diff --git a/blueprints/fedramp-high/gitlab/main.tf b/blueprints/fedramp-high/gitlab/main.tf index 676756036..ecacc085e 100644 --- a/blueprints/fedramp-high/gitlab/main.tf +++ b/blueprints/fedramp-high/gitlab/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ data "google_project" "project" {} diff --git a/blueprints/fedramp-high/gitlab/outputs.tf b/blueprints/fedramp-high/gitlab/outputs.tf index 7c2d96610..7e8f09847 100644 --- a/blueprints/fedramp-high/gitlab/outputs.tf +++ b/blueprints/fedramp-high/gitlab/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "gke-cluster" { description = "Deployed GKE cluster." diff --git a/blueprints/fedramp-high/gitlab/provider.tf b/blueprints/fedramp-high/gitlab/provider.tf index 3624c92af..f719154ee 100644 --- a/blueprints/fedramp-high/gitlab/provider.tf +++ b/blueprints/fedramp-high/gitlab/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/fedramp-high/gitlab/terraform.tfvars.sample b/blueprints/fedramp-high/gitlab/terraform.tfvars.sample index a91c86560..220daf4a1 100644 --- a/blueprints/fedramp-high/gitlab/terraform.tfvars.sample +++ b/blueprints/fedramp-high/gitlab/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + gitlab_uri = "gitlab.mine.com" network = "projects//global/networks/" subnetwork = "projects//regions/us-east4/subnetworks/" diff --git a/blueprints/fedramp-high/gitlab/variables.tf b/blueprints/fedramp-high/gitlab/variables.tf index c9ae3428a..5f1814427 100644 --- a/blueprints/fedramp-high/gitlab/variables.tf +++ b/blueprints/fedramp-high/gitlab/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "gitlab_uri" { description = "The URL hostname that the gitlab instance will be attached to." diff --git a/blueprints/fedramp-high/network-connectivity-center/README.md b/blueprints/fedramp-high/network-connectivity-center/README.md index 0b4f39839..e7b4b527c 100644 --- a/blueprints/fedramp-high/network-connectivity-center/README.md +++ b/blueprints/fedramp-high/network-connectivity-center/README.md @@ -1,3 +1,19 @@ + + # Network Connectivity Center Blueprint This blueprint demonstrates how to create a Google Cloud Network Connectivity Center (NCC) Hub and connect existing VPC networks as spokes, supporting various network topologies (MESH/STAR) within a multi-project GCP environment. diff --git a/blueprints/fedramp-high/network-connectivity-center/main.tf b/blueprints/fedramp-high/network-connectivity-center/main.tf index 7d46185b9..c4e4fd84b 100644 --- a/blueprints/fedramp-high/network-connectivity-center/main.tf +++ b/blueprints/fedramp-high/network-connectivity-center/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ locals { spoke_projects = distinct( diff --git a/blueprints/fedramp-high/network-connectivity-center/outputs.tf b/blueprints/fedramp-high/network-connectivity-center/outputs.tf index b46a5d2f1..b148b8152 100644 --- a/blueprints/fedramp-high/network-connectivity-center/outputs.tf +++ b/blueprints/fedramp-high/network-connectivity-center/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "hub" { description = "The NCC hub ID." diff --git a/blueprints/fedramp-high/network-connectivity-center/provider.tf b/blueprints/fedramp-high/network-connectivity-center/provider.tf index efc88ffd9..6fe72df9c 100644 --- a/blueprints/fedramp-high/network-connectivity-center/provider.tf +++ b/blueprints/fedramp-high/network-connectivity-center/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/fedramp-high/network-connectivity-center/terraform.tfvars.sample b/blueprints/fedramp-high/network-connectivity-center/terraform.tfvars.sample index 40bb8ed6c..924bbf6de 100644 --- a/blueprints/fedramp-high/network-connectivity-center/terraform.tfvars.sample +++ b/blueprints/fedramp-high/network-connectivity-center/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-main-0" # Replace with your main project ID ncc_hub_name = "ncc-hub-name-00" # The name of your NCC hub diff --git a/blueprints/fedramp-high/network-connectivity-center/variables.tf b/blueprints/fedramp-high/network-connectivity-center/variables.tf index 8df8cf3d8..4210ee3b6 100644 --- a/blueprints/fedramp-high/network-connectivity-center/variables.tf +++ b/blueprints/fedramp-high/network-connectivity-center/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "main_project_id" { description = "The Google Cloud Project ID where the NCC hub will be created." diff --git a/blueprints/fedramp-high/secret-manager/README.md b/blueprints/fedramp-high/secret-manager/README.md index 7f556ceb6..5c2d88c7b 100644 --- a/blueprints/fedramp-high/secret-manager/README.md +++ b/blueprints/fedramp-high/secret-manager/README.md @@ -1,3 +1,19 @@ + + # Secret Manager Blueprint This blueprint demonstrates how to create Google Secret Manager secrets, configure them with Customer-Managed Encryption Keys (CMEK) using Cloud KMS, and manage their IAM permissions, all within a multi-project GCP environment. It guides users on securely adding secret versions outside of Terraform state using a bash script. diff --git a/blueprints/fedramp-high/secret-manager/add_secret_versions.sh b/blueprints/fedramp-high/secret-manager/add_secret_versions.sh index 74374cb5c..9e034a18d 100755 --- a/blueprints/fedramp-high/secret-manager/add_secret_versions.sh +++ b/blueprints/fedramp-high/secret-manager/add_secret_versions.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,6 +14,7 @@ # limitations under the License. + # Exit immediately if a command exits with a non-zero status. set -e diff --git a/blueprints/fedramp-high/secret-manager/main.tf b/blueprints/fedramp-high/secret-manager/main.tf index 14be94705..9367339e4 100644 --- a/blueprints/fedramp-high/secret-manager/main.tf +++ b/blueprints/fedramp-high/secret-manager/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ locals { # Grab all the keys from the secrets variable in order to grant permissions to secret manager service account diff --git a/blueprints/fedramp-high/secret-manager/outputs.tf b/blueprints/fedramp-high/secret-manager/outputs.tf index b6eb07ea7..c0ca555b8 100644 --- a/blueprints/fedramp-high/secret-manager/outputs.tf +++ b/blueprints/fedramp-high/secret-manager/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "ids" { description = "Secret IDs." diff --git a/blueprints/fedramp-high/secret-manager/provider.tf b/blueprints/fedramp-high/secret-manager/provider.tf index a0b9b3107..bfb29570a 100644 --- a/blueprints/fedramp-high/secret-manager/provider.tf +++ b/blueprints/fedramp-high/secret-manager/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/fedramp-high/secret-manager/terraform.tfvars.sample b/blueprints/fedramp-high/secret-manager/terraform.tfvars.sample index 53cb934f2..aa0dde317 100644 --- a/blueprints/fedramp-high/secret-manager/terraform.tfvars.sample +++ b/blueprints/fedramp-high/secret-manager/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-main-0" # Replace with your main project ID gcp_region = "us-east4" # Renamed from 'region' diff --git a/blueprints/fedramp-high/secret-manager/variables.tf b/blueprints/fedramp-high/secret-manager/variables.tf index 69d388730..ffd6c9afd 100644 --- a/blueprints/fedramp-high/secret-manager/variables.tf +++ b/blueprints/fedramp-high/secret-manager/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "iam" { description = "IAM bindings in {SECRET => {ROLE => [MEMBERS]}} format." diff --git a/blueprints/fedramp-high/vertex-mlops/README.md b/blueprints/fedramp-high/vertex-mlops/README.md index def9f5662..535736c05 100644 --- a/blueprints/fedramp-high/vertex-mlops/README.md +++ b/blueprints/fedramp-high/vertex-mlops/README.md @@ -1,3 +1,19 @@ + + # MLOps with Vertex AI This blueprint demonstrates how to create a Vertex AI Workbench on Google Cloud Platform (GCP) with Customer-Managed Encryption Keys (CMEK) using Cloud KMS. diff --git a/blueprints/fedramp-high/vertex-mlops/main.tf b/blueprints/fedramp-high/vertex-mlops/main.tf index d21dfdfc8..11c9875af 100644 --- a/blueprints/fedramp-high/vertex-mlops/main.tf +++ b/blueprints/fedramp-high/vertex-mlops/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { vpc = "projects/${var.network_config.network_project_id}/global/networks/${var.network_config.network_name}" subnet = "projects/${var.network_config.network_project_id}/regions/${var.region}/subnetworks/${var.network_config.subnetwork_name}" diff --git a/blueprints/fedramp-high/vertex-mlops/outputs.tf b/blueprints/fedramp-high/vertex-mlops/outputs.tf index ac4651649..73bfb358a 100644 --- a/blueprints/fedramp-high/vertex-mlops/outputs.tf +++ b/blueprints/fedramp-high/vertex-mlops/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "notebook" { description = "Vertex AI notebook ids." value = merge( diff --git a/blueprints/fedramp-high/vertex-mlops/provider.tf b/blueprints/fedramp-high/vertex-mlops/provider.tf index f6af2f36e..92449b1fd 100644 --- a/blueprints/fedramp-high/vertex-mlops/provider.tf +++ b/blueprints/fedramp-high/vertex-mlops/provider.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - terraform { required_version = ">= 1.7.4" required_providers { diff --git a/blueprints/fedramp-high/vertex-mlops/terraform.tfvars.sample b/blueprints/fedramp-high/vertex-mlops/terraform.tfvars.sample index 265b1e2ad..549b8e6f1 100644 --- a/blueprints/fedramp-high/vertex-mlops/terraform.tfvars.sample +++ b/blueprints/fedramp-high/vertex-mlops/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + project_config = { main_project_id = "xxxx-xxxx-main-0" } diff --git a/blueprints/fedramp-high/vertex-mlops/variables.tf b/blueprints/fedramp-high/vertex-mlops/variables.tf index 1342ae0f2..88e3aef0c 100644 --- a/blueprints/fedramp-high/vertex-mlops/variables.tf +++ b/blueprints/fedramp-high/vertex-mlops/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,8 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - - variable "bucket_name" { description = "GCS bucket name to store the Vertex AI artifacts." type = string diff --git a/blueprints/fedramp-high/vertex-mlops/vertex.tf b/blueprints/fedramp-high/vertex-mlops/vertex.tf index 2876e3ef0..a12a9650a 100644 --- a/blueprints/fedramp-high/vertex-mlops/vertex.tf +++ b/blueprints/fedramp-high/vertex-mlops/vertex.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - module "service-account-notebook" { source = "../../../modules/iam-service-account" project_id = module.project.project_id diff --git a/blueprints/fedramp-high/workflows/README.md b/blueprints/fedramp-high/workflows/README.md index c9f212a0d..8c6c70799 100644 --- a/blueprints/fedramp-high/workflows/README.md +++ b/blueprints/fedramp-high/workflows/README.md @@ -1,4 +1,18 @@ + - [Introduction to Workflows](#introduction-to-workflows) diff --git a/blueprints/fedramp-high/workflows/code/example.yaml b/blueprints/fedramp-high/workflows/code/example.yaml index d9f6d68a7..dfea5b73f 100644 --- a/blueprints/fedramp-high/workflows/code/example.yaml +++ b/blueprints/fedramp-high/workflows/code/example.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + # This is a sample workflow. You can replace it with your source code. # # This workflow does the following: diff --git a/blueprints/fedramp-high/workflows/main.tf b/blueprints/fedramp-high/workflows/main.tf index 898dc8081..1ab723a62 100644 --- a/blueprints/fedramp-high/workflows/main.tf +++ b/blueprints/fedramp-high/workflows/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ data "google_project" "current" {} diff --git a/blueprints/fedramp-high/workflows/outputs.tf b/blueprints/fedramp-high/workflows/outputs.tf index e1469f1fe..735877f4c 100644 --- a/blueprints/fedramp-high/workflows/outputs.tf +++ b/blueprints/fedramp-high/workflows/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "service_account" { description = "The workflow service account." diff --git a/blueprints/fedramp-high/workflows/provider.tf b/blueprints/fedramp-high/workflows/provider.tf index b4add3ba5..21e6e5490 100644 --- a/blueprints/fedramp-high/workflows/provider.tf +++ b/blueprints/fedramp-high/workflows/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/fedramp-high/workflows/terraform.tfvars.sample b/blueprints/fedramp-high/workflows/terraform.tfvars.sample index 2c4f65014..3c07bc2a6 100644 --- a/blueprints/fedramp-high/workflows/terraform.tfvars.sample +++ b/blueprints/fedramp-high/workflows/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-main-0" core_project_id = "xxxx-xxxx-iac-core-0" # project where KMS keys reside diff --git a/blueprints/fedramp-high/workflows/variables.tf b/blueprints/fedramp-high/workflows/variables.tf index 111617315..3adce02ee 100644 --- a/blueprints/fedramp-high/workflows/variables.tf +++ b/blueprints/fedramp-high/workflows/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "deletion_protection" { description = "Deletion protection for the workflow." diff --git a/blueprints/il5/README.md b/blueprints/il5/README.md index d02550588..bbfa9a3de 100644 --- a/blueprints/il5/README.md +++ b/blueprints/il5/README.md @@ -1,3 +1,19 @@ + + # Google Cloud service Blueprint projects The directory provide multiple Google Cloud Services that contains all the necessary Terraform modules to build and deploy a GCP service in an IL5 (Impact Level 5) Assured workload enviornment. - Enable Necessary APIs: Depending on the services your project will use (e.g., Compute Engine, Cloud Storage, Cloud SQL), enable the corresponding APIs in the Google Cloud Console. diff --git a/blueprints/il5/artifact-registry/README.md b/blueprints/il5/artifact-registry/README.md index f8ff1f70b..83793b547 100644 --- a/blueprints/il5/artifact-registry/README.md +++ b/blueprints/il5/artifact-registry/README.md @@ -1,3 +1,19 @@ + + # Artifact Registry diff --git a/blueprints/il5/artifact-registry/consumer.tf b/blueprints/il5/artifact-registry/consumer.tf index 02ab3842e..3c13c54b5 100644 --- a/blueprints/il5/artifact-registry/consumer.tf +++ b/blueprints/il5/artifact-registry/consumer.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ resource "google_service_account" "consumer" { account_id = "compute-service-account" diff --git a/blueprints/il5/artifact-registry/data/docker-registries.yaml b/blueprints/il5/artifact-registry/data/docker-registries.yaml index b607e62a8..d5da07ef8 100644 --- a/blueprints/il5/artifact-registry/data/docker-registries.yaml +++ b/blueprints/il5/artifact-registry/data/docker-registries.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + docker: registry-k8s-io: remote: diff --git a/blueprints/il5/artifact-registry/data/yum-repos.yaml b/blueprints/il5/artifact-registry/data/yum-repos.yaml index 29711a68b..cded62d6b 100644 --- a/blueprints/il5/artifact-registry/data/yum-repos.yaml +++ b/blueprints/il5/artifact-registry/data/yum-repos.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + yum: centos9-stream-baseos: remote: diff --git a/blueprints/il5/artifact-registry/main.tf b/blueprints/il5/artifact-registry/main.tf index 6c74a0355..e653267e8 100644 --- a/blueprints/il5/artifact-registry/main.tf +++ b/blueprints/il5/artifact-registry/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ locals { repositories = merge([ diff --git a/blueprints/il5/artifact-registry/outputs.tf b/blueprints/il5/artifact-registry/outputs.tf index 026171bf8..34429a02c 100644 --- a/blueprints/il5/artifact-registry/outputs.tf +++ b/blueprints/il5/artifact-registry/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "docker_registries" { description = "Docker registries created from the docker-registries.yaml file, with Docker Hub appended." diff --git a/blueprints/il5/artifact-registry/provider.tf b/blueprints/il5/artifact-registry/provider.tf index 1e626cd98..a192ae8e8 100644 --- a/blueprints/il5/artifact-registry/provider.tf +++ b/blueprints/il5/artifact-registry/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/il5/artifact-registry/terraform.tfvars.sample b/blueprints/il5/artifact-registry/terraform.tfvars.sample index ffe08c816..1631d543d 100644 --- a/blueprints/il5/artifact-registry/terraform.tfvars.sample +++ b/blueprints/il5/artifact-registry/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-xxxx-main-0" core_project_id = "xxxx-xxxx-xxxx-iac-core-0" network_project_id = "xxxx-xxxx-net-host" diff --git a/blueprints/il5/artifact-registry/variables.tf b/blueprints/il5/artifact-registry/variables.tf index b5e09f67b..e32bf6538 100644 --- a/blueprints/il5/artifact-registry/variables.tf +++ b/blueprints/il5/artifact-registry/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "core_project_id" { description = "Core project ID." diff --git a/blueprints/il5/bastion-pattern/README.md b/blueprints/il5/bastion-pattern/README.md index fbdcbd47b..f9d96da2e 100644 --- a/blueprints/il5/bastion-pattern/README.md +++ b/blueprints/il5/bastion-pattern/README.md @@ -1,3 +1,19 @@ + + ## Bastion Pattern diff --git a/blueprints/il5/bastion-pattern/main.tf b/blueprints/il5/bastion-pattern/main.tf index 1e0dc4c14..ec52dd331 100644 --- a/blueprints/il5/bastion-pattern/main.tf +++ b/blueprints/il5/bastion-pattern/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - data "google_project" "current" {} data "google_compute_network" "network" { diff --git a/blueprints/il5/bastion-pattern/outputs.tf b/blueprints/il5/bastion-pattern/outputs.tf index c92993615..8d7397ab8 100644 --- a/blueprints/il5/bastion-pattern/outputs.tf +++ b/blueprints/il5/bastion-pattern/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "compute_service_account_email" { description = "The email of the compute service account." value = google_service_account.compute.email diff --git a/blueprints/il5/bastion-pattern/provider.tf b/blueprints/il5/bastion-pattern/provider.tf index 946323a13..ee9acfee0 100644 --- a/blueprints/il5/bastion-pattern/provider.tf +++ b/blueprints/il5/bastion-pattern/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/il5/bastion-pattern/terraform.tfvars.sample b/blueprints/il5/bastion-pattern/terraform.tfvars.sample index df63029af..b765b72e3 100644 --- a/blueprints/il5/bastion-pattern/terraform.tfvars.sample +++ b/blueprints/il5/bastion-pattern/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-xxxx-main-0" core_project_id = "xxxx-xxxx-xxxx-iac-core-0" network_project_id = "xxxx-xxxx-net-host" diff --git a/blueprints/il5/bastion-pattern/variables.tf b/blueprints/il5/bastion-pattern/variables.tf index f779e0f6f..b2968f261 100644 --- a/blueprints/il5/bastion-pattern/variables.tf +++ b/blueprints/il5/bastion-pattern/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "allowed_firewall_ports" { description = "The allowed ports for the firewall." type = list(string) diff --git a/blueprints/il5/bcap/README.md b/blueprints/il5/bcap/README.md index 4969a7015..c1a23df18 100644 --- a/blueprints/il5/bcap/README.md +++ b/blueprints/il5/bcap/README.md @@ -1,3 +1,19 @@ + + # Boundary Cloud Access Point (BCAP) This Terraform blueprint provisions the necessary Google Cloud infrastructure to establish a highly available connection to a Boundary Cloud Access Point (BCAP) provider, such as DISA, using Google Cloud Partner Interconnect. diff --git a/blueprints/il5/bcap/main.tf b/blueprints/il5/bcap/main.tf index 5a273473a..8e02a0228 100644 --- a/blueprints/il5/bcap/main.tf +++ b/blueprints/il5/bcap/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ locals { router_configs = var.router_configs diff --git a/blueprints/il5/bcap/outputs.tf b/blueprints/il5/bcap/outputs.tf index 79737d431..c884109eb 100644 --- a/blueprints/il5/bcap/outputs.tf +++ b/blueprints/il5/bcap/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "attachment_names" { description = "Names of the created VLAN attachments." diff --git a/blueprints/il5/bcap/provider.tf b/blueprints/il5/bcap/provider.tf index fcea442fe..467e675e2 100644 --- a/blueprints/il5/bcap/provider.tf +++ b/blueprints/il5/bcap/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/il5/bcap/terraform.tfvars.sample b/blueprints/il5/bcap/terraform.tfvars.sample index 56e3e2a56..a9d03a61d 100644 --- a/blueprints/il5/bcap/terraform.tfvars.sample +++ b/blueprints/il5/bcap/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + hub_project_id = "xxxx-net-vdss-host" # VPC Configuration diff --git a/blueprints/il5/bcap/variables.tf b/blueprints/il5/bcap/variables.tf index 78b51bf6e..43258f3aa 100644 --- a/blueprints/il5/bcap/variables.tf +++ b/blueprints/il5/bcap/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "attachment_configs" { description = "Configuration map for the four Partner VLAN attachments required for 99.99% availability. The region for each attachment is derived from its associated `router_key`." diff --git a/blueprints/il5/bigquery/README.md b/blueprints/il5/bigquery/README.md index b61c0e826..3c27b9cbf 100644 --- a/blueprints/il5/bigquery/README.md +++ b/blueprints/il5/bigquery/README.md @@ -1,3 +1,19 @@ + + # Google BigQuery (BigQuery) Project diff --git a/blueprints/il5/bigquery/main.tf b/blueprints/il5/bigquery/main.tf index cbcb4e755..d62df0f29 100644 --- a/blueprints/il5/bigquery/main.tf +++ b/blueprints/il5/bigquery/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - data "google_bigquery_default_service_account" "bq_sa" { depends_on = [ google_project_service.bigquery_api diff --git a/blueprints/il5/bigquery/outputs.tf b/blueprints/il5/bigquery/outputs.tf index 19f629254..b9e99feed 100644 --- a/blueprints/il5/bigquery/outputs.tf +++ b/blueprints/il5/bigquery/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "dataset_name" { value = module.bigquery-dataset.id description = "Dataset name." diff --git a/blueprints/il5/bigquery/provider.tf b/blueprints/il5/bigquery/provider.tf index 2511302b6..9fdff5757 100644 --- a/blueprints/il5/bigquery/provider.tf +++ b/blueprints/il5/bigquery/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/il5/bigquery/terraform.tfvars.sample b/blueprints/il5/bigquery/terraform.tfvars.sample index 5b564ce16..a8f0db5a9 100644 --- a/blueprints/il5/bigquery/terraform.tfvars.sample +++ b/blueprints/il5/bigquery/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-xxxx-main-0" core_project_id = "xxxx-xxxx-xxxx-iac-core-0" diff --git a/blueprints/il5/bigquery/variables.tf b/blueprints/il5/bigquery/variables.tf index 208ac447d..dc73d333c 100644 --- a/blueprints/il5/bigquery/variables.tf +++ b/blueprints/il5/bigquery/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "core_project_id" { description = "Core project ID." type = string diff --git a/blueprints/il5/bq-project/README.md b/blueprints/il5/bq-project/README.md index 3fd064e59..5a7182aaa 100644 --- a/blueprints/il5/bq-project/README.md +++ b/blueprints/il5/bq-project/README.md @@ -1,3 +1,19 @@ + + # Google BigQuery (BigQuery) Project This blueprint contains all the necessary Terraform modules to build and deploy a BigQuery project on Google Cloud. diff --git a/blueprints/il5/bq-project/main.tf b/blueprints/il5/bq-project/main.tf index 2cc567420..003464afb 100644 --- a/blueprints/il5/bq-project/main.tf +++ b/blueprints/il5/bq-project/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - data "google_bigquery_default_service_account" "bq_sa" {} module "bigquery-dataset" { diff --git a/blueprints/il5/bq-project/outputs.tf b/blueprints/il5/bq-project/outputs.tf index 02dd0f1e0..29a67f49e 100644 --- a/blueprints/il5/bq-project/outputs.tf +++ b/blueprints/il5/bq-project/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "dataset_name" { value = module.bigquery-dataset.id description = "Dataset name." diff --git a/blueprints/il5/bq-project/provider.tf b/blueprints/il5/bq-project/provider.tf index 2511302b6..9fdff5757 100644 --- a/blueprints/il5/bq-project/provider.tf +++ b/blueprints/il5/bq-project/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/il5/bq-project/terraform.tfvars.sample b/blueprints/il5/bq-project/terraform.tfvars.sample index 91e01e9b0..a3b2e03b3 100644 --- a/blueprints/il5/bq-project/terraform.tfvars.sample +++ b/blueprints/il5/bq-project/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-xxxx-main-0" dataset_id = "dataset-id-00" diff --git a/blueprints/il5/bq-project/variables.tf b/blueprints/il5/bq-project/variables.tf index cd763fee8..c1e9d3716 100644 --- a/blueprints/il5/bq-project/variables.tf +++ b/blueprints/il5/bq-project/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "dataset_description" { description = "Provides a discription of the deployed BigQuery Dataset." type = string diff --git a/blueprints/il5/compute-engine/README.md b/blueprints/il5/compute-engine/README.md index bd093e938..ffbbd9890 100644 --- a/blueprints/il5/compute-engine/README.md +++ b/blueprints/il5/compute-engine/README.md @@ -1,3 +1,19 @@ + + # Google Compute Engine VM with Persistent Disk Project This blueprint contains all the necessary Terraform modules to build and deploy a Compute Engine VM (virtual machines VMs on Google Cloud) attached to a persistent disk having encryption using the Cloud Key Management Service (KMS). @@ -119,4 +135,4 @@ keyrings-keys = { ## Verification of a successful deployment? - Go to the Compute Engine in the GCP Console. Select the VM. Check the Presistent Disk Encryption -![GCP Compute Engine Instance Presistent Disk Encryption](./images/vm-disk-1.png?raw=true "GCP Compute Engine Instance Presistent Disk Encryption") + diff --git a/blueprints/il5/compute-engine/main.tf b/blueprints/il5/compute-engine/main.tf index 170182fa4..202d165f2 100644 --- a/blueprints/il5/compute-engine/main.tf +++ b/blueprints/il5/compute-engine/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/blueprints/il5/compute-engine/outputs.tf b/blueprints/il5/compute-engine/outputs.tf index e29a2fd58..c1c42b799 100644 --- a/blueprints/il5/compute-engine/outputs.tf +++ b/blueprints/il5/compute-engine/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "compute-engine-vm-instance" { description = "Instance resource." sensitive = true diff --git a/blueprints/il5/compute-engine/provider.tf b/blueprints/il5/compute-engine/provider.tf index 2018b3124..d2a2edc3b 100644 --- a/blueprints/il5/compute-engine/provider.tf +++ b/blueprints/il5/compute-engine/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/il5/compute-engine/terraform.tfvars.sample b/blueprints/il5/compute-engine/terraform.tfvars.sample index 7353df8e2..687e9a96c 100644 --- a/blueprints/il5/compute-engine/terraform.tfvars.sample +++ b/blueprints/il5/compute-engine/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-xxxx-main-0" core_project_id = "xxxx-xxxx-xxxx-iac-core-0" network_project_id = "xxxx-xxxx-net-host" diff --git a/blueprints/il5/compute-engine/variables.tf b/blueprints/il5/compute-engine/variables.tf index 92f085e21..1fec424ec 100644 --- a/blueprints/il5/compute-engine/variables.tf +++ b/blueprints/il5/compute-engine/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "auto_delete" { description = "Persistent Disk auto delete options." type = bool diff --git a/blueprints/il5/dataflow/README.md b/blueprints/il5/dataflow/README.md index 03301dc6e..f5750db5f 100644 --- a/blueprints/il5/dataflow/README.md +++ b/blueprints/il5/dataflow/README.md @@ -1,3 +1,19 @@ + + Copyright 2023 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/blueprints/il5/dataflow/main.tf b/blueprints/il5/dataflow/main.tf index 41a4e59ea..dc79772c5 100644 --- a/blueprints/il5/dataflow/main.tf +++ b/blueprints/il5/dataflow/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - data "google_project" "project" { project_id = var.main_project_id } diff --git a/blueprints/il5/dataflow/outputs.tf b/blueprints/il5/dataflow/outputs.tf index fd7d80828..256cc2ddf 100644 --- a/blueprints/il5/dataflow/outputs.tf +++ b/blueprints/il5/dataflow/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "dataflow-job" { description = "Dataflow job." diff --git a/blueprints/il5/dataflow/provider.tf b/blueprints/il5/dataflow/provider.tf index 01e5d8abe..d2b2eb0c2 100644 --- a/blueprints/il5/dataflow/provider.tf +++ b/blueprints/il5/dataflow/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/il5/dataflow/terraform.tfvars.sample b/blueprints/il5/dataflow/terraform.tfvars.sample index e53b82c89..74655f06f 100644 --- a/blueprints/il5/dataflow/terraform.tfvars.sample +++ b/blueprints/il5/dataflow/terraform.tfvars.sample @@ -1,3 +1,18 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ main_project_id = "xxxx-xxxx-xxxx-main-0" core_project_id = "xxxx-xxxx-xxxx-iac-core-0" diff --git a/blueprints/il5/dataflow/variables.tf b/blueprints/il5/dataflow/variables.tf index 513689588..c23e7d05f 100644 --- a/blueprints/il5/dataflow/variables.tf +++ b/blueprints/il5/dataflow/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "allowed_firewall_ports" { description = "The allowed ports for the firewall. Dataflow requires 12345 and 12346." type = list(string) diff --git a/blueprints/il5/gcs-project/README.md b/blueprints/il5/gcs-project/README.md index b07abb126..5662085fe 100644 --- a/blueprints/il5/gcs-project/README.md +++ b/blueprints/il5/gcs-project/README.md @@ -1,3 +1,19 @@ + + # Google Cloud Storage diff --git a/blueprints/il5/gcs-project/main.tf b/blueprints/il5/gcs-project/main.tf index 7ff10ad89..f60874b4a 100644 --- a/blueprints/il5/gcs-project/main.tf +++ b/blueprints/il5/gcs-project/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - data "google_project" "current" { project_id = var.main_project_id } diff --git a/blueprints/il5/gcs-project/outputs.tf b/blueprints/il5/gcs-project/outputs.tf index 36a1e8d75..649cb0684 100644 --- a/blueprints/il5/gcs-project/outputs.tf +++ b/blueprints/il5/gcs-project/outputs.tf @@ -1,14 +1,16 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/blueprints/il5/gcs-project/provider.tf b/blueprints/il5/gcs-project/provider.tf index 5c5403538..24b1030bd 100644 --- a/blueprints/il5/gcs-project/provider.tf +++ b/blueprints/il5/gcs-project/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/il5/gcs-project/terraform.tfvars.sample b/blueprints/il5/gcs-project/terraform.tfvars.sample index 834a8dea8..bb4dc023b 100644 --- a/blueprints/il5/gcs-project/terraform.tfvars.sample +++ b/blueprints/il5/gcs-project/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-xxxx-main-0" core_project_id = "xxxx-xxxx-xxxx-iac-core-0" diff --git a/blueprints/il5/gcs-project/variables.tf b/blueprints/il5/gcs-project/variables.tf index 681140478..7cdc87b59 100644 --- a/blueprints/il5/gcs-project/variables.tf +++ b/blueprints/il5/gcs-project/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tflint-ignore: terraform_unused_declarations variable "autoclass" { description = "Enable autoclass to automatically transition objects to appropriate storage classes based on their access pattern. If set to true, storage_class must be set to STANDARD. When set to true, All objects added to the bucket begin in Standard storage, even if a different storage class is specified in the request." diff --git a/blueprints/il5/gke-hardened/README.md b/blueprints/il5/gke-hardened/README.md index a836bccbf..b758f61b4 100644 --- a/blueprints/il5/gke-hardened/README.md +++ b/blueprints/il5/gke-hardened/README.md @@ -1,3 +1,19 @@ + + # Google Kubernetes Engine (GKE) Standard Project This blueprint contains all the necessary Terraform modules to build and deploy a Google Kubernetes Engine (GKE), a managed Kubernetes cluster having encryption using the Cloud Key Management Service (KMS). diff --git a/blueprints/il5/gke-hardened/main.tf b/blueprints/il5/gke-hardened/main.tf index 84f78619d..cfed9789e 100644 --- a/blueprints/il5/gke-hardened/main.tf +++ b/blueprints/il5/gke-hardened/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - data "google_project" "current" {} # Only uncomment if no organization policies enforce the below diff --git a/blueprints/il5/gke-hardened/outputs.tf b/blueprints/il5/gke-hardened/outputs.tf index 853840c53..7c8aa5601 100644 --- a/blueprints/il5/gke-hardened/outputs.tf +++ b/blueprints/il5/gke-hardened/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "cluster_master_version" { description = "Master version." diff --git a/blueprints/il5/gke-hardened/provider.tf b/blueprints/il5/gke-hardened/provider.tf index 45d4ac5b9..c77df7c3b 100644 --- a/blueprints/il5/gke-hardened/provider.tf +++ b/blueprints/il5/gke-hardened/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/il5/gke-hardened/terraform.tfvars.sample b/blueprints/il5/gke-hardened/terraform.tfvars.sample index 283a274dc..1f016a60b 100644 --- a/blueprints/il5/gke-hardened/terraform.tfvars.sample +++ b/blueprints/il5/gke-hardened/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + gatekeeper_sa = "gatekeeper-XXX-XXX-sa" gke_cluster_enable_private_endpoint = true gke_cluster_master_global_access = true @@ -51,7 +67,7 @@ remove_default_node_pool = true source_branch = "gitops-constraints" source_dir = "policies" -source_repo = "https://github.com/DarkWolf-Labs/stellar-engine-gke-policies" +source_repo = "https://github.com/enterprise-Labs/stellar-engine-gke-policies" subnetwork_name = "il5ssaa-int-dwsssa-subnet" subnetwork_ip_cidr_range_1 = "10.0.4.0/22" diff --git a/blueprints/il5/gke-hardened/variables.tf b/blueprints/il5/gke-hardened/variables.tf index 0feaf5876..4b423c60f 100644 --- a/blueprints/il5/gke-hardened/variables.tf +++ b/blueprints/il5/gke-hardened/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "gatekeeper_sa" { description = "The service account Gatekeeper uses to push metrics to GCP." diff --git a/blueprints/il5/gke/README.md b/blueprints/il5/gke/README.md index 6a886dd4a..f7d565cfa 100644 --- a/blueprints/il5/gke/README.md +++ b/blueprints/il5/gke/README.md @@ -1,3 +1,19 @@ + + # GKE Cluster with Shared VPC and KMS Blueprint - [Purpose](#purpose) diff --git a/blueprints/il5/gke/main.tf b/blueprints/il5/gke/main.tf index 04378f7f1..e49eb7406 100644 --- a/blueprints/il5/gke/main.tf +++ b/blueprints/il5/gke/main.tf @@ -1,11 +1,11 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { # --- General Configuration --- # A 30-second delay to ensure IAM permissions fully propagate before dependent diff --git a/blueprints/il5/gke/outputs.tf b/blueprints/il5/gke/outputs.tf index 3d3e6fd6c..57ac6265b 100644 --- a/blueprints/il5/gke/outputs.tf +++ b/blueprints/il5/gke/outputs.tf @@ -1,11 +1,11 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "gke_cluster_endpoint" { description = "The endpoint of the GKE cluster." value = module.cluster.endpoint diff --git a/blueprints/il5/gke/provider.tf b/blueprints/il5/gke/provider.tf index babf7046f..0402bbef0 100644 --- a/blueprints/il5/gke/provider.tf +++ b/blueprints/il5/gke/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_providers { diff --git a/blueprints/il5/gke/terraform.tfvars.sample b/blueprints/il5/gke/terraform.tfvars.sample index 4b0026782..5fc59c1bf 100644 --- a/blueprints/il5/gke/terraform.tfvars.sample +++ b/blueprints/il5/gke/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + # ----------------------------------------------------------------------------- # PROJECT CONFIGURATION # ----------------------------------------------------------------------------- diff --git a/blueprints/il5/gke/variables.tf b/blueprints/il5/gke/variables.tf index 2b9679ea9..81d0abfb9 100644 --- a/blueprints/il5/gke/variables.tf +++ b/blueprints/il5/gke/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # --- Project Configuration --- variable "main_project_id" { diff --git a/blueprints/il5/kms-project/README.md b/blueprints/il5/kms-project/README.md index 7ebf1c8bb..6502e694d 100644 --- a/blueprints/il5/kms-project/README.md +++ b/blueprints/il5/kms-project/README.md @@ -1,3 +1,19 @@ + + # Cloud KMS Project Blueprint This blueprint demonstrates how to manage existing Google Cloud Key Management Service (Cloud KMS) KeyRings and CryptoKeys, applying IAM policies and potentially other configurations (like rotation policies) to them within a multi-project GCP environment. It assumes KMS infrastructure is created by a foundational layer. diff --git a/blueprints/il5/kms-project/main.tf b/blueprints/il5/kms-project/main.tf index 8be19d27e..651eac353 100644 --- a/blueprints/il5/kms-project/main.tf +++ b/blueprints/il5/kms-project/main.tf @@ -1,11 +1,11 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - data "google_project" "current" { project_id = var.main_project_id } diff --git a/blueprints/il5/kms-project/outputs.tf b/blueprints/il5/kms-project/outputs.tf index 5991dfa5f..5411a872f 100644 --- a/blueprints/il5/kms-project/outputs.tf +++ b/blueprints/il5/kms-project/outputs.tf @@ -1,11 +1,11 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "managed_keyring_id" { description = "The fully qualified ID of the existing KMS KeyRing being managed by this blueprint." value = data.google_kms_key_ring.existing_keyring.id diff --git a/blueprints/il5/kms-project/provider.tf b/blueprints/il5/kms-project/provider.tf index 7daf224f1..52d784dd3 100644 --- a/blueprints/il5/kms-project/provider.tf +++ b/blueprints/il5/kms-project/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/il5/kms-project/terraform.tfvars.sample b/blueprints/il5/kms-project/terraform.tfvars.sample index 19002b896..3724b682d 100644 --- a/blueprints/il5/kms-project/terraform.tfvars.sample +++ b/blueprints/il5/kms-project/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-main-0" # The project where IAM policies will be managed (should be the project where KMS keys reside) gcp_region = "us-east4" # The region where the existing KMS KeyRing is located diff --git a/blueprints/il5/kms-project/variables.tf b/blueprints/il5/kms-project/variables.tf index a2f089d11..70e0c73be 100644 --- a/blueprints/il5/kms-project/variables.tf +++ b/blueprints/il5/kms-project/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "main_project_id" { description = "The Google Cloud Project ID where KMS-related IAM policies will be managed (i.e., the project where the existing KMS keys reside)." diff --git a/blueprints/il5/postgresql/README.md b/blueprints/il5/postgresql/README.md index 0a40159ee..cbe1ee9e4 100644 --- a/blueprints/il5/postgresql/README.md +++ b/blueprints/il5/postgresql/README.md @@ -1,3 +1,19 @@ + + Copyright 2023 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/blueprints/il5/postgresql/main.tf b/blueprints/il5/postgresql/main.tf index 2615710d2..cfdc0e082 100644 --- a/blueprints/il5/postgresql/main.tf +++ b/blueprints/il5/postgresql/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - data "google_project" "current" {} data "google_compute_network" "network" { diff --git a/blueprints/il5/postgresql/outputs.tf b/blueprints/il5/postgresql/outputs.tf index 97c261a45..31ddc470d 100644 --- a/blueprints/il5/postgresql/outputs.tf +++ b/blueprints/il5/postgresql/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "connection_internal_ip" { value = module.postgres.ip description = "Conntection internal IP address." diff --git a/blueprints/il5/postgresql/provider.tf b/blueprints/il5/postgresql/provider.tf index 45d4ac5b9..c77df7c3b 100644 --- a/blueprints/il5/postgresql/provider.tf +++ b/blueprints/il5/postgresql/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/il5/postgresql/terraform.tfvars.sample b/blueprints/il5/postgresql/terraform.tfvars.sample index e1ef8c720..a7d64d2d1 100644 --- a/blueprints/il5/postgresql/terraform.tfvars.sample +++ b/blueprints/il5/postgresql/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-xxxx-main-0" core_project_id = "xxxx-xxxx-xxxx-iac-core-0" network_project_id = "xxxx-xxxx-net-host" diff --git a/blueprints/il5/postgresql/variables.tf b/blueprints/il5/postgresql/variables.tf index 5a6b2a9ab..ff43efaa8 100644 --- a/blueprints/il5/postgresql/variables.tf +++ b/blueprints/il5/postgresql/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "allowed_firewall_ports" { description = "Allowed firewall ports. Postgresql used 5432." type = list(number) diff --git a/blueprints/il5/private-service-connect/README.md b/blueprints/il5/private-service-connect/README.md index 337f490f9..a98305dc9 100644 --- a/blueprints/il5/private-service-connect/README.md +++ b/blueprints/il5/private-service-connect/README.md @@ -1,3 +1,19 @@ + + # PSC Blueprint This blueprint demonstrates how to deploy a Private Service Connection on Google Cloud Platform (GCP). It provides a secure and flexible solution for consumers to access managed services. diff --git a/blueprints/il5/private-service-connect/main.tf b/blueprints/il5/private-service-connect/main.tf index d4b251e4c..049e16701 100644 --- a/blueprints/il5/private-service-connect/main.tf +++ b/blueprints/il5/private-service-connect/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ module "psc" { source = "../../../modules/private-service-connect" diff --git a/blueprints/il5/private-service-connect/outputs.tf b/blueprints/il5/private-service-connect/outputs.tf index 6a9a0fb90..8abc4fa99 100644 --- a/blueprints/il5/private-service-connect/outputs.tf +++ b/blueprints/il5/private-service-connect/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "dns_zone_gcr_name" { value = module.psc.dns_zone_gcr_name diff --git a/blueprints/il5/private-service-connect/provider.tf b/blueprints/il5/private-service-connect/provider.tf index d4b6cc156..3adf5588b 100644 --- a/blueprints/il5/private-service-connect/provider.tf +++ b/blueprints/il5/private-service-connect/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/il5/private-service-connect/terraform.tfvars.sample b/blueprints/il5/private-service-connect/terraform.tfvars.sample index dfeb963d7..26510b453 100644 --- a/blueprints/il5/private-service-connect/terraform.tfvars.sample +++ b/blueprints/il5/private-service-connect/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-xxxx-main-0" region = "us-east4" network_name = "projects//global/networks/" \ No newline at end of file diff --git a/blueprints/il5/private-service-connect/variables.tf b/blueprints/il5/private-service-connect/variables.tf index 522ef5113..0c2138138 100644 --- a/blueprints/il5/private-service-connect/variables.tf +++ b/blueprints/il5/private-service-connect/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "address" { description = "The IP address of the private service connection." diff --git a/blueprints/il5/pub-sub-project/README.md b/blueprints/il5/pub-sub-project/README.md index e4fd48c31..c0bd4f9e9 100644 --- a/blueprints/il5/pub-sub-project/README.md +++ b/blueprints/il5/pub-sub-project/README.md @@ -1,3 +1,19 @@ + + # Google Cloud Pub/Sub Project Blueprint This blueprint creates a Google Cloud Pub/Sub topic and associated service accounts, configured for Customer-Managed Encryption Keys (CMEK) from an existing KMS key, and supports various subscription types. diff --git a/blueprints/il5/pub-sub-project/main.tf b/blueprints/il5/pub-sub-project/main.tf index 5267e8229..eacfdabdc 100644 --- a/blueprints/il5/pub-sub-project/main.tf +++ b/blueprints/il5/pub-sub-project/main.tf @@ -1,11 +1,11 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - data "google_project" "current" {} # Explicitly enable the Pub/Sub API diff --git a/blueprints/il5/pub-sub-project/outputs.tf b/blueprints/il5/pub-sub-project/outputs.tf index d28e2fbd0..a6dfe8db2 100644 --- a/blueprints/il5/pub-sub-project/outputs.tf +++ b/blueprints/il5/pub-sub-project/outputs.tf @@ -1,11 +1,11 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "pubsub_topic_name" { description = "The name of the created Pub/Sub topic." value = module.pubsub.name diff --git a/blueprints/il5/pub-sub-project/provider.tf b/blueprints/il5/pub-sub-project/provider.tf index 7daf224f1..52d784dd3 100644 --- a/blueprints/il5/pub-sub-project/provider.tf +++ b/blueprints/il5/pub-sub-project/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/il5/pub-sub-project/terraform.tfvars.sample b/blueprints/il5/pub-sub-project/terraform.tfvars.sample index 41ffec6d5..f323b9f70 100644 --- a/blueprints/il5/pub-sub-project/terraform.tfvars.sample +++ b/blueprints/il5/pub-sub-project/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-main-0" # The Google Cloud Project ID where the Pub/Sub topic and associated service accounts will be created. core_project_id = "xxxx-xxxx-iac-core-0" # The Google Cloud Project ID where the existing KMS KeyRing and CryptoKeys are provisioned. diff --git a/blueprints/il5/pub-sub-project/variables.tf b/blueprints/il5/pub-sub-project/variables.tf index ffe24c689..942aa55c7 100644 --- a/blueprints/il5/pub-sub-project/variables.tf +++ b/blueprints/il5/pub-sub-project/variables.tf @@ -1,11 +1,11 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "allowed_persistence_regions" { description = "A list of Google Cloud regions where messages are allowed to be stored. If empty, the topic will use the default global storage policy." type = list(string) diff --git a/blueprints/il5/shielded-vm-project/README.md b/blueprints/il5/shielded-vm-project/README.md index 3459f58aa..aef62ab5c 100644 --- a/blueprints/il5/shielded-vm-project/README.md +++ b/blueprints/il5/shielded-vm-project/README.md @@ -1,3 +1,19 @@ + + # Google Compute Shielded VM diff --git a/blueprints/il5/shielded-vm-project/main.tf b/blueprints/il5/shielded-vm-project/main.tf index 80887e5ca..243130779 100644 --- a/blueprints/il5/shielded-vm-project/main.tf +++ b/blueprints/il5/shielded-vm-project/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - data "google_project" "current" { project_id = var.main_project_id } diff --git a/blueprints/il5/shielded-vm-project/outputs.tf b/blueprints/il5/shielded-vm-project/outputs.tf index 79347380f..8d05d43cb 100644 --- a/blueprints/il5/shielded-vm-project/outputs.tf +++ b/blueprints/il5/shielded-vm-project/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "shielded-vm-instance" { description = "Instance resource." sensitive = true diff --git a/blueprints/il5/shielded-vm-project/provider.tf b/blueprints/il5/shielded-vm-project/provider.tf index 5c5403538..24b1030bd 100644 --- a/blueprints/il5/shielded-vm-project/provider.tf +++ b/blueprints/il5/shielded-vm-project/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/il5/shielded-vm-project/terraform.tfvars.sample b/blueprints/il5/shielded-vm-project/terraform.tfvars.sample index a743c9e69..8a9b0bdb5 100644 --- a/blueprints/il5/shielded-vm-project/terraform.tfvars.sample +++ b/blueprints/il5/shielded-vm-project/terraform.tfvars.sample @@ -1,3 +1,18 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ main_project_id = "xxxx-xxxx-xxxx-main-0" core_project_id = "xxxx-xxxx-xxxx-iac-core-0" diff --git a/blueprints/il5/shielded-vm-project/variables.tf b/blueprints/il5/shielded-vm-project/variables.tf index efe072710..bcf67f223 100644 --- a/blueprints/il5/shielded-vm-project/variables.tf +++ b/blueprints/il5/shielded-vm-project/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "allowed_firewall_ports" { description = "The list of the Allowed Ports." type = list(any) diff --git a/blueprints/stand-alone/vpc-peering-project/README.md b/blueprints/stand-alone/vpc-peering-project/README.md index 9cb00a33b..ea89342da 100644 --- a/blueprints/stand-alone/vpc-peering-project/README.md +++ b/blueprints/stand-alone/vpc-peering-project/README.md @@ -1,3 +1,19 @@ + + # VPC Peering Project Blueprint This blueprint provides a self-contained solution for creating two new Google Cloud VPC networks and establishing a peering connection between them. It is intended for customers who want to develop their own network infrastructure without the full Stellar Engine deployment. diff --git a/blueprints/stand-alone/vpc-peering-project/main.tf b/blueprints/stand-alone/vpc-peering-project/main.tf index d114d6c87..64bb2321d 100644 --- a/blueprints/stand-alone/vpc-peering-project/main.tf +++ b/blueprints/stand-alone/vpc-peering-project/main.tf @@ -1,11 +1,11 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { # Define the configurations for both VPCs in a map for use with for_each vpc_configs = { diff --git a/blueprints/stand-alone/vpc-peering-project/outputs.tf b/blueprints/stand-alone/vpc-peering-project/outputs.tf index 003f5fce0..dfb4b521e 100644 --- a/blueprints/stand-alone/vpc-peering-project/outputs.tf +++ b/blueprints/stand-alone/vpc-peering-project/outputs.tf @@ -1,11 +1,11 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # --- Peering Connection Outputs --- output "local_network_peering" { description = "The peering resource for the local VPC side of the connection." diff --git a/blueprints/stand-alone/vpc-peering-project/provider.tf b/blueprints/stand-alone/vpc-peering-project/provider.tf index efc88ffd9..6fe72df9c 100644 --- a/blueprints/stand-alone/vpc-peering-project/provider.tf +++ b/blueprints/stand-alone/vpc-peering-project/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/blueprints/stand-alone/vpc-peering-project/terraform.tfvars.sample b/blueprints/stand-alone/vpc-peering-project/terraform.tfvars.sample index adf7aba63..687aa0393 100644 --- a/blueprints/stand-alone/vpc-peering-project/terraform.tfvars.sample +++ b/blueprints/stand-alone/vpc-peering-project/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + main_project_id = "xxxx-xxxx-main-0" # Project ID where the peering resource will be created (can be local or peer VPC project) gcp_region = "us-east4" # Google Cloud region for both VPCs diff --git a/blueprints/stand-alone/vpc-peering-project/variables.tf b/blueprints/stand-alone/vpc-peering-project/variables.tf index c9b6367d9..ab7d328f1 100644 --- a/blueprints/stand-alone/vpc-peering-project/variables.tf +++ b/blueprints/stand-alone/vpc-peering-project/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "main_project_id" { description = "The Google Cloud Project ID where the peering connection will be managed (should be one of the VPC projects)." diff --git a/blueprints/third-party-solutions/gitlab/README.md b/blueprints/third-party-solutions/gitlab/README.md index f0bebdfb8..fdb8f5219 100644 --- a/blueprints/third-party-solutions/gitlab/README.md +++ b/blueprints/third-party-solutions/gitlab/README.md @@ -1,3 +1,19 @@ + + # Gitlab Blueprint This blueprint is responsible for provisioning a production ready Gitlab Community Edition instance on the landing zone infrastructure. The [reference architecture](https://docs.gitlab.com/ee/administration/reference_architectures/1k_users.html) of this deployment target 1K users, updates to the current code is required in of HA and/or higher capacity requirements. @@ -242,7 +258,7 @@ following [link](https://docs.gitlab.com/omnibus/settings/ssl/#configure-https-m If you want to deploy from your Cloud Shell, click on the image below, sign in if required and when the prompt appears, click on “confirm”. -[![Open Cloudshell](../../../assets/images/cloud-shell-button.png)](https://shell.cloud.google.com/cloudshell/editor?cloudshell_git_repo=https%3A%2F%2Fgithub.com%2FGoogleCloudPlatform%2Fcloud-foundation-fabric&cloudshell_workspace=blueprints%2Fthird-party-solutions%2Fwordpress%2Fcloudrun) +[**[Open in Cloud Shell]**](https://shell.cloud.google.com/cloudshell/editor?cloudshell_git_repo=https%3A%2F%2Fgithub.com%2FGoogleCloudPlatform%2Fcloud-foundation-fabric&cloudshell_workspace=blueprints%2Fthird-party-solutions%2Fwordpress%2Fcloudrun) Otherwise, in your console of choice: diff --git a/blueprints/third-party-solutions/gitlab/TODO.md b/blueprints/third-party-solutions/gitlab/TODO.md index e6eae43ec..795b08c26 100644 --- a/blueprints/third-party-solutions/gitlab/TODO.md +++ b/blueprints/third-party-solutions/gitlab/TODO.md @@ -1,3 +1,19 @@ + + # Gitlab TODOs - Integrations diff --git a/blueprints/third-party-solutions/gitlab/assets/cloud-config.yaml b/blueprints/third-party-solutions/gitlab/assets/cloud-config.yaml index cfce725eb..95b4ee0a3 100644 --- a/blueprints/third-party-solutions/gitlab/assets/cloud-config.yaml +++ b/blueprints/third-party-solutions/gitlab/assets/cloud-config.yaml @@ -1,12 +1,12 @@ #cloud-config -# Copyright 2024 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# https://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + # https://hub.docker.com/r/nginx/nginx/ # https://nginx.io/manual/toc/#installation diff --git a/blueprints/third-party-solutions/gitlab/gitlab.tf b/blueprints/third-party-solutions/gitlab/gitlab.tf index b21aeb8eb..9ec6b3079 100644 --- a/blueprints/third-party-solutions/gitlab/gitlab.tf +++ b/blueprints/third-party-solutions/gitlab/gitlab.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { gitlab_rb = templatefile("${path.module}/assets/config.rb.tpl", { project_id = module.project.project_id diff --git a/blueprints/third-party-solutions/gitlab/main.tf b/blueprints/third-party-solutions/gitlab/main.tf index 054ea8fcf..5348d9cee 100644 --- a/blueprints/third-party-solutions/gitlab/main.tf +++ b/blueprints/third-party-solutions/gitlab/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - module "project" { source = "../../../modules/project" parent = try(var.project_create.parent, null) diff --git a/blueprints/third-party-solutions/gitlab/outputs.tf b/blueprints/third-party-solutions/gitlab/outputs.tf index e578f0fc3..44f9cb4f5 100644 --- a/blueprints/third-party-solutions/gitlab/outputs.tf +++ b/blueprints/third-party-solutions/gitlab/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { ssl_certs = { "${var.gitlab_config.hostname}.crt" = local.gitlab_ssl_crt diff --git a/blueprints/third-party-solutions/gitlab/services.tf b/blueprints/third-party-solutions/gitlab/services.tf index 54b09eb37..36d2a0418 100644 --- a/blueprints/third-party-solutions/gitlab/services.tf +++ b/blueprints/third-party-solutions/gitlab/services.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,8 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - - locals { gitlab_buckets = [ "gitlab-artifacts", "gitlab-mr-diffs", "gitlab-lfs", "gitlab-uploads", diff --git a/blueprints/third-party-solutions/gitlab/ssl.tf b/blueprints/third-party-solutions/gitlab/ssl.tf index a1ae9a6cd..c53ee3fbc 100644 --- a/blueprints/third-party-solutions/gitlab/ssl.tf +++ b/blueprints/third-party-solutions/gitlab/ssl.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { cert_subjects = [ { diff --git a/blueprints/third-party-solutions/gitlab/terraform.tfvars.sample b/blueprints/third-party-solutions/gitlab/terraform.tfvars.sample index e76642af4..b8b6b5532 100644 --- a/blueprints/third-party-solutions/gitlab/terraform.tfvars.sample +++ b/blueprints/third-party-solutions/gitlab/terraform.tfvars.sample @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + gitlab_config = { hostname = "gitlab.gcp.example.com" mail = { diff --git a/blueprints/third-party-solutions/gitlab/variables.tf b/blueprints/third-party-solutions/gitlab/variables.tf index 7d6d24455..220178b72 100644 --- a/blueprints/third-party-solutions/gitlab/variables.tf +++ b/blueprints/third-party-solutions/gitlab/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "admin_principals" { description = "Users, groups and/or service accounts that are assigned roles, in IAM format (`group:foo@example.com`)." type = list(string) diff --git a/default-versions.tf b/default-versions.tf index 3d6a43260..f4fe2dc01 100644 --- a/default-versions.tf +++ b/default-versions.tf @@ -1,16 +1,18 @@ -# Copyright 2024 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index b16bd9442..98acf7207 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -1,3 +1,19 @@ + + # How to contribute We'd love to accept your patches and contributions to this project. diff --git a/docs/code-of-conduct.md b/docs/code-of-conduct.md index a85d5a02a..41165c907 100644 --- a/docs/code-of-conduct.md +++ b/docs/code-of-conduct.md @@ -1,3 +1,19 @@ + + # Code of Conduct ## Our Pledge diff --git a/docs/ddg.md b/docs/ddg.md index 9bd794692..2f2b7cc81 100644 --- a/docs/ddg.md +++ b/docs/ddg.md @@ -1,3 +1,19 @@ + + # **Stellar Engine** Cloud Foundation Fabric Detailed Deployment Guide @@ -42,7 +58,7 @@ it easy to copy and paste. The deployment process is broken up into stages. During each stage, certain variables are required to be added to the **`terraform.tfvars`** file. Upon completion of a stage, the Terraform code will write out a **```-tfvar.auto.tfvars.json`** file to the Google Cloud Storage -(GCS) bucket created in the initial **0-bootstrap stage**. Subsequent stages +(GCS) bucket created in the initial **0-organization-bootstrap stage**. Subsequent stages will use the **gcloud** command line interface (CLI) to copy the files into the new stage folder, as well as a provider file that impersonates a stage-specific service account. @@ -61,7 +77,7 @@ takes approximately 1 hour. To make using this deployment guide easier, the variables described below need to be populated into specific `terraform.tfvars` files in the repository. -**Most of these variables are configured in the Stage 0 Bootstrap `terraform.tfvars` file (a sample can be found at [`fast/stages-aw/0-bootstrap/terraform.tfvars.sample`](../fast/stages-aw/0-bootstrap/terraform.tfvars.sample)), except for the Tenant names, which are configured in Stage 1 (a sample can be found at [`fast/stages-aw/1-resman/terraform.tfvars.sample`](../fast/stages-aw/1-resman/terraform.tfvars.sample)).** +**Most of these variables are configured in the Stage 0 Bootstrap `terraform.tfvars` file (a sample can be found at [`fast/stages-aw/0-organization-bootstrap/terraform.tfvars.sample`](../fast/stages-aw/0-organization-bootstrap/terraform.tfvars.sample)), except for the Tenant names, which are configured in Stage 1 (a sample can be found at [`fast/stages-aw/2-resman/terraform.tfvars.sample`](../fast/stages-aw/2-resman/terraform.tfvars.sample)).** | VARIABLE | TFVARS LOCATION | DESCRIPTION | | :------------------------------------ | :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | @@ -134,7 +150,7 @@ permissions.** automated by running the following script: - **Warning: You will lose all current permissions for your user besides Super User** - - **./setIam.sh \ ``** from within the fast/stages-aw/0-bootstrap folder + - **./setIam.sh \ ``** from within the fast/stages-aw/0-organization-bootstrap folder - Navigate to the [Super Admin](https://admin.google.com/ac/roles) roles section in Google Workspace to ensure that the deploying user is a Super @@ -158,7 +174,7 @@ permissions.** - gcp-security-admins@`` - We need to enable these Google Cloud Services by running the following script: - - fast/stages-aw/0-bootstrap/enableServices.sh + - fast/stages-aw/0-organization-bootstrap/enableServices.sh - If you run into issues with the above command, you can simply run the following deprecated command (on MacOS, works on other *nix variants) - `echo "iam cloudkms pubsub serviceusage cloudresourcemanager bigquery assuredworkloads cloudbilling logging iamcredentials orgpolicy" | xargs -n1 -I {} gcloud services enable "{}.googleapis.com”` - [Enable Access @@ -186,15 +202,15 @@ state. - Enable [billing](https://console.cloud.google.com/billing/projects) for your bootstrap project if it is not enabled -- Change directory into **fast/stages-aw/0-bootstrap** +- Change directory into **fast/stages-aw/0-organization-bootstrap** - Copy file **terraform.tfvars.sample** to **terraform.tfvars** - `cp terraform.tfvars.sample terraform.tfvars` -- Copy file **providers.tf.tmp** to **0-bootstrap-providers.tf** - - `cp providers.tf.tmp 0-bootstrap-providers.tf` +- Copy file **providers.tf.tmp** to **0-organization-bootstrap-providers.tf** + - `cp providers.tf.tmp 0-organization-bootstrap-providers.tf` - Update information in **terraform.tfvars** as follows below, the variables from the above sections are already included -**`fast/stages-aw/0-bootstrap/terraform.tfvars`** +**`fast/stages-aw/0-organization-bootstrap/terraform.tfvars`** ```hcl # use `gcloud beta billing accounts list` @@ -256,7 +272,7 @@ alert_email = "``" - Export the prefix as an environment variable to simplify subsequent commands: - `export FAST_PREFIX=$(sed -n 's/^[[:space:]]*prefix[[:space:]]*=[[:space:]]*"\(.*\)"/\1/p' terraform.tfvars)` - **Note:** If you open a new terminal or change directories during the deployment, you can re-run this command from the repository root to restore the variable: - - `export FAST_PREFIX=$(sed -n 's/^[[:space:]]*prefix[[:space:]]*=[[:space:]]*"\(.*\)"/\1/p' $(git rev-parse --show-toplevel)/fast/stages-aw/0-bootstrap/terraform.tfvars)` + - `export FAST_PREFIX=$(sed -n 's/^[[:space:]]*prefix[[:space:]]*=[[:space:]]*"\(.*\)"/\1/p' $(git rev-parse --show-toplevel)/fast/stages-aw/0-organization-bootstrap/terraform.tfvars)` - Run `terraform init` - Run `terraform apply -var bootstrap_user=$(gcloud config list --format 'value(core.account)')` - Type `yes` when prompted @@ -278,7 +294,7 @@ alert_email = "``" - Switch project to your new project - `gcloud config set project ${FAST_PREFIX}-prod-iac-core-0` - Copy the new providers local - - `gcloud storage cp gs://${FAST_PREFIX}-prod-iac-core-outputs-0/providers/0-bootstrap-providers.tf ./` + - `gcloud storage cp gs://${FAST_PREFIX}-prod-iac-core-outputs-0/providers/0-organization-bootstrap-providers.tf ./` - Migrate the state from local to remote using - `terraform init --migrate-state` - Type `yes` when prompted @@ -294,20 +310,20 @@ alert_email = "``" In this stage, we begin to build out the different folders, projects, and service accounts that will be used at the organization level for subsequent stages. In order to build out the environment, you will have to update the -**terraform.tfvars** file in **fast/stages-aw/1-resman** to include a tenants +**terraform.tfvars** file in **fast/stages-aw/2-resman** to include a tenants variable as seen below. ### Steps - **Note:** If you are using an environment variable for the prefix, make sure it is set: - - `export FAST_PREFIX=$(sed -n 's/^[[:space:]]*prefix[[:space:]]*=[[:space:]]*"\(.*\)"/\1/p' $(git rev-parse --show-toplevel)/fast/stages-aw/0-bootstrap/terraform.tfvars)` + - `export FAST_PREFIX=$(sed -n 's/^[[:space:]]*prefix[[:space:]]*=[[:space:]]*"\(.*\)"/\1/p' $(git rev-parse --show-toplevel)/fast/stages-aw/0-organization-bootstrap/terraform.tfvars)` - **Note:** If you are using an external billing account, you have to add the Billing Account Administrator for the following service account to the external billing account: - **``-prod-resman-0@``-prod-iac-core-0.iam.gserviceaccount.com** - **Note:** If you are using an external billing account where the resman service account cannot be granted billing permissions, you can use a **billing override** to run the project creation/billing links under your personal credentials. -To do this, define the `billing_override` variable in your **fast/stages-aw/1-resman/terraform.tfvars**: +To do this, define the `billing_override` variable in your **fast/stages-aw/2-resman/terraform.tfvars**: ```hcl billing_override = { @@ -330,13 +346,13 @@ To do this, define the `billing_override` variable in your **fast/stages-aw/1-re - Select a permission for the principal(s) from Select a role as “Billing Account Administrator”. - When done, click Save. -- Change directory into **fast/stages-aw/1-resman** +- Change directory into **fast/stages-aw/2-resman** - Copy file **terraform.tfvars.sample** to **terraform.tfvars** - `cp terraform.tfvars.sample terraform.tfvars` - Update information in **terraform.tfvars** as follows - Note: Change “tenant_name(s)” below -**`fast/stages-aw/1-resman/terraform.tfvars`** +**`fast/stages-aw/2-resman/terraform.tfvars`** ```hcl tenants = { @@ -376,9 +392,9 @@ envs_folders = { - Copy the tfvars files from GCS ``` -gcloud storage cp gs://${FAST_PREFIX}-prod-iac-core-outputs-0/providers/1-resman-providers.tf ./ && +gcloud storage cp gs://${FAST_PREFIX}-prod-iac-core-outputs-0/providers/2-resman-providers.tf ./ && gcloud storage cp gs://${FAST_PREFIX}-prod-iac-core-outputs-0/tfvars/0-globals.auto.tfvars.json ./ && -gcloud storage cp gs://${FAST_PREFIX}-prod-iac-core-outputs-0/tfvars/0-bootstrap.auto.tfvars.json ./ +gcloud storage cp gs://${FAST_PREFIX}-prod-iac-core-outputs-0/tfvars/0-organization-bootstrap.auto.tfvars.json ./ ``` - Run `terraform init` - Run `terraform apply` @@ -391,14 +407,14 @@ gcloud storage cp gs://${FAST_PREFIX}-prod-iac-core-outputs-0/tfvars/0-bootstrap ### Steps - **Note:** If you are using an environment variable for the prefix, make sure it is set: - - `export FAST_PREFIX=$(sed -n 's/^[[:space:]]*prefix[[:space:]]*=[[:space:]]*"\(.*\)"/\1/p' $(git rev-parse --show-toplevel)/fast/stages-aw/0-bootstrap/terraform.tfvars)` + - `export FAST_PREFIX=$(sed -n 's/^[[:space:]]*prefix[[:space:]]*=[[:space:]]*"\(.*\)"/\1/p' $(git rev-parse --show-toplevel)/fast/stages-aw/0-organization-bootstrap/terraform.tfvars)` - **Note:** If you are using an external billing account, you have to add the Billing Account Administrator for the following service account to the external billing account: - **``-prod-resman-net-0@``-prod-iac-core-0.iam.gserviceaccount.com** - **Note:** If you are using an external billing account where the networking service account cannot be granted billing permissions, you can use a **billing override** to run the project creation/billing links under your personal credentials. -To do this, define the `billing_override` variable in **fast/stages-aw/1-resman/terraform.tfvars** file +To do this, define the `billing_override` variable in **fast/stages-aw/2-resman/terraform.tfvars** file ```hcl billing_override = { @@ -426,8 +442,8 @@ To do this, define the `billing_override` variable in **fast/stages-aw/1-resman/ ```bash gcloud storage cp gs://${FAST_PREFIX}-prod-iac-core-outputs-0/providers/2-networking-providers.tf ./ && \ gcloud storage cp gs://${FAST_PREFIX}-prod-iac-core-outputs-0/tfvars/0-globals.auto.tfvars.json ./ && \ -gcloud storage cp gs://${FAST_PREFIX}-prod-iac-core-outputs-0/tfvars/0-bootstrap.auto.tfvars.json ./ && \ -gcloud storage cp gs://${FAST_PREFIX}-prod-iac-core-outputs-0/tfvars/1-resman.auto.tfvars.json ./ +gcloud storage cp gs://${FAST_PREFIX}-prod-iac-core-outputs-0/tfvars/0-organization-bootstrap.auto.tfvars.json ./ && \ +gcloud storage cp gs://${FAST_PREFIX}-prod-iac-core-outputs-0/tfvars/2-resman.auto.tfvars.json ./ ``` - Copy the sample `terraform.tfvars` file and configure your network settings: - `cp terraform.tfvars.sample terraform.tfvars` @@ -449,14 +465,14 @@ a VM code and register them. For more instructions, see the README in the the ### Steps - **Note:** If you are using an environment variable for the prefix, make sure it is set: - - `export FAST_PREFIX=$(sed -n 's/^[[:space:]]*prefix[[:space:]]*=[[:space:]]*"\(.*\)"/\1/p' $(git rev-parse --show-toplevel)/fast/stages-aw/0-bootstrap/terraform.tfvars)` + - `export FAST_PREFIX=$(sed -n 's/^[[:space:]]*prefix[[:space:]]*=[[:space:]]*"\(.*\)"/\1/p' $(git rev-parse --show-toplevel)/fast/stages-aw/0-organization-bootstrap/terraform.tfvars)` - **Note:** If you are using an external billing account, you have to add the Billing Account Administrator for the following service account to the external billing account: - **``-prod-resman-net-0@``-prod-iac-core-0.iam.gserviceaccount.com** - **Note:** If you are using an external billing account where the networking service account cannot be granted billing permissions, you can use a **billing override** to run the project creation/billing links under your personal credentials. -To do this, define the `billing_override` variable in **fast/stages-aw/1-resman/terraform.tfvars** file +To do this, define the `billing_override` variable in **fast/stages-aw/2-resman/terraform.tfvars** file ```hcl billing_override = { @@ -484,8 +500,8 @@ To do this, define the `billing_override` variable in **fast/stages-aw/1-resman/ ```bash gcloud storage cp gs://${FAST_PREFIX}-prod-iac-core-outputs-0/providers/2-networking-providers.tf ./ && \ gcloud storage cp gs://${FAST_PREFIX}-prod-iac-core-outputs-0/tfvars/0-globals.auto.tfvars.json ./ && \ -gcloud storage cp gs://${FAST_PREFIX}-prod-iac-core-outputs-0/tfvars/0-bootstrap.auto.tfvars.json ./ && \ -gcloud storage cp gs://${FAST_PREFIX}-prod-iac-core-outputs-0/tfvars/1-resman.auto.tfvars.json ./ +gcloud storage cp gs://${FAST_PREFIX}-prod-iac-core-outputs-0/tfvars/0-organization-bootstrap.auto.tfvars.json ./ && \ +gcloud storage cp gs://${FAST_PREFIX}-prod-iac-core-outputs-0/tfvars/2-resman.auto.tfvars.json ./ ``` - Copy the sample `terraform.tfvars` file and configure your network settings: - `cp terraform.tfvars.sample terraform.tfvars` @@ -539,14 +555,14 @@ are responsible for the audit project. ### Steps - **Note:** If you are using an environment variable for the prefix, make sure it is set: - - `export FAST_PREFIX=$(sed -n 's/^[[:space:]]*prefix[[:space:]]*=[[:space:]]*"\(.*\)"/\1/p' $(git rev-parse --show-toplevel)/fast/stages-aw/0-bootstrap/terraform.tfvars)` + - `export FAST_PREFIX=$(sed -n 's/^[[:space:]]*prefix[[:space:]]*=[[:space:]]*"\(.*\)"/\1/p' $(git rev-parse --show-toplevel)/fast/stages-aw/0-organization-bootstrap/terraform.tfvars)` - **Note:** If you are using an external billing account, you have to add the Billing Account Administrator for the following service account to the external billing account:** - ``-security-0@``-prod-iac-core-0.iam.gserviceaccount.com - **Note:** If you are using an external billing account where the networking service account cannot be granted billing permissions, you can use a **billing override** to run the project creation/billing links under your personal credentials. -To do this, define the `billing_override` variable in **fast/stages-aw/1-resman/terraform.tfvars** file +To do this, define the `billing_override` variable in **fast/stages-aw/2-resman/terraform.tfvars** file ```hcl billing_override = { @@ -574,8 +590,8 @@ To do this, define the `billing_override` variable in **fast/stages-aw/1-resman/ ``` gcloud storage cp gs://${FAST_PREFIX}-prod-iac-core-outputs-0/providers/3-security-providers.tf ./ && gcloud storage cp gs://${FAST_PREFIX}-prod-iac-core-outputs-0/tfvars/0-globals.auto.tfvars.json ./ && -gcloud storage cp gs://${FAST_PREFIX}-prod-iac-core-outputs-0/tfvars/0-bootstrap.auto.tfvars.json ./ && -gcloud storage cp gs://${FAST_PREFIX}-prod-iac-core-outputs-0/tfvars/1-resman.auto.tfvars.json ./ +gcloud storage cp gs://${FAST_PREFIX}-prod-iac-core-outputs-0/tfvars/0-organization-bootstrap.auto.tfvars.json ./ && +gcloud storage cp gs://${FAST_PREFIX}-prod-iac-core-outputs-0/tfvars/2-resman.auto.tfvars.json ./ ``` - Run `terraform init` - Run `terraform apply` @@ -622,8 +638,8 @@ Perform the following steps when adding or removing tenants projects for an exis - Change directory into fast/stages-aw/3-security - `./sa_lockdown.sh --enable` -#### Apply FAST Stage: 01-resman -- Change directory into fast/stages-aw/1-resman +#### Apply FAST Stage: 02-resman +- Change directory into fast/stages-aw/2-resman - Update information in terraform.tfvars to your new requirements - Run terraform init - Run terraform apply @@ -633,8 +649,8 @@ Perform the following steps when adding or removing tenants projects for an exis - Change directory into appropriate network folder for your Stellar Engine deployment: - fast/stages-aw/2-networking-a-fedramp-high - fast/stages-aw/2-networking-b-il5-ngfw -- Copy the 1-resman 1-resman tfvars file from the GCS bucket - - `gcloud storage cp gs://${FAST_PREFIX}-prod-iac-core-outputs-0/tfvars/1-resman.auto.tfvars.json ./` +- Copy the 2-resman 2-resman tfvars file from the GCS bucket + - `gcloud storage cp gs://${FAST_PREFIX}-prod-iac-core-outputs-0/tfvars/2-resman.auto.tfvars.json ./` - Run terraform init - Run terraform apply - Type yes when prompted diff --git a/docs/path-to-authorization.md b/docs/path-to-authorization.md index 7d4e39853..65364fe83 100644 --- a/docs/path-to-authorization.md +++ b/docs/path-to-authorization.md @@ -1,3 +1,19 @@ + + # Path to Authorization _Impact Level 5 (H-H-X) & FedRAMP High_ diff --git a/docs/runbooks/compromised-iam-credentials.md b/docs/runbooks/compromised-iam-credentials.md index 4f725d5d0..922feaa78 100644 --- a/docs/runbooks/compromised-iam-credentials.md +++ b/docs/runbooks/compromised-iam-credentials.md @@ -1,3 +1,19 @@ + + # Incident Response Runbook: Compromised IAM Credentials ## Document Control diff --git a/docs/runbooks/compute-resource-compromise.md b/docs/runbooks/compute-resource-compromise.md index c1122624e..b7777e53d 100644 --- a/docs/runbooks/compute-resource-compromise.md +++ b/docs/runbooks/compute-resource-compromise.md @@ -1,3 +1,19 @@ + + # Incident Response Runbook: Compute Resource Compromise ## Document Control diff --git a/docs/runbooks/customer-managed-encryption-keys-compromise.md b/docs/runbooks/customer-managed-encryption-keys-compromise.md index 07fbb47a2..18ceac13f 100644 --- a/docs/runbooks/customer-managed-encryption-keys-compromise.md +++ b/docs/runbooks/customer-managed-encryption-keys-compromise.md @@ -1,3 +1,19 @@ + + # Incident Response Runbook: Customer Managed Encryption Keys (CMEK) Compromise or Loss ## Document Control diff --git a/docs/runbooks/incident_response_runbook_template.md b/docs/runbooks/incident_response_runbook_template.md index 5de375c17..3c05cd05a 100644 --- a/docs/runbooks/incident_response_runbook_template.md +++ b/docs/runbooks/incident_response_runbook_template.md @@ -1,3 +1,19 @@ + + # Incident Response Runbook: [Threat Scenario Title] ## Document Control diff --git a/docs/runbooks/network-intrusion-detected.md b/docs/runbooks/network-intrusion-detected.md index 5e4ebb16b..e0ec4949a 100644 --- a/docs/runbooks/network-intrusion-detected.md +++ b/docs/runbooks/network-intrusion-detected.md @@ -1,3 +1,19 @@ + + # Incident Response Runbook: Network Intrusion Detected ## Document Control diff --git a/docs/runbooks/vpc-service-controls-violation.md b/docs/runbooks/vpc-service-controls-violation.md index 6134b3d1c..ede480453 100644 --- a/docs/runbooks/vpc-service-controls-violation.md +++ b/docs/runbooks/vpc-service-controls-violation.md @@ -1,3 +1,19 @@ + + # Incident Response Runbook: VPC Service Controls (VPC-SC) Perimeter Violations ## Document Control diff --git a/docs/scc-deployment-guide.md b/docs/scc-deployment-guide.md index e76e9f887..370405a60 100644 --- a/docs/scc-deployment-guide.md +++ b/docs/scc-deployment-guide.md @@ -1,3 +1,19 @@ + + # Stellar Engine: Security Command Center (SCC) Deployment Guide Procedures to deploy Security Command Center into a Stellar Engine deployment diff --git a/docs/security-best-practices.md b/docs/security-best-practices.md index 5b7e91ef6..78f851254 100644 --- a/docs/security-best-practices.md +++ b/docs/security-best-practices.md @@ -1,3 +1,19 @@ + + # SE Security Best Practices Guide **Created Date:** Nov 21, 2024 diff --git a/docs/tdd.md b/docs/tdd.md index 4014e2b4e..3b4451520 100644 --- a/docs/tdd.md +++ b/docs/tdd.md @@ -1,3 +1,19 @@ + + # **Stellar Engine** Technical Design Document diff --git a/documentation/naming-convention.md b/documentation/naming-convention.md index ef867bd9c..c1c09e186 100644 --- a/documentation/naming-convention.md +++ b/documentation/naming-convention.md @@ -1,3 +1,19 @@ + + # Google Cloud Naming Convention Google Cloud services and assets have strict naming conventions in the form of character count, capitalization or lowercase, dashes, hyphens, underscores and reserved internal words. There are also several Google Cloud services that require globally unique naming to avoid collisions, while also forever "burning" the name so it cannot be used again ever, anywhere on Google Cloud. diff --git a/fast/README.md b/fast/README.md index dbf98affe..b549e5539 100644 --- a/fast/README.md +++ b/fast/README.md @@ -1,3 +1,19 @@ + + # Stellar Engine FAST Security _Documenting the desired infrastructure state of the `/fast/stages-aw/3-security` Terraform codebase._ @@ -44,11 +60,11 @@ FAST also aims to minimize the number of permissions granted to principals accor A resource factory consumes a simple representation of a resource (e.g., in YAML) and deploys it (e.g., using Terraform). Used correctly, factories can help decrease the management overhead of large-scale infrastructure deployments. See "[Resource Factories: A descriptive approach to Terraform](https://medium.com/google-cloud/resource-factories-a-descriptive-approach-to-terraform-581b3ebb59c)" for more details and the rationale behind factories. -FAST uses YAML-based factories to deploy subnets and firewall rules and, as its name suggests, in the [project factory](./stages/3-project-factory/) stage. +FAST uses YAML-based factories to deploy subnets and firewall rules and, as its name suggests, in the [project factory](./stages-aw/5-tenants/) stage. ### CI/CD -One of our objectives with FAST is to provide a lightweight reference design for the IaC repositories, and a built-in implementation for running our code in automated pipelines. Our CI/CD approach leverages [Workload Identity Federation](https://cloud.google.com/iam/docs/workload-identity-federation), and provides sample workflow configurations for several major providers. Refer to the [CI/CD section in the bootstrap stage](./stages/0-bootstrap/README.md#cicd) for more details. We also provide separate [optional small stages](./extras/) to help you configure your CI/CD provider. +One of our objectives with FAST is to provide a lightweight reference design for the IaC repositories, and a built-in implementation for running our code in automated pipelines. Our CI/CD approach leverages [Workload Identity Federation](https://cloud.google.com/iam/docs/workload-identity-federation), and provides sample workflow configurations for several major providers. Refer to the [CI/CD section in the bootstrap stage](./0-organization-bootstrap/README.md#cicd) for more details. We also provide separate [optional small stages](./stages-aw/shared-services/) to help you configure your CI/CD provider. ## Implementation diff --git a/fast/assets/schemas/firewall_rules.schema.yaml b/fast/assets/schemas/firewall_rules.schema.yaml index 74aba4b5e..493abe404 100644 --- a/fast/assets/schemas/firewall_rules.schema.yaml +++ b/fast/assets/schemas/firewall_rules.schema.yaml @@ -1,10 +1,10 @@ -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + egress: map(include('firewall_rule'), required=False) ingress: map(include('firewall_rule'), required=False) --- diff --git a/fast/assets/schemas/hierarchical_rules.schema.yaml b/fast/assets/schemas/hierarchical_rules.schema.yaml index ad49bfa57..2546d1c43 100644 --- a/fast/assets/schemas/hierarchical_rules.schema.yaml +++ b/fast/assets/schemas/hierarchical_rules.schema.yaml @@ -1,10 +1,10 @@ -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + map(include('hierarchical_rule')) --- hierarchical_rule: diff --git a/fast/assets/schemas/project.schema.yaml b/fast/assets/schemas/project.schema.yaml index 2b3f14b3a..943361a67 100644 --- a/fast/assets/schemas/project.schema.yaml +++ b/fast/assets/schemas/project.schema.yaml @@ -1,10 +1,10 @@ -# Copyright 2024 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + billing_account_id: str(matches='[A-F0-9]{6}-[A-F0-9]{6}-[A-F0-9]{6}', required=False) billing_alert: any(include('billing_alert'), null(), required=False) # If set to null, use defaults dns_zones: list(str(), required=False) diff --git a/fast/assets/schemas/project_defaults.schema.yaml b/fast/assets/schemas/project_defaults.schema.yaml index 32e98ffc6..4a6c2cc65 100644 --- a/fast/assets/schemas/project_defaults.schema.yaml +++ b/fast/assets/schemas/project_defaults.schema.yaml @@ -1,10 +1,10 @@ -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + billing_account_id: str(matches='[A-F0-9]{6}-[A-F0-9]{6}-[A-F0-9]{6}', required=False) billing_alert: any(include('billing_alert'), null(), required=False) essential_contacts: list(str(), required=False) diff --git a/fast/assets/schemas/subnet.schema.yaml b/fast/assets/schemas/subnet.schema.yaml index cc5aa10d7..8d0785d95 100644 --- a/fast/assets/schemas/subnet.schema.yaml +++ b/fast/assets/schemas/subnet.schema.yaml @@ -1,10 +1,10 @@ -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + region: str() description: str() ip_cidr_range: str() diff --git a/fast/assets/templates/workflow-github.yaml b/fast/assets/templates/workflow-github.yaml index 4fa5a3359..f9fbf0c80 100644 --- a/fast/assets/templates/workflow-github.yaml +++ b/fast/assets/templates/workflow-github.yaml @@ -1,10 +1,10 @@ -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + name: "FAST ${stage_name} stage" on: diff --git a/fast/assets/templates/workflow-gitlab.yaml b/fast/assets/templates/workflow-gitlab.yaml index c50f8e58e..ac847ef31 100644 --- a/fast/assets/templates/workflow-gitlab.yaml +++ b/fast/assets/templates/workflow-gitlab.yaml @@ -1,10 +1,10 @@ -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + variables: GOOGLE_CREDENTIALS: cicd-sa-credentials.json FAST_OUTPUTS_BUCKET: ${outputs_bucket} diff --git a/fast/assets/templates/workflow-sourcerepo.yaml b/fast/assets/templates/workflow-sourcerepo.yaml index 88c04fac5..58c0b4701 100644 --- a/fast/assets/templates/workflow-sourcerepo.yaml +++ b/fast/assets/templates/workflow-sourcerepo.yaml @@ -1,10 +1,10 @@ -# Copyright 2024 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + steps: - name: alpine:3 id: tf-download diff --git a/fast/docs/0-bootstram-user-iam.md b/fast/docs/0-bootstram-user-iam.md index 51fa31ab2..68c04cc80 100644 --- a/fast/docs/0-bootstram-user-iam.md +++ b/fast/docs/0-bootstram-user-iam.md @@ -1,3 +1,19 @@ + + # Remove initial gcloud commands needed to bootstrap **authors:** [Ludo](https://github.com/ludoo)\ diff --git a/fast/docs/0-cicd-plan-sa.md b/fast/docs/0-cicd-plan-sa.md index 944dea5f8..ba19a8c1d 100644 --- a/fast/docs/0-cicd-plan-sa.md +++ b/fast/docs/0-cicd-plan-sa.md @@ -1,3 +1,19 @@ + + # Add new service accounts for CI/CD with plan-only permissions **authors:** [Ludo](https://github.com/ludoo) \ diff --git a/fast/docs/0-domainless-iam.md b/fast/docs/0-domainless-iam.md index cfe3e9f19..1bf170716 100644 --- a/fast/docs/0-domainless-iam.md +++ b/fast/docs/0-domainless-iam.md @@ -1,3 +1,19 @@ + + # Support for domain-less organizations **authors:** [Ludo](https://github.com/ludoo) \ diff --git a/fast/docs/0-org-policies.md b/fast/docs/0-org-policies.md index e7d58ae57..4605bd78c 100644 --- a/fast/docs/0-org-policies.md +++ b/fast/docs/0-org-policies.md @@ -1,3 +1,19 @@ + + # Move organization policies to bootstrap stage **authors:** [Julio](https://github.com/juliocc), [Ludo](https://github.com/ludoo), [Roberto](https://github.com/drebes) \ diff --git a/fast/docs/1-network-ranges.md b/fast/docs/1-network-ranges.md index 2a5c64754..f19169271 100644 --- a/fast/docs/1-network-ranges.md +++ b/fast/docs/1-network-ranges.md @@ -1,3 +1,19 @@ + + # IP ranges for network stages **authors:** [Ludo](https://github.com/ludoo), [Roberto](https://github.com/drebes), [Julio](https://github.com/jccb) \ diff --git a/fast/docs/README.md b/fast/docs/README.md index d6c722c23..5e2cb2194 100644 --- a/fast/docs/README.md +++ b/fast/docs/README.md @@ -1,3 +1,19 @@ + + # FAST architectural documents This folder contains assorted bits of documentation used to log current architectural choices, or past decisions. Format is inspired by [Michael Nygard's decision record template](https://github.com/joelparkerhenderson/architecture-decision-record/blob/main/templates/decision-record-template-by-michael-nygard/index.md). diff --git a/fast/stage-links.sh b/fast/stage-links.sh index 7c1ba5686..a3eda8d96 100755 --- a/fast/stage-links.sh +++ b/fast/stage-links.sh @@ -1,11 +1,11 @@ #!/bin/bash -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + if [ $# -eq 0 ]; then echo "Error: no folder or GCS bucket specified. Use -h or --help for usage." exit 1 diff --git a/fast/stages-aw/0-bootstrap/budgets.tf b/fast/stages-aw/0-bootstrap/budgets.tf deleted file mode 100644 index a4fb0aa24..000000000 --- a/fast/stages-aw/0-bootstrap/budgets.tf +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright 2026 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -# tfdoc:file:description Billing budgets. - -locals { - folder_name = var.assured_workloads.regime != "COMPLIANCE_REGIME_UNSPECIFIED" ? "${google_assured_workloads_workload.primary[0].display_name}" : "${module.no-compliance-folder[0].folder.name}" -} - -module "billing-account-budget" { - source = "../../../modules/billing-account" - count = var.billing_budget_amount != null ? 1 : 0 - id = var.billing_account.id - budgets = { - aw-folder-budget = { - display_name = "Budget for ${local.folder_name} Folder" - amount = { - units = var.billing_budget_amount.amount - } - threshold_rules = [ - for t in var.billing_budget_amount.threshold_rules : { - percent = t - } - ] - filter = { - resource_ancestors = [ - var.assured_workloads.regime != "COMPLIANCE_REGIME_UNSPECIFIED" - ? "folders/${google_assured_workloads_workload.primary[0].resources[0].resource_id}" - : module.no-compliance-folder[0].folder.id - ] - } - } - } -} diff --git a/fast/stages-aw/0-bootstrap/data/custom-constraint-policies/cloudkms.yaml b/fast/stages-aw/0-bootstrap/data/custom-constraint-policies/cloudkms.yaml deleted file mode 100644 index c43323ce1..000000000 --- a/fast/stages-aw/0-bootstrap/data/custom-constraint-policies/cloudkms.yaml +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This prevents users from creating keys that are not CIS compliant -# Keys must be rotated within a period of 90 days (CIS Compliance Benchmark 1.10) -# SHOULD HAVE - -custom.kmsRotation: - name: Enforce maximum rotation period for KMS keys - display_name: Enforce maximum rotation period for KMS keys - action_type: ALLOW - resource_types: - - cloudkms.googleapis.com/CryptoKey - method_types: - - CREATE - - UPDATE - condition: "((resource.rotationPeriod != duration('0s')) && (resource.rotationPeriod <= duration('7776000s')))" - description: The rotation period for Cloud KMS keys must be set to 90 days or less. \ No newline at end of file diff --git a/fast/stages-aw/0-bootstrap/data/custom-constraint-policies/networking.yaml b/fast/stages-aw/0-bootstrap/data/custom-constraint-policies/networking.yaml deleted file mode 100644 index 51144cb03..000000000 --- a/fast/stages-aw/0-bootstrap/data/custom-constraint-policies/networking.yaml +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This prevents users from creating firewall rules that allow traffic from 0.0.0.0/0 -# Rules must explicitly allow smaller subnets, or preferably tags -# COULD HAVE - -custom.restrictFirewallRanges: - name: Restrict Firewall rules using the source-range 0.0.0.0/0 - display_name: Restrict Firewall rules using the source-range 0.0.0.0/0 - action_type: DENY - resource_types: - - compute.googleapis.com/Firewall - method_types: - - CREATE - - UPDATE - condition: "resource.direction.matches('INGRESS') && resource.sourceRanges.all(range, range == '0.0.0.0/0') && resource.allowed.exists(entry, entry != null)" - description: Firewall rules must be more specific than 0.0.0.0/0. diff --git a/fast/stages-aw/0-bootstrap/import.sh b/fast/stages-aw/0-bootstrap/import.sh deleted file mode 100755 index 8e77b1a10..000000000 --- a/fast/stages-aw/0-bootstrap/import.sh +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/env bash -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Assign Organization ID -ORG=$(gcloud organizations list --format='value(ID)') -if [[ -z "${ORG}" ]]; then - echo "Error: Failed to get organization ID." >&2 - exit 1 -fi - -# Import Organization Policies - get all existing policies -policies=$(gcloud org-policies list \ - --organization="${ORG}" \ - --format='value(constraint)' 2>/dev/null) - -if [[ -z "${policies}" ]]; then - echo "No existing organization policies found to import. This is normal for a fresh deployment." - exit 0 -fi - -echo "Fetching current Terraform state list..." -state_list=$(terraform state list 2>/dev/null) - -rm -f imports.tf -import_count=0 - -# Policy Iteration -while IFS= read -r constraint_path; do - constraint_name=${constraint_path##*/} - constraint_self_link="organizations/${ORG}/policies/${constraint_name}" - target_resource="module.organization.google_org_policy_policy.default[\"${constraint_name}\"]" - - # Check if constraint is declared in local configuration files - if ! grep -rq "^${constraint_name}:" ./data/org-policies/ ./data/custom-org-policies/ 2>/dev/null; then - continue - fi - - # Check if already in state - if echo "${state_list}" | grep -qF "${target_resource}"; then - echo "${constraint_name} already managed, skipping." - elif [[ "${constraint_name}" == custom.* ]]; then - echo "${constraint_name} is a custom policy, skipping." - else - echo "Staging import for ${constraint_name}..." - cat <> imports.tf -import { - to = ${target_resource} - id = "${constraint_self_link}" -} -EOF - ((import_count++)) - fi -done <<< "$policies" - -if [[ $import_count -gt 0 ]]; then - echo -e "\nStaged $import_count imports. Running parallel import apply..." - terraform apply -auto-approve - rm -f imports.tf - echo -e "\nOrganization Policy import operation is complete!" -else - echo "All policies are already up to date." -fi \ No newline at end of file diff --git a/fast/stages-aw/0-bootstrap/kms.tf b/fast/stages-aw/0-bootstrap/kms.tf deleted file mode 100644 index 569804eee..000000000 --- a/fast/stages-aw/0-bootstrap/kms.tf +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -locals { - version_template = { - algorithm = "GOOGLE_SYMMETRIC_ENCRYPTION" - protection_level = "HSM" - } -} -module "logging-kms" { - source = "../../../modules/kms" - project_id = module.log-export-project.project_id - - keyring = { - location = local.locations.logging - name = "logging" - } - keys = { - "log-sink" = { - rotation_period = "7776000s" # CIS Compliance Benchmark 1.10 - version_template = local.version_template - } - } - - iam_bindings_additive = { - "pubsub" = { - member = "serviceAccount:service-${module.log-export-project.number}@gcp-sa-pubsub.iam.gserviceaccount.com" - role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - }, - "bq" = { - member = "serviceAccount:bq-${module.log-export-project.number}@bigquery-encryption.iam.gserviceaccount.com" - role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - }, - "gcs" = { - member = "serviceAccount:service-${module.log-export-project.number}@gs-project-accounts.iam.gserviceaccount.com" - role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - } - } -} - -module "gcs-kms" { - source = "../../../modules/kms" - project_id = module.automation-project.project_id - - keyring = { - location = local.locations.gcs - name = "gcs" - } - keys = { - "gcs" = { - rotation_period = "7776000s" # CIS Compliance Benchmark 1.10 - version_template = local.version_template - } - } - iam = { - - "roles/cloudkms.cryptoKeyEncrypterDecrypter" = [ - "serviceAccount:service-${module.automation-project.number}@gs-project-accounts.iam.gserviceaccount.com", - ], - "roles/cloudkms.admin" = [ - "serviceAccount:${var.prefix}-prod-resman-0@${var.prefix}-prod-iac-core-0.iam.gserviceaccount.com" - ] - "roles/cloudkms.viewer" = [ - "serviceAccount:${var.prefix}-prod-resman-0r@${var.prefix}-prod-iac-core-0.iam.gserviceaccount.com" - ] - } -} \ No newline at end of file diff --git a/fast/stages-aw/0-bootstrap/log-export.tf b/fast/stages-aw/0-bootstrap/log-export.tf deleted file mode 100644 index b76df3dc8..000000000 --- a/fast/stages-aw/0-bootstrap/log-export.tf +++ /dev/null @@ -1,125 +0,0 @@ -/** - * Copyright 2024 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -# tfdoc:file:description Audit log project and sink. - -locals { - log_sink_destinations = merge( - # use the same dataset for all sinks with `bigquery` as destination - { - for k, v in var.log_sinks : - k => module.log-export-dataset[0] if v.type == "bigquery" - }, - # use the same gcs bucket for all sinks with `storage` as destination - { - for k, v in var.log_sinks : - k => module.log-export-gcs[0] if v.type == "storage" - }, - # use separate pubsub topics and logging buckets for sinks with - # destination `pubsub` and `logging` - module.log-export-pubsub, - module.log-export-logbucket - ) - log_types = toset([for k, v in var.log_sinks : v.type]) -} - -module "log-export-project" { - source = "../../../modules/project" - name = "audit-logs-0" - default_service_account = "deprivilege" - lien_reason = "Protected by default as a core project." - parent = coalesce( - var.project_parent_ids.logging, module.branch-common-services-folder.folder.name - ) - prefix = local.prefix - billing_account = var.billing_account.id - contacts = ( - var.bootstrap_user != null || var.essential_contacts == null - ? {} - : { (var.essential_contacts) = ["ALL"] } - ) - iam = { - "roles/owner" = [module.automation-tf-bootstrap-sa.iam_email] - "roles/viewer" = [module.automation-tf-bootstrap-r-sa.iam_email] - } - services = [ - # "cloudresourcemanager.googleapis.com", - # "iam.googleapis.com", - # "serviceusage.googleapis.com", - "bigquery.googleapis.com", - "storage.googleapis.com", - "stackdriver.googleapis.com", - "cloudkms.googleapis.com", - "pubsub.googleapis.com", - "compute.googleapis.com" - ] -} - -resource "google_compute_project_metadata" "metadata-log-export" { - project = module.log-export-project.project_id - metadata = { - block-project-ssh-keys = "TRUE" # CIS Compliance Benchmark 4.3 - enable-oslogin = "TRUE" # CIS Compliance Benchmark 4.4 - } -} - -# one log export per type, with conditionals to skip those not needed - -module "log-export-dataset" { - source = "../../../modules/bigquery-dataset" - count = contains(local.log_types, "bigquery") ? 1 : 0 - project_id = module.log-export-project.project_id - id = "logs" - friendly_name = "Audit logs export." - location = local.locations.bq - encryption_key = try(var.logging_kms_key, module.logging-kms.keys["log-sink"]) - -} - -module "log-export-gcs" { - source = "../../../modules/gcs" - count = contains(local.log_types, "storage") ? 1 : 0 - project_id = module.log-export-project.project_id - name = "logs" - prefix = local.prefix - location = local.locations.gcs - storage_class = local.gcs_storage_class - force_destroy = true - encryption_key = try(var.logging_kms_key, module.logging-kms.keys["log-sink"]) -} - -module "log-export-logbucket" { - source = "../../../modules/logging-bucket" - for_each = toset([for k, v in var.log_sinks : k if v.type == "logging"]) - parent_type = "project" - parent = module.log-export-project.project_id - id = each.key - location = local.locations.logging - log_analytics = { enable = true } - kms_key_name = try(var.logging_kms_key, module.logging-kms.keys["log-sink"]) - retention = var.logging_bucket_retention - # org-level logging settings ready before we create any logging buckets - depends_on = [module.organization-logging] -} - -module "log-export-pubsub" { - source = "../../../modules/pubsub" - for_each = toset([for k, v in var.log_sinks : k if v.type == "pubsub"]) - project_id = module.log-export-project.project_id - name = each.key - regions = local.locations.pubsub - kms_key = try(var.logging_kms_key, module.logging-kms.keys["log-sink"]) -} diff --git a/fast/stages-aw/0-bootstrap/main.tf b/fast/stages-aw/0-bootstrap/main.tf deleted file mode 100644 index c8bf8c25f..000000000 --- a/fast/stages-aw/0-bootstrap/main.tf +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -locals { - gcs_storage_class = ( - length(split("-", local.locations.gcs)) < 2 - ? "MULTI_REGIONAL" - : "REGIONAL" - ) - principals = { - for k, v in var.groups : k => ( - can(regex("^[a-zA-Z]+:", v)) - ? v - : "group:${v}@${var.organization.domain}" - ) - } - locations = { - bq = var.regions.primary - gcs = var.regions.primary - logging = coalesce(try(local.checklist.location, null), var.regions.primary) - pubsub = [var.regions.primary] - kms = var.regions.primary - } - # naming: environment used in most resource names - prefix = join("-", compact([var.prefix, "prod"])) -} diff --git a/fast/stages-aw/0-bootstrap/organization-iam.tf b/fast/stages-aw/0-bootstrap/organization-iam.tf deleted file mode 100644 index 8d1a30486..000000000 --- a/fast/stages-aw/0-bootstrap/organization-iam.tf +++ /dev/null @@ -1,198 +0,0 @@ -/** - * Copyright 2023 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -# tfdoc:file:description Organization-level IAM bindings locals. - -locals { - # IAM roles in the org to reset (remove principals) - iam_delete_roles = [ - "roles/billing.creator" - ] - # domain IAM bindings - iam_domain_bindings = var.organization.domain == null ? {} : { - "domain:${var.organization.domain}" = { - authoritative = ["roles/browser"] - additive = [] - } - } - # human (groups) IAM bindings - iam_principal_bindings = { - (local.principals.gcp-billing-admins) = { - authoritative = [] - additive = ( - local.billing_mode != "org" ? [] : [ - "roles/billing.admin" - ] - ) - } - (local.principals.gcp-vpc-network-admins) = { - authoritative = [ - "roles/cloudasset.owner", - "roles/cloudsupport.techSupportEditor", - ] - additive = [ - "roles/compute.orgFirewallPolicyAdmin", - "roles/compute.xpnAdmin" - ] - } - (local.principals.gcp-organization-admins) = { - authoritative = [ - "roles/axt.admin", - "roles/cloudasset.owner", - "roles/cloudsupport.admin", - "roles/compute.osAdminLogin", - "roles/compute.osLoginExternalUser", - "roles/resourcemanager.folderAdmin", - "roles/resourcemanager.organizationAdmin", - "roles/resourcemanager.projectCreator", - "roles/resourcemanager.tagAdmin", - "roles/iam.workforcePoolAdmin", - "roles/assuredworkloads.admin" - ] - additive = concat( - [ - "roles/orgpolicy.policyAdmin", - "roles/iam.organizationRoleAdmin" - ], - local.billing_mode != "org" ? [] : [ - "roles/billing.admin" - ] - ) - } - (local.principals.gcp-security-admins) = { - authoritative = [ - "roles/cloudasset.owner", - "roles/cloudsupport.techSupportEditor", - "roles/iam.securityReviewer", - "roles/logging.admin", - "roles/securitycenter.admin", - ] - additive = [ - "roles/accesscontextmanager.policyAdmin", - "roles/iam.organizationRoleAdmin", - "roles/orgpolicy.policyAdmin" - ] - } - (local.principals.gcp-support) = { - authoritative = [ - "roles/cloudsupport.techSupportEditor", - "roles/logging.viewer", - "roles/monitoring.viewer", - ] - additive = [] - } - } - # machine (service accounts) IAM bindings, in logical format - # the service account module's "magic" outputs allow us to use dynamic values - iam_sa_bindings = { - (module.automation-tf-bootstrap-sa.iam_email) = { - authoritative = [ - "roles/essentialcontacts.admin", - "roles/logging.admin", - "roles/resourcemanager.organizationAdmin", - "roles/resourcemanager.projectCreator", - "roles/resourcemanager.projectMover", - "roles/resourcemanager.tagAdmin", - "roles/assuredworkloads.admin" - ] - additive = concat( - [ - "roles/iam.organizationRoleAdmin", - "roles/orgpolicy.policyAdmin" - ], - local.billing_mode != "org" ? [] : [ - "roles/billing.admin" - ] - ) - } - (module.automation-tf-bootstrap-r-sa.iam_email) = { - authoritative = [ - "roles/essentialcontacts.viewer", - "roles/logging.viewer", - "roles/resourcemanager.folderViewer", - "roles/resourcemanager.tagViewer", - "roles/assuredworkloads.reader" - ] - additive = concat( - [ - # the organizationAdminViewer custom role is granted via the SA module - "roles/iam.organizationRoleViewer", - "roles/orgpolicy.policyViewer" - ], - local.billing_mode != "org" ? [] : [ - "roles/billing.viewer" - ] - ) - } - (module.automation-tf-resman-sa.iam_email) = { - authoritative = [ - "roles/assuredworkloads.admin", - "roles/logging.admin", - "roles/resourcemanager.folderAdmin", - "roles/resourcemanager.projectCreator", - "roles/resourcemanager.tagAdmin", - "roles/resourcemanager.tagUser", - ] - additive = concat( - [ - "roles/orgpolicy.policyAdmin" - ], - local.billing_mode != "org" ? [] : [ - "roles/billing.admin" - ] - ) - } - (module.automation-tf-resman-r-sa.iam_email) = { - authoritative = [ - "roles/assuredworkloads.reader", - "roles/logging.viewer", - "roles/resourcemanager.folderViewer", - "roles/resourcemanager.tagViewer", - "roles/serviceusage.serviceUsageViewer" - ] - additive = concat( - [ - # the organizationAdminViewer custom role is granted via the SA module - "roles/orgpolicy.policyViewer" - ], - local.billing_mode != "org" ? [] : [ - "roles/billing.viewer" - ] - ) - } - } - # bootstrap user bindings - iam_user_bootstrap_bindings = var.bootstrap_user == null ? {} : { - "user:${var.bootstrap_user}" = { - authoritative = [ - "roles/logging.admin", - "roles/resourcemanager.folderAdmin", - "roles/resourcemanager.organizationAdmin", - "roles/resourcemanager.projectCreator", - "roles/resourcemanager.tagAdmin" - ] - # TODO: align additive roles with the README - additive = concat( - [ - "roles/iam.organizationRoleAdmin" - ], - local.billing_mode != "org" ? [] : [ - "roles/billing.admin" - ] - ) - } - } -} diff --git a/fast/stages-aw/0-bootstrap/organization.tf b/fast/stages-aw/0-bootstrap/organization.tf deleted file mode 100644 index 87165c43a..000000000 --- a/fast/stages-aw/0-bootstrap/organization.tf +++ /dev/null @@ -1,314 +0,0 @@ -/** - * Copyright 2024 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -# tfdoc:file:description Organization-level IAM. - -locals { - # reassemble logical bindings into the formats expected by the module - _iam_bindings = merge( - local.iam_domain_bindings, - local.iam_sa_bindings, - local.iam_user_bootstrap_bindings, - { - for k, v in local.iam_principal_bindings : k => { - authoritative = [] - additive = v.additive - } - } - ) - _iam_bindings_auth = flatten([ - for member, data in local._iam_bindings : [ - for role in data.authoritative : { - member = member - role = role - } - ] - ]) - _iam_bindings_add = flatten([ - for member, data in local._iam_bindings : [ - for role in data.additive : { - member = member - role = role - } - ] - ]) - # tflint-ignore: terraform_unused_declarations - drs_domains = concat(var.organization.customer_id == null ? [] : [var.organization.customer_id], - var.org_policies_config.constraints.allowed_policy_member_domains - ) - drs_tag_name = "${var.organization.id}/${var.org_policies_config.tag_name}" - - # intermediate values before we merge in what comes from the checklist - _iam_principals = { - for k, v in local.iam_principal_bindings : k => v.authoritative - } - _iam = merge( - { - for r in local.iam_delete_roles : r => [] - }, - { - for b in local._iam_bindings_auth : b.role => b.member... - } - ) - _iam_bindings_additive = { - for b in local._iam_bindings_add : "${b.role}-${b.member}" => { - member = b.member - role = b.role - } - } - # final values combining all sources - iam_principals = { - for k, v in local._iam_principals : k => distinct(concat( - v, - try(local.checklist.iam_principals[k], []) - )) - } - iam = { - for k, v in local._iam : k => distinct(concat( - v, - try(local.checklist.iam[k].authoritative, []) - )) - } - iam_bindings_additive = merge( - local._iam_bindings_additive, - { - for k, v in try(local.checklist.iam_bindings, {}) : - v.key => v if lookup(local._iam_bindings_additive, v.key, null) == null - } - ) - # compute authoritative and additive roles for use by add-ons (checklist, etc.) - iam_roles_authoritative = distinct(concat( - flatten(values(local._iam_principals)), - keys(local._iam) - )) - - # Some of the org policies require templating to construct, they have been moved to data/custom-org-policies - # load org policy yaml files from a subdirectory - _org_policies_raw = merge(concat( - [ - for f in try(fileset("./data/org-policies/", "*_policy.yaml"), []) : - yamldecode(file("./data/org-policies/${f}")) - ], - [ - for f in try(fileset("./data/custom-org-policies/", "*_policy.yaml"), []) : - yamldecode(templatefile("./data/custom-org-policies/${f}", { - # NOTE: - # If there are more variables need to be substituted, put them - # into a separate yaml file or map, use the following line to - # loop throught them. For list values use yamlencode() function. - # for k, v in local.common_settings : k => v - organization_id : var.organization.id - domain_name : var.organization.domain - customer_id : var.organization.customer_id - drs_tag_name : local.drs_tag_name - allowed_domains : var.org_policies_config.constraints.allowed_policy_member_domains - })) - ] - )...) - # formalize the policies - org_policies = { - for k, v in local._org_policies_raw : - k => { - inherit_from_parent = try(v.inherit_from_parent, null) - reset = try(v.reset, null) - rules = [ - for r in try(v.rules, []) : { - allow = can(r.allow) ? { - all = try(r.allow.all, null) - values = try(r.allow.values, null) - } : null - deny = can(r.deny) ? { - all = try(r.deny.all, null) - values = try(r.deny.values, null) - } : null - enforce = try(r.enforce, null) - parameters = try(jsonencode(r.parameters), null) - condition = { - description = try(r.condition.description, null) - expression = try(r.condition.expression, null) - location = try(r.condition.location, null) - title = try(r.condition.title, null) - } - } - ] - } - } -} - -# TODO: add a check block to ensure our custom roles exist in the factory files - -# import org policy constraints enabled by default in new orgs since February 2024 -import { - for_each = ( - var.org_policies_config.import_defaults && var.bootstrap_user == null - ? toset([ - # source: https://cloud.google.com/resource-manager/docs/secure-by-default-organizations#organization_policies_enforced_on_organization_resources - # listed in the order as on page - "iam.managed.disableServiceAccountKeyCreation", - "iam.managed.disableServiceAccountKeyUpload", - "iam.managed.preventPrivilegedBasicRolesForDefaultServiceAccounts", - # "iam.automaticIamGrantsForDefaultServiceAccounts", - "iam.allowedPolicyMemberDomains", - "essentialcontacts.managed.allowedContactDomains", - "storage.uniformBucketLevelAccess", - # "compute.setNewProjectDefaultToZonalDNSOnly", - "compute.managed.restrictProtocolForwardingCreationForTypes", # not confirmed that this is live, but listed on webpage - ]) : toset([]) - ) - id = "organizations/${var.organization.id}/policies/${each.key}" - to = module.organization.google_org_policy_policy.default[each.key] -} - -module "organization-logging" { - # Preconfigure organization-wide logging settings to ensure project - # log buckets (_Default, _Required) are created in the location - # specified by local.locations.logging. This separate - # organization-block prevents circular dependencies with later - # project creation. - source = "../../../modules/organization" - organization_id = "organizations/${var.organization.id}" - logging_settings = { - storage_location = local.locations.logging - } -} - -resource "google_assured_workloads_workload" "primary" { - count = var.assured_workloads.regime != "COMPLIANCE_REGIME_UNSPECIFIED" ? 1 : 0 - compliance_regime = var.assured_workloads.regime - display_name = "StellarEngine-${var.prefix}" - location = var.assured_workloads.location - organization = var.organization.id - billing_account = var.billing_account.id != null && var.billing_account.id != "" ? "billingAccounts/${var.billing_account.id}" : null - provisioned_resources_parent = "" - resource_settings { - display_name = "StellarEngine-${var.prefix}" - resource_type = "CONSUMER_FOLDER" - } - - violation_notifications_enabled = true - lifecycle { - create_before_destroy = true - ignore_changes = [billing_account] - } -} - -module "no-compliance-folder" { - count = var.assured_workloads.regime == "COMPLIANCE_REGIME_UNSPECIFIED" ? 1 : 0 - source = "../../../modules/folder" - parent = "organizations/${var.organization.id}" - name = "StellarEngine-${var.prefix}" -} - -module "branch-common-services-folder" { - source = "../../../modules/folder" - parent = var.assured_workloads.regime != "COMPLIANCE_REGIME_UNSPECIFIED" ? "folders/${google_assured_workloads_workload.primary[0].resources[0].resource_id}" : "${module.no-compliance-folder[0].folder.id}" - name = "${lookup(var.regime_mapping, var.assured_workloads.regime, var.assured_workloads.regime)} Common Services" -} - - -module "organization" { - source = "../../../modules/organization-se" - organization_id = module.organization-logging.id - prefix = var.prefix - iam_by_principals = { - for k in distinct(concat(keys(local.iam_principals), keys(var.iam_by_principals))) : - k => distinct(concat( - try(local.iam_principals[k], []), - try(var.iam_by_principals[k], []) - )) - } - # machine (service accounts) IAM bindings - iam = merge( - { - for k, v in local.iam : k => distinct(concat(v, lookup(var.iam, k, []))) - }, - { - for k, v in var.iam : k => v if lookup(local.iam, k, null) == null - } - ) - # additive bindings, used for roles co-managed by different stages - iam_bindings_additive = merge( - local.iam_bindings_additive, - var.iam_bindings_additive - ) - # delegated role grant for resource manager service account - iam_bindings = merge( - { - organization_iam_admin_conditional = { - members = [module.automation-tf-resman-sa.iam_email] - role = module.organization.custom_role_id["organization_iam_admin"] - condition = { - expression = format( - "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])", - join(",", formatlist("'%s'", [ - "roles/accesscontextmanager.policyAdmin", - "roles/cloudasset.viewer", - "roles/compute.orgFirewallPolicyAdmin", - "roles/compute.xpnAdmin", - "roles/orgpolicy.policyAdmin", - "roles/orgpolicy.policyViewer", - "roles/resourcemanager.organizationViewer", - module.organization.custom_role_id["tenant_network_admin"] - ])) - ) - title = "automation_sa_delegated_grants" - description = "Automation service account delegated grants." - } - } - }, - local.billing_mode != "org" ? {} : { - organization_billing_conditional = { - members = [module.automation-tf-resman-sa.iam_email] - role = module.organization.custom_role_id["organization_iam_admin"] - condition = { - expression = format( - "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])", - join(",", formatlist("'%s'", [ - "roles/billing.admin", - "roles/billing.costsManager", - "roles/billing.user", - ])) - ) - title = "automation_sa_delegated_grants" - description = "Automation service account delegated grants." - } - } - } - ) - custom_roles = var.custom_roles - factories_config = { - custom_roles = var.factories_config.custom_roles - org_policies = ( - var.bootstrap_user != null ? null : var.factories_config.org_policy - ) - org_policy_custom_constraints = "./data/custom-constraint-policies/" - context = { - org_policies = { - root_node = var.organization.id - } - } - } - logging_sinks = { - for name, attrs in var.log_sinks : name => { - bq_partitioned_table = attrs.type == "bigquery" - destination = local.log_sink_destinations[name].id - filter = attrs.filter - type = attrs.type - } - } - org_policies = var.bootstrap_user != null ? null : local.org_policies - -} diff --git a/fast/stages-aw/0-bootstrap/outputs-gcs.tf b/fast/stages-aw/0-bootstrap/outputs-gcs.tf deleted file mode 100644 index c9f662161..000000000 --- a/fast/stages-aw/0-bootstrap/outputs-gcs.tf +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -# tfdoc:file:description Output files persistence to automation GCS bucket. - -resource "google_storage_bucket_object" "providers" { - for_each = local.providers - bucket = module.automation-tf-output-gcs.name - # provider suffix allows excluding via .gitignore when linked from stages - name = "providers/${each.key}-providers.tf" - content = each.value - # kms_key_name = module.gcs-kms.keys.gcs.id # may need to add back in -} - -resource "google_storage_bucket_object" "tfvars" { - bucket = module.automation-tf-output-gcs.name - name = "tfvars/0-bootstrap.auto.tfvars.json" - content = jsonencode(local.tfvars) - # kms_key_name = module.gcs-kms.keys.gcs.id # may need to add back in -} - -resource "google_storage_bucket_object" "tfvars_globals" { - bucket = module.automation-tf-output-gcs.name - name = "tfvars/0-globals.auto.tfvars.json" - content = jsonencode(local.tfvars_globals) - # kms_key_name = module.gcs-kms.keys.gcs.id # may need to add back in -} - -resource "google_storage_bucket_object" "workflows" { - for_each = local.cicd_workflows - bucket = module.automation-tf-output-gcs.name - name = "workflows/${each.key}-workflow.yaml" - content = each.value - # kms_key_name = module.gcs-kms.keys.gcs.id # may need to add back in -} diff --git a/fast/stages-aw/0-bootstrap/terraform.tfvars.sample b/fast/stages-aw/0-bootstrap/terraform.tfvars.sample deleted file mode 100644 index 4abe2f434..000000000 --- a/fast/stages-aw/0-bootstrap/terraform.tfvars.sample +++ /dev/null @@ -1,74 +0,0 @@ -# use `gcloud beta billing accounts list` -# if you have too many accounts, check the Cloud Console :) -billing_account = { - id = "012345-67890A-BCDEF0" -} - -# Optional Billing budget for the Assured Workload folder. If not set, no budget will be created. -# billing_budget_amount = { -# amount = 1000 -# } - -# region configuration - this will automatically populate locations for GCS, BigQuery, KMS, and logging buckets -# Default to us-east4 for IL5/FedRAMP compliance - adjust as needed -regions = { - primary = "us-east4" # Change to your preferred region - this will be used for all bootstrap resources -} - -# use `gcloud organizations list` -organization = { - domain = "example.org" - id = 1234567890 - customer_id = "C000001" -} - -outputs_location = "~/fast-config" - -# Retention period (in days) for organization logging buckets (defaults to 365 days for compliance) -# logging_bucket_retention = 365 - -# use something unique and no longer than 9 characters -prefix = "abcd" -# Default log routing is set to "logging" (Cloud Logging buckets with 30-day default retention) -# To use long-term storage, change type to "storage" (GCS) or "bigquery" -# To route to a SIEM, use "pubsub" (note: requires active subscriber to avoid log loss after 7 days) -log_sinks = { - audit-logs = { - filter = "logName:\"/logs/cloudaudit.googleapis.com%2Factivity\" OR logName:\"/logs/cloudaudit.googleapis.com%2Fsystem_event\" OR protoPayload.metadata.@type=\"type.googleapis.com/google.cloud.audit.TransparencyLog\"" - type = "logging" - } - vpc-sc = { - filter = "protoPayload.metadata.@type=\"type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata\"" - type = "logging" - } - workspace-audit-logs = { - filter = "logName:\"/logs/cloudaudit.googleapis.com%2Fdata_access\" and protoPayload.serviceName:\"login.googleapis.com\"" - type = "logging" - } - - # CIS Compliance Benchmark 2.2 - empty-audit-logs = { - filter = "" - type = "logging" - } -} - -org_policies_config = { - import_defaults = false # No policies to import as of 27 SEP 2024 - constraints = { - allowed_policy_member_domains = [] # Additional externally allowed customer_ids - } -} - -fast_features = { - envs = true -} - -assured_workloads = { - regime = "compliance-regime" #"IL4, IL5, FEDRAMP_HIGH, etc... if you wish to not use assured_workloads, set this value to COMPLIANCE_REGIME_UNSPECIFIED" - location = "us-east4" # Uses the same region as other resources for consistency - change to match your regions.primary if different -} - -bootstrap_project = "bootstrap-project-name" - -alert_email = "user@domain.com" diff --git a/fast/stages-aw/0-bootstrap/workload-identity.tf b/fast/stages-aw/0-bootstrap/workload-identity.tf deleted file mode 100644 index 546f716fa..000000000 --- a/fast/stages-aw/0-bootstrap/workload-identity.tf +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Copyright 2024 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -# tfdoc:file:description Workload Identity Federation configurations. - -locals { - workload_identity_providers = { - for k, v in coalesce(var.federated_identity_providers, {}) : k => v - if v.issuer != null - } - workload_identity_providers_defs = { - github = { - issuer = "https://token.actions.githubusercontent.com" - principal_branch = "principal://iam.googleapis.com/%s/subject/repo:%s:ref:refs/heads/%s" - principal_repo = "principal://iam.googleapis.com/%s/subject/repo:%s:pull_request" - } - gitlab = { - issuer = "https://gitlab.com" - principal_branch = "principal://iam.googleapis.com/%s/subject/project_path:%s:ref_type:branch:ref:%s" - principal_repo = "principal://iam.googleapis.com/%s/subject/project_path:%s:ref_type:branch:ref:main" - } - } -} - -resource "google_iam_workload_identity_pool" "default" { - count = length(local.workload_identity_providers) > 0 ? 1 : 0 - provider = google-beta - project = module.automation-project.project_id - workload_identity_pool_id = "${local.prefix}-bootstrap" - display_name = "Bootstrap workload identity pool." -} - -resource "google_iam_workload_identity_pool_provider" "default" { - for_each = local.workload_identity_providers - provider = google-beta - project = module.automation-project.project_id - workload_identity_pool_id = google_iam_workload_identity_pool.default[0].workload_identity_pool_id - workload_identity_pool_provider_id = each.key - display_name = "Bootstrap workload identity provider ${each.key}." - attribute_mapping = each.value.attribute_mapping - attribute_condition = each.value.attribute_condition - oidc { - allowed_audiences = each.value.audiences - issuer_uri = each.value.issuer - } -} - -resource "google_iam_workforce_pool" "default" { - count = var.workforce_identity_pool != null ? 1 : 0 - provider = google-beta - parent = "organizations/${var.organization.id}" - workforce_pool_id = "${local.prefix}-bootstrap" - location = "global" - display_name = "Bootstrap workforce identity pool." - description = "Bootstrap workforce identity pool." - disabled = false -} diff --git a/fast/stages-aw/0-organization-bootstrap/README.md b/fast/stages-aw/0-organization-bootstrap/README.md new file mode 100644 index 000000000..499710119 --- /dev/null +++ b/fast/stages-aw/0-organization-bootstrap/README.md @@ -0,0 +1,250 @@ + + +# Google Cloud Organization Bootstrap + +The purpose of this stage is to enable critical Google Cloud Organization level functionalities that depend on broad administrative permissions, and prepare the prerequisites needed to enable automation in this and future stages. As multiple Stellar Engine Landing Zone (stellar-engine) instances can be deployed to a single Google Cloud Organization, the bootstrap phase has be separated into an Organization level and an Assured Workload level. This allows for the Organization level bootstrap to only need to be run once per Google Cloud Organization and for the Assured Workload level bootstrap to be ran as many times as needed. + + +- [Design Overview and Choices](#design-overview-and-choices) + - [User Groups](#user-groups) + - [Google Cloud Organization Level IAM](#google-cloud-organization-level-iam) + - [Google Cloud Organization Policies and Tag-Based Conditions](#google-cloud-organization-policies-and-tag-based-conditions) + - [Automation Google Cloud Project and Resources](#automation-google-cloud-project-and-resources) + - [Organization-Level Audit Project](#organization-level-audit-project) + - [Billing Account](#billing-account) + - [Google Cloud Organization Level Logging+](#google-cloud-organization-level-logging) + - [Log Sinks and Log Destinations](#log-sinks-and-log-destinations) + - [Workforce Identity Federation](#workforce-identity-federation) +- [How to Run This Stage](#how-to-run-this-stage) +- [Customizations](#customizations) + - [Group Names](#group-names) + - [IAM](#iam) +- [Variables](#variables) +- [Outputs](#outputs) + + +## Design Overview and Choices + +This stage only does the bare minimum required to configure a Google Cloud Organization so it can be used to bootstrap Assured Workloads, automation, and common services. It ensures that the Google Cloud Organization level auditing, IAM roles and organization policies are configured so multiple stellar-engine instances can be deployed to a single Google Cloud Organization without each deployment managing organization level resources. + +### User Groups + +User groups are important, not only here but throughout the whole automation process. They provide a stable frame of reference that allows decoupling the final set of permissions for each group, from the stage where entities and resources are created and their IAM bindings defined. For example, the final set of roles for the networking group is contributed by this stage at the Google Cloud Organization level (XPN Admin, Cloud Asset Viewer, etc.), and by the Resource Management stage at the Google Cloud Folder level. + +We have standardized the initial set of groups on those outlined in the [GCP Enterprise Setup Checklist](https://cloud.google.com/docs/enterprise/setup-checklist) to simplify adoption. They provide a comprehensive and flexible starting point that can suit most users. Adding new groups, or deviating from the initial setup is possible and reasonably simple, and it's briefly outlined in the customization section below. + +### Google Cloud Organization Level IAM + +The service account used in the [Resource Management stage](../2-resman) needs to be able to grant specific permissions at the Google Cloud Organization level, to enable specific functionality for subsequent stages that deal with network or security resources, or billing-related activities. + +In order to be able to assign those roles without having the full authority of the Google Cloud Organization Admin role, this stage defines a custom role that only allows setting IAM policies on the Google Cloud Organization, and grants it via a [delegated role grant](https://cloud.google.com/iam/docs/setting-limits-on-granting-roles) that only allows it to be used to grant a limited subset of roles. + +In this way, the Resource Management service account can effectively act as a Google Cloud Organization Admin, but only to grant the specific roles it needs to control. + +One consequence of the above setup is the need to configure IAM bindings that can be assigned via the condition as non-authoritative, since those same roles are effectively under the control of two stages: this one and Resource Management. Using authoritative bindings for these roles (instead of non-authoritative ones) would generate potential conflicts, where each stage could try to overwrite and negate the bindings applied by the other at each `apply` cycle. + +A full reference of IAM roles managed by this stage [is available here](#). + +### Google Cloud Organization Policies and Tag-Based Conditions + +It's often desirable to have Google Cloud Organization policies deployed before any other resource in the org, so as to ensure compliance with specific requirements (e.g. location restrictions), or control the configuration of specific resources (e.g. default network at Google Cloud Project creation or service account grants). + +Google Cloud Organization policy exceptions are managed via a dedicated resource management tag hierarchy, rooted in the `org-policies` tag key. A default condition is already present for the `iam.allowedPolicyMemberDomains` constraint, that relaxes the policy on resources that have the `org-policies/allowed-policy-member-domains-all` tag value bound or inherited. + +Further tag values can be defined via the `org_policies_config.tag_values` variable, and IAM access can be granted on them via the same variable. Once a tag value has been created, its id can be used in constraint rule conditions. + +Management of the rest of the tag hierarchy is delegated to the resource management stage, as that is often intimately tied to the Google Cloud Folder hierarchy design. + +The Google Cloud Organization policy tag key and values managed by this stage have been added to the `0-organization-bootstrap.auto.tfvars` stage, so that IAM can be delegated to the resource management or successive stages via their ids. + +The following example shows an example on how to define an additional tag value, and use it in a boolean constraint rule. + +This snippet defines a new tag value under the `org-policies` tag key via the `org_policies_config` variable, and assigns the permission to bind it to a group. + +```hcl +# stage 0 custom tfvars +org_policies_config = { + tag_values = { + compute-require-oslogin-false = { + description = "Bind this tag to set oslogin to false." + iam = { + "roles/resourcemanager.tagUser" = [ + "group:foo@example.com" + ] + } + } + } +} +``` + +The above tag can be used to define a constraint condition via the `data/org-policies/compute.yaml` or similar factory file. The id in the condition is the Google Cloud Organization id, followed by the name of the Google Cloud Organization policy tag key (defaults to `org-policies`). + +```yaml +compute.requireOsLogin: + rules: + - enforce: true + - enforce: false + condition: + expression: resource.matchTag('12345678/org-policies-config', 'compute-require-oslogin-false') +``` + +### Automation Google Cloud Project and Resources + +One other design choice worth mentioning here is using a single automation Google Cloud Project for all foundational stages. We trade off some complexity on the API side (single source for usage quota, multiple service activation) for increased flexibility and simpler operations, while still effectively providing the same degree of separation via resource-level IAM. + +### Organization-Level Audit Project + +As multiple Stellar Engine Landing Zone instances can be deployed to a single Google Cloud Organization, a new project is created specifically for organization-level logging. This project contains the Logging bucket and M-21-31 compliant Google Cloud Storage bucket for the organization. Any logs relevant at the organization level will be stored in these locations. This allows each Stellar Engine Landing Zone instance to be deployed independently and no overlap with the organization. + +### Billing Account + +We support three use cases in regards to billing: + +- the billing account is part of this same Google Cloud Organization, IAM bindings will be set at the Google Cloud Organization level +- the billing account is not considered part of an Google Cloud Organization (even though it might be), billing IAM bindings are set on the billing account itself +- billing IAM is managed separately, and no bindings should (or can) be set via Terraform, this requires a few extra steps and is definitely not recommended and mainly used for development purposes + +For same Google Cloud Organization billing, we configure a custom Google Cloud Organization role that can set IAM bindings, via a delegated role grant to limit its scope to the relevant roles. + +For details on configuring the different billing account modes, refer to the [How to run this stage](#how-to-run-this-stage) section below. + +Due to limitations of API availability, manual steps have to be followed to enable billing export within the billing Google Cloud Project to BigQuery dataset `billing_export`, which will be created as part of the bootstrap stage. The process to share billing data [is outlined here](https://cloud.google.com/billing/docs/how-to/export-data-bigquery-setup#enable-bq-export). + +### Google Cloud Organization Level Logging+ + +Google Cloud Organization level log sinks are created early in the bootstrap process to ensure a proper audit trail is in place from the very beginning. Multi-tenant log buckets are each customized to serve their purpose to supply dynamic creation based on `config.env` and the organization. Supported log exports for those dedicated projects including features like KMS encryption, log analytics, custom retention policies, and support for Google SecOps. The `tenant_log_bucket` output is used in the "2-resman" stage to ensure multi-tenancy logging to support Assured Workloads framework. + +### Log Sinks and Log Destinations + +You can customize Google Cloud Organization level logs through the `log_sinks` variable in two ways + +- creating additional log sinks to capture more logs +- changing the destination of captured logs + +By default, all logs are exported to a log bucket, but FAST can create sinks to BigQuery, GCS, or PubSub. + +If you need to capture additional logs, please refer to GCP's documentation on [Scenarios for Exporting Logging Data](https://cloud.google.com/architecture/exporting-stackdriver-logging-for-security-and-access-analytics), where you can find ready-made filter expressions for different use cases. + +### Workforce Identity Federation + +This stage supports configuration of [Workforce Identity Federation](https://cloud.google.com/iam/docs/workforce-identity-federation) which lets an external identity provider (IdP) to authenticate and authorize a group of users (usually employees) using IAM, so that the users can access Google Cloud services. + +The following example shows an example on how to define a Workforce Identity pool for the Google Cloud Organization. + +```hcl +# stage 0 wif tfvars +workforce_identity_providers = { + test = { + issuer = "azuread" + display_name = "wif-provider" + description = "Workforce Identity pool" + saml = { + idp_metadata_xml = "..." + } + } +} +``` + +## How to Run This Stage + +For detailed information on prerequisites and steps to deploy this stage, please see the latest [stellar-engine Cloud Engineer Development Guide](https://docs.google.com/document/d/1o39QZ-K5CTP8FdTs9Jgz3JRF7HZ8in-1QoM0SCcIEAk/edit?tab=t.0#heading=h.tvlxzbk3nqgs) and scroll down to stellar-engine - Automation section. If you do not have access, you will have to request it. + +## Customizations + +Most variables (e.g. `billing_account` and `organization`) are only used to input actual values and should be self-explanatory. The only meaningful customizations that apply here are groups, and IAM roles. + +### Group Names + +As we mentioned above, groups reflect the convention used in the [GCP Enterprise Setup Checklist](https://cloud.google.com/docs/enterprise/setup-checklist), with an added level of indirection: the `groups` variable maps logical names to actual names, so that you don't need to delve into the code if your group names do not comply with the checklist convention. + +Each group also has an individual variable (e.g., `gcp_vpc_network_admins_group`) to allow for easy overrides via environment variables. + +For example, if your network admins team is called `network-admins@example.com`, you can set the name (minus the domain) in either the `groups` variable or the individual `gcp_vpc_network_admins_group` variable: + +```hcl +# Option 1: Using the individual variable (easiest for environment variables) +gcp_vpc_network_admins_group = "network-admins" + +# Option 2: Using the groups object +groups = { + gcp-vpc-network-admins = "network-admins" +} +``` + +If your groups layout differs substantially from the checklist, define all relevant groups in the `groups` variable, then rearrange IAM roles in the code to match your setup. + +### IAM + +One other area where we directly support customizations is IAM. The code here, as in all stages, follows a simple pattern derived from best practices + +- operational roles for humans are assigned to groups +- any other principal is a service account + +In code, the distinction above reflects on how IAM bindings are specified in the underlying module variables + +- group roles "for humans" always use `iam_groups` variables +- service account roles always use `iam` variables + +This makes it easy to tweak user roles by adding mappings to the `iam_groups` variables of the relevant resources, without having to understand and deal with the details of service account roles. + +One more critical difference in IAM bindings is between authoritative and additive: + +- authoritative bindings have complete control on principals for a given role; this is the recommended best practice when a single automation actor controls the role, as it removes drift each time Terraform runs +- additive bindings have control only on given role/principal pairs, and need to be used whenever multiple automation actors need to control the role, as is the case for the network user role in Shared VPC setups, and many other situations + +This stage groups all IAM definitions in the [organization-iam.tf](./organization-iam.tf) file, to allow easy parsing of roles assigned to each group and machine identity. + +When customizations are needed, three stage-level variables allow injecting additional bindings to match the desired setup + +- `group_iam` allows adding authoritative bindings for groups +- `iam` allows adding authoritative bindings for any type of supported principal, and is merged with the internal `iam` local and then with group bindings at the module level +- `iam_bindings_additive` allows adding individual role/member pairs, and also supports IAM conditions + +Refer to the [project module](../../../modules/project/) for examples on how to use the IAM variables, and they are an interface shared across all our modules. + +## Variables + +| name | description | type | required | default | +|---|---|:---:|:---:|:---:| +| [billing_account](variables.tf#L30) | Billing account id. If billing account is not part of the same org set `is_org_level` to `false`. To disable handling of billing IAM roles set `no_iam` to `true`. | object({…}) | ✓ | | +| [bootstrap_project](variables.tf#L40) | Bootstrap project ID. | string | ✓ | | +| [organization](variables.tf#L182) | Organization details. | object({…}) | ✓ | | +| [top_level_folder](variables.tf#L191) | Top Level Folder Details. | object({…}) | ✓ | | +| [assured_workloads](variables.tf#L17) | Configuration for Assured Workloads. | object({…}) | | {…} | +| [custom_roles](variables.tf#L45) | Map of role names => list of permissions to additionally create at the organization level. | map(list(string)) | | {} | +| [factories_config](variables.tf#L52) | Configuration for the resource factories or external data. | object({…}) | | {} | +| [gcp_billing_admins_group](variables.tf#L64) | GCP Billing Admins group name. | string | | "gcp-billing-admins" | +| [gcp_devops_group](variables.tf#L70) | GCP DevOps group name. | string | | "gcp-devops" | +| [gcp_organization_admins_group](variables.tf#L76) | GCP Organization Admins group name. | string | | "gcp-organization-admins" | +| [gcp_security_admins_group](variables.tf#L82) | GCP Security Admins group name. | string | | "gcp-security-admins" | +| [gcp_support_group](variables.tf#L88) | GCP Support group name. | string | | null | +| [gcp_vpc_network_admins_group](variables.tf#L94) | GCP VPC Network Admins group name. | string | | "gcp-vpc-network-admins" | +| [groups](variables.tf#L100) | Group names or IAM-format principals to grant organization-level permissions. If just the name is provided, the 'group:' principal and organization domain are interpolated. | object({…}) | | {} | +| [iam](variables.tf#L116) | Organization-level custom IAM settings in role => [principal] format. | map(list(string)) | | {} | +| [iam_bindings_additive](variables.tf#L123) | Organization-level custom additive IAM bindings. Keys are arbitrary. | map(object({…})) | | {} | +| [iam_by_principals](variables.tf#L138) | Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid cycle errors. Merged internally with the `iam` variable. | map(list(string)) | | {} | +| [locations](variables.tf#L145) | Optional locations for GCS, BigQuery, and logging buckets created here. | object({…}) | | {} | +| [logging_kms_key](variables.tf#L158) | value of the KMS key used for logging. | string | | null | +| [org_policies_config](variables.tf#L164) | Organization policies customization. | object({…}) | | {} | +| [workforce_identity_providers](variables.tf#L199) | Workforce Identity Federation pools. | map(object({…})) | | {} | + +## Outputs + +| name | description | sensitive | +|---|---|:---:| +| [workforce_identity_pool](outputs.tf#L24) | Workforce Identity Federation pool. | | + diff --git a/fast/stages-aw/0-organization-bootstrap/audit-logging.tf b/fast/stages-aw/0-organization-bootstrap/audit-logging.tf new file mode 100644 index 000000000..de0a72482 --- /dev/null +++ b/fast/stages-aw/0-organization-bootstrap/audit-logging.tf @@ -0,0 +1,32 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +# CIS Compliance Benchmark 2.1 - Folder Scope + +resource "google_folder_iam_audit_config" "folder_audit_logs" { + folder = var.top_level_folder.id # Replaces 'org_id'. Expects format "folders/1234567" or just "1234567" + service = "allServices" + + audit_log_config { + log_type = "ADMIN_READ" + } + audit_log_config { + log_type = "DATA_WRITE" + } + audit_log_config { + log_type = "DATA_READ" + } +} diff --git a/fast/stages-aw/0-organization-bootstrap/billing.tf b/fast/stages-aw/0-organization-bootstrap/billing.tf new file mode 100644 index 000000000..d4dbf5e6e --- /dev/null +++ b/fast/stages-aw/0-organization-bootstrap/billing.tf @@ -0,0 +1,43 @@ + +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# tfdoc:file:description Billing export project and dataset. + +locals { + # used here for convenience, in organization.tf members are explicit + billing_ext_admins = [ + local.principals.gcp-billing-admins, + local.principals.gcp-organization-admins, + ] + + billing_mode = ( + var.billing_account.no_iam + ? null + : var.billing_account.is_org_level ? "org" : "resource" + ) +} + +# standalone billing account + +resource "google_billing_account_iam_member" "billing_ext_admin" { + for_each = toset( + local.billing_mode == "resource" ? local.billing_ext_admins : [] + ) + billing_account_id = var.billing_account.id + role = "roles/billing.admin" + member = each.key +} + diff --git a/fast/stages-aw/0-organization-bootstrap/changelog b/fast/stages-aw/0-organization-bootstrap/changelog new file mode 100644 index 000000000..e070724d8 --- /dev/null +++ b/fast/stages-aw/0-organization-bootstrap/changelog @@ -0,0 +1,2 @@ +2606091411 +2606091512 \ No newline at end of file diff --git a/fast/stages-aw/0-organization-bootstrap/checklist.tf b/fast/stages-aw/0-organization-bootstrap/checklist.tf new file mode 100644 index 000000000..0f96d02a3 --- /dev/null +++ b/fast/stages-aw/0-organization-bootstrap/checklist.tf @@ -0,0 +1,120 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +locals { + # group mapping from checklist to ours + _cl_groups = { + BILLING_ADMINS = local.principals.gcp-billing-admins + DEVOPS = local.principals.gcp-devops + # LOGGING_ADMINS + # MONITORING_ADMINS + NETWORK_ADMINS = local.principals.gcp-vpc-network-admins + ORG_ADMINS = local.principals.gcp-organization-admins + SECURITY_ADMINS = local.principals.gcp-security-admins + } + # parse raw data from JSON files if they exist + _cl_data_raw = ( + var.factories_config.checklist_data == null + ? null + : jsondecode(file(pathexpand(var.factories_config.checklist_data))) + ) + _cl_org_raw = ( + var.factories_config.checklist_org_iam == null + ? null + : jsondecode(file(pathexpand(var.factories_config.checklist_org_iam))) + ) + # check that files are for the correct organization and ignore them if not + _cl_data = ( + try(local._cl_data_raw.cloud_setup_config.organization.id, null) != tostring(var.organization.id) + ? null + : local._cl_data_raw.cloud_setup_config + ) + _cl_org = ( + try(local._cl_org_raw.cloud_setup_org_iam.organization.id, null) != tostring(var.organization.id) + ? null + : local._cl_org_raw.cloud_setup_org_iam + ) + # do a first pass on IAM bindings to identify groups and normalize + _cl_org_iam_bindings = { + for b in try(local._cl_org.iam_bindings, []) : + lookup(local._cl_groups, b.group_id, b.principal) => { + additive = [ + for r in b.role : r if !contains(local.iam_roles_authoritative, r) + ] + authoritative = [ + for r in b.role : r if contains(local.iam_roles_authoritative, r) + ] + roles = b.role + is_group = lookup(local._cl_groups, b.group_id, null) != null + } + } + # compile the final data structure we will consume from various places + checklist = { + billing_account = try(local._cl_data.billing_account, null) + iam_principals = { + for k, v in local._cl_org_iam_bindings : + k => v.authoritative if v.is_group && length(v.authoritative) > 0 + } + iam = { + for k, v in local._cl_org_iam_bindings : + k => v.authoritative if !v.is_group && length(v.authoritative) > 0 + } + iam_bindings = concat(flatten([ + for k, v in local._cl_org_iam_bindings : [ + for r in v.additive : [ + { + key = "${r}-${k}" + member = k + role = r + } + ] + ] + ])) + location = try(local._cl_data.logging.sinks[0].destination.location, null) + } +} +check "checklist" { + # checklist data files don't need to be both present so we check independently + # version mismatch might be ok, we just alert users + assert { + condition = ( + var.factories_config.checklist_data == null || + try(local._cl_data_raw.cloud_setup_config.version, null) == "0.1.0" + ) + error_message = "Checklist data version mismatch." + } + assert { + condition = ( + var.factories_config.checklist_org_iam == null || + try(local._cl_org_raw.cloud_setup_org_iam.version, null) == "0.1.0" + ) + error_message = "Checklist org IAM version mismatch." + } + # wrong org id forces us to ignore the files, but we also alert users + assert { + condition = ( + var.factories_config.checklist_data == null || + try(local._cl_data_raw.cloud_setup_config.organization.id, null) == tostring(var.organization.id) + ) + error_message = "Checklist data organization id mismatch, file ignored." + } + assert { + condition = ( + var.factories_config.checklist_org_iam == null || + try(local._cl_org_raw.cloud_setup_org_iam.organization.id, null) == tostring(var.organization.id) + ) + error_message = "Checklist org IAM organization id mismatch, file ignored." + } +} \ No newline at end of file diff --git a/fast/stages-aw/0-bootstrap/data/custom-org-policies/cloudconsole_policy.yaml b/fast/stages-aw/0-organization-bootstrap/data/custom-org-policies/cloudconsole_policy.yaml similarity index 97% rename from fast/stages-aw/0-bootstrap/data/custom-org-policies/cloudconsole_policy.yaml rename to fast/stages-aw/0-organization-bootstrap/data/custom-org-policies/cloudconsole_policy.yaml index 6ef746c3e..db1043574 100644 --- a/fast/stages-aw/0-bootstrap/data/custom-org-policies/cloudconsole_policy.yaml +++ b/fast/stages-aw/0-organization-bootstrap/data/custom-org-policies/cloudconsole_policy.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/fast/stages-aw/0-bootstrap/data/custom-org-policies/networking_policy.yaml b/fast/stages-aw/0-organization-bootstrap/data/custom-org-policies/networking_policy.yaml similarity index 99% rename from fast/stages-aw/0-bootstrap/data/custom-org-policies/networking_policy.yaml rename to fast/stages-aw/0-organization-bootstrap/data/custom-org-policies/networking_policy.yaml index 01d8f6293..eaa31b8b3 100644 --- a/fast/stages-aw/0-bootstrap/data/custom-org-policies/networking_policy.yaml +++ b/fast/stages-aw/0-organization-bootstrap/data/custom-org-policies/networking_policy.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/fast/stages-aw/0-bootstrap/data/custom-org-policies/platform_policy.yaml b/fast/stages-aw/0-organization-bootstrap/data/custom-org-policies/platform_policy.yaml similarity index 66% rename from fast/stages-aw/0-bootstrap/data/custom-org-policies/platform_policy.yaml rename to fast/stages-aw/0-organization-bootstrap/data/custom-org-policies/platform_policy.yaml index 408b6a316..92471d92f 100644 --- a/fast/stages-aw/0-bootstrap/data/custom-org-policies/platform_policy.yaml +++ b/fast/stages-aw/0-organization-bootstrap/data/custom-org-policies/platform_policy.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -28,21 +28,6 @@ resourcemanager.allowedImportSources: values: - under:organizations/${organization_id} - -# This list constraint defines the set of domains that email addresses added to -# Essential Contacts can have. By default, email addresses with any domain can -# be added to Essential Contacts. The allowed/denied list must specify one or -# more domains of the form @dino-runner.darkwolfsolutions.com. If this constraint is active and -# configured with allowed values, only email addresses with a suffix matching -# one of the entries from the list of allowed domains can be added in Essential -# Contacts.This constraint has no effect on updating or removing existing contacts. -# MUST HAVE -essentialcontacts.allowedContactDomains: - rules: - - allow: - values: - - "@${domain_name}" - # This list constraint defines the set of external Organizations to which resources # can be moved, and denies all moves to all other Organizations. By default, # resources cannot be moved between Organizations. If this constraint is applied @@ -58,6 +43,20 @@ resourcemanager.allowedExportDestinations: values: - under:organizations/${organization_id} +# This list constraint defines the set of domains that email addresses added to +# Essential Contacts can have. By default, email addresses with any domain can +# be added to Essential Contacts. The allowed/denied list must specify one or +# more domains of the form @dino-runner.example.com. If this constraint is active and +# configured with allowed values, only email addresses with a suffix matching +# one of the entries from the list of allowed domains can be added in Essential +# Contacts.This constraint has no effect on updating or removing existing contacts. +# MUST HAVE +essentialcontacts.allowedContactDomains: + rules: + - allow: + values: + - "@${domain_name}" + # This list constraint defines one or more Cloud Identity or Google Workspace # customer IDs whose principals can be added to IAM policies. By default, all @@ -80,48 +79,24 @@ iam.allowedPolicyMemberDomains: - allow: values: - ${customer_id} -%{ for domain in allowed_domains ~} - - ${domain} +%{ for customer_id in allowed_policy_member_domains ~} + - ${customer_id} %{ endfor ~} -#Added due to ./import.sh issue - -# This list constraint defines the set of domains that email addresses added to -# Essential Contacts can have. By default, email addresses with any domain can -# be added to Essential Contacts. The allowed/denied list must specify one or -# more domains of the form @dino-runner.darkwolfsolutions.com. If this constraint is active and -# configured with allowed values, only email addresses with a suffix matching -# one of the entries from the list of allowed domains can be added in Essential -# Contacts.This constraint has no effect on updating or removing existing contacts. +# This list constraint defines the set of Google Cloud resources that are returned +# in list and search methods for users in the domain of the organization where +# this constraint is enforced. This can be used to limit what resources are +# visible in various parts of the Cloud Console, such as the Resource Picker, +# Search, and Manage Resources page. Note that this constraint is only ever +# evaluated at the Organization level. Values specified in allow/deny lists +# must be in the form: under:organizations/ORGANIZATION_ID. # MUST HAVE -essentialcontacts.managed.allowedContactDomains: +resourcemanager.accessBoundaries: rules: - - enforce: true - - -# Policy: compute.managed.restrictProtocolForwardingCreationForTypes -# Description: Restricts the creation of protocol forwarding. -# You might need to adjust rules based on your exact requirements, -# but 'enforce: true' typically means the default Google-managed behavior is enforced. -compute.managed.restrictProtocolForwardingCreationForTypes: - rules: - - enforce: true - -# Policy: iam.managed.preventPrivilegedBasicRolesForDefaultServiceAccounts -# Description: Prevents default service accounts from being granted privileged basic roles. -iam.managed.preventPrivilegedBasicRolesForDefaultServiceAccounts: - rules: - - enforce: true - -# Policy: iam.managed.disableServiceAccountKeyCreation -# Description: Disables the creation of service account keys. -iam.managed.disableServiceAccountKeyCreation: - rules: - - enforce: true - -# Policy: iam.managed.disableServiceAccountKeyUpload -# Description: Disables the upload of service account keys. -iam.managed.disableServiceAccountKeyUpload: - rules: - - enforce: true \ No newline at end of file + - allow: + values: + - under:organizations/${organization_id} +%{ for org_id in allowed_access_boundaries ~} + - under:organizations/${org_id} +%{ endfor ~} \ No newline at end of file diff --git a/fast/stages-aw/0-bootstrap/data/custom-roles/gcve_network_admin.yaml b/fast/stages-aw/0-organization-bootstrap/data/custom-roles/gcve_network_admin.yaml similarity index 90% rename from fast/stages-aw/0-bootstrap/data/custom-roles/gcve_network_admin.yaml rename to fast/stages-aw/0-organization-bootstrap/data/custom-roles/gcve_network_admin.yaml index 255ac781e..9d8fc35b2 100644 --- a/fast/stages-aw/0-bootstrap/data/custom-roles/gcve_network_admin.yaml +++ b/fast/stages-aw/0-organization-bootstrap/data/custom-roles/gcve_network_admin.yaml @@ -1,10 +1,10 @@ -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + name: gcveNetworkAdmin includedPermissions: - vmwareengine.networkPeerings.create diff --git a/fast/stages-aw/0-bootstrap/data/custom-roles/organization_admin_viewer.yaml b/fast/stages-aw/0-organization-bootstrap/data/custom-roles/organization_admin_viewer.yaml similarity index 93% rename from fast/stages-aw/0-bootstrap/data/custom-roles/organization_admin_viewer.yaml rename to fast/stages-aw/0-organization-bootstrap/data/custom-roles/organization_admin_viewer.yaml index d20ca2f7d..575decf08 100644 --- a/fast/stages-aw/0-bootstrap/data/custom-roles/organization_admin_viewer.yaml +++ b/fast/stages-aw/0-organization-bootstrap/data/custom-roles/organization_admin_viewer.yaml @@ -1,10 +1,10 @@ -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + # this is used by the plan-only admin SA name: organizationAdminViewer includedPermissions: diff --git a/fast/stages-aw/0-bootstrap/data/custom-roles/organization_iam_admin.yaml b/fast/stages-aw/0-organization-bootstrap/data/custom-roles/organization_iam_admin.yaml similarity index 90% rename from fast/stages-aw/0-bootstrap/data/custom-roles/organization_iam_admin.yaml rename to fast/stages-aw/0-organization-bootstrap/data/custom-roles/organization_iam_admin.yaml index 9ce8ac5c0..8dd9e8e23 100644 --- a/fast/stages-aw/0-bootstrap/data/custom-roles/organization_iam_admin.yaml +++ b/fast/stages-aw/0-organization-bootstrap/data/custom-roles/organization_iam_admin.yaml @@ -1,10 +1,10 @@ -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + # this is needed for use in additive IAM bindings, to avoid conflicts name: organizationIamAdmin includedPermissions: diff --git a/fast/stages-aw/0-bootstrap/data/custom-roles/service_project_network_admin.yaml b/fast/stages-aw/0-organization-bootstrap/data/custom-roles/service_project_network_admin.yaml similarity index 93% rename from fast/stages-aw/0-bootstrap/data/custom-roles/service_project_network_admin.yaml rename to fast/stages-aw/0-organization-bootstrap/data/custom-roles/service_project_network_admin.yaml index a0eaf9b3b..7e2d710b1 100644 --- a/fast/stages-aw/0-bootstrap/data/custom-roles/service_project_network_admin.yaml +++ b/fast/stages-aw/0-organization-bootstrap/data/custom-roles/service_project_network_admin.yaml @@ -1,10 +1,10 @@ -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + name: serviceProjectNetworkAdmin includedPermissions: - compute.globalOperations.get diff --git a/fast/stages-aw/0-bootstrap/data/custom-roles/storage_viewer.yaml b/fast/stages-aw/0-organization-bootstrap/data/custom-roles/storage_viewer.yaml similarity index 91% rename from fast/stages-aw/0-bootstrap/data/custom-roles/storage_viewer.yaml rename to fast/stages-aw/0-organization-bootstrap/data/custom-roles/storage_viewer.yaml index e7ae5794c..19e7f5120 100644 --- a/fast/stages-aw/0-bootstrap/data/custom-roles/storage_viewer.yaml +++ b/fast/stages-aw/0-organization-bootstrap/data/custom-roles/storage_viewer.yaml @@ -1,10 +1,10 @@ -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,7 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. + # the following permissions are a descoped version of storage.admin +name: storageViewer includedPermissions: - storage.buckets.get - storage.buckets.getIamPolicy diff --git a/fast/stages-aw/0-organization-bootstrap/data/custom-roles/tag_editor.yaml b/fast/stages-aw/0-organization-bootstrap/data/custom-roles/tag_editor.yaml new file mode 100644 index 000000000..859ec1f56 --- /dev/null +++ b/fast/stages-aw/0-organization-bootstrap/data/custom-roles/tag_editor.yaml @@ -0,0 +1,380 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +name: tagEditor +title: "Custom Tag Editor Role" +description: "View all common resources and ONLY manage Tag Bindings." +includedPermissions: + # --- Core Resource Manager Permissions --- + - resourcemanager.projects.get + - resourcemanager.projects.list + - resourcemanager.tagKeys.get + - resourcemanager.tagKeys.list + - resourcemanager.tagValues.get + - resourcemanager.tagValues.list + - resourcemanager.tagValueBindings.create + - resourcemanager.tagValueBindings.delete + - resourcemanager.tagValueBindings.list + - resourcemanager.tagHolds.list + - resourcemanager.resourceTagBindings.list + + # --- Compute Engine (VMs, Disks, etc.) --- + - compute.instances.get + - compute.instances.list + - compute.instances.createTagBinding + - compute.instances.deleteTagBinding + - compute.instances.listEffectiveTags + - compute.instances.listTagBindings + - compute.zones.list + - compute.projects.get + - compute.instanceGroupManagers.get + - compute.instanceGroupManagers.list + - compute.instanceGroupManagers.createTagBinding + - compute.instanceGroupManagers.deleteTagBinding + - compute.instanceGroupManagers.listEffectiveTags + - compute.instanceGroupManagers.listTagBindings + - compute.instanceGroups.get + - compute.instanceGroups.list + - compute.instanceGroups.createTagBinding + - compute.instanceGroups.deleteTagBinding + - compute.instanceGroups.listEffectiveTags + - compute.instanceGroups.listTagBindings + - compute.disks.get + - compute.disks.list + - compute.disks.createTagBinding + - compute.disks.deleteTagBinding + - compute.disks.listEffectiveTags + - compute.disks.listTagBindings + - compute.machineImages.get + - compute.machineImages.list + - compute.machineImages.createTagBinding + - compute.machineImages.deleteTagBinding + - compute.machineImages.listEffectiveTags + - compute.machineImages.listTagBindings + - compute.images.get + - compute.images.list + - compute.images.createTagBinding + - compute.images.deleteTagBinding + - compute.images.listEffectiveTags + - compute.images.listTagBindings + + # --- Containers --- + - artifactregistry.repositories.get + - artifactregistry.repositories.list + - artifactregistry.repositories.createTagBinding + - artifactregistry.repositories.deleteTagBinding + - artifactregistry.repositories.listEffectiveTags + - artifactregistry.repositories.listTagBindings + - container.clusters.get + - container.clusters.list + - container.clusters.createTagBinding + - container.clusters.deleteTagBinding + - container.clusters.listEffectiveTags + - container.clusters.listTagBindings + + # --- Cloud Storage (Buckets) --- + - storage.buckets.get + - storage.buckets.list + - storage.buckets.createTagBinding + - storage.buckets.deleteTagBinding + - storage.buckets.listTagBindings + - storage.buckets.listEffectiveTags + + # --- BigQuery (Datasets & Tables) --- + - bigquery.datasets.get + - bigquery.datasets.createTagBinding + - bigquery.datasets.deleteTagBinding + - bigquery.datasets.listEffectiveTags + - bigquery.datasets.listTagBindings + - bigquery.tables.get + - bigquery.tables.list + - bigquery.tables.createTagBinding + - bigquery.tables.deleteTagBinding + - bigquery.tables.listEffectiveTags + - bigquery.tables.listTagBindings + + # --- Cloud SQL --- + - cloudsql.instances.get + - cloudsql.instances.list + - cloudsql.instances.createTagBinding + - cloudsql.instances.deleteTagBinding + - cloudsql.instances.listEffectiveTags + - cloudsql.instances.listTagBindings + +# --- VPC Networking --- + - compute.networks.get + - compute.networks.list + - compute.networks.createTagBinding + - compute.networks.deleteTagBinding + - compute.networks.listEffectiveTags + - compute.networks.listTagBindings + - compute.subnetworks.get + - compute.subnetworks.list + - compute.subnetworks.createTagBinding + - compute.subnetworks.deleteTagBinding + - compute.subnetworks.listEffectiveTags + - compute.subnetworks.listTagBindings + + # --- NCC --- + - networkconnectivity.hubs.get + - networkconnectivity.hubs.list + - networkconnectivity.hubs.createTagBinding + - networkconnectivity.hubs.deleteTagBinding + - networkconnectivity.hubs.listEffectiveTags + - networkconnectivity.hubs.listTagBindings + - networkconnectivity.spokes.get + - networkconnectivity.spokes.list + - networkconnectivity.spokes.createTagBinding + - networkconnectivity.spokes.deleteTagBinding + - networkconnectivity.spokes.listEffectiveTags + - networkconnectivity.spokes.listTagBindings + + # --- Firewall Policies & Rules --- + - compute.firewallPolicies.get + - compute.firewallPolicies.list + - compute.firewallPolicies.createTagBinding + - compute.firewallPolicies.deleteTagBinding + - compute.firewallPolicies.listEffectiveTags + - compute.firewallPolicies.listTagBindings + - compute.firewalls.get + - compute.firewalls.list + - compute.firewalls.createTagBinding + - compute.firewalls.deleteTagBinding + - compute.firewalls.listEffectiveTags + - compute.firewalls.listTagBindings + + # --- Load Balancing --- + - compute.forwardingRules.get + - compute.forwardingRules.list + - compute.forwardingRules.createTagBinding + - compute.forwardingRules.deleteTagBinding + - compute.forwardingRules.listEffectiveTags + - compute.forwardingRules.listTagBindings + - compute.backendServices.get + - compute.backendServices.list + - compute.backendServices.createTagBinding + - compute.backendServices.deleteTagBinding + - compute.backendServices.listEffectiveTags + - compute.backendServices.listTagBindings + - compute.backendBuckets.get + - compute.backendBuckets.list + - compute.backendBuckets.createTagBinding + - compute.backendBuckets.deleteTagBinding + - compute.backendBuckets.listEffectiveTags + - compute.backendBuckets.listTagBindings + - compute.healthChecks.get + - compute.healthChecks.list + - compute.healthChecks.createTagBinding + - compute.healthChecks.deleteTagBinding + - compute.healthChecks.listEffectiveTags + - compute.healthChecks.listTagBindings + - compute.httpHealthChecks.get + - compute.httpHealthChecks.list + - compute.httpHealthChecks.createTagBinding + - compute.httpHealthChecks.deleteTagBinding + - compute.httpHealthChecks.listEffectiveTags + - compute.httpHealthChecks.listTagBindings + - compute.httpsHealthChecks.get + - compute.httpsHealthChecks.list + - compute.httpsHealthChecks.createTagBinding + - compute.httpsHealthChecks.deleteTagBinding + - compute.httpsHealthChecks.listEffectiveTags + - compute.httpsHealthChecks.listTagBindings + + # --- DNS --- + - dns.managedZones.get + - dns.managedZones.list + - dns.policies.get + - dns.policies.list + - dns.policies.createTagBinding + - dns.policies.deleteTagBinding + - dns.policies.listEffectiveTags + - dns.policies.listTagBindings + + # --- Redis --- + - redis.instances.get + - redis.instances.list + - redis.instances.createTagBinding + - redis.instances.deleteTagBinding + - redis.instances.listEffectiveTags + - redis.instances.listTagBindings + + # --- VPN & Interconnects --- + - compute.vpnGateways.get + - compute.vpnGateways.list + - compute.vpnGateways.createTagBinding + - compute.vpnGateways.deleteTagBinding + - compute.vpnGateways.listEffectiveTags + - compute.vpnGateways.listTagBindings + - compute.vpnTunnels.get + - compute.vpnTunnels.list + - compute.vpnTunnels.createTagBinding + - compute.vpnTunnels.deleteTagBinding + - compute.vpnTunnels.listEffectiveTags + - compute.vpnTunnels.listTagBindings + - compute.externalVpnGateways.get + - compute.externalVpnGateways.list + - compute.externalVpnGateways.createTagBinding + - compute.externalVpnGateways.deleteTagBinding + - compute.externalVpnGateways.listEffectiveTags + - compute.externalVpnGateways.listTagBindings + - compute.interconnects.get + - compute.interconnects.list + - compute.interconnects.createTagBinding + - compute.interconnects.deleteTagBinding + - compute.interconnects.listEffectiveTags + - compute.interconnects.listTagBindings + - compute.interconnectAttachments.get + - compute.interconnectAttachments.list + - compute.interconnectAttachments.createTagBinding + - compute.interconnectAttachments.deleteTagBinding + - compute.interconnectAttachments.listEffectiveTags + - compute.interconnectAttachments.listTagBindings + + # --- Cloud Routers --- + - compute.routers.get + - compute.routers.list + - compute.routers.createTagBinding + - compute.routers.deleteTagBinding + - compute.routers.listEffectiveTags + - compute.routers.listTagBindings + - compute.routes.get + - compute.routes.list + - compute.routes.createTagBinding + - compute.routes.deleteTagBinding + - compute.routes.listEffectiveTags + - compute.routes.listTagBindings + + # --- IP Addresses --- + - compute.addresses.get + - compute.addresses.list + - compute.addresses.createTagBinding + - compute.addresses.deleteTagBinding + - compute.addresses.listEffectiveTags + - compute.addresses.listTagBindings + - compute.globalAddresses.get + - compute.globalAddresses.list + - compute.globalAddresses.createTagBinding + - compute.globalAddresses.deleteTagBinding + - compute.globalAddresses.listEffectiveTags + - compute.globalAddresses.listTagBindings + + # --- Compute Security + - compute.securityPolicies.get + - compute.securityPolicies.list + - compute.securityPolicies.createTagBinding + - compute.securityPolicies.deleteTagBinding + - compute.securityPolicies.listEffectiveTags + - compute.securityPolicies.listTagBindings + - compute.sslPolicies.get + - compute.sslPolicies.list + - compute.sslPolicies.createTagBinding + - compute.sslPolicies.deleteTagBinding + - compute.sslPolicies.listEffectiveTags + - compute.sslPolicies.listTagBindings + + # --- Network Services --- + - networkservices.gateways.get + - networkservices.gateways.list + - networkservices.gateways.createTagBinding + - networkservices.gateways.deleteTagBinding + - networkservices.gateways.listEffectiveTags + - networkservices.gateways.listTagBindings + - networkservices.meshes.get + - networkservices.meshes.list + - networkservices.meshes.createTagBinding + - networkservices.meshes.deleteTagBinding + - networkservices.meshes.listEffectiveTags + - networkservices.meshes.listTagBindings + - networkservices.endpointConfigSelectors.get + - networkservices.endpointConfigSelectors.list + - networkservices.endpointConfigSelectors.createTagBinding + - networkservices.endpointConfigSelectors.deleteTagBinding + - networkservices.endpointConfigSelectors.listEffectiveTags + - networkservices.endpointConfigSelectors.listTagBindings + + # --- Network Management --- + - networkmanagement.connectivitytests.get + - networkmanagement.connectivitytests.list + - networkmanagement.connectivitytests.createTagBinding + - networkmanagement.connectivitytests.deleteTagBinding + - networkmanagement.connectivitytests.listEffectiveTags + - networkmanagement.connectivitytests.listTagBindings + + # --- Cloud KMS --- + - cloudkms.keyRings.get + - cloudkms.keyRings.list + - cloudkms.keyRings.createTagBinding + - cloudkms.keyRings.deleteTagBinding + - cloudkms.keyRings.listEffectiveTags + - cloudkms.keyRings.listTagBindings + + # --- Logging & Monitoring --- + - logging.buckets.get + - logging.buckets.list + - logging.buckets.createTagBinding + - logging.buckets.deleteTagBinding + - logging.buckets.listEffectiveTags + - logging.buckets.listTagBindings + - pubsub.subscriptions.get + - pubsub.subscriptions.list + - pubsub.subscriptions.createTagBinding + - pubsub.subscriptions.deleteTagBinding + - pubsub.subscriptions.listEffectiveTags + - pubsub.subscriptions.listTagBindings + - pubsub.topics.get + - pubsub.topics.list + - pubsub.topics.createTagBinding + - pubsub.topics.deleteTagBinding + - pubsub.topics.listEffectiveTags + - pubsub.topics.listTagBindings + - monitoring.alertPolicies.get + - monitoring.alertPolicies.list + - monitoring.alertPolicies.createTagBinding + - monitoring.alertPolicies.deleteTagBinding + - monitoring.alertPolicies.listEffectiveTags + - monitoring.alertPolicies.listTagBindings + - monitoring.dashboards.get + - monitoring.dashboards.list + - monitoring.dashboards.createTagBinding + - monitoring.dashboards.deleteTagBinding + - monitoring.dashboards.listEffectiveTags + - monitoring.dashboards.listTagBindings + +# --- Identity (Service Accounts & WIF) --- + - iam.serviceAccounts.get + - iam.serviceAccounts.list + - iam.serviceAccounts.createTagBinding + - iam.serviceAccounts.deleteTagBinding + - iam.serviceAccounts.listEffectiveTags + - iam.serviceAccounts.listTagBindings + - secretmanager.secrets.get + - secretmanager.secrets.list + - secretmanager.secrets.createTagBinding + - secretmanager.secrets.deleteTagBinding + - secretmanager.secrets.listEffectiveTags + - secretmanager.secrets.listTagBindings + - iam.roles.get + - iam.roles.list + - iam.roles.createTagBinding + - iam.roles.deleteTagBinding + - iam.roles.listEffectiveTags + - iam.roles.listTagBindings + + # --- VPC-SC Discovery --- + - accesscontextmanager.policies.get + - accesscontextmanager.policies.list + - accesscontextmanager.servicePerimeters.get + - accesscontextmanager.servicePerimeters.list \ No newline at end of file diff --git a/fast/stages-aw/0-bootstrap/data/custom-roles/tag_viewer.yaml b/fast/stages-aw/0-organization-bootstrap/data/custom-roles/tag_viewer.yaml similarity index 91% rename from fast/stages-aw/0-bootstrap/data/custom-roles/tag_viewer.yaml rename to fast/stages-aw/0-organization-bootstrap/data/custom-roles/tag_viewer.yaml index 756d0e935..89d5f8493 100644 --- a/fast/stages-aw/0-bootstrap/data/custom-roles/tag_viewer.yaml +++ b/fast/stages-aw/0-organization-bootstrap/data/custom-roles/tag_viewer.yaml @@ -1,10 +1,10 @@ -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + # the following permissions are a descoped version of tagAdm name: tagViewer includedPermissions: diff --git a/fast/stages-aw/0-bootstrap/data/custom-roles/tenant_network_admin.yaml b/fast/stages-aw/0-organization-bootstrap/data/custom-roles/tenant_network_admin.yaml similarity index 88% rename from fast/stages-aw/0-bootstrap/data/custom-roles/tenant_network_admin.yaml rename to fast/stages-aw/0-organization-bootstrap/data/custom-roles/tenant_network_admin.yaml index 9d1e02822..ee69474b5 100644 --- a/fast/stages-aw/0-bootstrap/data/custom-roles/tenant_network_admin.yaml +++ b/fast/stages-aw/0-organization-bootstrap/data/custom-roles/tenant_network_admin.yaml @@ -1,10 +1,10 @@ -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + name: tenantNetworkAdmin includedPermissions: - compute.globalOperations.get diff --git a/fast/stages-aw/0-bootstrap/data/org-policies/appengine_policy.yaml b/fast/stages-aw/0-organization-bootstrap/data/org-policies/appengine_policy.yaml similarity index 96% rename from fast/stages-aw/0-bootstrap/data/org-policies/appengine_policy.yaml rename to fast/stages-aw/0-organization-bootstrap/data/org-policies/appengine_policy.yaml index e22fe0b4a..752358133 100644 --- a/fast/stages-aw/0-bootstrap/data/org-policies/appengine_policy.yaml +++ b/fast/stages-aw/0-organization-bootstrap/data/org-policies/appengine_policy.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/fast/stages-aw/0-bootstrap/data/org-policies/assuredworkloads_policy.yaml b/fast/stages-aw/0-organization-bootstrap/data/org-policies/assuredworkloads_policy.yaml similarity index 97% rename from fast/stages-aw/0-bootstrap/data/org-policies/assuredworkloads_policy.yaml rename to fast/stages-aw/0-organization-bootstrap/data/org-policies/assuredworkloads_policy.yaml index 3f1738039..ace561a24 100644 --- a/fast/stages-aw/0-bootstrap/data/org-policies/assuredworkloads_policy.yaml +++ b/fast/stages-aw/0-organization-bootstrap/data/org-policies/assuredworkloads_policy.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/fast/stages-aw/0-bootstrap/data/org-policies/bigquery_policy.yaml b/fast/stages-aw/0-organization-bootstrap/data/org-policies/bigquery_policy.yaml similarity index 97% rename from fast/stages-aw/0-bootstrap/data/org-policies/bigquery_policy.yaml rename to fast/stages-aw/0-organization-bootstrap/data/org-policies/bigquery_policy.yaml index 8d2e73df4..e49a9bea8 100644 --- a/fast/stages-aw/0-bootstrap/data/org-policies/bigquery_policy.yaml +++ b/fast/stages-aw/0-organization-bootstrap/data/org-policies/bigquery_policy.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/fast/stages-aw/0-organization-bootstrap/data/org-policies/cloudbuild_policy.yaml b/fast/stages-aw/0-organization-bootstrap/data/org-policies/cloudbuild_policy.yaml new file mode 100644 index 000000000..31e0b6ff8 --- /dev/null +++ b/fast/stages-aw/0-organization-bootstrap/data/org-policies/cloudbuild_policy.yaml @@ -0,0 +1,54 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +# This list constraint defines the allowed Cloud Build integrations +# for performing Builds through receiving webhooks from services outside +# Google Cloud. When this constraint is enforced, only webhooks for +# services whose host matches one of the allowed values will be processed. +# By default, Cloud Build processes all webhooks for projects that have at +# least one LIVE trigger. +# COULD HAVE +# Recommendation: +# - allow all if there's no restrictions, otherwise add domain names +# according to the event, for example: +# - RepoSync event: source.developers.google.com +# - GitHub app event: github.com +# - GitHub Enterprise event: ghe-staging-test.com +# - Pub/Sub event: derived from the source specified in the trigger. +# - Webhook event: derived from the source specified in the trigger. +# +cloudbuild.allowedIntegrations: + rules: + - allow: + values: + - github.com + +# This list constraint defines the set of allowed Cloud Build Worker Pools +# for performing Builds using Cloud Build. When this constraint is enforced, +# builds will be required to build in a Worker Pool that matches one of the +# allowed values. By default, Cloud Build can use any Worker Pool. The allowed +# list of Worker Pools must be of the form: +# [ under:organizations/ORGANIZATION_ID, +# under:folders/FOLDER_ID , +# under:projects/PROJECT_ID , +# projects/PROJECT_ID/locations/REGION/workerPools/WORKER_POOL_ID +# ]. +# COULD HAVE +# +# cloudbuild.allowedWorkerPools: +# rules: +# - allow: +# values: +# - diff --git a/fast/stages-aw/0-bootstrap/data/org-policies/cloudconsole_policy.yaml b/fast/stages-aw/0-organization-bootstrap/data/org-policies/cloudconsole_policy.yaml similarity index 96% rename from fast/stages-aw/0-bootstrap/data/org-policies/cloudconsole_policy.yaml rename to fast/stages-aw/0-organization-bootstrap/data/org-policies/cloudconsole_policy.yaml index 6d45e383a..b4137a801 100644 --- a/fast/stages-aw/0-bootstrap/data/org-policies/cloudconsole_policy.yaml +++ b/fast/stages-aw/0-organization-bootstrap/data/org-policies/cloudconsole_policy.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/fast/stages-aw/0-bootstrap/data/org-policies/clouddeploy_policy.yaml b/fast/stages-aw/0-organization-bootstrap/data/org-policies/clouddeploy_policy.yaml similarity index 96% rename from fast/stages-aw/0-bootstrap/data/org-policies/clouddeploy_policy.yaml rename to fast/stages-aw/0-organization-bootstrap/data/org-policies/clouddeploy_policy.yaml index 13708cb24..94a8f19fe 100644 --- a/fast/stages-aw/0-bootstrap/data/org-policies/clouddeploy_policy.yaml +++ b/fast/stages-aw/0-organization-bootstrap/data/org-policies/clouddeploy_policy.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/fast/stages-aw/0-bootstrap/data/org-policies/cloudkms_policy.yaml b/fast/stages-aw/0-organization-bootstrap/data/org-policies/cloudkms_policy.yaml similarity index 92% rename from fast/stages-aw/0-bootstrap/data/org-policies/cloudkms_policy.yaml rename to fast/stages-aw/0-organization-bootstrap/data/org-policies/cloudkms_policy.yaml index eec9081c6..d73c3f66a 100644 --- a/fast/stages-aw/0-bootstrap/data/org-policies/cloudkms_policy.yaml +++ b/fast/stages-aw/0-organization-bootstrap/data/org-policies/cloudkms_policy.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -22,10 +22,11 @@ # policies are disallowed. # COULD HAVE -# cloudkms.allowedProtectionLevels: -# rules: -# - allow: -# HSM: true +cloudkms.allowedProtectionLevels: + rules: + - allow: + values: + - HSM # This list constraint defines which projects may be used to supply # Customer-Managed Encryption Keys (CMEK) when creating resources. Setting this @@ -77,15 +78,17 @@ # Cloud resources must be reconfigured or recreated manually to ensure enforcement. # COULD HAVE -gcp.restrictNonCmekServices: - rules: - - deny: - values: - - documentai.googleapis.com +# gcp.restrictNonCmekServices: +# rules: +# - deny: +# values: +# - bigquery.googleapis.com +# - composer.googleapis.com +# - # Utilize our custom constraint to prevent users from creating KMS keys without # the proper rotation period. -custom.kmsRotation: - rules: - - enforce: true \ No newline at end of file +# custom.kmsRotation: +# rules: +# - enforce: true \ No newline at end of file diff --git a/fast/stages-aw/0-bootstrap/data/org-policies/compute_policy.yaml b/fast/stages-aw/0-organization-bootstrap/data/org-policies/compute_policy.yaml similarity index 99% rename from fast/stages-aw/0-bootstrap/data/org-policies/compute_policy.yaml rename to fast/stages-aw/0-organization-bootstrap/data/org-policies/compute_policy.yaml index 3841a823a..29d14b0a8 100644 --- a/fast/stages-aw/0-bootstrap/data/org-policies/compute_policy.yaml +++ b/fast/stages-aw/0-organization-bootstrap/data/org-policies/compute_policy.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -94,9 +94,9 @@ compute.requireOsLogin: # to create Compute Engine VM instances. Shielded VM features add verifiable # integrity and exfiltration resistance to your VMs. # SHOULD HAVE, at folder or project level -compute.requireShieldedVm: - rules: - - enforce: true +# compute.requireShieldedVm: +# rules: +# - enforce: true # The deny list of this list constraint defines the set of services that require diff --git a/fast/stages-aw/0-bootstrap/data/org-policies/data_policy.yaml b/fast/stages-aw/0-organization-bootstrap/data/org-policies/data_policy.yaml similarity index 98% rename from fast/stages-aw/0-bootstrap/data/org-policies/data_policy.yaml rename to fast/stages-aw/0-organization-bootstrap/data/org-policies/data_policy.yaml index 2fe308f55..0ed403208 100644 --- a/fast/stages-aw/0-bootstrap/data/org-policies/data_policy.yaml +++ b/fast/stages-aw/0-organization-bootstrap/data/org-policies/data_policy.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/fast/stages-aw/0-bootstrap/data/org-policies/dns_policy.yaml b/fast/stages-aw/0-organization-bootstrap/data/org-policies/dns_policy.yaml similarity index 97% rename from fast/stages-aw/0-bootstrap/data/org-policies/dns_policy.yaml rename to fast/stages-aw/0-organization-bootstrap/data/org-policies/dns_policy.yaml index 6a3a8eaa3..286935141 100644 --- a/fast/stages-aw/0-bootstrap/data/org-policies/dns_policy.yaml +++ b/fast/stages-aw/0-organization-bootstrap/data/org-policies/dns_policy.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/fast/stages-aw/0-bootstrap/data/org-policies/function_policy.yaml b/fast/stages-aw/0-organization-bootstrap/data/org-policies/function_policy.yaml similarity index 99% rename from fast/stages-aw/0-bootstrap/data/org-policies/function_policy.yaml rename to fast/stages-aw/0-organization-bootstrap/data/org-policies/function_policy.yaml index 61d6747f0..b0ccb3295 100644 --- a/fast/stages-aw/0-bootstrap/data/org-policies/function_policy.yaml +++ b/fast/stages-aw/0-organization-bootstrap/data/org-policies/function_policy.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/fast/stages-aw/0-bootstrap/data/org-policies/gke_policy.yaml b/fast/stages-aw/0-organization-bootstrap/data/org-policies/gke_policy.yaml similarity index 97% rename from fast/stages-aw/0-bootstrap/data/org-policies/gke_policy.yaml rename to fast/stages-aw/0-organization-bootstrap/data/org-policies/gke_policy.yaml index 949e14be8..1744e4fba 100644 --- a/fast/stages-aw/0-bootstrap/data/org-policies/gke_policy.yaml +++ b/fast/stages-aw/0-organization-bootstrap/data/org-policies/gke_policy.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/fast/stages-aw/0-bootstrap/data/org-policies/iam_policy.yaml b/fast/stages-aw/0-organization-bootstrap/data/org-policies/iam_policy.yaml similarity index 98% rename from fast/stages-aw/0-bootstrap/data/org-policies/iam_policy.yaml rename to fast/stages-aw/0-organization-bootstrap/data/org-policies/iam_policy.yaml index ea54e4890..20da7129c 100644 --- a/fast/stages-aw/0-bootstrap/data/org-policies/iam_policy.yaml +++ b/fast/stages-aw/0-organization-bootstrap/data/org-policies/iam_policy.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -80,7 +80,7 @@ iam.disableServiceAccountKeyUpload: # List of AWS account IDs that can be configured for workload identity # federation in Cloud IAM. # SHOULD HAVE -# contraints/iam.workloadIdentityPoolAwsAccounts: +# constraints/iam.workloadIdentityPoolAwsAccounts: # rules: # - deny: # all: true diff --git a/fast/stages-aw/0-organization-bootstrap/data/org-policies/lb_policy.yaml b/fast/stages-aw/0-organization-bootstrap/data/org-policies/lb_policy.yaml new file mode 100644 index 000000000..2ab13cb57 --- /dev/null +++ b/fast/stages-aw/0-organization-bootstrap/data/org-policies/lb_policy.yaml @@ -0,0 +1,81 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +# This boolean constraint, when enforced, disables creating Cloud Armor security +# policies. By default, you can create Cloud Armor security policies in any +# organization, folder, or project. +# COULD HAVE +compute.disableGlobalCloudArmorPolicy: + rules: + - enforce: true + +# This boolean constraint disables creation of global load balancing products. +# When enforced, only regional load balancing products without global dependencies +# can be created. By default, creation of global load balancing is allowed. +# COULD HAVE +compute.disableGlobalLoadBalancing: + rules: + - enforce: true + +# This boolean constraint, when enforced, disables creation of global +# self-managed SSL Certificates. Creation of google-managed or regional +# self-managed certificates is not disabled by this constraint. By default, +# you can create global self-managed SSL Certificates in any organization, +# folder, or project. +# COULD HAVE +compute.disableGlobalSelfManagedSslCertificate: + rules: + - enforce: true + +# This list constraint defines the set of load balancer types which can be +# created for an organization, folder, or project. Every load balancer type +# to be allowed or denied must be listed explicitly. By default, creation of +# all types of load balancers is allowed. The list of allowed or denied values +# must be identified as the string name of a load balancer, and can only +# include values from the list below: +# [ INTERNAL_TCP_UDP, INTERNAL_HTTP_HTTPS, EXTERNAL_NETWORK_TCP_UDP, +# EXTERNAL_TCP_PROXY, EXTERNAL_SSL_PROXY, EXTERNAL_HTTP_HTTPS, +# EXTERNAL_MANAGED_HTTP_HTTPS, REGIONAL_INTERNAL_MANAGED_TCP_PROXY, +# REGIONAL_EXTERNAL_MANAGED_TCP_PROXY, +# GLOBAL_EXTERNAL_MANAGED_HTTP_HTTPS]. +# To include all internal or all external load balancer types, use the +# in: prefix followed by INTERNAL or EXTERNAL. For example, allowing +# in:INTERNAL will allow all load balancer types from the above list that +# include INTERNAL. +# COULD HAVE +compute.restrictLoadBalancerCreationForTypes: + rules: + - allow: + values: + - in:INTERNAL + - EXTERNAL_NETWORK_TCP_UDP + +# This boolean constraint, when enforced, disables turning on Identity-Aware +# Proxy on global resources. Enabling IAP on regional resources is not +# restricted by this constraint. By default, enabling IAP on global resources +# is allowed. +# COULD HAVE +iap.requireGlobalIapWebDisabled: + rules: + - enforce: false + +# This boolean constraint, when enforced, disables turning on Identity-Aware +# Proxy on regional resources. Enabling IAP on global resources is not +# restricted by this constraint. By default, enabling IAP on regional resources +# is allowed. +# COULD HAVE +iap.requireRegionalIapWebDisabled: + rules: + - enforce: false diff --git a/fast/stages-aw/0-bootstrap/data/org-policies/marketplace_policy.yaml b/fast/stages-aw/0-organization-bootstrap/data/org-policies/marketplace_policy.yaml similarity index 96% rename from fast/stages-aw/0-bootstrap/data/org-policies/marketplace_policy.yaml rename to fast/stages-aw/0-organization-bootstrap/data/org-policies/marketplace_policy.yaml index 7a083fd19..1912aeaaa 100644 --- a/fast/stages-aw/0-bootstrap/data/org-policies/marketplace_policy.yaml +++ b/fast/stages-aw/0-organization-bootstrap/data/org-policies/marketplace_policy.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/fast/stages-aw/0-bootstrap/data/org-policies/networking_policy.yaml b/fast/stages-aw/0-organization-bootstrap/data/org-policies/networking_policy.yaml similarity index 94% rename from fast/stages-aw/0-bootstrap/data/org-policies/networking_policy.yaml rename to fast/stages-aw/0-organization-bootstrap/data/org-policies/networking_policy.yaml index 9580fca86..25788d43e 100644 --- a/fast/stages-aw/0-bootstrap/data/org-policies/networking_policy.yaml +++ b/fast/stages-aw/0-organization-bootstrap/data/org-policies/networking_policy.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -74,12 +74,12 @@ compute.disableVpcInternalIpv6: # COMPREHENSIVE (allows values == 1.0) # ]. # COULD HAVE -# TODO: Resolve issue in 2-networking-a-fedramp-high and uncomment out below -compute.requireVpcFlowLogs: - rules: - - allow: - values: - - COMPREHENSIVE +# TODO: Resolve issue in 3-networking-a-fedramp-high and uncomment out below +# compute.requireVpcFlowLogs: +# rules: +# - allow: +# values: +# - COMPREHENSIVE # This list constraint defines the type of protocol forwarding rule objects # with target instance that a user can create. When this constraint is enforced, @@ -107,11 +107,11 @@ compute.restrictProtocolForwardingCreationForTypes: # under:projects/PROJECT_ID, # or projects/PROJECT_ID/global/networks/NETWORK_NAME. # SHOULD HAVE -compute.restrictVpcPeering: - rules: - - allow: - values: - - under:${root_node} +# compute.restrictVpcPeering: +# rules: +# - allow: +# values: +# - under:${root_node} # This list constraint defines the set of valid IP-v4 addresses that can be # configured as VPN peer IPs. By default, any IP can be a VPN peer IP for a @@ -145,6 +145,6 @@ compute.skipDefaultNetworkCreation: # Utilize our custom constraint to prevent users from creating overly permissive firewalls -custom.restrictFirewallRanges: - rules: - - enforce: true +# custom.restrictFirewallRanges: +# rules: +# - enforce: true diff --git a/fast/stages-aw/0-bootstrap/data/org-policies/platform_policy.yaml b/fast/stages-aw/0-organization-bootstrap/data/org-policies/platform_policy.yaml similarity index 98% rename from fast/stages-aw/0-bootstrap/data/org-policies/platform_policy.yaml rename to fast/stages-aw/0-organization-bootstrap/data/org-policies/platform_policy.yaml index 8dc07bf2a..6c483f016 100644 --- a/fast/stages-aw/0-bootstrap/data/org-policies/platform_policy.yaml +++ b/fast/stages-aw/0-organization-bootstrap/data/org-policies/platform_policy.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -24,8 +24,7 @@ # COULD HAVE gcp.detailedAuditLoggingMode: rules: - - enforce: true - + - enforce: false # This boolean constraint, when enforced, disables Cloud Logging for the Cloud # Healthcare API. Audit logs aren't affected by this constraint. Cloud Logs @@ -61,6 +60,7 @@ gcp.resourceLocations: - allow: values: - in:us-locations + - global # This constraint defines the set of Google Cloud resource services that can be # used within an organization, folder, or project, such as compute.googleapis.com diff --git a/fast/stages-aw/0-bootstrap/data/org-policies/psc_policy.yaml b/fast/stages-aw/0-organization-bootstrap/data/org-policies/psc_policy.yaml similarity index 98% rename from fast/stages-aw/0-bootstrap/data/org-policies/psc_policy.yaml rename to fast/stages-aw/0-organization-bootstrap/data/org-policies/psc_policy.yaml index 3833199db..8e9674f56 100644 --- a/fast/stages-aw/0-bootstrap/data/org-policies/psc_policy.yaml +++ b/fast/stages-aw/0-organization-bootstrap/data/org-policies/psc_policy.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/fast/stages-aw/0-bootstrap/data/org-policies/storage_policy.yaml b/fast/stages-aw/0-organization-bootstrap/data/org-policies/storage_policy.yaml similarity index 99% rename from fast/stages-aw/0-bootstrap/data/org-policies/storage_policy.yaml rename to fast/stages-aw/0-organization-bootstrap/data/org-policies/storage_policy.yaml index c18c23a17..ebecf6669 100644 --- a/fast/stages-aw/0-bootstrap/data/org-policies/storage_policy.yaml +++ b/fast/stages-aw/0-organization-bootstrap/data/org-policies/storage_policy.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/fast/stages-aw/0-bootstrap/enableServices.sh b/fast/stages-aw/0-organization-bootstrap/enableServices.sh old mode 100755 new mode 100644 similarity index 97% rename from fast/stages-aw/0-bootstrap/enableServices.sh rename to fast/stages-aw/0-organization-bootstrap/enableServices.sh index 4d8e52244..0c60833bb --- a/fast/stages-aw/0-bootstrap/enableServices.sh +++ b/fast/stages-aw/0-organization-bootstrap/enableServices.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/fast/stages-aw/0-organization-bootstrap/identity-providers.tf b/fast/stages-aw/0-organization-bootstrap/identity-providers.tf new file mode 100644 index 000000000..408213329 --- /dev/null +++ b/fast/stages-aw/0-organization-bootstrap/identity-providers.tf @@ -0,0 +1,59 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# tfdoc:file:description Workload Identity Federation provider definitions. + +locals { + workforce_identity_providers = { + for k, v in var.workforce_identity_providers : k => merge( + v, + lookup(local.workforce_identity_providers_defs, v.issuer, {}) + ) + } + workforce_identity_providers_defs = { + azuread = { + attribute_mapping = { + "google.subject" = "assertion.subject" + "google.display_name" = "assertion.attributes.userprincipalname[0]" + "google.groups" = "assertion.attributes.groups" + "attribute.first_name" = "assertion.attributes.givenname[0]" + "attribute.last_name" = "assertion.attributes.surname[0]" + "attribute.user_email" = "assertion.attributes.mail[0]" + } + } + } +} + +resource "google_iam_workforce_pool" "default" { + count = length(local.workforce_identity_providers) > 0 ? 1 : 0 + parent = "organizations/${var.organization.id}" + location = "global" + workforce_pool_id = "${element(split(".", var.organization.domain), 0)}-bootstrap" +} + +resource "google_iam_workforce_pool_provider" "default" { + for_each = local.workforce_identity_providers + attribute_condition = each.value.attribute_condition + attribute_mapping = each.value.attribute_mapping + description = each.value.description + disabled = each.value.disabled + display_name = each.value.display_name + location = google_iam_workforce_pool.default[0].location + provider_id = "${element(split(".", var.organization.domain), 0)}-bootstrap-${each.key}" + workforce_pool_id = google_iam_workforce_pool.default[0].workforce_pool_id + saml { + idp_metadata_xml = each.value.saml.idp_metadata_xml + } +} \ No newline at end of file diff --git a/fast/stages-aw/0-organization-bootstrap/kms.tf b/fast/stages-aw/0-organization-bootstrap/kms.tf new file mode 100644 index 000000000..2d863b01c --- /dev/null +++ b/fast/stages-aw/0-organization-bootstrap/kms.tf @@ -0,0 +1,69 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +locals { + version_template = { + algorithm = "GOOGLE_SYMMETRIC_ENCRYPTION" + protection_level = "HSM" + } +} + +module "logging-kms" { + source = "../../../modules/kms" + for_each = toset(local.locations.logging) + project_id = module.centralized-logging-project.project_id + + keyring = { + location = each.value + name = "logging-${each.key}" + } + keys = { + "log-sink" = { + rotation_period = "7776000s" # CIS Compliance Benchmark 1.10 + version_template = local.version_template + } + } + iam_bindings_additive = { + "logging" = { + member = "serviceAccount:service-${module.centralized-logging-project.number}@gcp-sa-logging.iam.gserviceaccount.com" + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + } + } + depends_on = [data.google_logging_project_cmek_settings.settings] +} + +module "gcs-kms" { + source = "../../../modules/kms" + for_each = toset(local.locations.gcs) + project_id = module.centralized-logging-project.project_id + + keyring = { + location = each.value + name = "gcs-${each.key}" + } + keys = { + "gcs" = { + rotation_period = "7776000s" # CIS Compliance Benchmark 1.10 + version_template = local.version_template + } + } + iam = { + "roles/cloudkms.cryptoKeyEncrypterDecrypter" = [ + "serviceAccount:service-${module.centralized-logging-project.number}@gs-project-accounts.iam.gserviceaccount.com", + # module.automation-tf-resman-sa.iam_email + ] + } +} \ No newline at end of file diff --git a/fast/stages-aw/0-organization-bootstrap/log-export.tf b/fast/stages-aw/0-organization-bootstrap/log-export.tf new file mode 100644 index 000000000..867f68974 --- /dev/null +++ b/fast/stages-aw/0-organization-bootstrap/log-export.tf @@ -0,0 +1,158 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +locals { + primary_gcs_region = element(local.locations.gcs, 0) +} + +module "org-logging-bucket" { + source = "../../../modules/logging-bucket" + for_each = toset(local.locations.logging) + name = "${element(split(".", var.organization.domain), 0)}-org-log-bucket-${each.key}" + parent_type = "project" + parent = module.centralized-logging-project.project_id + location = each.value + retention = 30 + description = "Organization-level audit logs - captures org-level IAM, billing, org policies, and administrative activities" + log_analytics = { enable = true } + kms_key_name = coalesce(var.logging_kms_key, module.logging-kms[each.key].keys["log-sink"].id) + depends_on = [ + module.organization-logging, + module.logging-kms + ] +} + +module "folder-logging-bucket" { + source = "../../../modules/logging-bucket" + for_each = toset(local.locations.logging) + name = "${lower(replace(google_assured_workloads_workload.organization[0].display_name, " ", "-"))}-log-bucket-${each.key}" + parent_type = "project" + parent = module.centralized-logging-project.project_id + location = each.value + retention = 30 + description = "Folder-level audit logs." + log_analytics = { enable = true } + kms_key_name = coalesce(var.logging_kms_key, module.logging-kms[each.key].keys["log-sink"].id) + depends_on = [ + module.organization-logging, + module.logging-kms + ] +} + +resource "google_logging_organization_sink" "org_logging_sink" { + for_each = toset(local.locations.logging) + name = "org-logging-sink-${each.key}" + org_id = var.organization.id + destination = "logging.googleapis.com/${module.org-logging-bucket[each.key].id}" + depends_on = [ + module.org-logging-bucket + ] +} + +resource "google_logging_folder_sink" "folder_logging_sink" { + for_each = toset(local.locations.logging) + name = "${lower(replace(google_assured_workloads_workload.organization[0].display_name, " ", "-"))}-sink-${each.key}" + folder = "folders/${local.consumer_folder_id}" + destination = "logging.googleapis.com/${module.folder-logging-bucket[each.key].id}" + depends_on = [ + module.folder-logging-bucket + ] +} + +resource "google_project_iam_member" "org_log_writer_permission" { + for_each = toset(local.locations.logging) + project = module.centralized-logging-project.project_id + role = "roles/logging.bucketWriter" + member = google_logging_organization_sink.org_logging_sink[each.key].writer_identity + depends_on = [ + module.org-logging-bucket, + google_logging_organization_sink.org_logging_sink + ] +} + +resource "google_project_iam_member" "folder_log_writer_permission" { + for_each = toset(local.locations.logging) + project = module.centralized-logging-project.project_id + role = "roles/logging.bucketWriter" + member = google_logging_folder_sink.folder_logging_sink[each.key].writer_identity + depends_on = [ + module.folder-logging-bucket, + google_logging_folder_sink.folder_logging_sink + ] +} + +module "lz-logs-state-gcs" { + source = "../../../modules/gcs" + project_id = module.centralized-logging-project.project_id + name = "${element(split(".", var.top_level_folder.name), 0)}-org-iac" + location = local.primary_gcs_region + storage_class = local.gcs_storage_class[local.primary_gcs_region] + versioning = true + depends_on = [module.centralized-logging-project, module.gcs-kms] + encryption_key = module.gcs-kms[local.primary_gcs_region].keys.gcs.id +} + +module "lz-logs-bootstrap-gcs" { + source = "../../../modules/gcs" + project_id = module.centralized-logging-project.project_id + name = "${element(split(".", var.top_level_folder.name), 0)}-org-iac-bootstrap" + location = local.primary_gcs_region + storage_class = local.gcs_storage_class[local.primary_gcs_region] + versioning = true + depends_on = [module.centralized-logging-project, module.gcs-kms] + encryption_key = module.gcs-kms[local.primary_gcs_region].keys.gcs.id +} + +module "centralized-logging-project" { + source = "../../../modules/project" + billing_account = var.billing_account.id + name = local.project_map["centralized-logging-project"] + parent = var.assured_workloads.regime != "COMPLIANCE_REGIME_UNSPECIFIED" ? "folders/${local.consumer_folder_id}" : module.no-compliance-folder[0].folder.id + org_policies = { + "compute.skipDefaultNetworkCreation" = { + rules = [{ enforce = true }] + } + "iam.automaticIamGrantsForDefaultServiceAccounts" = { + rules = [{ enforce = true }] + } + "iam.disableServiceAccountKeyCreation" = { + rules = [{ enforce = true }] + } + } + services = concat( + [ + "cloudkms.googleapis.com", + "logging.googleapis.com", + "storage.googleapis.com" + ] + ) + depends_on = [ + module.organization, + google_assured_workloads_workload.organization + ] +} + +resource "google_project_service_identity" "logging" { + provider = google-beta + project = module.centralized-logging-project.project_id + service = "logging.googleapis.com" +} + +# tflint-ignore: terraform_unused_declarations +data "google_logging_project_cmek_settings" "settings" { + project = module.centralized-logging-project.project_id + depends_on = [google_project_service_identity.logging] +} \ No newline at end of file diff --git a/fast/stages-aw/0-organization-bootstrap/main.tf b/fast/stages-aw/0-organization-bootstrap/main.tf new file mode 100644 index 000000000..6d53c0b15 --- /dev/null +++ b/fast/stages-aw/0-organization-bootstrap/main.tf @@ -0,0 +1,53 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +locals { + gcs_storage_class = { + for loc in local.locations.gcs : loc => ( + length(split("-", loc)) < 2 ? "MULTI_REGIONAL" : "REGIONAL" + ) + } + locations = { + bq = var.locations.bq + gcs = var.locations.gcs + logging = compact(concat([try(local.checklist.location, null)], var.locations.logging)) + pubsub = var.locations.pubsub + kms = var.locations.kms + } + _gcp_devops_group = coalesce(var.groups.gcp-devops, var.gcp_devops_group) + _groups = { + gcp-billing-admins = coalesce(var.groups.gcp-billing-admins, var.gcp_billing_admins_group) + gcp-devops = local._gcp_devops_group + gcp-vpc-network-admins = coalesce(var.groups.gcp-vpc-network-admins, var.gcp_vpc_network_admins_group) + gcp-organization-admins = coalesce(var.groups.gcp-organization-admins, var.gcp_organization_admins_group) + gcp-security-admins = coalesce(var.groups.gcp-security-admins, var.gcp_security_admins_group) + gcp-support = coalesce(var.groups.gcp-support, var.gcp_support_group, local._gcp_devops_group) + } + principals = { + for k, v in local._groups : k => ( + can(regex("^[a-zA-Z]+:", v)) + ? v + : "group:${v}@${var.organization.domain}" + ) + } + + # The following section maps project names for stage 0 using the projects-config.yml inside of the root directory + project_config_yaml = yamldecode(file("../../../project-config.yml")) + project_map = { + for p in local.project_config_yaml.projects : p.name => + p.name == "centralized-logging-project" ? replace(p.project_name, "", substr(tostring(google_assured_workloads_workload.organization[0].resources[0].resource_id), -4, 4)) : # lz-audit- + p.project_name + } +} diff --git a/fast/stages-aw/0-organization-bootstrap/organization-iam.tf b/fast/stages-aw/0-organization-bootstrap/organization-iam.tf new file mode 100644 index 000000000..bfff789e4 --- /dev/null +++ b/fast/stages-aw/0-organization-bootstrap/organization-iam.tf @@ -0,0 +1,98 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# tfdoc:file:description Organization-level IAM bindings locals. + +locals { + # IAM roles in the org to reset (remove principals) + iam_delete_roles = [ + "roles/billing.creator" + ] + # domain IAM bindings + iam_domain_bindings = var.organization.domain == null ? {} : { + "domain:${var.organization.domain}" = { + authoritative = ["roles/browser"] + additive = [] + } + } + # human (groups) IAM bindings + iam_principal_bindings = { + (local.principals.gcp-billing-admins) = { + authoritative = [] + additive = ( + local.billing_mode != "org" ? [] : [ + "roles/billing.admin" + ] + ) + } + (local.principals.gcp-vpc-network-admins) = { + authoritative = [ + "roles/cloudasset.owner", + "roles/cloudsupport.techSupportEditor", + ] + additive = [ + "roles/compute.orgFirewallPolicyAdmin", + "roles/compute.xpnAdmin" + ] + } + (local.principals.gcp-organization-admins) = { + authoritative = [ + "roles/axt.admin", + "roles/cloudasset.owner", + "roles/cloudsupport.admin", + "roles/compute.osAdminLogin", + "roles/compute.osLoginExternalUser", + "roles/owner", + "roles/iam.workforcePoolAdmin", + ] + additive = concat( + [ + "roles/assuredworkloads.admin", + "roles/resourcemanager.folderAdmin", + "roles/resourcemanager.organizationAdmin", + "roles/resourcemanager.projectCreator", + "roles/resourcemanager.tagAdmin", + "roles/orgpolicy.policyAdmin" + ], + local.billing_mode != "org" ? [] : [ + "roles/billing.admin" + ] + ) + } + (local.principals.gcp-security-admins) = { + authoritative = [ + "roles/cloudasset.owner", + "roles/cloudsupport.techSupportEditor", + "roles/iam.securityReviewer", + "roles/logging.admin", + "roles/securitycenter.admin", + ] + additive = [ + "roles/accesscontextmanager.policyAdmin", + "roles/iam.organizationRoleAdmin", + "roles/orgpolicy.policyAdmin", + ] + } + (local.principals.gcp-support) = { + authoritative = [ + "roles/cloudsupport.techSupportEditor", + "roles/monitoring.viewer", + ] + additive = [ + "roles/logging.viewer", + ] + } + } +} diff --git a/fast/stages-aw/0-organization-bootstrap/organization.tf b/fast/stages-aw/0-organization-bootstrap/organization.tf new file mode 100644 index 000000000..f0984075d --- /dev/null +++ b/fast/stages-aw/0-organization-bootstrap/organization.tf @@ -0,0 +1,283 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# tfdoc:file:description Organization-level IAM. + +locals { + # reassemble logical bindings into the formats expected by the module + _iam_bindings = merge( + local.iam_domain_bindings, + { + for k, v in local.iam_principal_bindings : k => { + authoritative = [] + additive = v.additive + } + } + ) + _iam_bindings_auth = flatten([ + for member, data in local._iam_bindings : [ + for role in data.authoritative : { + member = member + role = role + } + ] + ]) + _iam_bindings_add = flatten([ + for member, data in local._iam_bindings : [ + for role in data.additive : { + member = member + role = role + } + ] + ]) + _org_only_roles = [ + "roles/billing.admin", + "roles/billing.creator", + "roles/orgpolicy.policyAdmin", + "roles/iam.organizationRoleAdmin", + "roles/cloudsupport.admin", + "roles/assuredworkloads.admin", + "roles/compute.osLoginExternalUser", + "roles/resourcemanager.organizationAdmin", + ] + # tflint-ignore: terraform_unused_declarations + drs_domains = concat(var.organization.customer_id == null ? [] : [var.organization.customer_id], + var.org_policies_config.constraints.allowed_policy_member_domains + ) + drs_tag_name = "${var.organization.id}/${var.org_policies_config.tag_name}" + + # intermediate values before we merge in what comes from the checklist + _iam_principals = { + for k, v in local.iam_principal_bindings : k => v.authoritative + } + _iam = merge( + { + for r in local.iam_delete_roles : r => [] + }, + { + for b in local._iam_bindings_auth : b.role => b.member... + } + ) + _iam_bindings_additive = { + for b in local._iam_bindings_add : "${b.role}-${b.member}" => { + member = b.member + role = b.role + } + } + + # final values combining all sources + iam_principals = { + for k, v in local._iam_principals : k => distinct(concat( + v, + try(local.checklist.iam_principals[k], []) + )) + } + folder_iam_principals = { + for principal, roles in local.iam_principals : + principal => [ + for role in roles : role if !contains(local._org_only_roles, role) + ] + if length([for role in roles : role if !contains(local._org_only_roles, role)]) > 0 + } + org_iam_principals = { + for principal, roles in local.iam_principals : + principal => [ + for role in roles : role if contains(local._org_only_roles, role) + ] + if length([for role in roles : role if contains(local._org_only_roles, role)]) > 0 + } + iam = { + for k, v in local._iam : k => distinct(concat( + v, + try(local.checklist.iam[k].authoritative, []) + )) + } + iam_bindings_additive = merge( + local._iam_bindings_additive, + { + for k, v in try(local.checklist.iam_bindings, {}) : + v.key => v if lookup(local._iam_bindings_additive, v.key, null) == null + } + ) + folder_iam_bindings_additive = { + for k, v in local.iam_bindings_additive : k => v + if !contains(local._org_only_roles, v.role) + } + org_iam_bindings_additive = { + for k, v in local.iam_bindings_additive : k => v + if contains(local._org_only_roles, v.role) + } + # compute authoritative and additive roles for use by add-ons (checklist, etc.) + iam_roles_authoritative = distinct(concat( + flatten(values(local._iam_principals)), + keys(local._iam) + )) + + # Some of the org policies require templating to construct, they have been moved to data/custom-org-policies + # load org policy yaml files from a subdirectory + _org_policies_raw = merge([ + for f in try(fileset("./data/custom-org-policies/", "*_policy.yaml"), []) : + yamldecode(templatefile("./data/custom-org-policies/${f}", { + # NOTE: + # If there are more variables need to be substituted, put them + # into a separate yaml file or map, use the following line to + # loop through them. For list values use yamlencode() function. + # for k, v in local.common_settings : k => v + organization_id : var.organization.id + domain_name : var.organization.domain + customer_id : var.organization.customer_id + drs_tag_name : local.drs_tag_name + allowed_policy_member_domains : var.org_policies_config.constraints.allowed_policy_member_domains + allowed_access_boundaries : var.org_policies_config.constraints.allowed_access_boundaries + } + ))]...) + # formalize the policies + org_policies = { + for k, v in local._org_policies_raw : + k => { + inherit_from_parent = try(v.inherit_from_parent, null) + reset = try(v.reset, null) + rules = [ + for r in try(v.rules, []) : { + allow = can(r.allow) ? { + all = try(r.allow.all, null) + values = try(r.allow.values, null) + } : null + deny = can(r.deny) ? { + all = try(r.deny.all, null) + values = try(r.deny.values, null) + } : null + enforce = try(r.enforce, null) + condition = { + description = try(r.condition.description, null) + expression = try(r.condition.expression, null) + location = try(r.condition.location, null) + title = try(r.condition.title, null) + } + } + ] + } + } + folder_org_policies = { + for k, v in local.org_policies : k => v + if k != "resourcemanager.accessBoundaries" + } + org_only_policies = { + for k, v in local.org_policies : k => v + if k == "resourcemanager.accessBoundaries" + } + consumer_folder_id = try(one([ + for r in google_assured_workloads_workload.organization[0].resources : r.resource_id if r.resource_type == "CONSUMER_FOLDER" + ]), null) +} + +resource "google_assured_workloads_workload" "organization" { + count = var.assured_workloads.regime != "COMPLIANCE_REGIME_UNSPECIFIED" ? 1 : 0 + compliance_regime = var.assured_workloads.regime + display_name = "${var.top_level_folder.name} Logging" + location = lower(var.assured_workloads.location) + organization = var.organization.id + billing_account = var.billing_account.id != null ? "billingAccounts/${var.billing_account.id}" : null + provisioned_resources_parent = "folders/${var.top_level_folder.id}" + resource_settings { + display_name = "${var.top_level_folder.name} Logging" + resource_type = "CONSUMER_FOLDER" + } + + violation_notifications_enabled = true + lifecycle { + create_before_destroy = true + ignore_changes = [billing_account] + } +} + +module "no-compliance-folder" { + count = var.assured_workloads.regime == "COMPLIANCE_REGIME_UNSPECIFIED" ? 1 : 0 + source = "../../../modules/folder" + parent = "organizations/${var.organization.id}" + name = "${var.top_level_folder.name} Logging" +} + +# TODO: add a check block to ensure our custom roles exist in the factory files + +module "organization-logging" { + # Preconfigure organization-wide logging settings to ensure project + # log buckets (_Default, _Required) are created in the location + # specified by `var.locations.logging`. This separate + # organization-block prevents circular dependencies with later + # project creation. + count = 1 + source = "../../../modules/organization" + organization_id = "organizations/${var.organization.id}" + logging_settings = { + storage_location = "global" + } +} + +module "organization" { + source = "../../../modules/organization-se" + organization_id = "organizations/${var.organization.id}" + # human (groups) IAM bindings + iam_by_principals = { + for k, v in local.org_iam_principals : + k => distinct(concat(v, lookup(var.iam_by_principals, k, []))) + } + # additive bindings, used for roles co-managed by different stages + iam_bindings_additive = merge( + local.org_iam_bindings_additive, + var.iam_bindings_additive + ) + custom_roles = var.custom_roles + factories_config = { + custom_roles = var.factories_config.custom_roles + org_policy_custom_constraints = "./data/custom-constraint-policies/" + } + org_policies = local.org_only_policies +} + +module "top_level_folder" { + source = "../../../modules/folder" + folder_create = false + id = "folders/${var.top_level_folder.id}" + parent = "organizations/${var.organization.id}" + iam_by_principals = { + for k, v in local.folder_iam_principals : # Use the filtered folder local + k => distinct(concat(v, lookup(var.iam_by_principals, k, []))) + } + # machine (service accounts) IAM bindings + iam = { + for k, v in merge( + { + for k, v in local.iam : k => distinct(concat(v, lookup(var.iam, k, []))) + }, + { + for k, v in var.iam : k => v if lookup(local.iam, k, null) == null + } + ) : k => v if !contains(local._org_only_roles, k) + } + # additive bindings, used for roles co-managed by different stages + iam_bindings_additive = merge( + local.folder_iam_bindings_additive, + var.iam_bindings_additive + ) + factories_config = { + custom_roles = var.factories_config.custom_roles + org_policies = ( + var.factories_config.org_policy + ) + org_policy_custom_constraints = "./data/custom-constraint-policies/" + } + org_policies = local.folder_org_policies +} diff --git a/fast/stages-aw/0-organization-bootstrap/outputs-gcs.tf b/fast/stages-aw/0-organization-bootstrap/outputs-gcs.tf new file mode 100644 index 000000000..78eef73e7 --- /dev/null +++ b/fast/stages-aw/0-organization-bootstrap/outputs-gcs.tf @@ -0,0 +1,29 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# tfdoc:file:description Output files persistence to automation GCS bucket. + +resource "google_storage_bucket_object" "providers" { + for_each = local.providers + bucket = module.lz-logs-bootstrap-gcs.name + name = "providers/${each.key}-providers.tf" + content = each.value +} + +resource "google_storage_bucket_object" "input_tfvars" { + bucket = module.lz-logs-bootstrap-gcs.name + name = "tfvars/stage-0-inputs.auto.tfvars.json" + content = local.tfvars_content +} \ No newline at end of file diff --git a/fast/stages-aw/0-organization-bootstrap/outputs.tf b/fast/stages-aw/0-organization-bootstrap/outputs.tf new file mode 100644 index 000000000..a3e35cecd --- /dev/null +++ b/fast/stages-aw/0-organization-bootstrap/outputs.tf @@ -0,0 +1,47 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +locals { + _tpl_providers = "${path.module}/templates/providers.tf.tpl" + inputs_tfvars = { + assured_workloads = var.assured_workloads + billing_account = var.billing_account + locations = var.locations + organization = var.organization + org_policies_config = var.org_policies_config + bootstrap_project = var.bootstrap_project + top_level_folder = var.top_level_folder + } + providers = { + "0-organization-bootstrap" = templatefile(local._tpl_providers, { + backend_extra = null + bucket = module.lz-logs-state-gcs.name + name = "organization bootstrap" + prefix = "terraform/state" + project = module.centralized-logging-project.project_id + }) + } + tfvars_content = jsonencode(local.inputs_tfvars) +} + +output "workforce_identity_pool" { + description = "Workforce Identity Federation pool." + value = { + pool = try( + google_iam_workforce_pool.default[0].name, null + ) + } +} diff --git a/fast/stages-aw/0-bootstrap/providers.tf.tmp b/fast/stages-aw/0-organization-bootstrap/providers.tf.tmp similarity index 100% rename from fast/stages-aw/0-bootstrap/providers.tf.tmp rename to fast/stages-aw/0-organization-bootstrap/providers.tf.tmp diff --git a/fast/stages-aw/0-bootstrap/setIAM.sh b/fast/stages-aw/0-organization-bootstrap/setIAM.sh old mode 100755 new mode 100644 similarity index 99% rename from fast/stages-aw/0-bootstrap/setIAM.sh rename to fast/stages-aw/0-organization-bootstrap/setIAM.sh index fb9c1e591..8cc79cecb --- a/fast/stages-aw/0-bootstrap/setIAM.sh +++ b/fast/stages-aw/0-organization-bootstrap/setIAM.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. - # Color definitions RED='\033[0;31m' GREEN='\033[0;32m' diff --git a/fast/stages-aw/0-bootstrap/setIAM.yaml.sample b/fast/stages-aw/0-organization-bootstrap/setIAM.yaml.sample similarity index 69% rename from fast/stages-aw/0-bootstrap/setIAM.yaml.sample rename to fast/stages-aw/0-organization-bootstrap/setIAM.yaml.sample index 2f17f9bda..10f4c06cd 100644 --- a/fast/stages-aw/0-bootstrap/setIAM.yaml.sample +++ b/fast/stages-aw/0-organization-bootstrap/setIAM.yaml.sample @@ -1,3 +1,17 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + { "bindings": [ { @@ -65,18 +79,6 @@ "user:{USER}" ], "role": "roles/billing.admin" - }, - { - "members": [ - "user:{USER}" - ], - "role": "roles/resourcemanager.projectDeleter" - }, - { - "members": [ - "user:{USER}" - ], - "role": "roles/iam.serviceAccountTokenCreator" } ] } \ No newline at end of file diff --git a/fast/stages-aw/0-organization-bootstrap/templates/providers.tf.tpl b/fast/stages-aw/0-organization-bootstrap/templates/providers.tf.tpl new file mode 100644 index 000000000..48c242348 --- /dev/null +++ b/fast/stages-aw/0-organization-bootstrap/templates/providers.tf.tpl @@ -0,0 +1,37 @@ +/** + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +terraform { + backend "gcs" { + bucket = "${bucket}" + prefix = "${prefix}" + %{~ if backend_extra != null ~} + ${indent(4, backend_extra)} + %{~ endif ~} + } +} +provider "google" { + project = var.bootstrap_project + billing_project = var.bootstrap_project + user_project_override = true +} +provider "google-beta" { + project = var.bootstrap_project + billing_project = var.bootstrap_project + user_project_override = true +} + +# end provider.tf for ${name} diff --git a/fast/stages-aw/0-organization-bootstrap/terraform.tfvars.sample b/fast/stages-aw/0-organization-bootstrap/terraform.tfvars.sample new file mode 100644 index 000000000..4d8c803ba --- /dev/null +++ b/fast/stages-aw/0-organization-bootstrap/terraform.tfvars.sample @@ -0,0 +1,57 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +# use `gcloud beta billing accounts list` +# if you have too many accounts, check the Cloud Console :) +assured_workloads = { + regime = "compliance-regime" #"IL4, IL5, FEDRAMP_HIGH, etc... if you wish to not use assured_workloads, set this value to COMPLIANCE_REGIME_UNSPECIFIED" + location = "us-east4" +} + +billing_account = { + id = "012345-67890A-BCDEF0" +} + +bootstrap_project = "bootstrap-project-name" + +# locations for GCS, BigQuery, KMS, and logging buckets created here +locations = { + bq = "us-east4" + gcs = ["us-east4"] + logging = ["us-east4"] + pubsub = ["us-east4"] + kms = "us-east4" +} + +# use `gcloud organizations list` +organization = { + domain = "example.org" + id = 1234567890 + customer_id = "C000001" +} + +org_policies_config = { + import_defaults = false # No policies to import as of 27 SEP 2024 + constraints = { + allowed_policy_member_domains = [] # Additional externally allowed customer_ids + allowed_access_boundaries = [] # Additional externally allowed organization_ids + } +} + +top_level_folder = { + name = "Top_level_folder_name" #replace with given folder name + id = "123456788" #replace with given folder id +} \ No newline at end of file diff --git a/fast/stages-aw/0-organization-bootstrap/variables.tf b/fast/stages-aw/0-organization-bootstrap/variables.tf new file mode 100644 index 000000000..ea2a19b01 --- /dev/null +++ b/fast/stages-aw/0-organization-bootstrap/variables.tf @@ -0,0 +1,212 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +variable "assured_workloads" { + description = "Configuration for Assured Workloads." + type = object({ + regime = string + location = string + }) + nullable = false + default = { + regime = "IL5" + location = "US" + } +} + +variable "billing_account" { + description = "Billing account id. If billing account is not part of the same org set `is_org_level` to `false`. To disable handling of billing IAM roles set `no_iam` to `true`." + type = object({ + id = string + is_org_level = optional(bool, true) + no_iam = optional(bool, false) + }) + nullable = false +} + +variable "bootstrap_project" { + description = "Bootstrap project ID." + type = string +} + +variable "custom_roles" { + description = "Map of role names => list of permissions to additionally create at the organization level." + type = map(list(string)) + nullable = false + default = {} +} + +variable "factories_config" { + description = "Configuration for the resource factories or external data." + type = object({ + checklist_data = optional(string) + checklist_org_iam = optional(string) + custom_roles = optional(string, "data/custom-roles") + org_policy = optional(string, "data/org-policies") + }) + nullable = false + default = {} +} + +variable "gcp_billing_admins_group" { + description = "GCP Billing Admins group name." + type = string + default = "gcp-billing-admins" +} + +variable "gcp_devops_group" { + description = "GCP DevOps group name." + type = string + default = "gcp-devops" +} + +variable "gcp_organization_admins_group" { + description = "GCP Organization Admins group name." + type = string + default = "gcp-organization-admins" +} + +variable "gcp_security_admins_group" { + description = "GCP Security Admins group name." + type = string + default = "gcp-security-admins" +} + +variable "gcp_support_group" { + description = "GCP Support group name." + type = string + default = null +} + +variable "gcp_vpc_network_admins_group" { + description = "GCP VPC Network Admins group name." + type = string + default = "gcp-vpc-network-admins" +} + +variable "groups" { + # https://cloud.google.com/docs/enterprise/setup-checklist + description = "Group names or IAM-format principals to grant organization-level permissions. If just the name is provided, the 'group:' principal and organization domain are interpolated." + type = object({ + gcp-billing-admins = optional(string) + gcp-devops = optional(string) + gcp-vpc-network-admins = optional(string) + gcp-organization-admins = optional(string) + gcp-security-admins = optional(string) + # aliased to gcp-devops as the checklist does not create it + gcp-support = optional(string) + }) + nullable = false + default = {} +} + +variable "iam" { + description = "Organization-level custom IAM settings in role => [principal] format." + type = map(list(string)) + nullable = false + default = {} +} + +variable "iam_bindings_additive" { + description = "Organization-level custom additive IAM bindings. Keys are arbitrary." + type = map(object({ + member = string + role = string + condition = optional(object({ + expression = string + title = string + description = optional(string) + })) + })) + nullable = false + default = {} +} + +variable "iam_by_principals" { + description = "Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid cycle errors. Merged internally with the `iam` variable." + type = map(list(string)) + default = {} + nullable = false +} + +variable "locations" { + description = "Optional locations for GCS, BigQuery, and logging buckets created here." + type = object({ + bq = optional(string, "US") + gcs = optional(list(string), ["US"]) + logging = optional(list(string), ["global"]) + pubsub = optional(list(string), []) + kms = optional(list(string), ["US"]) + }) + nullable = false + default = {} +} + +variable "logging_kms_key" { + description = "value of the KMS key used for logging." + type = string + default = null +} + +variable "org_policies_config" { + description = "Organization policies customization." + type = object({ + constraints = optional(object({ + allowed_policy_member_domains = optional(list(string), []) + allowed_access_boundaries = optional(list(string), []) + }), {}) + import_defaults = optional(bool, false) + tag_name = optional(string, "org-policies") + tag_values = optional(map(object({ + description = optional(string, "Managed by the Terraform organization module.") + iam = optional(map(list(string)), {}) + id = optional(string) + })), {}) + }) + default = {} +} + +variable "organization" { + description = "Organization details." + type = object({ + id = number + domain = optional(string) + customer_id = optional(string) + }) +} + +variable "top_level_folder" { + description = "Top Level Folder Details." + type = object({ + name = string + id = string + }) +} + +variable "workforce_identity_providers" { + description = "Workforce Identity Federation pools." + type = map(object({ + attribute_condition = optional(string) + issuer = string + display_name = string + description = string + disabled = optional(bool, false) + saml = optional(object({ + idp_metadata_xml = string + }), null) + })) + default = {} + nullable = false +} diff --git a/fast/stages-aw/0-bootstrap/IAM.md b/fast/stages-aw/1-assured-workload/IAM.md similarity index 95% rename from fast/stages-aw/0-bootstrap/IAM.md rename to fast/stages-aw/1-assured-workload/IAM.md index 7a0ed0677..f4cccb5ad 100644 --- a/fast/stages-aw/0-bootstrap/IAM.md +++ b/fast/stages-aw/1-assured-workload/IAM.md @@ -1,3 +1,19 @@ + + # IAM bindings reference Legend: + additive, conditional. diff --git a/fast/stages-aw/0-bootstrap/README.md b/fast/stages-aw/1-assured-workload/README.md similarity index 61% rename from fast/stages-aw/0-bootstrap/README.md rename to fast/stages-aw/1-assured-workload/README.md index 998d4e545..25224961d 100644 --- a/fast/stages-aw/0-bootstrap/README.md +++ b/fast/stages-aw/1-assured-workload/README.md @@ -1,24 +1,37 @@ -# Google Cloud Organization Bootstrap + + +# Google Cloud Assured Workload Bootstrap + +The purpose of this stage is to enable critical Google Cloud Assured Workload level functionalities that prepare the prerequisites needed to enable automation in this and future stages. In addition, this stage ensures that all future fast stages are compliant with the selected compliance regime. - [Design Overview and Choices](#design-overview-and-choices) - [Assured Workloads](#assured-workloads) - [User Groups](#user-groups) - - [Google Cloud Organization Level IAM](#google-cloud-organization-level-iam) - - [Google Cloud Organization Policies and Tag-Based Conditions](#google-cloud-organization-policies-and-tag-based-conditions) - [Automation Google Cloud Project and Resources](#automation-google-cloud-project-and-resources) - [Billing Account](#billing-account) - - [Google Cloud Organization Level Logging](#google-cloud-organization-level-logging) + - [Tenant Log Sinks](#tenant-log-sinks) + - [Log Sinks and Log Destinations](#log-sinks-and-log-destinations) - [Naming](#naming) - - [Workforce Identity Federation](#workforce-identity-federation) - [Workload Identity Federation and CI/CD](#workload-identity-federation-and-cicd) - [How to Run This Stage](#how-to-run-this-stage) - [Customizations](#customizations) - [Group Names](#group-names) - [IAM](#iam) - - [Log Sinks and Log Destinations](#log-sinks-and-log-destinations) - [Names and Naming Convention](#names-and-naming-convention) - [Workload Identity Federation](#workload-identity-federation) - [CI/CD Repositories](#cicd-repositories) @@ -39,62 +52,7 @@ Assured Workloads Google Cloud Folders are provisioned in this stage to ensure a User groups are important, not only here but throughout the whole automation process. They provide a stable frame of reference that allows decoupling the final set of permissions for each group, from the stage where entities and resources are created and their IAM bindings defined. For example, the final set of roles for the networking group is contributed by this stage at the Google Cloud Organization level (XPN Admin, Cloud Asset Viewer, etc.), and by the Resource Management stage at the Google Cloud Folder level. -We have standardized the initial set of groups on those outlined in the [GCP Enterprise Setup Checklist](https://cloud.google.com/docs/enterprise/setup-checklist) to simplify adoption. They provide a comprehensive and flexible starting point that can suit most users. Adding new groups, or deviating from the initial setup is possible and reasonably simple, and it's briefly outlined in the customization section below. - -### Google Cloud Organization Level IAM - -The service account used in the [Resource Management stage](../1-resman) needs to be able to grant specific permissions at the Google Cloud Organization level, to enable specific functionality for subsequent stages that deal with network or security resources, or billing-related activities. - -In order to be able to assign those roles without having the full authority of the Google Cloud Organization Admin role, this stage defines a custom role that only allows setting IAM policies on the Google Cloud Organization, and grants it via a [delegated role grant](https://cloud.google.com/iam/docs/setting-limits-on-granting-roles) that only allows it to be used to grant a limited subset of roles. - -In this way, the Resource Management service account can effectively act as a Google Cloud Organization Admin, but only to grant the specific roles it needs to control. - -One consequence of the above setup is the need to configure IAM bindings that can be assigned via the condition as non-authoritative, since those same roles are effectively under the control of two stages: this one and Resource Management. Using authoritative bindings for these roles (instead of non-authoritative ones) would generate potential conflicts, where each stage could try to overwrite and negate the bindings applied by the other at each `apply` cycle. - -A full reference of IAM roles managed by this stage [is available here](./IAM.md). - -### Google Cloud Organization Policies and Tag-Based Conditions - -It's often desirable to have Google Cloud Organization policies deployed before any other resource in the org, so as to ensure compliance with specific requirements (e.g. location restrictions), or control the configuration of specific resources (e.g. default network at Google Cloud Project creation or service account grants). - -Google Cloud Organization policy exceptions are managed via a dedicated resource management tag hierarchy, rooted in the `org-policies` tag key. A default condition is already present for the `iam.allowedPolicyMemberDomains` constraint, that relaxes the policy on resources that have the `org-policies/allowed-policy-member-domains-all` tag value bound or inherited. - -Further tag values can be defined via the `org_policies_config.tag_values` variable, and IAM access can be granted on them via the same variable. Once a tag value has been created, its id can be used in constraint rule conditions. - -Management of the rest of the tag hierarchy is delegated to the resource management stage, as that is often intimately tied to the Google Cloud Folder hierarchy design. - -The Google Cloud Organization policy tag key and values managed by this stage have been added to the `0-bootstrap.auto.tfvars` stage, so that IAM can be delegated to the resource management or successive stages via their ids. - -The following example shows an example on how to define an additional tag value, and use it in a boolean constraint rule. - -This snippet defines a new tag value under the `org-policies` tag key via the `org_policies_config` variable, and assigns the permission to bind it to a group. - -```hcl -# stage 0 custom tfvars -org_policies_config = { - tag_values = { - compute-require-oslogin-false = { - description = "Bind this tag to set oslogin to false." - iam = { - "roles/resourcemanager.tagUser" = [ - "group:foo@example.com" - ] - } - } - } -} -``` - -The above tag can be used to define a constraint condition via the `data/org-policies/compute.yaml` or similar factory file. The id in the condition is the Google Cloud Organization id, followed by the name of the Google Cloud Organization policy tag key (defaults to `org-policies`). - -```yaml -compute.requireOsLogin: - rules: - - enforce: true - - enforce: false - condition: - expression: resource.matchTag('12345678/org-policies-config', 'compute-require-oslogin-false') -``` +We have standardized the initial set of groups on those outlined in the [GCP Enterprise Setup Checklist](https://cloud.google.com/docs/enterprise/setup-checklist) to simplify adoption. They provide a comprehensive and flexible starting point that can suit most users. Adding new groups, or deviating from the initial setup is possible and reasonably simple, and it's briefly outlined in the customization section below. ### Automation Google Cloud Project and Resources @@ -114,19 +72,24 @@ For details on configuring the different billing account modes, refer to the [Ho Due to limitations of API availability, manual steps have to be followed to enable billing export within the billing Google Cloud Project to BigQuery dataset `billing_export`, which will be created as part of the bootstrap stage. The process to share billing data [is outlined here](https://cloud.google.com/billing/docs/how-to/export-data-bigquery-setup#enable-bq-export). -#### Billing Budgets +### Tenant Log Sinks -A default billing budget can be created for the top-level folder of the landing zone by setting the `billing_budget_amount` variable. This budget will cover all projects created within the Assured Workload folder (or the "no-compliance" folder if Assured Workloads are disabled). The variable is an object that allows specifying the budget amount and optional threshold rules (defaults to 0.5, 0.75, and 0.9). +Organization-level logging sinks for tenants creates centralized log routing from tenant folders to dedicated log buckets during the stage they are created. This customization is integrated from the bootstrap stage where outputs are staged. It captures logs from the tenant folders, projects, and all their related activities including automated tenant mappings for routing and ingestion into Google SecOps. -### Google Cloud Organization Level Logging +### Log Sinks and Log Destinations + +You can customize Google Cloud Organization level logs through the `log_sinks` variable in two ways + +- creating additional log sinks to capture more logs +- changing the destination of captured logs -We create Google Cloud Organization level log sinks early in the bootstrap process to ensure a proper audit trail is in place from the very beginning. By default, we provide log filters to capture [Cloud Audit Logs](https://cloud.google.com/logging/docs/audit), [VPC Service Controls violations](https://cloud.google.com/vpc-service-controls/docs/troubleshooting#vpc-sc-errors) and [Workspace Logs](https://cloud.google.com/logging/docs/audit/configure-gsuite-audit-logs) into logging buckets in the top-level audit logging Google Cloud Project. In addition, a log sink with an empty filter is included to comply with [Center for Internet Security (CIS) Benchmarks](https://cloud.google.com/security/compliance/cis) related to log sinks. +By default, all logs are exported to a log bucket, but FAST can create sinks to BigQuery, GCS, or PubSub. -The [Customizations](#log-sinks-and-log-destinations) section explains how to change the logs captured and their destination. +If you need to capture additional logs, please refer to GCP's documentation on [Scenarios for Exporting Logging Data](https://cloud.google.com/architecture/exporting-stackdriver-logging-for-security-and-access-analytics), where you can find ready-made filter expressions for different use cases. ### Naming -We are intentionally not supporting random prefix/suffixes for names, as that is an antipattern typically only used in development. It does not map to our customer's actual production usage, where they always adopt a fixed naming convention. +We are intentionally not supporting random prefix/suffixes for names, as that is an anti-pattern typically only used in development. It does not map to our customer's actual production usage, where they always adopt a fixed naming convention. What is implemented here is a fairly common convention, composed of tokens ordered by relative importance @@ -142,26 +105,6 @@ The convention is used in its full form only for specific resources with globall The [Customizations](#names-and-naming-convention) section on names below explains how to configure tokens, or implement a different naming convention. -### Workforce Identity Federation - -This stage supports configuration of [Workforce Identity Federation](https://cloud.google.com/iam/docs/workforce-identity-federation) which lets an external identity provider (IdP) to authenticate and authorize a group of users (usually employees) using IAM, so that the users can access Google Cloud services. - -The following example shows an example on how to define a Workforce Identity pool for the Google Cloud Organization. - -```hcl -# stage 0 wif tfvars -workforce_identity_providers = { - test = { - issuer = "azuread" - display_name = "wif-provider" - description = "Workforce Identity pool" - saml = { - idp_metadata_xml = "..." - } - } -} -``` - ### Workload Identity Federation and CI/CD This stage also implements initial support for two interrelated features @@ -171,7 +114,7 @@ This stage also implements initial support for two interrelated features Workload Identity Federation support allows configuring external providers independently from CI/CD, and offers predefined attributes for a few well known ones (more can be easily added by editing the `identity-providers.tf` file). Once providers have been configured their names are passed to the following stages via interface outputs, and can be leveraged to set up access or impersonation in IAM bindings. -CI/CD support is fully implemented for GitHub, Gitlab, and Cloud Source Repositories / Cloud Build. For GitHub, we also offer a [separate supporting setup](../../extras/0-cicd-github/) to quickly create/configure repositories. +CI/CD support is fully implemented for GitHub, Gitlab, and Cloud Source Repositories / Cloud Build. For GitHub, we also offer a [separate supporting setup](../0-organization-bootstrap/) to quickly create/configure repositories. For details on how to configure both features, refer to the Customizations sections below on [Workload Identity Federation](#workload-identity-federation) and [CI/CD repositories](#cicd-repositories). @@ -179,7 +122,7 @@ These features are optional and only enabled if the relevant variables have been ## How to Run This Stage -For detailed information on prerequisites and steps to deploy this stage, please see the latest [Detailed Deployment Guide (DDG)](/docs/ddg.md) If you do not have access, you will have to request it. +For detailed information on prerequisites and steps to deploy this stage, please see the latest [stellar-engine Cloud Engineer Development Guide](https://docs.google.com/document/d/1o39QZ-K5CTP8FdTs9Jgz3JRF7HZ8in-1QoM0SCcIEAk/edit?tab=t.0#heading=h.tvlxzbk3nqgs) and scroll down to stellar-engine - Automation section. If you do not have access, you will have to request it. ## Customizations @@ -189,16 +132,17 @@ Most variables (e.g. `billing_account` and `organization`) are only used to inpu As we mentioned above, groups reflect the convention used in the [GCP Enterprise Setup Checklist](https://cloud.google.com/docs/enterprise/setup-checklist), with an added level of indirection: the `groups` variable maps logical names to actual names, so that you don't need to delve into the code if your group names do not comply with the checklist convention. -For example, if your network admins team is called `net-rockstars@example.com`, simply set that name in the variable, minus the domain which is interpolated internally with the Google Cloud Organization domain: +Each group also has an individual variable (e.g., `gcp_vpc_network_admins_group`) to allow for easy overrides via environment variables. + +For example, if your network admins team is called `network-admins@example.com`, you can set the name (minus the domain) in either the `groups` variable or the individual `gcp_vpc_network_admins_group` variable: ```hcl -variable "groups" { - description = "Group names to grant organization-level permissions." - type = map(string) - default = { - gcp-vpc-network-admins = "net-rockstars" - # [...] - } +# Option 1: Using the individual variable (easiest for environment variables) +gcp_vpc_network_admins_group = "network-admins" + +# Option 2: Using the groups object +groups = { + gcp-vpc-network-admins = "network-admins" } ``` @@ -233,17 +177,6 @@ When customizations are needed, three stage-level variables allow injecting addi Refer to the [project module](../../../modules/project/) for examples on how to use the IAM variables, and they are an interface shared across all our modules. -### Log Sinks and Log Destinations - -You can customize Google Cloud Organization level logs through the `log_sinks` variable in two ways - -- creating additional log sinks to capture more logs -- changing the destination of captured logs - -By default, all logs are exported to a log bucket, but FAST can create sinks to BigQuery, GCS, or PubSub. - -If you need to capture additional logs, please refer to GCP's documentation on [scenarios for exporting logging data](https://cloud.google.com/architecture/exporting-stackdriver-logging-for-security-and-access-analytics), where you can find ready-made filter expressions for different use cases. - ### Names and Naming Convention Configuring the individual tokens for the naming convention described above, has varying degrees of complexity @@ -253,7 +186,7 @@ Configuring the individual tokens for the naming convention described above, has All other tokens are set directly in resource names, as providing abstractions to manage them would have added too much complexity to the code, making it less readable and more fragile. -If a different convention is needed, identify names via search/grep (e.g. with `^\s+name\s+=\s+"`) and change them in an editor it should take a couple of minutes at most, as there's just a handful of modules and resources to change. +If a different convention is needed, identify names via search/grep (e.g. with `^\s+name\s+=\s+"`) and change them in an editor it should take a couple of minutes at most, as there's just a handful of modules and resources to change. Names used in internal references (e.g. `module.foo-prod.id`) are only used by Terraform and do not influence resource naming, so they are best left untouched to avoid having to debug complex errors. @@ -329,7 +262,7 @@ The `type` attribute can be set to one of the supported repository types: `githu Once the stage is applied the generated output files will contain pre-configured workflow files for each repository, that will use Workload Identity Federation via a dedicated service account for each repository to impersonate the automation service account for the stage. -You can use Terraform to automate creation of the repositories using the extra stage defined in [fast/extras/0-cicd-github](../../extras/0-cicd-github/) (only for Github for now). +You can use Terraform to automate creation of the repositories using the extra stage defined in [fast/extras/0-cicd-github](../0-organization-bootstrap/) (only for Github for now). The remaining configuration is manual, as it regards the repositories themselves @@ -340,6 +273,8 @@ The remaining configuration is manual, as it regards the repositories themselves - create a key pair - create a [deploy key](https://docs.github.com/en/developers/overview/managing-deploy-keys#deploy-keys) in the modules repository with the public key - create a `CICD_MODULES_KEY` secret with the private key in each of the repositories that need to access modules (for Gitlab, please Base64 encode the private key for masking) + - for Gitlab + - TODO - for Source Repositories - assign the reader role to the CI/CD service accounts - create one repository for each stage @@ -358,7 +293,7 @@ The remaining configuration is manual, as it regards the repositories themselves ### Toggling features -Note: This is not currently officially supported in Stellar Engine, but is left in as an experimental feature. +Note: This is not currently officially supported in Stellar Engine Landing Zone, but is left in as an experimental feature. Some FAST features can be enabled or disabled using the `fast_features` variables. While this variable is not directly used in the bootstrap stage, it can instruct the following stages to create certain resources only if needed. @@ -368,7 +303,7 @@ The `fast_features` variable consists of 4 toggles - **`gke`** controls the creation of required resources (Google Cloud Folders, service accounts, buckets, IAM bindings) to deploy the [3-gke-multitenant](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/tree/master/fast/stages/3-gke-multitenant) stage - **`project_factory`** controls the creation of required resources (Google Cloud Folders, service accounts, buckets, IAM bindings) to deploy the [3-project-factory](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/tree/master/fast/stages/3-project-factory) stage - **`sandbox`** controls the creation of a "Sandbox" top level Google Cloud Folder with relaxed policies, intended for sandbox environments where users can experiment -- **`teams`** controls the creation of the top level "Teams" Google Cloud Folder used by the [teams feature in resman](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/tree/master/fast/stages/1-resman#team-folders). +- **`teams`** controls the creation of the top level "Teams" Google Cloud Folder used by the [teams feature in resman](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/tree/master/fast/stages/2-resman#team-folders). --- @@ -376,49 +311,54 @@ The `fast_features` variable consists of 4 toggles | name | description | type | required | default | |---|---|:---:|:---:|:---:| -| [alert_email](variables.tf#L16) | Email to receive log alerts. | string | ✓ | | -| [billing_account](variables.tf#L34) | Billing account id. If billing account is not part of the same org set `is_org_level` to `false`. To disable handling of billing IAM roles set `no_iam` to `true`. | object({…}) | ✓ | | -| [billing_budget_amount](variables.tf#L44) | Budget configuration for the AW folder. Includes amount and optional threshold rules (defaults to 0.5, 0.75, 0.9). If null, no budget will be created. | object({…}) | | null | -| [bootstrap_project](variables.tf#L44) | Bootstrap project ID. | string | ✓ | | -| [organization](variables.tf#L260) | Organization details. | object({…}) | ✓ | | -| [prefix](variables.tf#L275) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | -| [assured_workloads](variables.tf#L21) | Configuration for Assured Workloads. | object({…}) | | {…} | -| [bootstrap_user](variables.tf#L49) | Email of the nominal user running this stage for the first time. | string | | null | -| [cicd_repositories](variables.tf#L55) | CI/CD repository configuration. Identity providers reference keys in the `federated_identity_providers` variable. Set to null to disable, or set individual repositories to null if not needed. | object({…}) | | null | -| [custom_roles](variables.tf#L101) | Map of role names => list of permissions to additionally create at the organization level. | map(list(string)) | | {} | -| [essential_contacts](variables.tf#L108) | Email used for essential contacts, unset if null. | string | | null | -| [factories_config](variables.tf#L114) | Configuration for the resource factories or external data. | object({…}) | | {} | -| [fast_features](variables.tf#L126) | Selective control for top-level FAST features. | object({…}) | | {} | -| [groups](variables.tf#L141) | Group names or IAM-format principals to grant organization-level permissions. If just the name is provided, the 'group:' principal and organization domain are interpolated. | object({…}) | | {} | -| [iam](variables.tf#L157) | Organization-level custom IAM settings in role => [principal] format. | map(list(string)) | | {} | -| [iam_bindings_additive](variables.tf#L164) | Organization-level custom additive IAM bindings. Keys are arbitrary. | map(object({…})) | | {} | -| [iam_by_principals](variables.tf#L179) | Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid cycle errors. Merged internally with the `iam` variable. | map(list(string)) | | {} | -| [locations](variables.tf#L186) | Optional locations for GCS, BigQuery, and logging buckets created here. | object({…}) | | {} | -| [log_sinks](variables.tf#L202) | Org-level log sinks, in name => {type, filter} format. | map(object({…})) | | {…} | -| [logging_kms_key](variables.tf#L237) | value of the KMS key used for logging. | string | | null | -| [org_policies_config](variables.tf#L243) | Organization policies customization. | object({…}) | | {} | -| [outputs_location](variables.tf#L269) | Enable writing provider, tfvars and CI/CD workflow files to local filesystem. Leave null to disable. | string | | null | -| [project_parent_ids](variables.tf#L284) | Optional parents for projects created here in folders/nnnnnnn format. Null values will use the organization as parent. | object({…}) | | {} | -| [regime_mapping](variables.tf#L295) | Mapping of compliance regime names to short codes. | map(string) | | {…} | -| [workforce_identity_providers](variables.tf#L328) | Workforce Identity Federation pools. | map(object({…})) | | {} | -| [workload_identity_providers](variables.tf#L344) | Workload Identity Federation pools. The `cicd_repositories` variable references keys here. | map(object({…})) | | {} | +| [alert_email](variables.tf#L17) | Email to receive log alerts. | string | ✓ | | +| [billing_account](variables.tf#L42) | Billing account id. If billing account is not part of the same org set `is_org_level` to `false`. To disable handling of billing IAM roles set `no_iam` to `true`. | object({…}) | ✓ | | +| [bootstrap_project](variables.tf#L52) | Bootstrap project ID. | string | ✓ | | +| [organization](variables.tf#L229) | Organization details. | object({…}) | ✓ | | +| [prefix](variables.tf#L244) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | +| [top_level_folder](variables.tf#L297) | Top Level Folder Details. | object({…}) | ✓ | | +| [apply_tier_1_pubsub_sink](variables.tf#L22) | Toggles whether to apply org tier-1 pubsub sink. | bool | | true | +| [assured_workloads](variables.tf#L29) | Configuration for Assured Workloads. | object({…}) | | {…} | +| [bootstrap_user](variables.tf#L57) | Email of the nominal user running this stage for the first time. | string | | null | +| [cicd_repositories](variables.tf#L63) | CI/CD repository configuration. Identity providers reference keys in the `federated_identity_providers` variable. Set to null to disable, or set individual repositories to null if not needed. | object({…}) | | null | +| [essential_contacts](variables.tf#L115) | Email used for essential contacts, unset if null. | string | | null | +| [factories_config](variables.tf#L121) | Configuration for the resource factories or external data. | object({…}) | | {} | +| [fast_features](variables.tf#L133) | Selective control for top-level FAST features. | object({…}) | | {} | +| [gcp_billing_admins_group](variables.tf#L148) | GCP Billing Admins group name. | string | | "gcp-billing-admins" | +| [gcp_devops_group](variables.tf#L154) | GCP DevOps group name. | string | | "gcp-devops" | +| [gcp_organization_admins_group](variables.tf#L160) | GCP Organization Admins group name. | string | | "gcp-organization-admins" | +| [gcp_security_admins_group](variables.tf#L166) | GCP Security Admins group name. | string | | "gcp-security-admins" | +| [gcp_support_group](variables.tf#L172) | GCP Support group name. | string | | null | +| [gcp_vpc_network_admins_group](variables.tf#L178) | GCP VPC Network Admins group name. | string | | "gcp-vpc-network-admins" | +| [groups](variables.tf#L184) | Group names or IAM-format principals to grant organization-level permissions. If just the name is provided, the 'group:' principal and organization domain are interpolated. | object({…}) | | {} | +| [locations](variables.tf#L200) | Optional locations for GCS, BigQuery, and logging buckets created here. | object({…}) | | {} | +| [log_sinks](variables.tf#L213) | Organization-level log sinks configuration. | map(object({…})) | | {} | +| [logging_kms_key](variables.tf#L223) | value of the KMS key used for logging. | string | | null | +| [outputs_location](variables.tf#L238) | Enable writing provider, tfvars and CI/CD workflow files to local filesystem. Leave null to disable. | string | | null | +| [project_parent_ids](variables.tf#L253) | Optional parents for projects created here in folders/nnnnnnn format. Null values will use the organization as parent. | object({…}) | | {} | +| [regime_mapping](variables.tf#L264) | Mapping of compliance regime names to short codes. | map(string) | | {…} | +| [workload_identity_providers](variables.tf#L305) | Workload Identity Federation pools. The `cicd_repositories` variable references keys here. | map(object({…})) | | {} | ## Outputs | name | description | sensitive | |---|---|:---:| -| [alert_email](outputs.tf#L120) | Email to receive log alerts. | | -| [assured_workload](outputs.tf#L125) | Assured Workload folder for the deployment. | | -| [automation](outputs.tf#L130) | Automation resources. | | -| [billing_dataset](outputs.tf#L135) | BigQuery dataset prepared for billing export. | | -| [cicd_repositories](outputs.tf#L140) | CI/CD repository configurations. | | -| [common_services_folder](outputs.tf#L152) | Common services folder where non-tenant related resources should be kept. | | -| [custom_roles](outputs.tf#L157) | Organization-level custom roles. | | -| [outputs_bucket](outputs.tf#L162) | GCS bucket where generated output files are stored. | | -| [project_ids](outputs.tf#L167) | Projects created by this stage. | | -| [providers](outputs.tf#L177) | Terraform provider files for this stage and dependent stages. | ✓ | -| [service_accounts](outputs.tf#L184) | Automation service accounts created by this stage. | | -| [tfvars](outputs.tf#L202) | Terraform variable files for the following stages. | ✓ | -| [workforce_identity_pool](outputs.tf#L208) | Workforce Identity Federation pool. | | -| [workload_identity_pool](outputs.tf#L217) | Workload Identity Federation pool and providers. | | +| [alert_email](outputs.tf#L155) | Email to receive log alerts. | | +| [assured_workload](outputs.tf#L160) | Assured Workload folder for the deployment. | | +| [automation](outputs.tf#L165) | Automation resources. | | +| [automation_project_id](outputs.tf#L170) | The ID of the IaC Core project. | | +| [billing_dataset](outputs.tf#L175) | BigQuery dataset prepared for billing export. | | +| [cicd_repositories](outputs.tf#L180) | CI/CD repository configurations. | | +| [common_services_folder](outputs.tf#L192) | Common services folder where non-tenant related resources should be kept. | | +| [custom_roles](outputs.tf#L197) | Organization-level custom roles. | | +| [folder_ids](outputs.tf#L202) | The Assured Workloads Folder i.e. DEV (IL5 AW). | | +| [outputs_bucket](outputs.tf#L207) | GCS bucket where generated output files are stored. | | +| [project_ids](outputs.tf#L212) | Projects created by this stage. | | +| [providers](outputs.tf#L222) | Terraform provider files for this stage and dependent stages. | ✓ | +| [pubsub-topics-id](outputs.tf#L229) | Pubsub topics used for C5ISR logging. | | +| [service_accounts](outputs.tf#L236) | Automation service accounts created by this stage. | | +| [shared_services_project_id](outputs.tf#L245) | Project ID for NetSec Shared Services. | | +| [tenants_container_ids](outputs.tf#L259) | Folder IDs for the 'Tenants' sub-folders where tenant projects will live. | | +| [tfvars](outputs.tf#L264) | Terraform variable files for the following stages. | ✓ | +| [workload_identity_pool](outputs.tf#L270) | Workload Identity Federation pool and providers. | | diff --git a/fast/stages-aw/0-bootstrap/automation.tf b/fast/stages-aw/1-assured-workload/automation.tf similarity index 50% rename from fast/stages-aw/0-bootstrap/automation.tf rename to fast/stages-aw/1-assured-workload/automation.tf index 6e9925403..8fe3c9fb4 100644 --- a/fast/stages-aw/0-bootstrap/automation.tf +++ b/fast/stages-aw/1-assured-workload/automation.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,24 +13,47 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Automation project and resources. locals { cicd_resman_sa = try(module.automation-tf-cicd-sa["resman"].iam_email, "") cicd_resman_r_sa = try(module.automation-tf-cicd-r-sa["resman"].iam_email, "") + config_env_file = "${path.module}/../../../automation/config.env" + + config_env_vars = { + for l in split("\n", fileexists(local.config_env_file) ? file(local.config_env_file) : "") : + split("=", l)[0] => split("=", l)[1] if length(split("=", l)) == 2 + } + + tenant_envs = split(",", lookup(local.config_env_vars, "TENANT_ENVIRONMENTS", "")) + + config_env_bucket = length(module.automation-tf-config-gcs) > 0 ? { + "config_env_object" = { + bucket_name = module.automation-tf-config-gcs[0].name + object_name = "config.env" + source_path = local.config_env_file + } + } : {} + + allowed_api_data = yamldecode(file("${path.module}/data/allowed_apis.yaml")) + lz_data = yamldecode(file("${path.module}/data/lz_exceptions.yaml")) + compliance_list = local.allowed_api_data.allowed_apis + coa2_list = local.lz_data.COA2 + + billing_admins = [ + "serviceAccount:${module.automation-tf-bootstrap-sa.email}", + "serviceAccount:${module.automation-tf-tenants-sa.email}", + "serviceAccount:${module.automation-tf-resman-sa.email}" + ] } module "automation-project" { - source = "../../../modules/project" - billing_account = var.billing_account.id - name = "iac-core-0" - default_service_account = "deprivilege" - lien_reason = "Protected by default as a core project." + source = "../../../modules/project" + billing_account = var.billing_account.id + name = local.project_map["automation-project"] parent = coalesce( var.project_parent_ids.automation, module.branch-common-services-folder.folder.name ) - prefix = local.prefix contacts = ( var.bootstrap_user != null || var.essential_contacts == null ? {} @@ -52,10 +75,9 @@ module "automation-project" { "roles/browser" = [ module.automation-tf-resman-r-sa.iam_email ] - "roles/owner" = compact([ - module.automation-tf-bootstrap-sa.iam_email, - var.bootstrap_user != null ? "user:${var.bootstrap_user}" : null - ]) + "roles/owner" = [ + module.automation-tf-bootstrap-sa.iam_email + ] "roles/cloudbuild.builds.editor" = [ module.automation-tf-resman-sa.iam_email ] @@ -63,7 +85,8 @@ module "automation-project" { module.automation-tf-resman-r-sa.iam_email ] "roles/iam.serviceAccountAdmin" = [ - module.automation-tf-resman-sa.iam_email + module.automation-tf-resman-sa.iam_email, + module.automation-tf-tenants-sa.iam_email ] "roles/iam.serviceAccountViewer" = [ module.automation-tf-resman-r-sa.iam_email @@ -81,15 +104,18 @@ module "automation-project" { module.automation-tf-resman-r-sa.iam_email ] "roles/storage.admin" = [ - module.automation-tf-resman-sa.iam_email + module.automation-tf-resman-sa.iam_email, + module.automation-tf-tenants-sa.iam_email ] - (module.organization.custom_role_id["storage_viewer"]) = [ + ("organizations/${var.organization.id}/roles/storageViewer") = [ module.automation-tf-bootstrap-r-sa.iam_email, - module.automation-tf-resman-r-sa.iam_email + module.automation-tf-resman-r-sa.iam_email, + module.automation-tf-tenants-r-sa.iam_email ] "roles/viewer" = [ module.automation-tf-bootstrap-r-sa.iam_email, - module.automation-tf-resman-r-sa.iam_email + module.automation-tf-resman-r-sa.iam_email, + module.automation-tf-tenants-r-sa.iam_email ] } iam_bindings = { @@ -115,6 +141,14 @@ module "automation-project" { member = module.automation-tf-resman-r-sa.iam_email role = "roles/serviceusage.serviceUsageViewer" } + serviceusage_tenant = { + member = module.automation-tf-tenants-sa.iam_email + role = "roles/serviceusage.serviceUsageConsumer" + } + serviceusage_tenant_r = { + member = module.automation-tf-tenants-r-sa.iam_email + role = "roles/serviceusage.serviceUsageViewer" + } } org_policies = var.bootstrap_user != null ? {} : { "compute.skipDefaultNetworkCreation" = { @@ -137,6 +171,7 @@ module "automation-project" { "billingbudgets.googleapis.com", "cloudasset.googleapis.com", "cloudbilling.googleapis.com", + "cloudidentity.googleapis.com", "cloudkms.googleapis.com", "cloudquotas.googleapis.com", "cloudresourcemanager.googleapis.com", @@ -150,7 +185,8 @@ module "automation-project" { "stackdriver.googleapis.com", "storage-component.googleapis.com", "storage.googleapis.com", - "sts.googleapis.com" + "sts.googleapis.com", + "networksecurity.googleapis.com" ], # enable specific service only after org policies have been applied var.bootstrap_user != null ? [] : [ @@ -174,14 +210,13 @@ resource "google_compute_project_metadata" "metadata-automation" { module "automation-tf-output-gcs" { source = "../../../modules/gcs" project_id = module.automation-project.project_id - name = "iac-core-outputs-0" + name = lower("${replace(lookup(var.regime_mapping, var.assured_workloads.regime, var.assured_workloads.regime), "_", " ")}-prod-iac-core-outputs") prefix = local.prefix - location = local.locations.gcs + location = local.primary_location_gcs storage_class = local.gcs_storage_class versioning = true - force_destroy = true - depends_on = [module.organization, module.gcs-kms] - encryption_key = module.gcs-kms.keys.gcs.id + depends_on = [module.organization, module.top-level-folder, module.gcs-kms] + encryption_key = module.gcs-kms[local.primary_location_gcs].keys.gcs.id } # this stage's bucket and service account @@ -189,20 +224,19 @@ module "automation-tf-output-gcs" { module "automation-tf-bootstrap-gcs" { source = "../../../modules/gcs" project_id = module.automation-project.project_id - name = "iac-core-bootstrap-0" + name = lower("${replace(lookup(var.regime_mapping, var.assured_workloads.regime, var.assured_workloads.regime), "_", " ")}-prod-iac-core-bootstrap") prefix = local.prefix - location = local.locations.gcs + location = local.primary_location_gcs storage_class = local.gcs_storage_class versioning = true - force_destroy = true - depends_on = [module.organization] - encryption_key = module.gcs-kms.keys.gcs.id + depends_on = [module.organization, module.top-level-folder] + encryption_key = module.gcs-kms[local.primary_location_gcs].keys.gcs.id } module "automation-tf-bootstrap-sa" { source = "../../../modules/iam-service-account" project_id = module.automation-project.project_id - name = "bootstrap-0" + name = "prod-bootstrap-0" display_name = "Terraform organization bootstrap service account." prefix = local.prefix # allow SA used by CI/CD workflow to impersonate this SA @@ -211,15 +245,26 @@ module "automation-tf-bootstrap-sa" { try(module.automation-tf-cicd-sa["bootstrap"].iam_email, null) ]) } + iam_project_roles = { + (var.bootstrap_project) = ["roles/serviceusage.serviceUsageConsumer"] + } + iam_folder_roles = { + (var.top_level_folder.id) = [ + "roles/serviceusage.serviceUsageConsumer", + "roles/cloudkms.admin" + ] + } iam_storage_roles = { - (module.automation-tf-output-gcs.name) = ["roles/storage.admin"] + (module.automation-tf-output-gcs.name) = ["roles/storage.admin"] + (lower("${element(split(".", var.top_level_folder.name), 0)}-org-iac")) = ["roles/storage.admin"] + (lower("${element(split(".", var.top_level_folder.name), 0)}-org-iac-bootstrap")) = ["roles/storage.admin"] } } module "automation-tf-bootstrap-r-sa" { source = "../../../modules/iam-service-account" project_id = module.automation-project.project_id - name = "bootstrap-0r" + name = "prod-bootstrap-0r" display_name = "Terraform organization bootstrap service account (read-only)." prefix = local.prefix # allow SA used by CI/CD workflow to impersonate this SA @@ -232,12 +277,12 @@ module "automation-tf-bootstrap-r-sa" { # custom roles in the organization module, so these need to depend on it iam_organization_roles = { (var.organization.id) = [ - module.organization.custom_role_id["organization_admin_viewer"], - module.organization.custom_role_id["tag_viewer"] + "organizations/${var.organization.id}/roles/organizationAdminViewer", + "organizations/${var.organization.id}/roles/tagViewer" ] } iam_storage_roles = { - (module.automation-tf-output-gcs.name) = [module.organization.custom_role_id["storage_viewer"]] + (module.automation-tf-output-gcs.name) = ["organizations/${var.organization.id}/roles/storageViewer"] } } @@ -246,46 +291,51 @@ module "automation-tf-bootstrap-r-sa" { module "automation-tf-resman-gcs" { source = "../../../modules/gcs" project_id = module.automation-project.project_id - name = "iac-core-resman-0" + name = lower("${replace(lookup(var.regime_mapping, var.assured_workloads.regime, var.assured_workloads.regime), "_", " ")}-prod-iac-core-config-0") prefix = local.prefix - location = local.locations.gcs + location = local.primary_location_gcs storage_class = local.gcs_storage_class versioning = true - force_destroy = true - iam = { "roles/storage.objectAdmin" = [module.automation-tf-resman-sa.iam_email] "roles/storage.objectViewer" = [module.automation-tf-resman-r-sa.iam_email] } - depends_on = [module.organization, module.gcs-kms] - encryption_key = module.gcs-kms.keys.gcs.id + depends_on = [module.organization, module.top-level-folder, module.gcs-kms] + encryption_key = module.gcs-kms[local.primary_location_gcs].keys.gcs.id } module "automation-tf-resman-sa" { source = "../../../modules/iam-service-account" project_id = module.automation-project.project_id - name = "resman-0" + name = "prod-resman-0" display_name = "Terraform stage 1 resman service account." prefix = local.prefix # allow SA used by CI/CD workflow to impersonate this SA # we use additive IAM to allow tenant CI/CD SAs to impersonate it - iam_bindings_additive = ( - local.cicd_resman_sa == "" ? {} : { + iam_bindings_additive = merge( + (local.cicd_resman_sa == "" ? {} : { cicd_token_creator = { member = local.cicd_resman_sa role = "roles/iam.serviceAccountTokenCreator" } - } + }) ) iam_storage_roles = { (module.automation-tf-output-gcs.name) = ["roles/storage.admin"] } } +resource "google_billing_account_iam_member" "automation_billing_admins" { + for_each = toset(local.billing_admins) + billing_account_id = var.billing_account.id + role = "roles/billing.admin" + member = each.value +} + module "automation-tf-resman-r-sa" { source = "../../../modules/iam-service-account" project_id = module.automation-project.project_id - name = "resman-0r" + name = "prod-resman-0r" display_name = "Terraform stage 1 resman service account (read-only)." prefix = local.prefix # allow SA used by CI/CD workflow to impersonate this SA @@ -302,11 +352,111 @@ module "automation-tf-resman-r-sa" { # custom roles in the organization module, so these need to depend on it iam_organization_roles = { (var.organization.id) = [ - module.organization.custom_role_id["organization_admin_viewer"], - module.organization.custom_role_id["tag_viewer"] + "organizations/${var.organization.id}/roles/organizationAdminViewer", + "organizations/${var.organization.id}/roles/tagViewer" ] } iam_storage_roles = { - (module.automation-tf-output-gcs.name) = [module.organization.custom_role_id["storage_viewer"]] + (module.automation-tf-output-gcs.name) = ["organizations/${var.organization.id}/roles/storageViewer"] } } + +module "automation-tf-tenant-gcs" { + source = "../../../modules/gcs" + project_id = module.automation-project.project_id + name = lower("${replace(lookup(var.regime_mapping, var.assured_workloads.regime, var.assured_workloads.regime), "_", " ")}-prod-iac-core-tenants") + prefix = local.prefix + location = local.primary_location_gcs + storage_class = local.gcs_storage_class + versioning = true + iam = { + "roles/storage.objectAdmin" = [module.automation-tf-tenants-sa.iam_email] + "roles/storage.objectViewer" = [module.automation-tf-tenants-r-sa.iam_email] + } + depends_on = [module.organization, module.top-level-folder, module.gcs-kms] + encryption_key = module.gcs-kms[local.primary_location_gcs].keys.gcs.id +} + +# automation service account +module "automation-tf-tenants-sa" { + source = "../../../modules/iam-service-account" + project_id = module.automation-project.project_id + name = "prod-tenant-0" + display_name = "Terraform tenant service account." + prefix = var.prefix + iam_bindings_additive = merge( + try(module.automation-tf-cicd-sa["tenant"].iam_email, "") == "" ? {} : { + cicd_token_creator = { + member = module.automation-tf-cicd-sa["tenant"].iam_email + role = "roles/iam.serviceAccountTokenCreator" + } + } + ) + iam_storage_roles = { + (module.automation-tf-output-gcs.name) = ["roles/storage.admin"] + } + iam_organization_roles = { + (var.organization.id) = ["roles/iam.denyAdmin"] + } +} + +# automation read-only service account + +module "automation-tf-tenants-r-sa" { + source = "../../../modules/iam-service-account" + project_id = module.automation-project.project_id + name = "prod-tenant-0r" + display_name = "Terraform tenant service account (read-only)." + prefix = var.prefix + iam_bindings_additive = merge( + try(module.automation-tf-cicd-r-sa["tenant"].iam_email, "") == "" ? {} : { + cicd_token_creator = { + member = module.automation-tf-cicd-r-sa["tenant"].iam_email + role = "roles/iam.serviceAccountTokenCreator" + } + } + ) + iam_storage_roles = { + (module.automation-tf-output-gcs.name) = ["organizations/${var.organization.id}/roles/storageViewer"] + } +} + +module "automation-tf-inputs-gcs" { + source = "../../../modules/gcs" + project_id = module.automation-project.project_id + name = lower("${replace(lookup(var.regime_mapping, var.assured_workloads.regime, var.assured_workloads.regime), "_", " ")}-prod-iac-core-inputs") + prefix = local.prefix + location = local.primary_location_gcs + storage_class = local.gcs_storage_class + versioning = true + depends_on = [module.organization, module.top-level-folder] + encryption_key = module.gcs-kms[local.primary_location_gcs].keys.gcs.id +} + +module "automation-tf-config-gcs" { + count = fileexists(local.config_env_file) ? 1 : 0 + source = "../../../modules/gcs" + project_id = module.automation-project.project_id + name = lower("${replace(lookup(var.regime_mapping, var.assured_workloads.regime, var.assured_workloads.regime), "_", " ")}-prod-iac-core-config") + prefix = local.prefix + location = local.primary_location_gcs + storage_class = local.gcs_storage_class + versioning = true + depends_on = [module.organization, module.top-level-folder] + encryption_key = module.gcs-kms[local.primary_location_gcs].keys.gcs.id + force_destroy = true +} + +resource "google_project_organization_policy" "automation_project_policy" { + project = module.automation-project.project_id + constraint = "constraints/gcp.restrictServiceUsage" + + list_policy { + allow { + values = concat( + local.compliance_list, + local.coa2_list + ) + } + } +} \ No newline at end of file diff --git a/fast/stages-aw/0-bootstrap/billing.tf b/fast/stages-aw/1-assured-workload/billing.tf similarity index 75% rename from fast/stages-aw/0-bootstrap/billing.tf rename to fast/stages-aw/1-assured-workload/billing.tf index 5ff87f834..d60222346 100644 --- a/fast/stages-aw/0-bootstrap/billing.tf +++ b/fast/stages-aw/1-assured-workload/billing.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,17 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Billing export project and dataset. locals { # used here for convenience, in organization.tf members are explicit - billing_ext_admins = [ - local.principals.gcp-billing-admins, - local.principals.gcp-organization-admins, - module.automation-tf-bootstrap-sa.iam_email, - module.automation-tf-resman-sa.iam_email - ] + # billing_ext_admins = [ + # module.automation-tf-resman-sa.iam_email + # ] + + # billing_ext_users = [ + # module.automation-tf-tenants-sa.iam_email, + # module.automation-tf-bootstrap-sa.iam_email + # ] billing_ext_viewers = [ module.automation-tf-bootstrap-r-sa.iam_email, @@ -40,15 +41,13 @@ locals { # billing account in same org (IAM is in the organization.tf file) module "billing-export-project" { - source = "../../../modules/project" - count = local.billing_mode == "org" ? 1 : 0 - billing_account = var.billing_account.id - name = "billing-exp-0" - default_service_account = "deprivilege" + source = "../../../modules/project" + count = local.billing_mode == "org" ? 1 : 0 + billing_account = var.billing_account.id + name = local.project_map["billing-export-project"] parent = coalesce( var.project_parent_ids.billing, module.branch-common-services-folder.folder.name ) - prefix = local.prefix contacts = ( var.bootstrap_user != null || var.essential_contacts == null ? {} @@ -86,17 +85,6 @@ module "billing-export-dataset" { location = local.locations.bq } -# standalone billing account - -resource "google_billing_account_iam_member" "billing_ext_admin" { - for_each = toset( - local.billing_mode == "resource" ? local.billing_ext_admins : [] - ) - billing_account_id = var.billing_account.id - role = "roles/billing.admin" - member = each.key -} - resource "google_billing_account_iam_member" "billing_ext_viewer" { for_each = toset( local.billing_mode == "resource" ? local.billing_ext_viewers : [] @@ -104,4 +92,4 @@ resource "google_billing_account_iam_member" "billing_ext_viewer" { billing_account_id = var.billing_account.id role = "roles/billing.viewer" member = each.key -} +} \ No newline at end of file diff --git a/fast/stages-aw/1-assured-workload/changelog b/fast/stages-aw/1-assured-workload/changelog new file mode 100644 index 000000000..cbac4b437 --- /dev/null +++ b/fast/stages-aw/1-assured-workload/changelog @@ -0,0 +1,3 @@ +2606091411 +2606091512 +2606101328 \ No newline at end of file diff --git a/fast/stages-aw/0-bootstrap/checklist.tf b/fast/stages-aw/1-assured-workload/checklist.tf similarity index 85% rename from fast/stages-aw/0-bootstrap/checklist.tf rename to fast/stages-aw/1-assured-workload/checklist.tf index c82300995..64d42e454 100644 --- a/fast/stages-aw/0-bootstrap/checklist.tf +++ b/fast/stages-aw/1-assured-workload/checklist.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { # group mapping from checklist to ours _cl_groups = { @@ -51,12 +50,6 @@ locals { _cl_org_iam_bindings = { for b in try(local._cl_org.iam_bindings, []) : lookup(local._cl_groups, b.group_id, b.principal) => { - additive = [ - for r in b.role : r if !contains(local.iam_roles_authoritative, r) - ] - authoritative = [ - for r in b.role : r if contains(local.iam_roles_authoritative, r) - ] roles = b.role is_group = lookup(local._cl_groups, b.group_id, null) != null } @@ -64,20 +57,12 @@ locals { # compile the final data structure we will consume from various places checklist = { billing_account = try(local._cl_data.billing_account, null) - iam_principals = { - for k, v in local._cl_org_iam_bindings : - k => v.authoritative if v.is_group && length(v.authoritative) > 0 - } - iam = { - for k, v in local._cl_org_iam_bindings : - k => v.authoritative if !v.is_group && length(v.authoritative) > 0 - } iam_bindings = concat(flatten([ - for k, v in local._cl_org_iam_bindings : [ - for r in v.additive : [ + for member, data in local._cl_org_iam_bindings : [ + for r in data.roles : [ { - key = "${r}-${k}" - member = k + key = "${r}-${member}" + member = member role = r } ] @@ -131,12 +116,12 @@ module "automation-tf-checklist-gcs" { source = "../../../modules/gcs" count = local.uses_checklist ? 1 : 0 project_id = module.automation-project.project_id - name = "iac-core-checklist-0" + name = "prod-iac-core-checklist-0" prefix = local.prefix - location = local.locations.gcs + location = local.primary_location_gcs storage_class = local.gcs_storage_class versioning = true - depends_on = [module.organization] + depends_on = [module.organization, module.top-level-folder] } resource "google_storage_bucket_object" "checklist_data" { diff --git a/fast/stages-aw/0-bootstrap/cicd.tf b/fast/stages-aw/1-assured-workload/cicd.tf similarity index 76% rename from fast/stages-aw/0-bootstrap/cicd.tf rename to fast/stages-aw/1-assured-workload/cicd.tf index abd857f34..6edd1dcd5 100644 --- a/fast/stages-aw/0-bootstrap/cicd.tf +++ b/fast/stages-aw/1-assured-workload/cicd.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Workload Identity Federation configurations for CI/CD. locals { @@ -51,17 +50,20 @@ locals { ) } cicd_workflow_providers = { - bootstrap = "0-bootstrap-providers.tf" - bootstrap_r = "0-bootstrap-r-providers.tf" - resman = "1-resman-providers.tf" - resman_r = "1-resman-r-providers.tf" + bootstrap = "1-assured-workload-providers.tf" + bootstrap_r = "1-assured-workload-r-providers.tf" + resman = "2-resman-providers.tf" + resman_r = "2-resman-r-providers.tf" + tenant = "5-tenant-providers.tf" + tenant_r = "5-tenant-providers.tf" } cicd_workflow_var_files = { bootstrap = [] resman = [ - "0-bootstrap.auto.tfvars.json", - "0-globals.auto.tfvars.json" + "1-assured-workload.auto.tfvars.json", + "1-globals.auto.tfvars.json" ] + tenant = [] } } @@ -109,7 +111,7 @@ module "automation-tf-cicd-sa" { source = "../../../modules/iam-service-account" for_each = local.cicd_repositories project_id = module.automation-project.project_id - name = "${each.key}-1" + name = "prod-${each.key}-1" display_name = "Terraform CI/CD ${each.key} service account." prefix = local.prefix iam = ( @@ -137,16 +139,23 @@ module "automation-tf-cicd-sa" { iam_project_roles = { (module.automation-project.project_id) = ["roles/logging.logWriter"] } - iam_storage_roles = { - (module.automation-tf-output-gcs.name) = ["roles/storage.objectViewer"] - } + iam_storage_roles = merge( + { + (module.automation-tf-output-gcs.name) = ["roles/storage.objectViewer"] + }, + { + (lower("${element(split(".", var.top_level_folder.name), 0)}-org-iac")) = ["roles/storage.objectViewer"] + (lower("${element(split(".", var.top_level_folder.name), 0)}-org-iac-bootstrap")) = ["roles/storage.objectViewer"] + ("${var.prefix}-il5-prod-iac-core-config") = ["roles/storage.objectViewer"] + } + ) } module "automation-tf-cicd-r-sa" { source = "../../../modules/iam-service-account" for_each = local.cicd_repositories project_id = module.automation-project.project_id - name = "${each.key}-1r" + name = "prod-${each.key}-1r" display_name = "Terraform CI/CD ${each.key} service account (read-only)." prefix = local.prefix iam = ( @@ -167,7 +176,15 @@ module "automation-tf-cicd-r-sa" { iam_project_roles = { (module.automation-project.project_id) = ["roles/logging.logWriter"] } - iam_storage_roles = { - (module.automation-tf-output-gcs.name) = ["roles/storage.objectViewer"] - } + iam_storage_roles = merge( + { + (module.automation-tf-output-gcs.name) = ["roles/storage.objectViewer"] + }, + each.key == "bootstrap" ? { + (lower("${element(split(".", var.top_level_folder.name), 0)}-org-iac")) = ["roles/storage.objectViewer"] + (lower("${element(split(".", var.top_level_folder.name), 0)}-org-iac-bootstrap")) = ["roles/storage.objectViewer"] + ("${var.prefix}-il5-prod-iac-core-config") = ["roles/storage.objectViewer"] + + } : {} + ) } diff --git a/fast/stages-aw/1-assured-workload/data/allowed_apis.yaml b/fast/stages-aw/1-assured-workload/data/allowed_apis.yaml new file mode 100644 index 000000000..93a69fdff --- /dev/null +++ b/fast/stages-aw/1-assured-workload/data/allowed_apis.yaml @@ -0,0 +1,80 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#testing purposes API's that already match existing list in the org. +allowed_apis: + - pubsub.googleapis.com + - dataflow.googleapis.com + - bigquerydatatransfer.googleapis.com + - logging.googleapis.com + - cloudkms.googleapis.com + - composer.googleapis.com + - sqladmin.googleapis.com + - spanner.googleapis.com + - dataproc.googleapis.com + - cloudtasks.googleapis.com + - datafusion.googleapis.com + - artifactregistry.googleapis.com + - gkehub.googleapis.com + - workstations.googleapis.com + - container.googleapis.com + - cloudidentity.googleapis.com + - privateca.googleapis.com + - iam.googleapis.com + - datapipelines.googleapis.com + - compute.googleapis.com + - dns.googleapis.com + - storage.googleapis.com + - redis.googleapis.com + - secretmanager.googleapis.com + - run.googleapis.com + - speech.googleapis.com + - eventarc.googleapis.com + - monitoring.googleapis.com + - bigquery.googleapis.com + - cloudbuild.googleapis.com + - vision.googleapis.com + - dlp.googleapis.com + - accesscontextintelligence.googleapis.com + - accesscontextmanager.googleapis.com + - aiplatform.googleapis.com + - alloydb.googleapis.com + - anthosidentityservice.googleapis.com + - bigqueryconnection.googleapis.com + - bigquerydatapolicy.googleapis.com + - bigquerymigration.googleapis.com + - bigqueryreservation.googleapis.com + - bigquerystorage.googleapis.com + - chronicle.googleapis.com + - chronicleservicemanager.googleapis.com + - cloudresourcemanager.googleapis.com + - connectgateway.googleapis.com + - containersecurity.googleapis.com + - datalineage.googleapis.com + - dataplex.googleapis.com + - dataproc-control.googleapis.com + - file.googleapis.com + - gkeconnect.googleapis.com + - iap.googleapis.com + - mesh.googleapis.com + - meshca.googleapis.com + - meshconfig.googleapis.com + - networkconnectivity.googleapis.com + - networksecurity.googleapis.com + - networkservices.googleapis.com + - policytroubleshooter.googleapis.com + - resourcesettings.googleapis.com + - servicedirectory.googleapis.com + - servicenetworking.googleapis.com + - trafficdirector.googleapis.com \ No newline at end of file diff --git a/fast/stages-aw/1-assured-workload/data/custom-org-policies/cloudconsole_policy.yaml b/fast/stages-aw/1-assured-workload/data/custom-org-policies/cloudconsole_policy.yaml new file mode 100644 index 000000000..db1043574 --- /dev/null +++ b/fast/stages-aw/1-assured-workload/data/custom-org-policies/cloudconsole_policy.yaml @@ -0,0 +1,29 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +# This list constraint, when enforced on an organization resource, defines +# the set of Google Cloud resources that are returned in list and search +# methods for users in the domain of the organization where this constraint +# is enforced. This can be used to limit what resources are visible in various +# parts of the Cloud Console, such as the Resource Picker, Search, and Manage +# Resources page. Note that this Constraint is only ever evaluated at the +# Organization level. Values specified in allow/deny lists must be in the +# form: under:organizations/ORGANIZATION_ID. +# COULD HAVE +resourcemanager.accessBoundaries: + rules: + - allow: + values: + - under:organizations/${organization_id} diff --git a/fast/stages-aw/1-assured-workload/data/custom-org-policies/networking_policy.yaml b/fast/stages-aw/1-assured-workload/data/custom-org-policies/networking_policy.yaml new file mode 100644 index 000000000..eaa31b8b3 --- /dev/null +++ b/fast/stages-aw/1-assured-workload/data/custom-org-policies/networking_policy.yaml @@ -0,0 +1,75 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +# This list constraint defines the set of subnetworks that are allowed to use +# Cloud NAT. By default, all subnetworks are allowed to use Cloud NAT. The +# allowed/denied list of subnetworks must be identified in the form: +# under:organizations/ORGANIZATION_ID, +# under:folders/FOLDER_ID, +# under:projects/PROJECT_ID, +# or projects/PROJECT_ID/regions/REGION_NAME/subnetworks/SUBNETWORK_NAME. +# COULD HAVE +compute.restrictCloudNATUsage: + rules: + - allow: + values: + - under:organizations/${organization_id} + +# This list constraint defines the set of Compute Engine networks that are +# allowed to use Dedicated Interconnect. By default, networks are allowed to +# use any type of Interconnect. The allowed/denied list of networks must be +# identified in the form: +# under:organizations/ORGANIZATION_ID, +# under:folders/FOLDER_ID, +# under:projects/PROJECT_ID, +# or projects/PROJECT_ID/global/networks/NETWORK_NAME. +# SHOULD HAVE +compute.restrictDedicatedInterconnectUsage: + rules: + - allow: + values: + - under:organizations/${organization_id} + +# This list constraint defines the set of Compute Engine networks that are +# allowed to use Partner Interconnect. By default, networks are allowed to use +# any type of Interconnect. The allowed/denied list of networks must be +# identified in the form: +# under:organizations/ORGANIZATION_ID, +# under:folders/FOLDER_ID, +# under:projects/PROJECT_ID, +# or projects/PROJECT_ID/global/networks/NETWORK_NAME. +# SHOULD HAVE +compute.restrictPartnerInterconnectUsage: + rules: + - allow: + values: + - under:organizations/${organization_id} + +# This list constraint defines the set of VPC networks that are allowed to be +# peered with the VPC networks belonging to this project, folder, or +# organization. By default, a Network Admin for one network can peer with any +# other network. The allowed/denied list of networks must be identified in the +# form: +# under:organizations/ORGANIZATION_ID, +# under:folders/FOLDER_ID, +# under:projects/PROJECT_ID, +# or projects/PROJECT_ID/global/networks/NETWORK_NAME. +# SHOULD HAVE +compute.restrictVpcPeering: + rules: + - allow: + values: + - under:organizations/${organization_id} + - under:folders/832634261155 # https://autonomousthingz-life.medium.com/google-cloud-organisation-policies-get-the-restrict-vpc-peering-usage-organisation-policy-d87dce84a5e7 diff --git a/fast/stages-aw/1-assured-workload/data/custom-org-policies/platform_policy.yaml b/fast/stages-aw/1-assured-workload/data/custom-org-policies/platform_policy.yaml new file mode 100644 index 000000000..92471d92f --- /dev/null +++ b/fast/stages-aw/1-assured-workload/data/custom-org-policies/platform_policy.yaml @@ -0,0 +1,102 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +# This list constraint defines the set of external Organizations from which resources +# can be imported, and denies all moves from all other Organizations. By default, +# resources cannot be moved between Organizations. If this constraint is applied to +# a resource, imported resources directly under this resource must be explicitly +# allowed by this constraint. Moves within an Organization are not governed by this +# constraint. The move operation will still require the same IAM permissions as normal +# resource moves. Values specified in allow/deny lists must be in the form: +# under:organizations/ORGANIZATION_ID. +# SHOULD HAVE +resourcemanager.allowedImportSources: + rules: + - allow: + values: + - under:organizations/${organization_id} + +# This list constraint defines the set of external Organizations to which resources +# can be moved, and denies all moves to all other Organizations. By default, +# resources cannot be moved between Organizations. If this constraint is applied +# to a resource, the resource can be moved only to Organizations that are explicitly +# allowed by this constraint. Moves within an Organization are not governed by this +# constraint. The move operation will still require the same IAM permissions as normal +# resource moves. Values specified in allow/deny lists must be in the form: +# under:organizations/ORGANIZATION_ID. +# SHOULD HAVE +resourcemanager.allowedExportDestinations: + rules: + - allow: + values: + - under:organizations/${organization_id} + +# This list constraint defines the set of domains that email addresses added to +# Essential Contacts can have. By default, email addresses with any domain can +# be added to Essential Contacts. The allowed/denied list must specify one or +# more domains of the form @dino-runner.example.com. If this constraint is active and +# configured with allowed values, only email addresses with a suffix matching +# one of the entries from the list of allowed domains can be added in Essential +# Contacts.This constraint has no effect on updating or removing existing contacts. +# MUST HAVE +essentialcontacts.allowedContactDomains: + rules: + - allow: + values: + - "@${domain_name}" + + +# This list constraint defines one or more Cloud Identity or Google Workspace +# customer IDs whose principals can be added to IAM policies. By default, all +# user identities are allowed to be added to IAM policies. Only allowed values +# can be defined in this constraint, denied values are not supported. If this +# constraint is active, only principals that belong to the allowed customer IDs +# can be added to IAM policies. +# MUST HAVE +# Recommendation: +# This policy is strongly advised. Enforce at the organisation level but be +# cautious of potential issues. When this policy is enforced, even if the user +# has setIamPolicy on the APIs of Google Cloud services, they won't be allowed +# to add users of non-authorized domains. This also blocks the exposure of +# data; for example, a user won't be able to set permission to allUsers or +# authentificatedUsers in Cloud Storage to make the buckets public. +# use `gcloud organizations list` to query the domain id and/or directory +# customer id. +iam.allowedPolicyMemberDomains: + rules: + - allow: + values: + - ${customer_id} +%{ for customer_id in allowed_policy_member_domains ~} + - ${customer_id} +%{ endfor ~} + + +# This list constraint defines the set of Google Cloud resources that are returned +# in list and search methods for users in the domain of the organization where +# this constraint is enforced. This can be used to limit what resources are +# visible in various parts of the Cloud Console, such as the Resource Picker, +# Search, and Manage Resources page. Note that this constraint is only ever +# evaluated at the Organization level. Values specified in allow/deny lists +# must be in the form: under:organizations/ORGANIZATION_ID. +# MUST HAVE +resourcemanager.accessBoundaries: + rules: + - allow: + values: + - under:organizations/${organization_id} +%{ for org_id in allowed_access_boundaries ~} + - under:organizations/${org_id} +%{ endfor ~} \ No newline at end of file diff --git a/fast/stages-aw/1-assured-workload/data/custom-roles/gcve_network_admin.yaml b/fast/stages-aw/1-assured-workload/data/custom-roles/gcve_network_admin.yaml new file mode 100644 index 000000000..9d8fc35b2 --- /dev/null +++ b/fast/stages-aw/1-assured-workload/data/custom-roles/gcve_network_admin.yaml @@ -0,0 +1,22 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +name: gcveNetworkAdmin +includedPermissions: + - vmwareengine.networkPeerings.create + - vmwareengine.networkPeerings.delete + - vmwareengine.networkPeerings.get + - vmwareengine.networkPeerings.list + - vmwareengine.operations.get diff --git a/fast/stages-aw/1-assured-workload/data/custom-roles/organization_admin_viewer.yaml b/fast/stages-aw/1-assured-workload/data/custom-roles/organization_admin_viewer.yaml new file mode 100644 index 000000000..575decf08 --- /dev/null +++ b/fast/stages-aw/1-assured-workload/data/custom-roles/organization_admin_viewer.yaml @@ -0,0 +1,32 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# this is used by the plan-only admin SA +name: organizationAdminViewer +includedPermissions: + - essentialcontacts.contacts.get + - essentialcontacts.contacts.list + - logging.settings.get + - orgpolicy.constraints.list + - orgpolicy.policies.list + - orgpolicy.policy.get + - resourcemanager.folders.get + - resourcemanager.folders.getIamPolicy + - resourcemanager.folders.list + - resourcemanager.organizations.get + - resourcemanager.organizations.getIamPolicy + - resourcemanager.projects.get + - resourcemanager.projects.getIamPolicy + - resourcemanager.projects.list diff --git a/fast/stages-aw/1-assured-workload/data/custom-roles/organization_iam_admin.yaml b/fast/stages-aw/1-assured-workload/data/custom-roles/organization_iam_admin.yaml new file mode 100644 index 000000000..8dd9e8e23 --- /dev/null +++ b/fast/stages-aw/1-assured-workload/data/custom-roles/organization_iam_admin.yaml @@ -0,0 +1,21 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# this is needed for use in additive IAM bindings, to avoid conflicts +name: organizationIamAdmin +includedPermissions: + - resourcemanager.organizations.get + - resourcemanager.organizations.getIamPolicy + - resourcemanager.organizations.setIamPolicy diff --git a/fast/stages-aw/1-assured-workload/data/custom-roles/service_project_network_admin.yaml b/fast/stages-aw/1-assured-workload/data/custom-roles/service_project_network_admin.yaml new file mode 100644 index 000000000..7e2d710b1 --- /dev/null +++ b/fast/stages-aw/1-assured-workload/data/custom-roles/service_project_network_admin.yaml @@ -0,0 +1,32 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +name: serviceProjectNetworkAdmin +includedPermissions: + - compute.globalOperations.get + # compute.networks.updatePeering and compute.networks.get are + # used by automation service accounts who manage service + # projects where peering creation might be needed (e.g. GKE). If + # you remove them your network administrators should create + # peerings for service projects + - compute.networks.updatePeering + - compute.networks.get + - compute.organizations.disableXpnResource + - compute.organizations.enableXpnResource + - compute.projects.get + - compute.subnetworks.getIamPolicy + - compute.subnetworks.setIamPolicy + - dns.networks.bindPrivateDNSZone + - resourcemanager.projects.get diff --git a/fast/stages-aw/1-assured-workload/data/custom-roles/storage_viewer.yaml b/fast/stages-aw/1-assured-workload/data/custom-roles/storage_viewer.yaml new file mode 100644 index 000000000..19e7f5120 --- /dev/null +++ b/fast/stages-aw/1-assured-workload/data/custom-roles/storage_viewer.yaml @@ -0,0 +1,33 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# the following permissions are a descoped version of storage.admin +name: storageViewer +includedPermissions: + - storage.buckets.get + - storage.buckets.getIamPolicy + - storage.buckets.getObjectInsights + - storage.buckets.list + - storage.buckets.listEffectiveTags + - storage.buckets.listTagBindings + - storage.managedFolders.get + - storage.managedFolders.getIamPolicy + - storage.managedFolders.list + - storage.multipartUploads.list + - storage.multipartUploads.listParts + - storage.objects.create + - storage.objects.get + - storage.objects.getIamPolicy + - storage.objects.list diff --git a/fast/stages-aw/1-assured-workload/data/custom-roles/tag_viewer.yaml b/fast/stages-aw/1-assured-workload/data/custom-roles/tag_viewer.yaml new file mode 100644 index 000000000..89d5f8493 --- /dev/null +++ b/fast/stages-aw/1-assured-workload/data/custom-roles/tag_viewer.yaml @@ -0,0 +1,25 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# the following permissions are a descoped version of tagAdm +name: tagViewer +includedPermissions: + - resourcemanager.tagHolds.list + - resourcemanager.tagKeys.get + - resourcemanager.tagKeys.getIamPolicy + - resourcemanager.tagKeys.list + - resourcemanager.tagValues.get + - resourcemanager.tagValues.getIamPolicy + - resourcemanager.tagValues.list diff --git a/fast/stages-aw/1-assured-workload/data/custom-roles/tenant_network_admin.yaml b/fast/stages-aw/1-assured-workload/data/custom-roles/tenant_network_admin.yaml new file mode 100644 index 000000000..ee69474b5 --- /dev/null +++ b/fast/stages-aw/1-assured-workload/data/custom-roles/tenant_network_admin.yaml @@ -0,0 +1,18 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +name: tenantNetworkAdmin +includedPermissions: + - compute.globalOperations.get diff --git a/fast/stages-aw/1-assured-workload/data/lz_exceptions.yaml b/fast/stages-aw/1-assured-workload/data/lz_exceptions.yaml new file mode 100644 index 000000000..3e801ebce --- /dev/null +++ b/fast/stages-aw/1-assured-workload/data/lz_exceptions.yaml @@ -0,0 +1,43 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# lz_exceptions.yaml +# Combined list of Category 1 and Category 2 API exceptions for LZ Infrastructure +# These APIs are authorized for use in Core LZ projects only. +COA2: +# Category 1: IL5 Authorized / compliance Catalog Update Pending +#category_1_exceptions: + - accesscontextmanager.googleapis.com + - cloudasset.googleapis.com + - cloudbilling.googleapis.com + - networkconnectivity.googleapis.com + - servicedirectory.googleapis.com +# Category 2: Management/Enabling APIs Not Listed in compliance Catalog +# category_2_exceptions: + - assuredworkloads.googleapis.com + - bigqueryreservation.googleapis.com + - bigquerystorage.googleapis.com + - billingbudgets.googleapis.com + - cloudquotas.googleapis.com + - cloudresourcemanager.googleapis.com + - essentialcontacts.googleapis.com + - iamcredentials.googleapis.com + - iap.googleapis.com + - networksecurity.googleapis.com + - orgpolicy.googleapis.com + - servicenetworking.googleapis.com + - serviceusage.googleapis.com + - stackdriver.googleapis.com + - storage-component.googleapis.com + - sts.googleapis.com \ No newline at end of file diff --git a/fast/stages-aw/1-assured-workload/data/org-policies/appengine_policy.yaml b/fast/stages-aw/1-assured-workload/data/org-policies/appengine_policy.yaml new file mode 100644 index 000000000..752358133 --- /dev/null +++ b/fast/stages-aw/1-assured-workload/data/org-policies/appengine_policy.yaml @@ -0,0 +1,20 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +# Disables code downloads of source code previously uploaded to App Engine. +# SHOULD HAVE +appengine.disableCodeDownload: + rules: + - enforce: true diff --git a/fast/stages-aw/1-assured-workload/data/org-policies/assuredworkloads_policy.yaml b/fast/stages-aw/1-assured-workload/data/org-policies/assuredworkloads_policy.yaml new file mode 100644 index 000000000..ace561a24 --- /dev/null +++ b/fast/stages-aw/1-assured-workload/data/org-policies/assuredworkloads_policy.yaml @@ -0,0 +1,29 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# PREVIEW: This constraint defines the set of TLS versions that cannot be used on +# the organization, folder, or project where this constraint is enforced, or any +# of that resource's children in the resource hierarchy. By default, all TLS +# versions are allowed. TLS versions can only be specified in the denied list, +# and must be identified in the form TLS_VERSION_1 or TLS_VERSION_1_1.This +# constraint is only applied to requests using TLS. It will not be used to +# restrict unencrpyted requests. For more information, see +# https://cloud.google.com/assured-workloads/docs/restrict-tls-versions. +# SHOULD HAVE +gcp.restrictTLSVersion: + rules: + - deny: + values: + - TLS_VERSION_1 + - TLS_VERSION_1_1 \ No newline at end of file diff --git a/fast/stages-aw/1-assured-workload/data/org-policies/bigquery_policy.yaml b/fast/stages-aw/1-assured-workload/data/org-policies/bigquery_policy.yaml new file mode 100644 index 000000000..e49a9bea8 --- /dev/null +++ b/fast/stages-aw/1-assured-workload/data/org-policies/bigquery_policy.yaml @@ -0,0 +1,30 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +# This boolean constraint, when set to True, will disable users from +# using BigQuery Omni to process data on Amazon Web Services where this +# constraint is enforced. +# COULD HAVE +bigquery.disableBQOmniAWS: + rules: + - enforce: true + +# This boolean constraint, when set to True, will disable users from +# using BigQuery Omni to process data on Microsoft Azure where this +# constraint is enforced. +# COULD HAVE +bigquery.disableBQOmniAzure: + rules: + - enforce: true diff --git a/fast/stages-aw/0-bootstrap/data/org-policies/cloudbuild_policy.yaml b/fast/stages-aw/1-assured-workload/data/org-policies/cloudbuild_policy.yaml similarity index 96% rename from fast/stages-aw/0-bootstrap/data/org-policies/cloudbuild_policy.yaml rename to fast/stages-aw/1-assured-workload/data/org-policies/cloudbuild_policy.yaml index 950a543cb..c0083392b 100644 --- a/fast/stages-aw/0-bootstrap/data/org-policies/cloudbuild_policy.yaml +++ b/fast/stages-aw/1-assured-workload/data/org-policies/cloudbuild_policy.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -22,7 +22,7 @@ # COULD HAVE # Recommendation: # - allow all if there's no restrictions, otherwise add domain names -# acording to the event, for example: +# according to the event, for example: # - RepoSync event: source.developers.google.com # - GitHub app event: github.com # - GitHub Enterprise event: ghe-staging-test.com diff --git a/fast/stages-aw/1-assured-workload/data/org-policies/cloudconsole_policy.yaml b/fast/stages-aw/1-assured-workload/data/org-policies/cloudconsole_policy.yaml new file mode 100644 index 000000000..b4137a801 --- /dev/null +++ b/fast/stages-aw/1-assured-workload/data/org-policies/cloudconsole_policy.yaml @@ -0,0 +1,22 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +# This boolean constraint disables the SSH-in-browser tool in the +# Cloud Console. When enforced, the SSH-in-browser button is disabled. +# By default, using the SSH-in-browser tool is allowed. +# COULD HAVE +compute.disableSshInBrowser: + rules: + - enforce: false diff --git a/fast/stages-aw/1-assured-workload/data/org-policies/clouddeploy_policy.yaml b/fast/stages-aw/1-assured-workload/data/org-policies/clouddeploy_policy.yaml new file mode 100644 index 000000000..94a8f19fe --- /dev/null +++ b/fast/stages-aw/1-assured-workload/data/org-policies/clouddeploy_policy.yaml @@ -0,0 +1,24 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +# This boolean constraint, when enforced, prevents Cloud Deploy from adding +# Cloud Deploy identifier labels to deployed objects.By default, labels +# identifying Cloud Deploy resources are added to deployed objects during +# release creation. +# COULD HAVE + +clouddeploy.disableServiceLabelGeneration: + rules: + - enforce: false diff --git a/fast/stages-aw/1-assured-workload/data/org-policies/cloudkms_policy.yaml b/fast/stages-aw/1-assured-workload/data/org-policies/cloudkms_policy.yaml new file mode 100644 index 000000000..d73c3f66a --- /dev/null +++ b/fast/stages-aw/1-assured-workload/data/org-policies/cloudkms_policy.yaml @@ -0,0 +1,94 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +# This list constraint defines the Cloud KMS key types which may be created +# under a given hierarchy node. When this constraint is enforced, only KMS +# key types specified within this org policy may be created within the +# associated hierarchy node. Configuring this org policy will also impact the +# protection level of import jobs and key versions. By default, all key types +# are allowed. Valid values are: SOFTWARE, HSM, EXTERNAL, EXTERNAL_VPC. Deny +# policies are disallowed. +# COULD HAVE + +cloudkms.allowedProtectionLevels: + rules: + - allow: + values: + - HSM + +# This list constraint defines which projects may be used to supply +# Customer-Managed Encryption Keys (CMEK) when creating resources. Setting this +# constraint to Allow (i.e. only allow CMEK keys from these projects) ensures +# that CMEK keys from other projects cannot be used to protect newly created +# resources. Values for this constraint must be specified in the form of +# under:organizations/ORGANIZATION_ID, +# under:folders/FOLDER_ID, +# or projects/PROJECT_ID. +# Supported services that enforce this constraint are: +# [aiplatform.googleapis.com, artifactregistry.googleapis.com, +# bigquery.googleapis.com, bigtable.googleapis.com, composer.googleapis.com, +# compute.googleapis.com, container.googleapis.com, dataflow.googleapis.com, +# dataproc.googleapis.com, documentai.googleapis.com, logging.googleapis.com, +# pubsub.googleapis.com, run.googleapis.com, secretmanager.googleapis.com, +# spanner.googleapis.com, sqladmin.googleapis.com, storage.googleapis.com]. +# +# Enforcement of this constraint may grow over time to include additional +# services. +# Use caution when applying this constraint to projects, folders, or +# organizations where a mix of supported and unsupported services are used. +# Setting this constraint to Deny or Deny All is not permitted. Enforcement +# of this constraint is not retroactive. Existing CMEK Google Cloud resources +# with KMS CryptoKeys from disallowed projects must be reconfigured or +# recreated manually to ensure enforcement. +# SHOULD HAVE + +# gcp.restrictCmekCryptoKeyProjects: +# rules: +# - allow: +# values: +# - under:organizations/ + + +# This list constraint defines which services require Customer-Managed +# Encryption Keys (CMEK). Setting this constraint to Deny (i.e. deny resource +# creation without CMEK) requires that, for the specified services, newly +# created resources must be protected by a CMEK key. Supported services that +# can be set in this constraint are: +# [aiplatform.googleapis.com, artifactregistry.googleapis.com, +# bigquery.googleapis.com, bigtable.googleapis.com, composer.googleapis.com, +# compute.googleapis.com, container.googleapis.com, dataflow.googleapis.com, +# dataproc.googleapis.com, documentai.googleapis.com, logging.googleapis.com, +# pubsub.googleapis.com, run.googleapis.com, secretmanager.googleapis.com, +# spanner.googleapis.com, sqladmin.googleapis.com, storage.googleapis.com]. +# Setting this constraint to Deny All is not permitted. Setting this constraint +# to Allow is not permitted. +# Enforcement of this constraint is not retroactive. Existing non-CMEK Google +# Cloud resources must be reconfigured or recreated manually to ensure enforcement. +# COULD HAVE + +# gcp.restrictNonCmekServices: +# rules: +# - deny: +# values: +# - bigquery.googleapis.com +# - composer.googleapis.com +# - + +# Utilize our custom constraint to prevent users from creating KMS keys without +# the proper rotation period. + +# custom.kmsRotation: +# rules: +# - enforce: true \ No newline at end of file diff --git a/fast/stages-aw/1-assured-workload/data/org-policies/compute_policy.yaml b/fast/stages-aw/1-assured-workload/data/org-policies/compute_policy.yaml new file mode 100644 index 000000000..29d14b0a8 --- /dev/null +++ b/fast/stages-aw/1-assured-workload/data/org-policies/compute_policy.yaml @@ -0,0 +1,273 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +# This list constraint defines the set of Compute Engine VM instances that +# are allowed to use external IP addresses. By default, all VM instances are +# allowed to use external IP addresses. The allowed/denied list of VM instances +# must be identified by the VM instance name, in the form: +# projects/PROJECT_ID/zones/ZONE/instances/INSTANCE +# MUST HAVE +# Recommendations: +# Enable at org level and manage by exception for valid use cases. This is one +# of constraints that is commonly used and advised. +compute.vmExternalIpAccess: + rules: + - deny: + all: true + +# This boolean constraint disables Compute Engine API access to the Guest +# Attributes of Compute Engine VMs belonging to the organization, project, or +# folder where this constraint is set to True. By default, the Compute Engine +# API can be used to access Compute Engine VM guest attributes. +# This boolean constraint disables hardware-accelerated nested virtualization +# for all Compute Engine VMs belonging to the organization, project, or folder +# where this constraint is set to True. By default, hardware-accelerated nested +# virtualization is allowed for all Compute Engine VMs running on Intel Haswell +# or newer CPU platforms. +# COULD HAVE +compute.disableNestedVirtualization: + rules: + - enforce: true + + +# This boolean constraint disables serial port access to Compute Engine VMs +# belonging to the organization, project, or folder where this constraint is set +# to True. By default, customers can enable serial port access for Compute +# Engine VMs on a per-VM or per-project basis using metadata attributes. +# Enforcing this constraint will disable serial port access for Compute Engine +# VMs, regardless of the metadata attributes. +# SHOULD HAVE +compute.disableSerialPortAccess: + rules: + - enforce: true + + +# This boolean constraint disables serial port logging to Stackdriver from +# Compute Engine VMs belonging to the organization, project, or folder where +# this constraint is being enforced. By default, serial port logging for Compute +# Engine VMs is disabled, and can be selectively enabled on a per-VM or +# per-project basis using metadata attributes. When enforced, this constraint +# disables serial port logging for new Compute Engine VMs whenever a new VM is +# created, as well as preventing users from changing the metadata attribute of +# any VMs (old or new) to True. Disabling serial port logging can cause certain +# services that rely on it, such as GKE Autopilot, to not function correctly. +# Before you enforce this constraint, verify that the products in your project +# do not rely on serial port logging. +# SHOULD HAVE +# compute.disableSerialPortLogging: +# rules: +# - enforce: false + + +# This boolean constraint, when set to true, enables OS Login on all newly +# created Projects. All VM instances created in new projects will have OS Login +# enabled. On new and existing projects, this constraint prevents metadata +# updates that disable OS Login at the project or instance level. By default, +# the OS Login feature is disabled on Compute Engine projects.GKE instances in +# private clusters running node pool versions 1.20.5-gke.2000 and later support +# OS Login. GKE instances in public clusters do not currently support OS Login. +# If this constraint is applied to a Project running public clusters, GKE +# instances running in that Project may not function properly. +# COULD HAVE +compute.requireOsLogin: + rules: + - enforce: true + + +# This boolean constraint, when set to True, requires that all new Compute +# Engine VM instances use Shielded disk images with Secure Boot, vTPM, and +# Integrity Monitoring options enabled. Secure Boot can be disabled after +# creation, if desired. Existing running instances will continue to work as +# usual. By default, Shielded VM features do not need to be enabled in order +# to create Compute Engine VM instances. Shielded VM features add verifiable +# integrity and exfiltration resistance to your VMs. +# SHOULD HAVE, at folder or project level +# compute.requireShieldedVm: +# rules: +# - enforce: true + + +# The deny list of this list constraint defines the set of services that require +# all new resources to be created with Confidential Computing enabled. By +# default, new resources are not required to use Confidential Computing. While +# this list constraint is enforced, Confidential Computing cannot be disabled +# throughout the lifecycle of the resource. Existing resources will continue to +# work as usual. The denied list of services must be identified as the string +# name of an API, and can only include explicitly denied values from the list +# below. Explicitly allowing APIs is not currently supported. Explicitly denying +# APIs not in this list will result in an error. List of supported APIs: +# [compute.googleapis.com, container.googleapis.com] +# COULD HAVE +# compute.restrictNonConfidentialComputing: +# rules: +# - deny: +# values: +# - compute.googleapis.com + + +# This list constraint defines the set of Shared VPC host projects that projects +# at or below this resource can attach to. By default, a project can attach to +# any host project in the same organization, thereby becoming a service project. +# Projects, folders, and organizations in allowed/denied lists affect all +# objects underneath them in the resource hierarchy, and must be specified in +# the form: +# under:organizations/ORGANIZATION_ID, under:folders/FOLDER_ID, or +# projects/PROJECT_ID. +# SHOULD HAVE +# compute.restrictSharedVpcHostProjects: +# rules: +# - allow: +# values: +# - under:folders/ + + +# This list constraint defines the set of shared VPC subnetworks that eligible +# resources can use. This constraint does not apply to resources within the same +# project. By default, eligible resources can use any shared VPC subnetwork. The +# allowed/denied list of subnetworks must be specified in the form: +# under:organizations/ORGANIZATION_ID, under:folders/FOLDER_ID, +# under:projects/PROJECT_ID, or +# projects/PROJECT_ID/regions/REGION/subnetworks/SUBNETWORK-NAME. +# SHOULD HAVE +# compute.restrictSharedVpcSubnetworks: +# rules: +# - allow: +# values: +# - under:projects/ + + +# This boolean constraint restricts the set of users that can remove a Shared +# VPC host project lien without organization-level permission where this +# constraint is set to True. By default, any user with the permission to update +# liens can remove a Shared VPC host project lien. Enforcing this constraint +# requires that permission be granted at the organization level. +# SHOULD HAVE +# compute.restrictXpnProjectLienRemoval: +# rules: +# - enforce: false + + +# This list constraint defines the set of projects that are allowed to create +# and own shared reservations in the org. A shared reservation is similar to a +# local reservation, except that instead of being consumable by only owner +# projects, they can be consumed by other Compute Engine projects in the +# resource hierarchy. The list of projects allowed to access the shared +# reservation must be of the form: +# projects/PROJECT_NUMBER or under:projects/PROJECT_NUMBER. +# This list constraint defines a set of projects that are allowed to use Compute +# Engine's storage resources. By default, anyone with appropriate Cloud IAM +# permissions can access Compute Engine resources. When using this constraint, +# users must have Cloud IAM permissions, and they must not be restricted by the +# constraint to access the resource. Projects, folders, and organizations +# specified in allowed or denied lists must be in the form: +# under:projects/PROJECT_ID, under:folders/FOLDER_ID, +# under:organizations/ORGANIZATION_ID. +# COULD HAVE +# compute.sharedReservationsOwnerProjects: +# rules: +# - allow: +# all: true + + +# This list constraint defines the set of projects that can be used for image +# storage and disk instantiation for Compute Engine. By default, instances can +# be created from images in any project that shares images publicly or +# explicitly with the user. The allowed/denied list of publisher projects must +# be strings in the form: projects/PROJECT_ID. If this constraint is active, +# only images from trusted projects will be allowed as the source for boot +# disks for new instances. +# COULD HAVE +# compute.storageResourceUseRestrictions: +# rules: +# - allow: +# values: +# - projects/ + +# This list constraint defines the set of projects that can be used for image +# storage and disk instantiation for Compute Engine. By default, instances can +# be created from images in any project that shares images publicly or +# explicitly with the user. The allowed/denied list of publisher projects must +# be strings in the form: projects/PROJECT_ID. If this constraint is active, +# only images from trusted projects will be allowed as the source for boot +# disks for new instances. +compute.trustedImageProjects: + rules: + - allow: + values: + - "is:projects/centos-cloud" + - "is:projects/cos-cloud" + - "is:projects/debian-cloud" + - "is:projects/fedora-cloud" + - "is:projects/fedora-coreos-cloud" + - "is:projects/opensuse-cloud" + - "is:projects/rhel-cloud" + - "is:projects/rhel-sap-cloud" + - "is:projects/rocky-linux-cloud" + - "is:projects/suse-cloud" + - "is:projects/suse-sap-cloud" + - "is:projects/ubuntu-os-cloud" + - "is:projects/ubuntu-os-pro-cloud" + - "is:projects/windows-cloud" + - "is:projects/windows-sql-cloud" + - "is:projects/confidential-vm-images" + - "is:projects/backupdr-images" + - "is:projects/deeplearning-platform-release" + - "is:projects/serverless-vpc-access-images" + - "is:projects/paloaltonetworksgcp-public" + + +# This list constraint defines the set of VM instances that can enable IP +# forwarding. By default, any VM can enable IP forwarding in any virtual +# network. VM instances must be specified in the form: +# under:organizations/ORGANIZATION_ID, +# under:folders/FOLDER_ID, +# under:projects/PROJECT_ID, or +# projects/PROJECT_ID/zones/ZONE/instances/INSTANCE-NAME. +# This constraint is not retroactive. +# SHOULD HAVE +# Recommendations: +# Disable at org level and manage by exception for valid use cases +# (for example, proxy/NAT appliances). +# compute.vmCanIpForward +# rules: +# - allow: +# values: +# - under:folders/ + + +# This boolean constraint disables global serial port access to Compute Engine +# VMs belonging to the organization, project, or folder where the constraint is +# enforced. By default, customers can enable serial port access for Compute +# Engine VMs on a per-VM or per-project basis using metadata attributes. +# Enforcing this constraint will disable global serial port access for Compute +# Engine VMs, regardless of the metadata attributes. Regional serial port access +# is not affected by this constraint. To disable all serial port access, use the +# compute.disableSerialPortAccess constraint instead. +# COULD HAVE +# compute.disableGlobalSerialPortAccess: +# rules: +# - enforce: false + + +# This boolean constraint when enforced, disables creation of VM instance types +# that do not comply with FIPS requirements. +# COULD HAVE +# compute.disableNonFIPSMachineTypes: +# rules: +# - enforce: true + +compute.disableGuestAttributesAccess: + rules: + - enforce: true diff --git a/fast/stages-aw/1-assured-workload/data/org-policies/data_policy.yaml b/fast/stages-aw/1-assured-workload/data/org-policies/data_policy.yaml new file mode 100644 index 000000000..0ed403208 --- /dev/null +++ b/fast/stages-aw/1-assured-workload/data/org-policies/data_policy.yaml @@ -0,0 +1,54 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +# This boolean constraint restricts adding Authorized Networks for unproxied +# database access to Cloud SQL instances where this constraint is set to True. +# This constraint is not retroactive, Cloud SQL instances with existing +# Authorized Networks will still work even after this constraint is enforced. +# By default, Authorized Networks can be added to Cloud SQL instances. +# MUST HAVE +sql.restrictAuthorizedNetworks: + rules: + - enforce: true + +# This boolean constraint restricts configuring Public IP on Cloud SQL +# instances where this constraint is set to True. This constraint is not +# retroactive, Cloud SQL instances with existing Public IP access will still +# work even after this constraint is enforced. By default, Public IP access +# is allowed to Cloud SQL instances. +# MUST HAVE +sql.restrictPublicIp: + rules: + - enforce: true + +# By default, Datastream connection profiles can be created with public or +# private connectivity methods. If the boolean constraint for this organization +# policy is enforced, then only private connectivity methods (for example, VPC +# peering) can be used to create connection profiles. +# SHOULD HAVE +datastream.disablePublicConnectivity: + rules: + - enforce: true + +# This boolean constraint, when enforced, requires Firestore imports and +# exports to use the Firestore Service Agent. By default, Firestore imports +# and exports may use the App Engine service account. Firestore will stop +# using the App Engine service account for imports and exports in the future +# and all accounts will need to migrate to the Firestore Service Agent, after +# which time this constraint will no longer be necessary. +# SHOULD HAVE +firestore.requireP4SAforImportExport: + rules: + - enforce: false diff --git a/fast/stages-aw/1-assured-workload/data/org-policies/dns_policy.yaml b/fast/stages-aw/1-assured-workload/data/org-policies/dns_policy.yaml new file mode 100644 index 000000000..286935141 --- /dev/null +++ b/fast/stages-aw/1-assured-workload/data/org-policies/dns_policy.yaml @@ -0,0 +1,25 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +# When set to \`True\`, newly created projects will use Zonal DNS as default. +# By default, this constraint is set to \`False\` and newly created projects +# will be using the default DNS type. +# MUST HAVE +# Recommendation: +# Zonal DNS mitigates the risk of cross-regional outages. Google strongly +# recommends that you use internal zonal DNS names. +compute.setNewProjectDefaultToZonalDNSOnly: + rules: + - enforce: true diff --git a/fast/stages-aw/1-assured-workload/data/org-policies/function_policy.yaml b/fast/stages-aw/1-assured-workload/data/org-policies/function_policy.yaml new file mode 100644 index 000000000..b0ccb3295 --- /dev/null +++ b/fast/stages-aw/1-assured-workload/data/org-policies/function_policy.yaml @@ -0,0 +1,104 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This list constraint defines the allowed ingress settings for deployment of a +# Cloud Function. When this constraint is enforced, functions will be required +# to have ingress settings that match one of the allowed values. By default, +# Cloud Functions can use any ingress settings. Ingress settings must be +# specified in the allowed list using the values of the IngressSettings enum. +# SHOULD HAVE +# If unspecified, ALLOW_ALL will be used. +# - allowed values: +# - INGRESS_SETTINGS_UNSPECIFIED, +# - ALLOW_ALL, (default) +# - ALLOW_INTERNAL_ONLY, +# - ALLOW_INTERNAL_AND_GCLB +cloudfunctions.allowedIngressSettings: + rules: + - allow: + values: + - ALLOW_INTERNAL_AND_GCLB + +# This list constraint defines the allowed VPC Connector egress settings for +# deployment of a Cloud Function. When this constraint is enforced, functions +# will be required to have VPC Connector egress settings that match one of the +# allowed values. By default, Cloud Functions can use any VPC Connector egress +# settings. VPC Connector egress settings must be specified in the allowed list +# using the values of the VpcConnectorEgressSettings enum. +# SHOULD HAVE +# - allowed values: +# - VPC_CONNECTOR_EGRESS_SETTINGS_UNSPECIFIED, +# - PRIVATE_RANGES_ONLY, (default) +# - ALL_TRAFFIC +cloudfunctions.allowedVpcConnectorEgressSettings: + rules: + - allow: + values: + - ALL_TRAFFIC + +# This boolean constraint enforces setting a VPC Connector when deploying a +# Cloud Function. When this constraint is enforced, functions will be required +# to specify a VPC Connector. By default, specifying a VPC Connector is not +# required to deploy a Cloud Function. +# SHOULD HAVE +cloudfunctions.requireVPCConnector: + rules: + - enforce: false + +# This list constraint defines the set of Binary Authorization policy names +# that are allowed to be specified on a Cloud Run resource. To allow/disallow a +# default policy, use the value \`default\`. To allow/disallow one or more custom +# platform policies, the resource ID of each such policy must be added separately. +# COULD HAVE +run.allowedBinaryAuthorizationPolicies: + rules: + - allow: + values: + - default + +# This list constraint defines the allowed ingress settings for Cloud Run +# services. When this constraint is enforced, services will be required to have +# ingress settings that match one of the allowed values. Existing Cloud Run +# services with ingress settings that violate this constraint can continue to +# be updated until the service's ingress settings are changed to comply with +# this constraint. Once a service complies with this constraint the service can +# only use ingress settings allowed by this constraint. By default, Cloud Run +# services can use any ingress settings. The allowed list must contain supported +# ingress settings values, which are +# all, internal, and internal-and-cloud-load-balancing. +# SHOULD HAVE +run.allowedIngress: + rules: + - allow: + values: + - is:internal-and-cloud-load-balancing + +# This list constraint defines the allowed VPC egress settings for revisions of +# a Cloud Run service. When this constraint is enforced, a service's revisions +# are required to use a Serverless VPC Access connector and the revisions' VPC +# egress settings are required to match one of the allowed values. For existing +# services, all newly deployed revisions must comply with this constraint. +# Existing services with revisions serving traffic that violate this constraint +# can continue to migrate traffic to revisions that violate this constraint. +# Once all traffic for a service is served by revisions compliant with this +# constraint, all subsequent traffic migrations must only migrate traffic to +# revisions that comply with this constraint. By default, Cloud Run revisions +# can set VPC egress settings to any supported value. The allowed list must +# contain supported VPC egress settings values, which are private-ranges-only +# and all-traffic. +# SHOULD HAVE +run.allowedVPCEgress: + rules: + - allow: + all: true diff --git a/fast/stages-aw/1-assured-workload/data/org-policies/gke_policy.yaml b/fast/stages-aw/1-assured-workload/data/org-policies/gke_policy.yaml new file mode 100644 index 000000000..1744e4fba --- /dev/null +++ b/fast/stages-aw/1-assured-workload/data/org-policies/gke_policy.yaml @@ -0,0 +1,33 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +# This boolean constraint, when set to \`True\`, requires that all new GKE +# clusters have Workload Identity disabled at creation time. Existing GKE +# clusters with Workload Identity already enabled will continue to work as +# usual. By default, Workload Identity can be enabled for any GKE cluster. +# COULD HAVE +# iam.disableWorkloadIdentityClusterCreation: +# rules: +# - enforce: false + +# This constraint determines what VPC Service Controls modes can be set when +# provisioning a new Anthos Service Mesh Managed Control Plane. Valid values +# are "NONE" and "COMPATIBLE". +# COULD HAVE +# meshconfig.allowedVpcscModes: +# rules: +# values: +# - allow: +# - COMPATIBLE \ No newline at end of file diff --git a/fast/stages-aw/1-assured-workload/data/org-policies/iam_policy.yaml b/fast/stages-aw/1-assured-workload/data/org-policies/iam_policy.yaml new file mode 100644 index 000000000..20da7129c --- /dev/null +++ b/fast/stages-aw/1-assured-workload/data/org-policies/iam_policy.yaml @@ -0,0 +1,117 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +# This list constraint defines the set of service accounts that can be granted OAuth 2.0 access tokens with a lifetime of up to 12 hours. By default, the maximum lifetime for these access tokens is 1 hour. The allowed/denied list of service accounts must specify one or more service account email addresses. +# COULD HAVE +# iam.allowServiceAccountCredentialLifetimeExtension: +# rules: +# - allow: +# all: true + +# This boolean constraint, when enforced, prevents the default App Engine and +# Compute Engine service accounts that are created in your projects from being +# automatically granted any IAM role on the project when the accounts are +# created. By default, these service accounts automatically receive the Editor +# role when they are created. +# MUST HAVE +iam.automaticIamGrantsForDefaultServiceAccounts: + rules: + - enforce: true + + +# This boolean constraint disables the creation of service accounts where +# this constraint is set to \`True\`. By default, service accounts can be +# created by users based on their Cloud IAM roles and permissions. +# COULD HAVE +iam.disableServiceAccountCreation: + rules: + - enforce: false + +# This boolean constraint disables the creation of service account external +# keys where this constraint is set to \`True\`. By default, service account +# external keys can be created by users based on their Cloud IAM roles and +# permissions. +# SHOULD HAVE +iam.disableServiceAccountKeyCreation: + rules: + - enforce: true + +# This boolean constraint disables the feature that allows uploading public +# keys to service accounts where this constraint is set to \`True\`. By default, +# users can upload public keys to service accounts based on their Cloud IAM +# roles and permissions. +# COULD HAVE +iam.disableServiceAccountKeyUpload: + rules: + - enforce: true + +# This boolean constraint, when enforced, prevents you from exempting +# additional principals from audit logging. This constraint does not affect +# any audit-logging exemptions that existed before you enforced the constraint. +# COULD HAVE +# iam.disableAuditLoggingExemption: +# rules: +# - enforce: false + + +# This boolean constraint, when ENFORCED, prevents users from removing a +# Cross Project Service Account lien without organization-level permission. +# By default, any user with the permission to update liens can remove a Cross +# Project Service Account lien. Enforcing this constraint requires that +# permission to be granted at the organization level. +# COULD HAVE +# iam.restrictCrossProjectServiceAccountLienRemoval: +# rules: +# - enforce: false + + +# List of AWS account IDs that can be configured for workload identity +# federation in Cloud IAM. +# SHOULD HAVE +# constraints/iam.workloadIdentityPoolAwsAccounts: +# rules: +# - deny: +# all: true + +# Identity Providers that can be configured for workload authentication within +# Cloud IAM, specified by URI/URLs. +# SHOULD HAVE +# iam.workloadIdentityPoolProviders: +# rules: +# - allow: +# values: +# - + +# This list constraint defines the maximum duration allowed for service account +# key expiry. By default, created keys never expire. The allowed duration is +# specified in hours, and must come from the list below. Only one allowed value +# can be specified, and denied values are not supported. Specifying a duration +# not in this list will result in an error. [1h, 8h, 24h, 168h, 336h, 720h, +# 1440h, 2160h]. To enforce this constraint, you must set it to replace the +# parent policy in the Cloud Console, or set inheritFromParent=false in the +# policy file if using the gcloud CLI. This constraint can't be merged with a +# parent policy. Enforcement of the constraint is not retroactive and will not +# change pre-existing keys. +# SHOULD HAVE +# iam.serviceAccountKeyExpiryHours: +# rules: +# - allow: +# - 720h + +iam.serviceAccountKeyExposureResponse: + rules: + - allow: + values: + - DISABLE_KEY \ No newline at end of file diff --git a/fast/stages-aw/0-bootstrap/data/org-policies/lb_policy.yaml b/fast/stages-aw/1-assured-workload/data/org-policies/lb_policy.yaml similarity index 99% rename from fast/stages-aw/0-bootstrap/data/org-policies/lb_policy.yaml rename to fast/stages-aw/1-assured-workload/data/org-policies/lb_policy.yaml index 268a672c3..d64c9f974 100644 --- a/fast/stages-aw/0-bootstrap/data/org-policies/lb_policy.yaml +++ b/fast/stages-aw/1-assured-workload/data/org-policies/lb_policy.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/fast/stages-aw/1-assured-workload/data/org-policies/marketplace_policy.yaml b/fast/stages-aw/1-assured-workload/data/org-policies/marketplace_policy.yaml new file mode 100644 index 000000000..1912aeaaa --- /dev/null +++ b/fast/stages-aw/1-assured-workload/data/org-policies/marketplace_policy.yaml @@ -0,0 +1,20 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +# This boolean constraint, when enforced, disables public marketplace for all users under the org. By default, public marketplace access is enabled for the org. +# COULD HAVE +# commerceorggovernance.disablePublicMarketplace: +# rules: +# - enforce: false diff --git a/fast/stages-aw/1-assured-workload/data/org-policies/networking_policy.yaml b/fast/stages-aw/1-assured-workload/data/org-policies/networking_policy.yaml new file mode 100644 index 000000000..25788d43e --- /dev/null +++ b/fast/stages-aw/1-assured-workload/data/org-policies/networking_policy.yaml @@ -0,0 +1,150 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +# This boolean constraint, when set to True, disables the creation of or update +# to any Google Compute Engine resources involved in IPv6 usage. By default, +# anyone with appropriate Cloud IAM permissions can create or update Google +# Compute Engine resources with IPv6 usage in any projects, folders, and +# organizations. If set, this constraint will have higher priority than other +# IPv6 org constraints including disableVpcInternalIpv6, disableVpcExternalIpv6, +# and disableHybridCloudIpv6. +# COULD HAVE +compute.disableAllIpv6: + rules: + - enforce: false + +# This boolean constraint, when set to True, disables the creation of or update +# to hybrid cloud resources including Cloud Router, Interconnect Attachments, +# and Cloud VPN with a stack_type of IPV4_IPV6. By default, anyone with +# appropriate Cloud IAM permissions can create or update hybrid cloud resources +# with stack_type of IPV4_IPV6 in any projects, folders and organizations. +# COULD HAVE +compute.disableHybridCloudIpv6: + rules: + - enforce: false + +# This boolean constraint restricts whether a user can create Internet Network +# Endpoint Groups (NEG) with a type of INTERNET_FQDN_PORT and INTERNET_IP_PORT. +# By default, any user with appropriate IAM permissions can create Internet +# NEGs in any project. +# COULD HAVE +compute.disableInternetNetworkEndpointGroup: + rules: + - enforce: false + +# This boolean constraint, when set to True, disables the creation of or update +# to subnetworks with a stack_type of IPV4_IPV6 and ipv6_access_type of +# EXTERNAL. By default, anyone with appropriate Cloud IAM permissions can create +# or update subnetworks with stack_type of IPV4_IPV6 in any projects, folders, +# and organizations. +# COULD HAVE +compute.disableVpcExternalIpv6: + rules: + - enforce: false + +# This boolean constraint, when set to True, disables the creation of or update +# to subnetworks with a stack_type of IPV4_IPV6 and ipv6_access_type of +# INTERNAL. By default, anyone with appropriate Cloud IAM permissions can create +# or update subnetworks with stack_type of IPV4_IPV6 in any projects, folders, +# and organizations. +# COULD HAVE +compute.disableVpcInternalIpv6: + rules: + - enforce: false + +# This list constraint defines the set of predefined policies that can be +# enforced for VPC Flow logs.By default VPC Flow logs may be configured with +# any settings in each subnet.This constraint enforces enabling flow logs for +# all subnetworks in scope with a required minimum sampling rate. Specify one +# or more of the following valid values: +# [ ESSENTIAL (allows values >= 0.1 and < 0.5), +# LIGHT (allows values >= 0.5 and < 1.0), +# COMPREHENSIVE (allows values == 1.0) +# ]. +# COULD HAVE +# TODO: Resolve issue in 3-networking-a-fedramp-high and uncomment out below +# compute.requireVpcFlowLogs: +# rules: +# - allow: +# values: +# - COMPREHENSIVE + +# This list constraint defines the type of protocol forwarding rule objects +# with target instance that a user can create. When this constraint is enforced, +# new forwarding rule objects with target instance will be limited to internal +# and/or external IP addresses, based on the types specified. The types to be +# allowed or denied must be listed explicitly. By default, creation of both +# internal and external protocol forwarding rule objects with target instance +# are allowed. +# The list of allowed or denied values can only include values from the list +# below: [INTERNAL, EXTERNAL]. . +# COULD HAVE +compute.restrictProtocolForwardingCreationForTypes: + rules: + - allow: + values: + - INTERNAL + +# This list constraint defines the set of VPC networks that are allowed to be +# peered with the VPC networks belonging to this project, folder, or +# organization. By default, a Network Admin for one network can peer with any +# other network. The allowed/denied list of networks must be identified in the +# form: +# under:organizations/ORGANIZATION_ID, +# under:folders/FOLDER_ID, +# under:projects/PROJECT_ID, +# or projects/PROJECT_ID/global/networks/NETWORK_NAME. +# SHOULD HAVE +# compute.restrictVpcPeering: +# rules: +# - allow: +# values: +# - under:${root_node} + +# This list constraint defines the set of valid IP-v4 addresses that can be +# configured as VPN peer IPs. By default, any IP can be a VPN peer IP for a +# VPC network. The allowed/denied list of IP addresses must be specified as +# valid IP-v4 addresses in the form: IP_V4_ADDRESS. +# SHOULD HAVE +# compute.restrictVpnPeerIPs: +# rules: +# - allow: +# all: true + +# This boolean constraint skips the creation of the default network and +# related resources during Google Cloud Platform Project resource creation +# where this constraint is set to True. By default, a default network and +# supporting resources are automatically created when creating a Project resource. +# MUST HAVE +compute.skipDefaultNetworkCreation: + rules: + - enforce: true + +# This list constraint defines the allowed encryption settings for new VLAN +# Attachments. By default, VLAN Attachments are allowed to use any encryption +# settings. Set IPSEC as the allowed value to enforce creating encrypted VLAN +# attachments only. +# COULD HAVE +# compute.allowedVlanAttachmentEncryption: +# rules: +# - allow: +# values: +# - IPSEC + +# Utilize our custom constraint to prevent users from creating overly permissive firewalls + +# custom.restrictFirewallRanges: +# rules: +# - enforce: true diff --git a/fast/stages-aw/1-assured-workload/data/org-policies/platform_policy.yaml b/fast/stages-aw/1-assured-workload/data/org-policies/platform_policy.yaml new file mode 100644 index 000000000..6c483f016 --- /dev/null +++ b/fast/stages-aw/1-assured-workload/data/org-policies/platform_policy.yaml @@ -0,0 +1,121 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- + + +# When Detailed Audit Logging Mode is enforced, both the request and response +# are included in Cloud Audit Logs. Changes to this feature may take up to 10 +# minutes to reflect. This Org Policy is highly encouraged in coordination with +# Bucket Lock when seeking compliances such as SEC Rule 17a-4(f), +# CFTC Rule 1.31(c)-(d), and FINRA Rule 4511(c). This policy is currently only +# supported in Cloud Storage. +# COULD HAVE +gcp.detailedAuditLoggingMode: + rules: + - enforce: false + +# This boolean constraint, when enforced, disables Cloud Logging for the Cloud +# Healthcare API. Audit logs aren't affected by this constraint. Cloud Logs +# generated for the Cloud Healthcare API before the constraint is enforced are +# not deleted and can still be accessed. +# COULD HAVE +gcp.disableCloudLogging: + rules: + - enforce: false + +# This list constraint defines the set of locations where location-based Google +# Cloud resources can be created. By default, resources can be created in any +# location. Policies for this constraint can specify multi-regions such as asia +# and europe, regions such as us-east1 or europe-west1 as allowed or denied +# locations. Allowing or denying a multi-region does not imply that all included +# sub-locations should also be allowed or denied. For example, if the policy +# denies the us multi-region (which refers to multi-region resources, like some +# storage services), resources can still be created in the regional location +# us-east1. On the other hand, the in:us-locations group contains all locations +# within the us region, and can be used to block every region. We recommend +# using value groups to define your policy. You can specify value groups, +# collections of locations that are curated by Google to provide a simple way +# to define your resource locations. To use value groups in your organization +# policy, prefix your entries with the string in:, followed by the value group. +# For example, to create resources that will only be physically located within +# the US, set in:us-locations in the list of allowed values.If the +# suggested_value field is used in a location policy, it should be a region. +# If the value specified is a region, a UI for a zonal resource may pre-populate +# any zone in that region. +# SHOULD HAVE +gcp.resourceLocations: + rules: + - allow: + values: + - in:us-locations + - global + +# This constraint defines the set of Google Cloud resource services that can be +# used within an organization, folder, or project, such as compute.googleapis.com +# and storage.googleapis.com. By default, all Google Cloud resource services are +# allowed. For more information, see +# https://cloud.google.com/resource-manager/help/organization-policy/restricting-resources. +# COULD HAVE +# gcp.restrictServiceUsage: +# rules: +# - allow: +# all: true + +# This list constraint acts as a check to verify that a project with a service +# enabled is eligible for cross-organization move. A resource with a supported +# service enabled must have this constraint enforced and that supported service +# included in the allowed values to be eligible for a cross-organization move. +# The current list of allowed values for supported services that can be used is: +# [SHARED_VPC]. This constraint provides an additional control on top of +# constraints/resourcemanager.allowedExportDestinations. +# This list_constraint is empty by default and will not block cross organization +# moves unless a supported service is enabled on the resource to be exported. +# This constraint allows more fine-grained control over resources using features +# that require more caution when being moved to another organization. By default, +# a resource with a supported service enabled cannot be moved across organizations. +# SHOULD HAVE +# resourcemanager.allowEnabledServicesForExport: +# rules: +# - allow: +# all: true + + +# This boolean constraint, when enforced, allows organization policy administrators +# to ensure that only contacts assigned at the organization or folder level can +# receive security notifications. Specifically, enforcing this constraint blocks +# project owners and contact administrators from creating or updating an Essential +# Contact with a notification_category_subscriptions field that contains either +# the SECURITY or ALL category, if the contact also has a project resource as a parent. +# COULD HAVE +essentialcontacts.disableProjectSecurityContacts: + rules: + - enforce: false + +# This list constraint defines the set of Private Service Connect endpoint types +# for which users cannot create forwarding rules. When this constraint is +# enforced, users will be blocked from creating forwarding rules for the Private +# Service Connect endpoint type. This constraint is not retroactively enforced. +# By default, forwarding rules can be created for any Private Service Connect +# endpoint type. The allowed/denied list of Private Service Connect endpoints must +# come from the list below: [GOOGLE_APIS, SERVICE_PRODUCERS]. Using GOOGLE_APIS +# in the allowed/denied list will restrict the creation of Private Service Connect +# forwarding rules for accessing Google APIs. Using SERVICE_PRODUCERS in the +# allowed/denied list will restrict the creation of Private Service Connect forwarding +# rules for accessing services in another VPC network. +# COULD HAVE +cloudscheduler.allowedTargetTypes: + rules: + - allow: + all: true diff --git a/fast/stages-aw/1-assured-workload/data/org-policies/psc_policy.yaml b/fast/stages-aw/1-assured-workload/data/org-policies/psc_policy.yaml new file mode 100644 index 000000000..8e9674f56 --- /dev/null +++ b/fast/stages-aw/1-assured-workload/data/org-policies/psc_policy.yaml @@ -0,0 +1,35 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +# This list constraint defines the set of Private Service Connect endpoint types +# for which users cannot create forwarding rules. When this constraint is +# enforced, users will be blocked from creating forwarding rules for the Private +# Service Connect endpoint type. This constraint is not retroactively enforced. +# By default, forwarding rules can be created for any Private Service Connect +# endpoint type. The allowed/denied list of Private Service Connect endpoints +# must come from the list below: +# [GOOGLE_APIS, SERVICE_PRODUCERS]. +# Using GOOGLE_APIS in the allowed/denied list will restrict the creation of +# Private Service Connect forwarding rules for accessing Google APIs. Using +# SERVICE_PRODUCERS in the allowed/denied list will restrict the creation of +# Private Service Connect forwarding rules for accessing services in another +# VPC network. +# COULD HAVE +# compute.disablePrivateServiceConnectCreationForConsumers: +# rules: +# - allow: +# values: +# - GOOGLE_APIS +# - SERVICE_PRODUCERS diff --git a/fast/stages-aw/1-assured-workload/data/org-policies/storage_policy.yaml b/fast/stages-aw/1-assured-workload/data/org-policies/storage_policy.yaml new file mode 100644 index 000000000..ebecf6669 --- /dev/null +++ b/fast/stages-aw/1-assured-workload/data/org-policies/storage_policy.yaml @@ -0,0 +1,73 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +# Secure your Cloud Storage data from public exposure by enforcing public access +# prevention. This governance policy prevents existing and future resources from +# being accessed via the public internet by disabling and blocking ACLs and IAM +# permissions that grant access to allUsers and allAuthenticatedUsers. Enforce +# this policy on the entire organization (recommended), specific projects, or +# specific folders to ensure no data is publicly exposed.This policy overrides +# existing public permissions. Public access will be revoked for existing buckets +# and objects after this policy is enabled. +# MUST HAVE +storage.publicAccessPrevention: + rules: + - enforce: true + +# The constraint defines the set of authentication types that would be restricted +# from accessing any storage resources under the organization in Cloud Storage. +# Supported values are USER_ACCOUNT_HMAC_SIGNED_REQUESTS and +# SERVICE_ACCOUNT_HMAC_SIGNED_REQUESTS. Use in:ALL_HMAC_SIGNED_REQUESTS +# to include both. +# COULD HAVE +# storage.restrictAuthTypes: +# rules: +# - allow: +# values: +# - in:ALL_HMAC_SIGNED_REQUESTS + +# This list constraint defines the set of durations for retention policies that +# can be set on Cloud Storage buckets. By default, if no organization policy is +# specified, a Cloud Storage bucket can have a retention policy of any duration. +# The list of allowed durations must be specified as a positive integer value +# greater than zero, representing the retention policy in seconds. Any insert, +# update, or patch operation on a bucket in the organization resource must have +# a retention policy duration that matches the constraint. Enforcement of this +# constraint is not retroactive. When a new organization policy is applied, the +# retention policy of existing buckets remains unchanged and valid. +# COULD HAVE +# storage.retentionPolicySeconds: +# rules: +# - allow: +# all: true + +# This boolean constraint requires buckets to use uniform bucket-level access +# where this constraint is set to True. Any new bucket in the Organization +# resource must have uniform bucket-level access enabled, and no existing +# buckets in the organization resource can disable uniform bucket-level access. +# Enforcement of this constraint is not retroactive: existing buckets with +# uniform bucket-level access disabled continue to have it disabled. The default +# value for this constraint is False. Uniform bucket-level access disables the +# evaluation of ACLs assigned to Cloud Storage objects in the bucket. +# Consequently, only IAM policies grant access to objects in these buckets. +# MUST HAVE +storage.uniformBucketLevelAccess: + rules: + - enforce: true + + +storage.secureHttpTransport: + rules: + - enforce: true \ No newline at end of file diff --git a/fast/stages-aw/0-bootstrap/diagram.png b/fast/stages-aw/1-assured-workload/diagram.png similarity index 100% rename from fast/stages-aw/0-bootstrap/diagram.png rename to fast/stages-aw/1-assured-workload/diagram.png diff --git a/fast/stages-aw/0-bootstrap/diagram.svg b/fast/stages-aw/1-assured-workload/diagram.svg similarity index 100% rename from fast/stages-aw/0-bootstrap/diagram.svg rename to fast/stages-aw/1-assured-workload/diagram.svg diff --git a/fast/stages-aw/0-bootstrap/groups.gif b/fast/stages-aw/1-assured-workload/groups.gif similarity index 100% rename from fast/stages-aw/0-bootstrap/groups.gif rename to fast/stages-aw/1-assured-workload/groups.gif diff --git a/fast/stages-aw/1-assured-workload/identity-providers.tf b/fast/stages-aw/1-assured-workload/identity-providers.tf new file mode 100644 index 000000000..daf584436 --- /dev/null +++ b/fast/stages-aw/1-assured-workload/identity-providers.tf @@ -0,0 +1,96 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# tfdoc:file:description Workload Identity Federation provider definitions. + +locals { + workload_identity_providers = { + for k, v in var.workload_identity_providers : k => merge( + v, + lookup(local.workload_identity_providers_defs, v.issuer, {}) + ) + } + workload_identity_providers_defs = { + # https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect + github = { + attribute_mapping = { + "google.subject" = "assertion.sub" + "attribute.sub" = "assertion.sub" + "attribute.actor" = "assertion.actor" + "attribute.repository" = "assertion.repository" + "attribute.repository_owner" = "assertion.repository_owner" + "attribute.ref" = "assertion.ref" + "attribute.fast_sub" = "\"repo:\" + assertion.repository + \":ref:\" + assertion.ref" + } + issuer_uri = "https://token.actions.githubusercontent.com" + principal_branch = "principalSet://iam.googleapis.com/%s/attribute.fast_sub/repo:%s:ref:refs/heads/%s" + principal_repo = "principalSet://iam.googleapis.com/%s/attribute.repository/%s" + } + # https://docs.gitlab.com/ee/ci/secrets/id_token_authentication.html#token-payload + gitlab = { + attribute_mapping = { + "google.subject" = "assertion.sub" + "attribute.sub" = "assertion.sub" + "attribute.environment" = "assertion.environment" + "attribute.environment_protected" = "assertion.environment_protected" + "attribute.namespace_id" = "assertion.namespace_id" + "attribute.namespace_path" = "assertion.namespace_path" + "attribute.pipeline_id" = "assertion.pipeline_id" + "attribute.pipeline_source" = "assertion.pipeline_source" + "attribute.project_id" = "assertion.project_id" + "attribute.project_path" = "assertion.project_path" + "attribute.repository" = "assertion.project_path" + "attribute.ref" = "assertion.ref" + "attribute.ref_protected" = "assertion.ref_protected" + "attribute.ref_type" = "assertion.ref_type" + } + issuer_uri = "https://gitlab.com" + principal_branch = "principalSet://iam.googleapis.com/%s/attribute.sub/project_path:%s:ref_type:branch:ref:%s" + principal_repo = "principalSet://iam.googleapis.com/%s/attribute.repository/%s" + } + } +} + +resource "google_iam_workload_identity_pool" "default" { + provider = google-beta + count = length(local.workload_identity_providers) > 0 ? 1 : 0 + project = module.automation-project.project_id + workload_identity_pool_id = "${var.prefix}-bootstrap" +} + +resource "google_iam_workload_identity_pool_provider" "default" { + provider = google-beta + for_each = local.workload_identity_providers + project = module.automation-project.project_id + workload_identity_pool_id = ( + google_iam_workload_identity_pool.default[0].workload_identity_pool_id + ) + workload_identity_pool_provider_id = "${var.prefix}-bootstrap-${each.key}" + attribute_condition = each.value.attribute_condition + attribute_mapping = each.value.attribute_mapping + oidc { + # Setting an empty list configures allowed_audiences to the url of the provider + allowed_audiences = each.value.custom_settings.audiences + # If users don't provide an issuer_uri, we set the public one for the platform chosen. + issuer_uri = ( + each.value.custom_settings.issuer_uri != null + ? each.value.custom_settings.issuer_uri + : try(each.value.issuer_uri, null) + ) + # OIDC JWKs in JSON String format. If no value is provided, they key is + # fetched from the `.well-known` path for the issuer_uri + jwks_json = try(trimspace(each.value.custom_settings.jwks_json), "") + } +} diff --git a/fast/stages-aw/1-assured-workload/import.sh b/fast/stages-aw/1-assured-workload/import.sh new file mode 100644 index 000000000..4bf51e4ec --- /dev/null +++ b/fast/stages-aw/1-assured-workload/import.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# TODO - replace with terraform + +# Assign Organization ID +ORG="$1" +if [[ -z "${ORG}" ]]; then + echo "Error: Failed to get organization ID." >&2 + exit 1 +fi + +# Import Organization Policies Filtered by "SET" Constraints +policies=$(gcloud resource-manager org-policies list \ + --organization="${ORG}" \ + --filter='booleanPolicy.enforced=true OR listPolicy:*' \ + --format='value(constraint)') + +if [[ -z "${policies}" ]]; then + echo "No organization policies found matching the filter." +else + echo -e "Importing policies...\n" + + failed_imports=() + + # Policy Iteration + while IFS= read -r constraint_path; do + constraint_name=${constraint_path##*/} + constraint_self_link="organizations/${ORG}/policies/${constraint_name}" + + # Check Policy State + if terraform state show "module.organization.google_org_policy_policy.default[\"${constraint_name}\"]" > /dev/null 2>&1; then + # Skip Import + echo "${constraint_name} already managed, skipping import." + else + + # Attempt Import + if ! terraform import \ + "module.organization.google_org_policy_policy.default[\"${constraint_name}\"]" \ + "${constraint_self_link}"; then + echo "Error: terraform import failed for constraint: ${constraint_name}" >&2 + failed_imports+=("${constraint_name}") + fi + fi + done <<< "$policies" + + if [[ ${#failed_imports[@]} -gt 0 ]]; then + echo -e "\nError: The following organizational policies failed to import:" >&2 + for failed_policy in "${failed_imports[@]}"; do + echo "- ${failed_policy}" >&2 + done + exit 1 + else + echo -e "\nOrganization Policy import operation is complete!" + fi +fi diff --git a/fast/stages-aw/1-assured-workload/kms.tf b/fast/stages-aw/1-assured-workload/kms.tf new file mode 100644 index 000000000..d16c72d1c --- /dev/null +++ b/fast/stages-aw/1-assured-workload/kms.tf @@ -0,0 +1,105 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +locals { + version_template = { + algorithm = "GOOGLE_SYMMETRIC_ENCRYPTION" + protection_level = "HSM" + } + primary_location_gcs = element(local.locations.gcs, 0) +} +module "logging-kms" { + source = "../../../modules/kms" + for_each = toset(local.locations.logging) + project_id = module.log-export-project.project_id + + keyring = { + location = each.value + name = "logging-${each.value}" + } + keys = { + "log-sink" = { + rotation_period = "7776000s" # CIS Compliance Benchmark 1.10 + version_template = local.version_template + } + "pubsub" = { + rotation_period = "7776000s" + version_template = local.version_template + iam_bindings = { + "pubsub" = { + members = [module.logging-c5isr-pubsub-sa.iam_email] + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + } + } + } + } + + iam_bindings_additive = { + "pubsub" = { + member = "serviceAccount:service-${module.log-export-project.number}@gcp-sa-pubsub.iam.gserviceaccount.com" + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + }, + "bq" = { + member = "serviceAccount:bq-${module.log-export-project.number}@bigquery-encryption.iam.gserviceaccount.com" + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + }, + "gcs" = { + member = "serviceAccount:service-${module.log-export-project.number}@gs-project-accounts.iam.gserviceaccount.com" + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + }, + "logging" = { + member = "serviceAccount:service-${module.log-export-project.number}@gcp-sa-logging.iam.gserviceaccount.com" + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + } + } + iam = { + "roles/cloudkms.viewer" = [ + module.automation-tf-tenants-sa.iam_email, + ] + } +} + +module "gcs-kms" { + source = "../../../modules/kms" + for_each = toset(local.locations.gcs) + project_id = module.automation-project.project_id + + keyring = { + location = each.value + name = "gcs-${each.value}" + } + keys = { + "gcs" = { + rotation_period = "7776000s" # CIS Compliance Benchmark 1.10 + version_template = local.version_template + } + } + iam = { + "roles/cloudkms.cryptoKeyEncrypterDecrypter" = [ + "serviceAccount:service-${module.automation-project.number}@gs-project-accounts.iam.gserviceaccount.com", + "serviceAccount:service-${module.log-export-project.number}@gs-project-accounts.iam.gserviceaccount.com", + module.automation-tf-resman-sa.iam_email + ], + "roles/cloudkms.admin" = [ + module.automation-tf-resman-r-sa.iam_email, + module.automation-tf-resman-sa.iam_email, # This might work as viewer + module.automation-tf-tenants-sa.iam_email + ], + "roles/cloudkms.viewer" = [ + module.automation-tf-tenants-sa.iam_email, + ] + } +} diff --git a/fast/stages-aw/1-assured-workload/log-export.tf b/fast/stages-aw/1-assured-workload/log-export.tf new file mode 100644 index 000000000..79b3b9ff4 --- /dev/null +++ b/fast/stages-aw/1-assured-workload/log-export.tf @@ -0,0 +1,199 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# tfdoc:file:description Audit log project and sink. + +locals { + # Organization and assured workload log buckets + aw_log_buckets = { + "${var.prefix}-${lower(replace(var.assured_workloads.regime, "_", "-"))}-logs" = { + type = "assured_workload" + filter = "" # Assured workload folder logs + description = "Assured workload ${var.assured_workloads.regime} folder audit logs - captures compliance regime folder activities and events" + } + "${var.prefix}-common-services-logs" = { + type = "common_services" + filter = "" # Common services folder logs + description = "Common Services folder audit logs - captures all activities from shared infrastructure projects (audit, automation, billing)" + } + } + + aw_log_buckets_redundant = merge([ + for bucket_key, bucket_val in local.aw_log_buckets : { + for loc in local.locations.logging : + "${bucket_key}-${loc}" => { + name = bucket_key + location = loc + description = bucket_val.description + } + } + ]...) + + pubsub_topics_tiers = [ + "tier-1", + "tier-2", + "tier-3" + ] + + pubsub_tier_region_map = { + for pair in setproduct(local.pubsub_topics_tiers, var.locations.pubsub) : + pair[0] => { + tier = pair[0] + region = pair[1] + } + } + + # Combine all log buckets + all_log_buckets = merge(local.aw_log_buckets) + + # Updated log sink destinations to include all buckets + log_sink_destinations_all = merge( + module.aw-log-buckets + ) + tier_1_audit_filter = "(logName:\"cloudaudit.googleapis.com\")" + tier_1_vpc_filter = "(resource.type=\"gce_subnetwork\" AND logName:\"logs/compute.googleapis.com%2Fvpc_flows\")" + _tier_2_base_filter = join(" OR ", flatten([ + "resource.type=\"gce_firewall_rule\"", + "resource.type=\"http_load_balancer\"", + "resource.type=\"dns_query\"", + "resource.type=\"cloud_armor_policy\"", + "resource.type=\"networkconnectivity.googleapis.com/Hub\"", + "resource.type=\"networkconnectivity.googleapis.com/Spoke\"", + "logName:\"logs/networksecurity.googleapis.com%2Ffirewall_threat\"", + "logName:\"logs/networksecurity.googleapis.com%2Ffirewall_url_filter\"", + "logName:\"proxy\"", + "logName:\"apache\"", + "logName:\"nginx\"", + "logName:\"iis\"" + ])) + tier_2_filter = local._tier_2_base_filter + _tier_3_base_filter = join(" OR ", flatten([ + "logName:\"logs/syslog\"", + "logName:\"logs/auth.log\"", + "logName:\"logs/windows.googleapis.com%2F\"", + "logName:\"logs/application\"", + "resource.type=\"k8s_container\"", + "resource.type=\"k8s_node\"", + "resource.type=\"k8s_pod\"", + "resource.type=\"gce_instance\"", + "logName:\"logs/gcce-agent\"", + "logName:\"directory\"" + ])) + tier_3_filter = local._tier_3_base_filter + tenant_exclusion_filter = "logName:\"${module.tenants-container-folders.folder.id}\" AND resource.labels.folder_id != \"${module.tenants-container-folders.folder.folder_id}\"" + tenant_exclusions_map = { + "exclude_tenant_children" = local.tenant_exclusion_filter + } +} + +module "log-export-project" { + source = "../../../modules/project" + name = local.project_map["log-export-project"] + parent = coalesce( + var.project_parent_ids.logging, module.branch-common-services-folder.folder.name + ) + billing_account = var.billing_account.id + contacts = ( + var.bootstrap_user != null || var.essential_contacts == null + ? {} + : { (var.essential_contacts) = ["ALL"] } + ) + iam = { + "roles/owner" = [module.automation-tf-bootstrap-sa.iam_email, module.automation-tf-tenants-sa.iam_email] + "roles/viewer" = [module.automation-tf-bootstrap-r-sa.iam_email] + } + services = [ + # "cloudresourcemanager.googleapis.com", + # "iam.googleapis.com", + # "serviceusage.googleapis.com", + "bigquery.googleapis.com", + "storage.googleapis.com", + "stackdriver.googleapis.com", + "cloudkms.googleapis.com", + "pubsub.googleapis.com" + ] +} + +module "logging-c5isr-pubsub-sa" { + source = "../../../modules/iam-service-account" + project_id = module.log-export-project.project_id + name = "c5isr-pubsub-sa" + display_name = "Pubsub service account for C5ISR logging." + prefix = local.prefix + iam_project_roles = { + (module.log-export-project.project_id) = [ + "roles/pubsub.viewer" + ] + } +} + +# Organization and assured workload logging buckets +module "aw-log-buckets" { + source = "../../../modules/logging-bucket" + for_each = local.aw_log_buckets_redundant + name = "${each.value.name}-bucket-${each.value.location}" + parent_type = "project" + parent = module.log-export-project.project_id + location = each.value.location + retention = 365 + description = each.value.description + log_analytics = { enable = true } + kms_key_name = coalesce(var.logging_kms_key, module.logging-kms[each.value.location].keys["log-sink"].id) +} + +resource "google_compute_project_metadata" "metadata-log-export" { + project = module.log-export-project.project_id + metadata = { + block-project-ssh-keys = "TRUE" # CIS Compliance Benchmark 4.3 + enable-oslogin = "TRUE" # CIS Compliance Benchmark 4.4 + } +} + +resource "google_project_service_identity" "logging" { + provider = google-beta + project = module.log-export-project.project_id + service = "logging.googleapis.com" +} + +# tflint-ignore: terraform_unused_declarations +data "google_logging_project_cmek_settings" "settings" { + project = module.log-export-project.project_id + depends_on = [google_project_service_identity.logging] +} + +module "pubsub-topics" { + source = "../../../modules/pubsub" + for_each = local.pubsub_tier_region_map + project_id = module.log-export-project.project_id + name = "${each.value.tier}-${each.value.region}-topic" + regions = [each.value.region] + kms_key = module.logging-kms[each.value.region].keys["pubsub"].id + iam_bindings_additive = { + "roles/pubsub.subscriber" = { + role = "roles/pubsub.subscriber" + member = module.logging-c5isr-pubsub-sa.iam_email + } + } + subscriptions = { + "${each.value.tier}-${each.value.region}-sub" = { + message_retention_duration = "604800s" + expiration_policy_ttl = "" + ack_deadline_seconds = 60 + } + } + depends_on = [ + module.logging-kms + ] +} \ No newline at end of file diff --git a/fast/stages-aw/0-bootstrap/log-metric-alerts.tf b/fast/stages-aw/1-assured-workload/log-metric-alerts.tf similarity index 58% rename from fast/stages-aw/0-bootstrap/log-metric-alerts.tf rename to fast/stages-aw/1-assured-workload/log-metric-alerts.tf index 719f53ba9..22a660006 100644 --- a/fast/stages-aw/0-bootstrap/log-metric-alerts.tf +++ b/fast/stages-aw/1-assured-workload/log-metric-alerts.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # CIS Compliance Benchmark 2.4 # CIS Compliance Benchmark 2.5 @@ -34,9 +36,15 @@ module "bootstrap_log_metrics" { for_each = toset(local.bootstrap_projects) project = each.key + + # Ensure metrics are created after logging infrastructure is stable + depends_on = [ + module.log-export-project, + module.automation-project + ] } -# Alerts require log-metrics to be configure +# Alerts require log-metrics to be configured resource "time_sleep" "bootstrap_wait_10_seconds" { depends_on = [module.bootstrap_log_metrics] create_duration = "10s" diff --git a/fast/stages-aw/1-assured-workload/main.tf b/fast/stages-aw/1-assured-workload/main.tf new file mode 100644 index 000000000..0507e7ca9 --- /dev/null +++ b/fast/stages-aw/1-assured-workload/main.tf @@ -0,0 +1,55 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +locals { + gcs_storage_class = ( + length(split("-", local.primary_location_gcs)) < 2 + ? "MULTI_REGIONAL" + : "REGIONAL" + ) + _gcp_devops_group = coalesce(var.groups.gcp-devops, var.gcp_devops_group) + _groups = { + gcp-billing-admins = coalesce(var.groups.gcp-billing-admins, var.gcp_billing_admins_group) + gcp-devops = local._gcp_devops_group + gcp-vpc-network-admins = coalesce(var.groups.gcp-vpc-network-admins, var.gcp_vpc_network_admins_group) + gcp-organization-admins = coalesce(var.groups.gcp-organization-admins, var.gcp_organization_admins_group) + gcp-security-admins = coalesce(var.groups.gcp-security-admins, var.gcp_security_admins_group) + gcp-support = coalesce(var.groups.gcp-support, var.gcp_support_group, local._gcp_devops_group) + } + principals = { + for k, v in local._groups : k => ( + can(regex("^[a-zA-Z]+:", v)) + ? v + : "group:${v}@${var.organization.domain}" + ) + } + locations = { + bq = var.locations.bq + gcs = var.locations.gcs + logging = distinct(compact(concat([try(local.checklist.location, null)], var.locations.logging))) + pubsub = var.locations.pubsub + kms = var.locations.kms + } + # naming: environment used in most resource names + prefix = join("-", compact([var.prefix])) + + # The following section maps project names for stage 1 using the projects-config.yml inside of the root directory + formatted_regime = lower(replace(lookup(var.regime_mapping, var.assured_workloads.regime, var.assured_workloads.regime), "_", " ")) + project_config_yaml = yamldecode(file("../../../project-config.yml")) + project_map = { + for p in local.project_config_yaml.projects : p.name => + replace(replace(p.project_name, "", local.prefix), "", local.formatted_regime) + } +} diff --git a/fast/stages-aw/1-assured-workload/organization-iam.tf b/fast/stages-aw/1-assured-workload/organization-iam.tf new file mode 100644 index 000000000..5e08d0d36 --- /dev/null +++ b/fast/stages-aw/1-assured-workload/organization-iam.tf @@ -0,0 +1,150 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# tfdoc:file:description Organization-level IAM bindings locals. + +locals { + # machine (service accounts) IAM bindings, in logical format + # the service account module's "magic" outputs allow us to use dynamic values + iam_sa_bindings = { + (module.automation-tf-bootstrap-sa.iam_email) = { + additive = concat( + [ + "roles/essentialcontacts.admin", + "roles/logging.admin", + "roles/resourcemanager.organizationAdmin", + "roles/resourcemanager.projectCreator", + "roles/resourcemanager.projectMover", + "roles/resourcemanager.tagAdmin", + "roles/assuredworkloads.admin", + "roles/iam.organizationRoleAdmin", + # "roles/orgpolicy.policyAdmin", + # "organizations/${var.organization.id}/roles/storageViewer", + # "roles/viewer", + # "roles/assuredworkloads.reader", + # "roles/serviceusage.serviceUsageViewer", + # "roles/bigquery.user", + # "roles/compute.viewer", + # "roles/logging.viewer", + # "roles/iam.serviceAccountTokenCreator", + # "roles/cloudkms.viewer", + # "roles/policyanalyzer.activityAnalysisViewer" # TODO DELETE - here to test + ], + local.billing_mode != "org" ? [] : [ + "roles/billing.admin" + ] + ) + } + (module.automation-tf-bootstrap-r-sa.iam_email) = { + additive = concat( + [ + # the organizationAdminViewer custom role is granted via the SA module + "roles/iam.organizationRoleViewer", + "roles/orgpolicy.policyViewer", + "roles/essentialcontacts.viewer", + "roles/logging.viewer", + "roles/resourcemanager.folderViewer", + "roles/resourcemanager.tagViewer", + "roles/assuredworkloads.reader" + ], + local.billing_mode != "org" ? [] : [ + "roles/billing.viewer" + ] + ) + } + (module.automation-tf-resman-sa.iam_email) = { + additive = concat( + [ + "roles/orgpolicy.policyAdmin", + "roles/assuredworkloads.admin", + "roles/logging.admin", + "roles/resourcemanager.folderAdmin", + "roles/resourcemanager.projectCreator", + "roles/resourcemanager.tagAdmin", + "roles/resourcemanager.tagUser", + "roles/resourcemanager.organizationAdmin" + ], + local.billing_mode != "org" ? [] : [ + "roles/billing.admin" + ] + ) + } + (module.automation-tf-resman-r-sa.iam_email) = { + additive = concat( + [ + # the organizationAdminViewer custom role is granted via the SA module + "roles/orgpolicy.policyViewer", + "roles/assuredworkloads.reader", + "roles/logging.viewer", + "roles/resourcemanager.folderViewer", + "roles/resourcemanager.tagViewer", + "roles/serviceusage.serviceUsageViewer" + ], + local.billing_mode != "org" ? [] : [ + "roles/billing.viewer", + + ] + ) + } + (module.automation-tf-tenants-sa.iam_email) = { + additive = concat( + [ + "roles/orgpolicy.policyAdmin", + "roles/assuredworkloads.admin", + "roles/logging.admin", + "roles/resourcemanager.folderAdmin", + "roles/resourcemanager.projectCreator", + "roles/resourcemanager.tagAdmin", + "roles/resourcemanager.tagUser", + "roles/resourcemanager.organizationAdmin", + "roles/compute.networkAdmin", + "roles/compute.xpnAdmin", + "roles/dns.admin", + "roles/networkconnectivity.hubAdmin" + ], + local.billing_mode != "org" ? [] : [ + "roles/billing.user" + ] + ) + } + (module.automation-tf-tenants-r-sa.iam_email) = { + additive = concat( + [], + local.billing_mode != "org" ? [] : [ + "roles/billing.viewer" + ] + ) + } + } + # TODO - look at this + # bootstrap user bindings + iam_user_bootstrap_bindings = var.bootstrap_user == null ? {} : { + "user:${var.bootstrap_user}" = { + # TODO: align additive roles with the README + additive = concat( + [ + "roles/logging.admin", + "roles/owner", + "roles/resourcemanager.organizationAdmin", + "roles/resourcemanager.projectCreator", + "roles/resourcemanager.tagAdmin" + ], + local.billing_mode != "org" ? [] : [ + "roles/billing.admin" + ] + ) + } + } +} diff --git a/fast/stages-aw/1-assured-workload/organization.tf b/fast/stages-aw/1-assured-workload/organization.tf new file mode 100644 index 000000000..745fb1155 --- /dev/null +++ b/fast/stages-aw/1-assured-workload/organization.tf @@ -0,0 +1,348 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# tfdoc:file:description Organization-level IAM. + +locals { + # reassemble logical bindings into the formats expected by the module + _iam_bindings = merge( + local.iam_sa_bindings, + local.iam_user_bootstrap_bindings + ) + _iam_bindings_add = flatten([ + for member, data in local._iam_bindings : [ + for role in data.additive : { + member = member + role = role + } + ] + ]) + _iam_bindings_additive = { + for b in local._iam_bindings_add : "${b.role}-${b.member}" => { + member = b.member + role = b.role + } + } + _org_only_roles = [ + "roles/billing.admin", + "roles/billing.creator", + "roles/billing.user", + "roles/orgpolicy.policyAdmin", + "roles/iam.organizationRoleAdmin", + "roles/cloudsupport.admin", + "roles/assuredworkloads.admin", + "roles/compute.osLoginExternalUser", + "roles/resourcemanager.organizationAdmin", + "roles/billing.viewer", + "roles/iam.organizationRoleViewer", + "roles/logging.admin" + ] + consumer_folder_id = try(one([ + for r in google_assured_workloads_workload.primary[0].resources : r.resource_id if r.resource_type == "CONSUMER_FOLDER" + ]), null) + + custom_role_ids = [ + "gcveNetworkAdmin", + "organizationAdminViewer", + "organizationIamAdmin", + "serviceProjectNetworkAdmin", + "storageViewer", + "tagEditor", + "tagViewer", + "tenantNetworkAdmin" + ] + + iam_bindings_additive = merge( + local._iam_bindings_additive, + { + for k, v in try(local.checklist.iam_bindings, {}) : + v.key => v if lookup(local._iam_bindings_additive, v.key, null) == null + } + ) + folder_iam_bindings_additive = { + for k, v in local.iam_bindings_additive : k => v + if !contains(local._org_only_roles, v.role) + } + org_iam_bindings_additive = { + for k, v in local.iam_bindings_additive : k => v + if contains(local._org_only_roles, v.role) + } + compliance_api_baseline = yamldecode(file("${path.module}/data/allowed_apis.yaml")).allowed_apis +} + +data "google_iam_role" "custom_iam_roles" { + for_each = toset(local.custom_role_ids) + name = "organizations/${var.organization.id}/roles/${each.key}" +} + +# TODO: add a check block to ensure our custom roles exist in the factory files + +resource "google_assured_workloads_workload" "primary" { + count = var.assured_workloads.regime != "COMPLIANCE_REGIME_UNSPECIFIED" ? 1 : 0 + compliance_regime = var.assured_workloads.regime + display_name = "${replace(lookup(var.regime_mapping, var.assured_workloads.regime, var.assured_workloads.regime), "_", " ")}-${var.prefix}" + location = lower(var.assured_workloads.location) + organization = var.organization.id + billing_account = var.billing_account.id != null ? "billingAccounts/${var.billing_account.id}" : null + provisioned_resources_parent = "folders/${var.top_level_folder.id}" + resource_settings { + display_name = "${replace(lookup(var.regime_mapping, var.assured_workloads.regime, var.assured_workloads.regime), "_", " ")}-${var.prefix}" + resource_type = "CONSUMER_FOLDER" + } + + violation_notifications_enabled = true + lifecycle { + create_before_destroy = true + ignore_changes = [billing_account] + } +} + +module "no-compliance-folder" { + count = var.assured_workloads.regime == "COMPLIANCE_REGIME_UNSPECIFIED" ? 1 : 0 + source = "../../../modules/folder" + parent = "organizations/${var.organization.id}" + name = "${replace(lookup(var.regime_mapping, var.assured_workloads.regime, var.assured_workloads.regime), "_", " ")}-${var.prefix}" +} + +module "tenants-container-folders" { + source = "../../../modules/folder" + parent = "folders/${local.consumer_folder_id}" + name = "Tenants" +} + +module "branch-common-services-folder" { + source = "../../../modules/folder" + parent = var.assured_workloads.regime != "COMPLIANCE_REGIME_UNSPECIFIED" ? "folders/${local.consumer_folder_id}" : module.no-compliance-folder[0].folder.id + name = "${lookup(var.regime_mapping, var.assured_workloads.regime, var.assured_workloads.regime)} NetSec Services" +} + +module "shared-services-subfolder" { + source = "../../../modules/folder" + parent = module.branch-common-services-folder.folder.id + name = "Shared Services" +} + +module "netsec-shared-project" { + source = "../../../modules/project" + name = "${var.prefix}-shared-svc" + parent = module.shared-services-subfolder.id + billing_account = var.billing_account.id + + iam = { + "roles/serviceusage.serviceUsageAdmin" = [ + module.automation-tf-resman-sa.iam_email, + module.automation-tf-bootstrap-sa.iam_email + ] + "roles/owner" = [ + module.automation-tf-resman-sa.iam_email + ] + } + + services = [ + "compute.googleapis.com", + "logging.googleapis.com", + "monitoring.googleapis.com", + "servicenetworking.googleapis.com", + "networkconnectivity.googleapis.com" + ] + + org_policies = { + "compute.trustedImageProjects" = { + inherit_from_parent = true + rules = [ + { + allow = { + values = ["projects/cis-public"] + } + } + ] + } + } +} + +resource "google_folder_organization_policy" "il5_folder_compliance_enforcement" { + folder = local.consumer_folder_id + constraint = "constraints/gcp.restrictServiceUsage" + + list_policy { + allow { + values = local.compliance_api_baseline + } + } +} + +# Common Services folder with logging sink +module "common-services-folder-logging" { + count = length(local.all_log_buckets) > 0 ? 1 : 0 + source = "../../../modules/folder" + + # Use existing common services folder + folder_create = false + id = module.branch-common-services-folder.folder.id + + logging_sinks = { + for loc in local.locations.logging : + "${var.prefix}-common-services-logs-${loc}" => { + bq_partitioned_table = false + destination = module.aw-log-buckets["${var.prefix}-common-services-logs-${loc}"].id + filter = join(" OR ", [ + # The common services folder itself + "(resource.type=\"folder\" AND resource.labels.folder_id=\"${replace(module.branch-common-services-folder.folder.id, "folders/", "")}\")", + + # All projects under this folder (by parent relationship) + "(resource.type=\"project\" AND resource.labels.parent_id=\"${replace(module.branch-common-services-folder.folder.id, "folders/", "")}\")", + + # All resources within the common services folder hierarchy + "(protoPayload.resourceName:\"${module.branch-common-services-folder.folder.id}\" OR protoPayload.resourceName:\"${module.branch-common-services-folder.folder.id}/*\")" + ]) + type = "logging" + } + } + + depends_on = [ + module.branch-common-services-folder, + module.aw-log-buckets + ] +} + +module "organization" { + source = "../../../modules/organization-se" + organization_id = "organizations/${var.organization.id}" + prefix = var.prefix + # additive bindings, used for roles co-managed by different stages + iam_bindings_additive = merge( + local.org_iam_bindings_additive, + { + organization_iam_admin_conditional = { + member = module.automation-tf-resman-sa.iam_email + role = "organizations/${var.organization.id}/roles/organizationIamAdmin" + condition = { + expression = format( + "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])", + join(",", formatlist("'%s'", [ + "roles/accesscontextmanager.policyAdmin", + "roles/cloudasset.viewer", + "roles/compute.orgFirewallPolicyAdmin", + "roles/compute.xpnAdmin", + "roles/orgpolicy.policyAdmin", + "roles/orgpolicy.policyViewer", + "roles/resourcemanager.organizationViewer", + "organizations/${var.organization.id}/roles/tenantNetworkAdmin"])) + ) + title = "automation_sa_delegated_grants" + description = "Automation service account delegated grants." + } + } + }, + local.billing_mode != "org" ? {} : { + organization_billing_conditional = { + member = module.automation-tf-resman-sa.iam_email + role = "organizations/${var.organization.id}/roles/organizationIamAdmin" + condition = { + expression = format( + "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])", + join(",", formatlist("'%s'", [ + "roles/billing.admin", + "roles/billing.costsManager", + "roles/billing.user", + ])) + ) + title = "automation_sa_delegated_grants" + description = "Automation service account delegated grants." + } + } + } + ) + logging_sinks = merge({ + for name, attrs in var.log_sinks : + name => { + for loc in local.locations.logging : + "${name}-${loc}" => { + bq_partitioned_table = attrs.type == "bigquery" + destination = local.log_sink_destinations_all["${name}-${loc}"].id + filter = attrs.filter + type = attrs.type + } + } + } == {} ? {} : merge([ + for name, attrs in var.log_sinks : { + for loc in local.locations.logging : + "${name}-${loc}" => { + bq_partitioned_table = attrs.type == "bigquery" + destination = local.log_sink_destinations_all["${name}-${loc}"].id + filter = attrs.filter + type = attrs.type + } + } + ]...), + var.apply_tier_1_pubsub_sink ? { + "tier-1-audit-logs-sink" = { + bq_partitioned_table = false + destination = module.pubsub-topics.tier-1.id + description = "Tier 1 landing zone Audit logs logging sink for C5ISR logging." + filter = local.tier_1_audit_filter + exclusions = local.tenant_exclusions_map + include_children = true + type = "pubsub" + } + } : {} + ) +} + +module "top-level-folder" { + source = "../../../modules/folder" + folder_create = false + id = "folders/${var.top_level_folder.id}" + parent = "organizations/${var.organization.id}" + # additive bindings, used for roles co-managed by different stages + iam_bindings_additive = merge( + local.folder_iam_bindings_additive, + ) +} + +module "assured-workload-folder-log-sink" { + source = "../../../modules/folder" + folder_create = false + id = "folders/${local.consumer_folder_id}" + logging_sinks = { + "tier-1-vpc-flow-logs-sink" = { + bq_partitioned_table = false + destination = module.pubsub-topics.tier-1.id + description = "Tier 1 landing zone VPC Flow logs logging sink for C5ISR logging." + filter = local.tier_1_vpc_filter + exclusions = local.tenant_exclusions_map + include_children = true + type = "pubsub" + } + "tier-2-pubsub-logs-sink" = { + bq_partitioned_table = false + destination = module.pubsub-topics.tier-2.id + description = "Tier 2 landing zone logging sink for C5ISR logging." + filter = local.tier_2_filter + exclusions = local.tenant_exclusions_map + include_children = true + type = "pubsub" + }, + "tier-3-pubsub-logs-sink" = { + bq_partitioned_table = false + destination = module.pubsub-topics.tier-3.id + description = "Tier 3 landing zone logging sink for C5ISR logging." + filter = local.tier_3_filter + exclusions = local.tenant_exclusions_map + include_children = true + type = "pubsub" + } + } +} \ No newline at end of file diff --git a/fast/stages-aw/0-bootstrap/outputs-files.tf b/fast/stages-aw/1-assured-workload/outputs-files.tf similarity index 86% rename from fast/stages-aw/0-bootstrap/outputs-files.tf rename to fast/stages-aw/1-assured-workload/outputs-files.tf index 541b4a9fa..59e3a3fa1 100644 --- a/fast/stages-aw/0-bootstrap/outputs-files.tf +++ b/fast/stages-aw/1-assured-workload/outputs-files.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,33 +13,32 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Output files persistence to local filesystem. resource "local_file" "providers" { for_each = var.outputs_location == null ? {} : local.providers file_permission = "0644" - filename = "${try(pathexpand(var.outputs_location), "")}/providers/${each.key}-providers.tf" + filename = "${try(pathexpand(var.outputs_location), "")}/providers/${each.key}-providers-${var.prefix}.tf" content = try(each.value, null) } resource "local_file" "tfvars" { for_each = var.outputs_location == null ? {} : { 1 = 1 } file_permission = "0644" - filename = "${try(pathexpand(var.outputs_location), "")}/tfvars/0-bootstrap.auto.tfvars.json" + filename = "${try(pathexpand(var.outputs_location), "")}/tfvars/1-assured-workload-${var.prefix}.auto.tfvars.json" content = jsonencode(local.tfvars) } resource "local_file" "tfvars_globals" { for_each = var.outputs_location == null ? {} : { 1 = 1 } file_permission = "0644" - filename = "${try(pathexpand(var.outputs_location), "")}/tfvars/0-globals.auto.tfvars.json" + filename = "${try(pathexpand(var.outputs_location), "")}/tfvars/1-globals-${var.prefix}.auto.tfvars.json" content = jsonencode(local.tfvars_globals) } resource "local_file" "workflows" { for_each = var.outputs_location == null ? {} : local.cicd_workflows file_permission = "0644" - filename = "${try(pathexpand(var.outputs_location), "")}/workflows/${each.key}-workflow.yaml" + filename = "${try(pathexpand(var.outputs_location), "")}/workflows/${each.key}-workflow-${var.prefix}.yaml" content = try(each.value, null) } \ No newline at end of file diff --git a/fast/stages-aw/1-assured-workload/outputs-gcs.tf b/fast/stages-aw/1-assured-workload/outputs-gcs.tf new file mode 100644 index 000000000..d498ddf18 --- /dev/null +++ b/fast/stages-aw/1-assured-workload/outputs-gcs.tf @@ -0,0 +1,127 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# tfdoc:file:description Output files persistence to automation GCS bucket. + +resource "google_storage_bucket_object" "providers" { + for_each = local.providers + bucket = module.automation-tf-output-gcs.name + # provider suffix allows excluding via .gitignore when linked from stages + name = "providers/${each.key}-providers.tf" + content = each.value + # kms_key_name = module.gcs-kms.keys.gcs.id # may need to add back in +} + +resource "google_storage_bucket_object" "stage_1_folder_outputs" { + bucket = module.automation-tf-output-gcs.name + name = "tfvars/1-folder-ids.auto.tfvars.json" + content = jsonencode({ + # Creates 'dev' -> Dev (il5 AW) ' + root_folder_id = "folders/${local.consumer_folder_id}" + tenant_container_id = module.tenants-container-folders.folder.id + shdsvc_folder_id = module.branch-common-services-folder.folder.id + shared_services_project_id = module.netsec-shared-project.project_id + }) +} + +resource "google_storage_bucket_object" "tenant_outputs" { + bucket = module.automation-tf-output-gcs.name + name = "stage_1_tenant_outputs.json" + content = jsonencode({ + alert_email = var.alert_email + automation = { + config_bucket = length(google_storage_bucket_object.config_env) > 0 ? google_storage_bucket_object.config_env["config_env_object"].bucket : null + federated_identity_pool = try( + google_iam_workload_identity_pool.default[0].name, null + ) + federated_identity_providers = local.cicd_providers + inputs_bucket = module.automation-tf-inputs-gcs.name + outputs_bucket = module.automation-tf-output-gcs.name + project_id = module.automation-project.project_id + project_number = module.automation-project.number + tenant_bucket = module.automation-tf-tenant-gcs.name + service_accounts = { + bootstrap = module.automation-tf-bootstrap-sa.email + bootstrap-r = module.automation-tf-bootstrap-r-sa.email + resman = module.automation-tf-resman-sa.email + resman-r = module.automation-tf-resman-r-sa.email + tenant = module.automation-tf-tenants-sa.email + tenant-r = module.automation-tf-tenants-r-sa.email + } + } + billing_account = var.billing_account + groups = var.groups + locations = local.locations + logging = { + project_id = module.log-export-project.project_id + project_number = module.log-export-project.number + writer_identities = module.organization.sink_writer_identities + pubsub_topics = { for k, v in module.pubsub-topics : k => v.id } + service_accounts = { + c5isr-pubsub = module.logging-c5isr-pubsub-sa.email + } + } + organization = var.organization + prefix = var.prefix + regions = { + primary = element(var.locations.kms, 0) + secondary = slice(var.locations.kms, 1, length(var.locations.kms)) + } + tenants_folder_id = module.tenants-container-folders.folder.id + }) +} + +resource "google_storage_bucket_object" "tenant_config_vars" { + bucket = module.automation-tf-output-gcs.name + name = "tfvars/1-tenant-names.auto.tfvars.json" + content = jsonencode({ + tenant_envs = local.tenant_envs + }) +} + +resource "google_storage_bucket_object" "tfvars" { + bucket = module.automation-tf-output-gcs.name + name = "tfvars/1-assured-workload.auto.tfvars.json" + content = jsonencode(local.tfvars) + # kms_key_name = module.gcs-kms.keys.gcs.id # may need to add back in +} + +resource "google_storage_bucket_object" "tfvars_globals" { + bucket = module.automation-tf-output-gcs.name + name = "tfvars/1-globals.auto.tfvars.json" + content = jsonencode(local.tfvars_globals) + # kms_key_name = module.gcs-kms.keys.gcs.id # may need to add back in +} + +resource "google_storage_bucket_object" "workflows" { + for_each = local.cicd_workflows + bucket = module.automation-tf-output-gcs.name + name = "workflows/${each.key}-workflow.yaml" + content = each.value + # kms_key_name = module.gcs-kms.keys.gcs.id # may need to add back in +} + +resource "google_storage_bucket_object" "input_tfvars" { + bucket = module.automation-tf-inputs-gcs.name + name = "stage-1/stage-1-inputs.auto.tfvars.json" + content = local.tfvars_content +} + +resource "google_storage_bucket_object" "config_env" { + for_each = local.config_env_bucket + bucket = each.value.bucket_name + name = each.value.object_name + source = each.value.source_path +} \ No newline at end of file diff --git a/fast/stages-aw/0-bootstrap/outputs.tf b/fast/stages-aw/1-assured-workload/outputs.tf similarity index 56% rename from fast/stages-aw/0-bootstrap/outputs.tf rename to fast/stages-aw/1-assured-workload/outputs.tf index 65e78a98c..b79a8b57e 100644 --- a/fast/stages-aw/0-bootstrap/outputs.tf +++ b/fast/stages-aw/1-assured-workload/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _tpl_providers = "${path.module}/templates/providers.tf.tpl" # render CI/CD workflow templates @@ -42,83 +41,114 @@ locals { } ) } + custom_roles_map = { + for id, role in data.google_iam_role.custom_iam_roles : + lower(replace(id, "/([A-Z])/", "_$1")) => role.name + } providers = { - "0-bootstrap" = templatefile(local._tpl_providers, { - backend_extra = null - bucket = module.automation-tf-bootstrap-gcs.name - name = "bootstrap" - sa = module.automation-tf-bootstrap-sa.email - bootstrap_project = var.bootstrap_project + "1-assured-workload" = templatefile(local._tpl_providers, { + backend_extra = null + bucket = module.automation-tf-bootstrap-gcs.name + name = "assured workload bootstrap" + sa = module.automation-tf-bootstrap-sa.email }) - "0-bootstrap-r" = templatefile(local._tpl_providers, { - backend_extra = null - bucket = module.automation-tf-bootstrap-gcs.name - name = "bootstrap" - sa = module.automation-tf-bootstrap-r-sa.email - bootstrap_project = var.bootstrap_project + "1-assured-workload-r" = templatefile(local._tpl_providers, { + backend_extra = null + bucket = module.automation-tf-bootstrap-gcs.name + name = "assured workload bootstrap" + sa = module.automation-tf-bootstrap-r-sa.email }) - "1-resman" = templatefile(local._tpl_providers, { - backend_extra = null - bucket = module.automation-tf-resman-gcs.name - name = "resman" - sa = module.automation-tf-resman-sa.email - bootstrap_project = var.bootstrap_project + "2-resman" = templatefile(local._tpl_providers, { + backend_extra = null + bucket = module.automation-tf-resman-gcs.name + name = "resman" + sa = module.automation-tf-resman-sa.email }) - "1-resman-r" = templatefile(local._tpl_providers, { - backend_extra = null - bucket = module.automation-tf-resman-gcs.name - name = "resman" - sa = module.automation-tf-resman-r-sa.email - bootstrap_project = var.bootstrap_project + "2-resman-r" = templatefile(local._tpl_providers, { + backend_extra = null + bucket = module.automation-tf-resman-gcs.name + name = "resman" + sa = module.automation-tf-resman-r-sa.email }) - "0-bootstrap-tenant" = templatefile(local._tpl_providers, { + "1-assured-workload-tenant" = templatefile(local._tpl_providers, { backend_extra = join("\n", [ "# remove the newline between quotes and set the tenant name as prefix", "prefix = \"", "\"" ]) - bucket = module.automation-tf-resman-gcs.name - name = "bootstrap-tenant" - sa = module.automation-tf-resman-sa.email - bootstrap_project = var.bootstrap_project + bucket = module.automation-tf-resman-gcs.name + name = "bootstrap-tenant" + sa = module.automation-tf-resman-sa.email }) } tfvars = { alert_email = var.alert_email automation = { + config_bucket = length(google_storage_bucket_object.config_env) > 0 ? google_storage_bucket_object.config_env["config_env_object"].bucket : null federated_identity_pool = try( google_iam_workload_identity_pool.default[0].name, null ) federated_identity_providers = local.cicd_providers + inputs_bucket = module.automation-tf-inputs-gcs.name outputs_bucket = module.automation-tf-output-gcs.name project_id = module.automation-project.project_id project_number = module.automation-project.number + tenant_bucket = module.automation-tf-tenant-gcs.name service_accounts = { bootstrap = module.automation-tf-bootstrap-sa.email bootstrap-r = module.automation-tf-bootstrap-r-sa.email resman = module.automation-tf-resman-sa.email resman-r = module.automation-tf-resman-r-sa.email + tenant = module.automation-tf-tenants-sa.email + tenant-r = module.automation-tf-tenants-r-sa.email } } - custom_roles = module.organization.custom_role_id + custom_roles = local.custom_roles_map + regime_label = replace(var.assured_workloads.regime, "_", " ") + logging = { project_id = module.log-export-project.project_id project_number = module.log-export-project.number writer_identities = module.organization.sink_writer_identities + pubsub_topics = { for k, v in module.pubsub-topics : k => v.id } + service_accounts = { + c5isr-pubsub = module.logging-c5isr-pubsub-sa.email + } + } + assured_workloads = merge(var.assured_workloads, { "folder" = "folders/${local.consumer_folder_id}" }) + tenants_folder_id = module.tenants-container-folders.folder.id + common_services_folder = module.branch-common-services-folder.folder.name + shared_services_project_id = module.netsec-shared-project.project_id + regions = { + primary = element(var.locations.kms, 0) + secondary = slice(var.locations.kms, 1, length(var.locations.kms)) } - assured_workloads = merge(var.assured_workloads, { "folder" = var.assured_workloads.regime != "COMPLIANCE_REGIME_UNSPECIFIED" ? "folders/${google_assured_workloads_workload.primary[0].resources[0].resource_id}" : "${module.no-compliance-folder[0].folder.id}" }) - common_services_folder = module.branch-common-services-folder.folder.name - regions = var.regions } tfvars_globals = { - billing_account = var.billing_account - fast_features = var.fast_features - groups = local.principals - organization = var.organization - prefix = var.prefix - regime_mapping = var.regime_mapping + billing_account = var.billing_account + fast_features = var.fast_features + groups = local.principals + locations = local.locations + organization = var.organization + prefix = var.prefix + regime_mapping = var.regime_mapping + top_level_folder = var.top_level_folder } + + inputs_tfvars = { + billing_account = var.billing_account + locations = var.locations + organization = var.organization + outputs_location = var.outputs_location + prefix = var.prefix + fast_features = var.fast_features + assured_workloads = var.assured_workloads + bootstrap_project = var.bootstrap_project + alert_email = var.alert_email + top_level_folder = var.top_level_folder + } + tfvars_content = jsonencode(local.inputs_tfvars) } output "alert_email" { @@ -128,7 +158,7 @@ output "alert_email" { output "assured_workload" { description = "Assured Workload folder for the deployment." - value = var.assured_workloads.regime != "COMPLIANCE_REGIME_UNSPECIFIED" ? "folders/${google_assured_workloads_workload.primary[0].resources[0].resource_id}" : "folders/${module.no-compliance-folder[0].folder.id}" + value = "folders/${local.consumer_folder_id}" } output "automation" { @@ -136,6 +166,11 @@ output "automation" { value = local.tfvars.automation } +output "automation_project_id" { + description = "The ID of the IaC Core project." + value = module.automation-project.project_id +} + output "billing_dataset" { description = "BigQuery dataset prepared for billing export." value = try(module.billing-export-dataset[0].id, null) @@ -160,7 +195,12 @@ output "common_services_folder" { output "custom_roles" { description = "Organization-level custom roles." - value = module.organization.custom_role_id + value = local.custom_roles_map +} + +output "folder_ids" { + description = "The Assured Workloads Folder i.e. DEV (IL5 AW)." + value = "folders/${local.consumer_folder_id}" } output "outputs_bucket" { @@ -185,14 +225,27 @@ output "providers" { value = local.providers } +output "pubsub-topics-id" { + description = "Pubsub topics used for C5ISR logging." + value = { + for k, v in module.pubsub-topics : k => v.id + } +} + output "service_accounts" { description = "Automation service accounts created by this stage." value = { bootstrap = module.automation-tf-bootstrap-sa.email resman = module.automation-tf-resman-sa.email + tenant = module.automation-tf-tenants-sa.email } } +output "shared_services_project_id" { + description = "Project ID for NetSec Shared Services." + value = module.netsec-shared-project.project_id +} + # output "test" { # value = { # checklist = local.checklist @@ -202,22 +255,17 @@ output "service_accounts" { # } # } -# ready to use variable values for subsequent stages +output "tenants_container_ids" { + description = "Folder IDs for the 'Tenants' sub-folders where tenant projects will live." + value = module.tenants-container-folders.folder.id +} + output "tfvars" { description = "Terraform variable files for the following stages." sensitive = true value = local.tfvars } -output "workforce_identity_pool" { - description = "Workforce Identity Federation pool." - value = { - pool = try( - google_iam_workforce_pool.default[0].name, null - ) - } -} - output "workload_identity_pool" { description = "Workload Identity Federation pool and providers." value = { diff --git a/fast/stages-aw/1-assured-workload/providers.tf.tmp b/fast/stages-aw/1-assured-workload/providers.tf.tmp new file mode 100644 index 000000000..c597fd227 --- /dev/null +++ b/fast/stages-aw/1-assured-workload/providers.tf.tmp @@ -0,0 +1,12 @@ +# Required for Assured Workloads +provider "google" { + project = var.bootstrap_project + billing_project = var.bootstrap_project + user_project_override = true +} + +provider "google-beta" { + project = var.bootstrap_project + billing_project = var.bootstrap_project + user_project_override = true +} \ No newline at end of file diff --git a/fast/stages-aw/1-resman/templates/providers.tf.tpl b/fast/stages-aw/1-assured-workload/templates/providers.tf.tpl similarity index 52% rename from fast/stages-aw/1-resman/templates/providers.tf.tpl rename to fast/stages-aw/1-assured-workload/templates/providers.tf.tpl index 65491ce50..d1c224c5c 100644 --- a/fast/stages-aw/1-resman/templates/providers.tf.tpl +++ b/fast/stages-aw/1-assured-workload/templates/providers.tf.tpl @@ -30,22 +30,4 @@ provider "google-beta" { impersonate_service_account = "${sa}" } -%{~ if try(bootstrap_project, null) != null ~} -# Billing-specific providers (Conditional Impersonation) -provider "google" { - alias = "billing" - impersonate_service_account = try(var.billing_override, null) != null ? null : "${sa}" - project = try(var.billing_override.project, "${bootstrap_project}") - billing_project = try(var.billing_override.billing_project, "${bootstrap_project}") - user_project_override = true -} -provider "google-beta" { - alias = "billing" - impersonate_service_account = try(var.billing_override, null) != null ? null : "${sa}" - project = try(var.billing_override.project, "${bootstrap_project}") - billing_project = try(var.billing_override.billing_project, "${bootstrap_project}") - user_project_override = true -} -%{~ endif ~} - # end provider.tf for ${name} diff --git a/fast/stages-aw/1-resman/templates/workflow-github.yaml b/fast/stages-aw/1-assured-workload/templates/workflow-github.yaml similarity index 98% rename from fast/stages-aw/1-resman/templates/workflow-github.yaml rename to fast/stages-aw/1-assured-workload/templates/workflow-github.yaml index 70ccfc50f..f6aa53cd7 100644 --- a/fast/stages-aw/1-resman/templates/workflow-github.yaml +++ b/fast/stages-aw/1-assured-workload/templates/workflow-github.yaml @@ -1,10 +1,10 @@ -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + name: "FAST ${stage_name} stage" on: diff --git a/fast/stages-aw/0-bootstrap/templates/workflow-gitlab.yaml b/fast/stages-aw/1-assured-workload/templates/workflow-gitlab.yaml similarity index 93% rename from fast/stages-aw/0-bootstrap/templates/workflow-gitlab.yaml rename to fast/stages-aw/1-assured-workload/templates/workflow-gitlab.yaml index c50f8e58e..289cbcd34 100644 --- a/fast/stages-aw/0-bootstrap/templates/workflow-gitlab.yaml +++ b/fast/stages-aw/1-assured-workload/templates/workflow-gitlab.yaml @@ -1,10 +1,10 @@ -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + variables: GOOGLE_CREDENTIALS: cicd-sa-credentials.json FAST_OUTPUTS_BUCKET: ${outputs_bucket} @@ -28,13 +29,13 @@ workflow: variables: COMMAND: apply FAST_SERVICE_ACCOUNT: ${service_accounts.apply} - TF_PROVIDERS_FILE: 0-bootstrap-providers.tf + TF_PROVIDERS_FILE: 1-assured-workload-providers.tf # pr / plan - if: $CI_PIPELINE_SOURCE == 'merge_request_event' variables: COMMAND: plan FAST_SERVICE_ACCOUNT: ${service_accounts.plan} - TF_PROVIDERS_FILE: 0-bootstrap-r-providers.tf + TF_PROVIDERS_FILE: 1-assured-workload-r-providers.tf stages: - gcp-setup diff --git a/fast/stages-aw/0-bootstrap/templates/workflow-sourcerepo.yaml b/fast/stages-aw/1-assured-workload/templates/workflow-sourcerepo.yaml similarity index 97% rename from fast/stages-aw/0-bootstrap/templates/workflow-sourcerepo.yaml rename to fast/stages-aw/1-assured-workload/templates/workflow-sourcerepo.yaml index 012ff93e7..fe3cea3f8 100644 --- a/fast/stages-aw/0-bootstrap/templates/workflow-sourcerepo.yaml +++ b/fast/stages-aw/1-assured-workload/templates/workflow-sourcerepo.yaml @@ -1,10 +1,10 @@ -# Copyright 2024 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + steps: - name: alpine:3 id: tf-download diff --git a/fast/stages-aw/1-assured-workload/terraform.tfvars.sample b/fast/stages-aw/1-assured-workload/terraform.tfvars.sample new file mode 100644 index 000000000..77dcc8c42 --- /dev/null +++ b/fast/stages-aw/1-assured-workload/terraform.tfvars.sample @@ -0,0 +1,92 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +# use `gcloud beta billing accounts list` +# if you have too many accounts, check the Cloud Console :) +billing_account = { + id = "012345-67890A-BCDEF0" +} + +# locations for GCS, BigQuery, KMS, and logging buckets created here +locations = { + bq = "us-east4" + gcs = "us-east4" + logging = "us-east4" + pubsub = ["us-east4"] + kms = "us-east4" +} + +# use `gcloud organizations list` +organization = { + domain = "example.org" + id = 1234567890 + customer_id = "C000001" +} + +outputs_location = "~/fast-config" + +# use something unique and no longer than 9 characters +prefix = "abcd" +# CIS Compliance Benchmark 2.2 +log_sinks = { + “prefix-compliance-regime-audit-log” = { + filter = "" + type = "logging" + } +} + +fast_features = { + envs = true +} + +assured_workloads = { + regime = "compliance-regime" #"IL4, IL5, FEDRAMP_HIGH, etc... if you wish to not use assured_workloads, set this value to COMPLIANCE_REGIME_UNSPECIFIED" + location = "us-east4" +} + +bootstrap_project = "bootstrap-project-name" + +alert_email = "user@domain.com" + +top_level_folder = { + name = "Top_level_folder_name" #replace with given folder name + id = "123456788" #replace with given folder id +} + +workload_identity_providers = { + gitlab-fed = { + issuer = "gitlab" + custom_settings = { + issuer_uri = "https://github.com" + audiences = ["https://github.com"] + } + } +} + +cicd_repositories = { + bootstrap = { + name = "google-cloud/project" + type = "gitlab" + identity_provider = "gitlab-fed" + branch = "main" + } + resman = { + name = "google-cloud/project" + type = "gitlab" + identity_provider = "gitlab-fed" + branch = "main" + } +} \ No newline at end of file diff --git a/fast/stages-aw/0-bootstrap/variables.tf b/fast/stages-aw/1-assured-workload/variables.tf similarity index 62% rename from fast/stages-aw/0-bootstrap/variables.tf rename to fast/stages-aw/1-assured-workload/variables.tf index d1c279608..10a817149 100644 --- a/fast/stages-aw/0-bootstrap/variables.tf +++ b/fast/stages-aw/1-assured-workload/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,13 @@ variable "alert_email" { type = string } +variable "apply_tier_1_pubsub_sink" { + description = "Toggles whether to apply org tier-1 pubsub sink." + type = bool + nullable = false + default = true +} + variable "assured_workloads" { description = "Configuration for Assured Workloads." type = object({ @@ -41,15 +48,6 @@ variable "billing_account" { nullable = false } -variable "billing_budget_amount" { - description = "Optional Budget configuration for the AW folder. Includes amount and optional threshold rules (defaults to 0.5, 0.75, 0.9). If null, no budget will be created." - type = object({ - amount = number - threshold_rules = optional(list(number), [0.5, 0.75, 0.9]) - }) - default = null -} - variable "bootstrap_project" { description = "Bootstrap project ID." type = string @@ -76,6 +74,12 @@ variable "cicd_repositories" { branch = optional(string) identity_provider = optional(string) })) + tenant = optional(object({ + name = string + type = string + branch = optional(string) + identity_provider = optional(string) + })) }) default = null validation { @@ -107,13 +111,6 @@ variable "cicd_repositories" { } } -variable "custom_roles" { - description = "Map of role names => list of permissions to additionally create at the organization level." - type = map(list(string)) - nullable = false - default = {} -} - variable "essential_contacts" { description = "Email used for essential contacts, unset if null." type = string @@ -147,101 +144,79 @@ variable "fast_features" { nullable = false } +variable "gcp_billing_admins_group" { + description = "GCP Billing Admins group name." + type = string + default = "gcp-billing-admins" +} + +variable "gcp_devops_group" { + description = "GCP DevOps group name." + type = string + default = "gcp-devops" +} + +variable "gcp_organization_admins_group" { + description = "GCP Organization Admins group name." + type = string + default = "gcp-organization-admins" +} + +variable "gcp_security_admins_group" { + description = "GCP Security Admins group name." + type = string + default = "gcp-security-admins" +} + +variable "gcp_support_group" { + description = "GCP Support group name." + type = string + default = null +} + +variable "gcp_vpc_network_admins_group" { + description = "GCP VPC Network Admins group name." + type = string + default = "gcp-vpc-network-admins" +} + variable "groups" { # https://cloud.google.com/docs/enterprise/setup-checklist description = "Group names or IAM-format principals to grant organization-level permissions. If just the name is provided, the 'group:' principal and organization domain are interpolated." type = object({ - gcp-billing-admins = optional(string, "gcp-billing-admins") - gcp-devops = optional(string, "gcp-devops") - gcp-vpc-network-admins = optional(string, "gcp-vpc-network-admins") - gcp-organization-admins = optional(string, "gcp-organization-admins") - gcp-security-admins = optional(string, "gcp-security-admins") + gcp-billing-admins = optional(string) + gcp-devops = optional(string) + gcp-vpc-network-admins = optional(string) + gcp-organization-admins = optional(string) + gcp-security-admins = optional(string) # aliased to gcp-devops as the checklist does not create it - gcp-support = optional(string, "gcp-devops") + gcp-support = optional(string) }) nullable = false default = {} } -variable "iam" { - description = "Organization-level custom IAM settings in role => [principal] format." - type = map(list(string)) - nullable = false - default = {} -} - -variable "iam_bindings_additive" { - description = "Organization-level custom additive IAM bindings. Keys are arbitrary." - type = map(object({ - member = string - role = string - condition = optional(object({ - expression = string - title = string - description = optional(string) - })) - })) - nullable = false - default = {} -} - -variable "iam_by_principals" { - description = "Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid cycle errors. Merged internally with the `iam` variable." - type = map(list(string)) - default = {} - nullable = false -} - variable "locations" { description = "Optional locations for GCS, BigQuery, and logging buckets created here." type = object({ bq = optional(string, "US") - gcs = optional(string, "US") - logging = optional(string, "global") + gcs = optional(list(string), ["US"]) + logging = optional(list(string), ["global"]) pubsub = optional(list(string), []) - kms = optional(string, "US") + kms = optional(list(string), ["US"]) }) nullable = false default = {} } -# See https://cloud.google.com/architecture/exporting-stackdriver-logging-for-security-and-access-analytics -# for additional logging filter examples - variable "log_sinks" { - description = "Org-level log sinks, in name => {type, filter} format. Valid types: 'logging' (routes to Cloud Logging bucket with 365-day default retention), 'pubsub' (routes to Pub/Sub topic with 7-day default retention; requires an active consumer to avoid log loss), 'storage' (routes to GCS bucket), 'bigquery' (routes to BigQuery dataset)." + description = "Organization-level log sinks configuration." type = map(object({ filter = string type = string })) - default = { - - audit-logs = { - filter = "logName:\"/logs/cloudaudit.googleapis.com%2Factivity\" OR logName:\"/logs/cloudaudit.googleapis.com%2Fsystem_event\" OR protoPayload.metadata.@type=\"type.googleapis.com/google.cloud.audit.TransparencyLog\"" - type = "logging" - } - vpc-sc = { - filter = "protoPayload.metadata.@type=\"type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata\"" - type = "logging" - } - workspace-audit-logs = { - filter = "logName:\"/logs/cloudaudit.googleapis.com%2Fdata_access\" and protoPayload.serviceName:\"login.googleapis.com\"" - type = "logging" - } - - # CIS Compliance Benchmark 2.2 - empty-audit-logs = { - filter = "" - type = "logging" - } - } - validation { - condition = alltrue([ - for k, v in var.log_sinks : - contains(["bigquery", "logging", "pubsub", "storage"], v.type) - ]) - error_message = "Type must be one of 'bigquery', 'logging', 'pubsub', 'storage'." - } + nullable = false + default = {} } variable "logging_kms_key" { @@ -250,29 +225,6 @@ variable "logging_kms_key" { default = null } -variable "logging_bucket_retention" { - description = "Retention period (in days) for the Cloud Logging buckets created for organization log exports." - type = number - default = 365 -} - -variable "org_policies_config" { - description = "Organization policies customization." - type = object({ - constraints = optional(object({ - allowed_policy_member_domains = optional(list(string), []) - }), {}) - import_defaults = optional(bool, false) - tag_name = optional(string, "org-policies") - tag_values = optional(map(object({ - description = optional(string, "Managed by the Terraform organization module.") - iam = optional(map(list(string)), {}) - id = optional(string) - })), {}) - }) - default = {} -} - variable "organization" { description = "Organization details." type = object({ @@ -292,7 +244,7 @@ variable "prefix" { description = "Prefix used for resources that need unique names. Use 9 characters or less." type = string validation { - condition = try(length(var.prefix), 0) <= 7 + condition = try(length(var.prefix), 0) <= 10 error_message = "Use a maximum of 7 characters for prefix." } } @@ -308,17 +260,6 @@ variable "project_parent_ids" { nullable = false } -variable "regions" { - description = "Region definitions. Must be specified in terraform.tfvars. Example: us-east4 for FedRAMP High compliance." - type = object({ - primary = string - }) - nullable = false - default = { - primary = "us-east4" - } -} - variable "regime_mapping" { description = "Mapping of compliance regime names to short codes." type = map(string) @@ -352,11 +293,16 @@ variable "regime_mapping" { } } +variable "top_level_folder" { + description = "Top Level Folder Details." + type = object({ + name = string + id = string + }) +} - - -variable "federated_identity_providers" { - description = "Workload Identity Federation providers." +variable "workload_identity_providers" { + description = "Workload Identity Federation pools. The `cicd_repositories` variable references keys here." type = map(object({ attribute_condition = optional(string) issuer = string @@ -365,20 +311,12 @@ variable "federated_identity_providers" { audiences = optional(list(string), []) jwks_json = optional(string) }), {}) - attribute_mapping = optional(map(string)) - audiences = optional(list(string)) })) default = {} nullable = false -} - -variable "workforce_identity_pool" { - description = "Workforce Identity Federation pool configuration." - type = object({ - display_name = optional(string) - description = optional(string) - disabled = optional(bool, false) - session_duration = optional(string) - }) - default = null + # TODO: fix validation + # validation { + # condition = var.federated_identity_providers.custom_settings == null + # error_message = "Custom settings cannot be null." + # } } diff --git a/fast/stages-aw/1-resman/branch-envs.tf b/fast/stages-aw/1-resman/branch-envs.tf deleted file mode 100644 index 89dc86d23..000000000 --- a/fast/stages-aw/1-resman/branch-envs.tf +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright 2024 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -# tfdoc:file:description Team stage resources. - -locals { - # FAST-specific IAM - _envs_folder_fast_iam = !var.fast_features.envs ? {} : { - "roles/logging.admin" = [module.branch-envs-sa[0].iam_email] - "roles/owner" = [module.branch-envs-sa[0].iam_email] - "roles/resourcemanager.folderAdmin" = [module.branch-envs-sa[0].iam_email] - "roles/resourcemanager.projectCreator" = [module.branch-envs-sa[0].iam_email] - "roles/compute.xpnAdmin" = [module.branch-envs-sa[0].iam_email] - } - # deep-merge FAST-specific IAM with user-provided bindings in var.folder_iam - _envs_folder_iam = merge( - var.folder_iam.envs, - { - for role, principals in local._envs_folder_fast_iam : - role => distinct(concat(principals, lookup(var.folder_iam.envs, role, []))) - } - ) -} - -module "branch-envs-folders" { - source = "../../../modules/folder" - for_each = var.envs_folders - parent = var.assured_workloads.folder - name = "${lookup(var.regime_mapping, var.assured_workloads.regime, var.assured_workloads.regime)} ${each.key}" - iam = local._envs_folder_iam - tag_bindings = null -} - -module "branch-envs-sa" { - source = "../../../modules/iam-service-account" - count = var.fast_features.envs ? 1 : 0 - project_id = var.automation.project_id - name = "prod-resman-envs-0" - display_name = "Terraform resman envs service account." - prefix = var.prefix - iam_project_roles = { - (var.automation.project_id) = ["roles/serviceusage.serviceUsageConsumer"] - } - iam_storage_roles = { - (var.automation.outputs_bucket) = ["roles/storage.objectAdmin"] - } -} diff --git a/fast/stages-aw/1-resman/branch-tenants.tf b/fast/stages-aw/1-resman/branch-tenants.tf deleted file mode 100644 index 8b3627c73..000000000 --- a/fast/stages-aw/1-resman/branch-tenants.tf +++ /dev/null @@ -1,344 +0,0 @@ -# /** -# * Copyright 2024 Google LLC -# * -# * Licensed under the Apache License, Version 2.0 (the "License"); -# * you may not use this file except in compliance with the License. -# * You may obtain a copy of the License at -# * -# * http://www.apache.org/licenses/LICENSE-2.0 -# * -# * Unless required by applicable law or agreed to in writing, software -# * distributed under the License is distributed on an "AS IS" BASIS, -# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# * See the License for the specific language governing permissions and -# * limitations under the License. -# */ - -# # tfdoc:file:description Lightweight tenant resources. - - -locals { - tenant_iam = { - for k, v in local.tenant_envs : k => [ - v.tenant_info.admin_principal, - module.tenant-self-iac-sa[k].iam_email - ] - } - gcs_locations = { for k, v in var.tenants : k => try(v.locations.gcs != "", false) ? v.locations.gcs : var.regions.primary } - tenant_envs = merge([for e, _ in var.envs_folders : { - for t, v in var.tenants : "${e}-${t}" => { - env = e - tenant = t - tenant_info = v - } - } - ]...) -} - -# Tenant folders (top, core, self) -module "tenant-top-folders" { - source = "../../../modules/folder" - for_each = local.tenant_envs - parent = module.branch-envs-folders[each.value.env].id - name = "Project ${each.value.tenant} ${each.value.env}" - iam_by_principals = { - (each.value.tenant_info.admin_principal) = ["roles/browser"] - } -} - -module "tenant-top-folders-iam" { - source = "../../../modules/folder" - for_each = local.tenant_envs - id = module.tenant-top-folders[each.key].id - folder_create = false - tag_bindings = null - iam = merge( - { - "roles/cloudasset.owner" = [module.tenant-core-sa[each.key].iam_email] - "roles/compute.xpnAdmin" = [module.tenant-core-sa[each.key].iam_email] - "roles/logging.admin" = [module.tenant-core-sa[each.key].iam_email] - "roles/resourcemanager.folderAdmin" = [module.tenant-core-sa[each.key].iam_email] - "roles/resourcemanager.projectCreator" = [module.tenant-core-sa[each.key].iam_email] - "roles/resourcemanager.tagUser" = [module.tenant-core-sa[each.key].iam_email] - }, - { - for k in var.tenants_config.top_folder_roles : - k => local.tenant_iam[each.value.tenant.name] - } - ) -} - -module "tenant-core-folders-iam" { - source = "../../../modules/folder" - for_each = local.tenant_envs - id = module.tenant-top-folders[each.key].id - folder_create = false - iam = merge( - { - "roles/owner" = [ - module.tenant-core-sa[each.key].iam_email - ] - "roles/viewer" = local.tenant_iam[each.key] - }, - { - for k in var.tenants_config.core_folder_roles : - k => local.tenant_iam[each.key] - } - ) -} - -module "tenant-self-folders-iam" { - source = "../../../modules/folder" - for_each = local.tenant_envs - id = module.tenant-top-folders[each.key].id - folder_create = false - iam = merge( - { - "roles/cloudasset.owner" = [module.tenant-core-sa[each.key].iam_email] - "roles/compute.xpnAdmin" = [module.tenant-core-sa[each.key].iam_email] - "roles/resourcemanager.folderAdmin" = [module.tenant-core-sa[each.key].iam_email] - "roles/resourcemanager.projectCreator" = [module.tenant-core-sa[each.key].iam_email] - "roles/resourcemanager.tagUser" = [module.tenant-core-sa[each.key].iam_email] - "roles/owner" = [module.tenant-core-sa[each.key].iam_email] - }, - { - for k in var.tenants_config.tenant_folder_roles : - k => local.tenant_iam[each.key] - } - ) -} - -# Tenant IaC resources (core) - -module "tenant-core-sa" { - source = "../../../modules/iam-service-account" - for_each = local.tenant_envs - project_id = var.automation.project_id - name = lower("tn-${each.key}-prod-0") - description = "Terraform service account for tenant ${each.key}." - prefix = var.prefix - iam_project_roles = { - (var.automation.project_id) = ["roles/serviceusage.serviceUsageConsumer"] - } -} - -module "tenant-core-gcs" { - source = "../../../modules/gcs" - for_each = local.tenant_envs - project_id = var.automation.project_id - name = lower("tn-${each.key}-0") - prefix = var.prefix - versioning = true - force_destroy = true - location = local.gcs_locations[each.value.tenant] - storage_class = ( - length(split("-", local.gcs_locations[each.value.tenant])) < 2 - ? "MULTI_REGIONAL" - : "REGIONAL" - ) - encryption_key = module.tenant-project-keys[each.key].key_ids["gcs"] - depends_on = [module.tenant-project-keys, google_kms_crypto_key_iam_member.tenant_kms] - iam = { - "roles/storage.objectAdmin" = [module.tenant-core-sa[each.key].iam_email] - } -} - -# Tenant IaC project and resources (self) -module "tenant-self-iac-projects" { - source = "../../../modules/project" - for_each = local.tenant_envs - providers = { - google = google.billing - google-beta = google-beta.billing - } - billing_account = ( - each.value.tenant_info.billing_account != null - ? each.value.tenant_info.billing_account - : var.billing_account.id - ) - name = lower("${each.key}-iac-core-0") - parent = module.tenant-top-folders[each.key].id - prefix = var.prefix - iam_by_principals = { - (each.value.tenant_info.admin_principal) = [ - "roles/iam.serviceAccountAdmin", - "roles/iam.serviceAccountTokenCreator", - "roles/iam.workloadIdentityPoolAdmin" - ] - } - iam = { - # Expected that the service account will have owner permissions on the project it - # creates this role will be removed during stage 3 when sa-lockdown-runs. - # This iam simply reaffirms the permissions resman should already have. - "roles/owner" = [ - "serviceAccount:${var.automation.service_accounts.resman}" - ] - (var.custom_roles.storage_viewer) = [ - "serviceAccount:${var.automation.service_accounts.resman-r}" - ] - "roles/viewer" = [ - "serviceAccount:${var.automation.service_accounts.resman-r}" - ] - } - services = [ - "accesscontextmanager.googleapis.com", - "bigquery.googleapis.com", - "bigqueryreservation.googleapis.com", - "bigquerystorage.googleapis.com", - "billingbudgets.googleapis.com", - "cloudbilling.googleapis.com", - "cloudbuild.googleapis.com", - "cloudkms.googleapis.com", - "cloudresourcemanager.googleapis.com", - "container.googleapis.com", - "compute.googleapis.com", - "container.googleapis.com", - "essentialcontacts.googleapis.com", - "iam.googleapis.com", - "iamcredentials.googleapis.com", - "orgpolicy.googleapis.com", - "pubsub.googleapis.com", - "servicenetworking.googleapis.com", - "serviceusage.googleapis.com", - "stackdriver.googleapis.com", - "storage-component.googleapis.com", - "storage.googleapis.com", - "sts.googleapis.com" - ] -} - -module "tenant-self-iac-gcs-outputs" { - source = "../../../modules/gcs" - for_each = local.tenant_envs - project_id = module.tenant-self-iac-projects[each.key].project_id - location = local.gcs_locations[each.value.tenant] - storage_class = ( - length(split("-", local.gcs_locations[each.value.tenant])) < 2 - ? "MULTI_REGIONAL" - : "REGIONAL" - ) - name = "${each.key}-iac-outputs-0" - prefix = var.prefix - versioning = true - force_destroy = true - iam = { - "roles/storage.objectAdmin" = [module.tenant-core-sa[each.key].iam_email] - } - encryption_key = module.tenant-project-keys[each.key].key_ids["gcs"] - depends_on = [module.tenant-project-keys, google_kms_crypto_key_iam_member.tenant_kms] - -} - -module "tenant-self-iac-gcs-states" { - source = "../../../modules/gcs" - for_each = local.tenant_envs - project_id = module.tenant-self-iac-projects[each.key].project_id - location = local.gcs_locations[each.value.tenant] - storage_class = ( - length(split("-", local.gcs_locations[each.value.tenant])) < 2 - ? "MULTI_REGIONAL" - : "REGIONAL" - ) - name = "${each.key}-iac-0" - prefix = var.prefix - versioning = true - force_destroy = true - encryption_key = module.tenant-project-keys[each.key].key_ids["gcs"] - depends_on = [module.tenant-project-keys, google_kms_crypto_key_iam_member.tenant_kms] -} - -module "tenant-self-iac-sa" { - source = "../../../modules/iam-service-account" - for_each = local.tenant_envs - project_id = module.tenant-self-iac-projects[each.key].project_id - name = lower("${each.key}-iac-0") - description = "Terraform automation service account." - prefix = var.prefix - iam_storage_roles = { - (module.tenant-self-iac-gcs-outputs[each.key].name) = [ - "roles/storage.admin" - ] - (module.tenant-self-iac-gcs-states[each.key].name) = [ - "roles/storage.admin" - ] - } -} - -# Tenant main project and resources (self) -module "tenant-self-main-projects" { - source = "../../../modules/project" - for_each = local.tenant_envs - providers = { - google = google.billing - google-beta = google-beta.billing - } - billing_account = ( - each.value.tenant_info.billing_account != null - ? each.value.tenant_info.billing_account - : var.billing_account.id - ) - name = lower("${each.key}-main-0") - parent = module.tenant-top-folders[each.key].id - prefix = var.prefix - iam_by_principals = { - (each.value.tenant_info.admin_principal) = [ - "roles/iam.serviceAccountAdmin", - "roles/iam.serviceAccountTokenCreator", - "roles/iam.workloadIdentityPoolAdmin" - ] - } - iam = { - # Expected that the service account will have owner permissions on the project it - # creates this role will be removed during stage 3 when sa-lockdown-runs. - # This iam simply reaffirms the permissions resman should already have. - "roles/owner" = [ - "serviceAccount:${var.automation.service_accounts.resman}" - ] - (var.custom_roles.storage_viewer) = [ - "serviceAccount:${var.automation.service_accounts.resman-r}" - ] - "roles/viewer" = [ - "serviceAccount:${var.automation.service_accounts.resman-r}" - ] - } - compute_metadata = { - google-compute-default-region = var.regions.primary - google-compute-default-zone = "${var.regions.primary}-b" # There always seems to be a -b zone - } - services = [ - "accesscontextmanager.googleapis.com", - "bigquery.googleapis.com", - "bigqueryreservation.googleapis.com", - "bigquerystorage.googleapis.com", - "billingbudgets.googleapis.com", - "cloudbilling.googleapis.com", - "cloudbuild.googleapis.com", - "cloudkms.googleapis.com", - "cloudresourcemanager.googleapis.com", - "container.googleapis.com", - "compute.googleapis.com", - "container.googleapis.com", - "essentialcontacts.googleapis.com", - "iam.googleapis.com", - "iamcredentials.googleapis.com", - "orgpolicy.googleapis.com", - "pubsub.googleapis.com", - "servicenetworking.googleapis.com", - "serviceusage.googleapis.com", - "stackdriver.googleapis.com", - "storage-component.googleapis.com", - "storage.googleapis.com", - "sts.googleapis.com" - ] -} - -#added for key and bucket provisioning -resource "time_sleep" "tenant_project_iam_propagation_delay" { - create_duration = "30s" - - depends_on = [ - module.tenant-self-iac-projects, - module.tenant-self-main-projects - ] -} - diff --git a/fast/stages-aw/1-resman/kms.tf b/fast/stages-aw/1-resman/kms.tf deleted file mode 100644 index 59d4d322c..000000000 --- a/fast/stages-aw/1-resman/kms.tf +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -module "tenant-project-keys" { - source = "../../../modules/kms" - project_id = module.tenant-self-iac-projects[each.key].project_id - for_each = local.tenant_envs - depends_on = [time_sleep.tenant_project_iam_propagation_delay] - iam = { - "roles/cloudkms.cryptoKeyEncrypterDecrypter" = [ - module.tenant-core-sa[each.key].iam_email, - "serviceAccount:service-${var.automation.project_number}@gs-project-accounts.iam.gserviceaccount.com" - ] - } - keyring = { - name = "${each.key}-keyring" - location = try(each.value.locations.kms != "", false) ? each.value.locations.kms : var.regions.primary - } - keys = { - gcs = { - purpose = "ENCRYPT_DECRYPT" - labels = { service = "gcs" } - locations = try(each.value.locations.kms != "", false) ? each.value.locations.kms : var.regions.primary - rotation_period = "7776000s" # CIS Compliance Benchmark 1.10 - version_template = { - algorithm = "GOOGLE_SYMMETRIC_ENCRYPTION" - protection_level = "HSM" - } - }, - default = { - purpose = "ENCRYPT_DECRYPT" - labels = { service = "iac-core" } - locations = try(each.value.locations.kms != "", false) ? each.value.locations.kms : var.regions.primary - rotation_period = "7776000s" - version_template = { - algorithm = "GOOGLE_SYMMETRIC_ENCRYPTION" - protection_level = "HSM" - } - } - } -} - -resource "google_kms_crypto_key_iam_member" "resman_bootstrap_kms" { - for_each = local.tenant_envs - crypto_key_id = "projects/${var.automation.project_id}/locations/${var.regions.primary}/keyRings/gcs/cryptoKeys/gcs" - member = "serviceAccount:service-${module.tenant-self-iac-projects[each.key].number}@gs-project-accounts.iam.gserviceaccount.com" - role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" -} - -resource "google_kms_crypto_key_iam_member" "tenant_kms" { - for_each = local.tenant_envs - crypto_key_id = module.tenant-project-keys[each.key].key_ids["gcs"] - member = "serviceAccount:service-${module.tenant-self-iac-projects[each.key].number}@gs-project-accounts.iam.gserviceaccount.com" - role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" -} diff --git a/fast/stages-aw/1-resman/log-metric-alerts.tf b/fast/stages-aw/1-resman/log-metric-alerts.tf deleted file mode 100644 index 6e4ea0bf1..000000000 --- a/fast/stages-aw/1-resman/log-metric-alerts.tf +++ /dev/null @@ -1,74 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# CIS Compliance Benchmark 2.4 -# CIS Compliance Benchmark 2.5 -# CIS Compliance Benchmark 2.6 -# CIS Compliance Benchmark 2.7 -# CIS Compliance Benchmark 2.8 -# CIS Compliance Benchmark 2.9 -# CIS Compliance Benchmark 2.10 -# CIS Compliance Benchmark 2.11 - -module "core_log_metrics" { - source = "../../../modules/cis-log-metrics" - - for_each = module.tenant-self-iac-projects - project = module.tenant-self-iac-projects[each.key].id -} - -module "main_log_metrics" { - source = "../../../modules/cis-log-metrics" - - for_each = module.tenant-self-main-projects - project = module.tenant-self-main-projects[each.key].id -} - -# Alerts require log-metrics to be configure -resource "time_sleep" "resman_wait_10_seconds" { - depends_on = [module.core_log_metrics, module.main_log_metrics] - create_duration = "10s" -} - -module "core_log_alerts" { - source = "../../../modules/cis-log-alerts" - - for_each = module.tenant-self-iac-projects - - project = module.tenant-self-iac-projects[each.key].id - combiner = "OR" - duration = "60s" - comparison = "COMPARISON_GT" - alignment_period = "60s" - per_series_aligner = "ALIGN_RATE" - alert_email = var.alert_email - - depends_on = [time_sleep.resman_wait_10_seconds] -} - -module "main_log_alerts" { - source = "../../../modules/cis-log-alerts" - - for_each = module.tenant-self-main-projects - - project = module.tenant-self-main-projects[each.key].id - combiner = "OR" - duration = "60s" - comparison = "COMPARISON_GT" - alignment_period = "60s" - per_series_aligner = "ALIGN_RATE" - alert_email = var.alert_email - - depends_on = [time_sleep.resman_wait_10_seconds] -} \ No newline at end of file diff --git a/fast/stages-aw/1-resman/terraform.tfvars.sample b/fast/stages-aw/1-resman/terraform.tfvars.sample deleted file mode 100644 index 994affe73..000000000 --- a/fast/stages-aw/1-resman/terraform.tfvars.sample +++ /dev/null @@ -1,34 +0,0 @@ -tenants = { - tenant_name = { ## change this - admin_principal = "group:gcp-devops@domain" - descriptive_name = "tenant_name" - locations = { - gcs = "us-east4" - kms = "us-east4" - } - }, - tenant_name-2 = { ## change this - admin_principal = "group:gcp-devops@domain" - descriptive_name = "tenant_name-2" - locations = { - gcs = "us-east4" - kms = "us-east4" - } - } -} - -fast_features = { - envs = true -} - -envs_folders = { - Prod = { - admin = "gcp-organization-admins@domain.com" - }, - Int = { - admin = "gcp-organization-admins@domain.com" - }, - Test = { - admin = "gcp-organization-admins@domain.com" - } -} diff --git a/fast/stages-aw/2-networking-a-fedramp-high/README.md b/fast/stages-aw/2-networking-a-fedramp-high/README.md deleted file mode 100644 index 520b0347f..000000000 --- a/fast/stages-aw/2-networking-a-fedramp-high/README.md +++ /dev/null @@ -1,53 +0,0 @@ -# FedRAMP High Network - -This stage deploys the networking infrastructure recommended with an Assured Workload FedRAMP High environment. - - -- [Variables](#variables) -- [Outputs](#outputs) - - ---- - -## Variables - -| name | description | type | required | default | -|---|---|:---:|:---:|:---:| -| [alert_email](variables.tf#L16) | Email to receive log alerts. | string | ✓ | | -| [automation](variables.tf#L21) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | -| [billing_account](variables.tf#L29) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | object({…}) | ✓ | | -| [envs_folders](variables.tf#L60) | List of environments to be created for projects to go into. | map(object({…})) | ✓ | | -| [folder_ids](variables.tf#L94) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | -| [organization](variables.tf#L114) | Organization details. | object({…}) | ✓ | | -| [prefix](variables.tf#L130) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | -| [regions](variables.tf#L161) | Region definitions. Inherited from 0-bootstrap outputs. Must be specified in bootstrap terraform.tfvars. | object({…}) | ✓ | | -| [tenant_accounts](variables.tf#L184) | Base Tenant accounts that are created for each folder, provided as a combination of environment and tenant. | map(object({…})) | ✓ | | -| [assured_workloads](variables.tf#L204) | Assured Workloads configuration. | any | | null | -| [billing_override](variables.tf#L195) | Optional billing override configuration. If set, disables service account impersonation for project billing linkage and runs under the user account using the specified quota projects. | object({…}) | | null | -| [cidrs](variables.tf#L285) | Named CIDR ranges to use in firewall rules. | map(list(string)) | | {} | -| [common_services_folder](variables.tf#L210) | Common services folder ID. | string | | null | -| [custom_roles](variables.tf#L42) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | -| [dns](variables.tf#L50) | DNS configuration. | object({…}) | | {} | -| [dns_policy_rules](variables.tf#L271) | DNS response policy rules in name => rule format. | map(object({…})) | | {} | -| [essential_contacts](variables.tf#L67) | Email used for essential contacts, unset if null. | string | | null | -| [factories_config](variables.tf#L73) | Configuration for network resource factories. | object({…}) | | {…} | -| [fast_features](variables.tf#L222) | FAST features enabled. | any | | null | -| [firewall_rules](variables.tf#L292) | Firewall rules for each VPC / environment spoke. | map(object({…})) | | {} | -| [gcp_ranges](variables.tf#L103) | GCP address ranges in name => range format. | map(string) | | {…} | -| [groups](variables.tf#L228) | IAM groups mapping. | any | | null | -| [logging](variables.tf#L216) | Logging configuration. | any | | null | -| [outputs_location](variables.tf#L124) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | -| [proxy_subnets](variables.tf#L264) | VPC proxy-only subnet CIDRs keyed by environment. | map(string) | | {} | -| [psa_ranges](variables.tf#L141) | IP ranges used for Private Service Access (e.g. CloudSQL). Ranges is in name => range format. | object({…}) | | {} | -| [regime_mapping](variables.tf#L234) | Compliance regime shorthand mapping. | any | | null | -| [service_accounts](variables.tf#L170) | Automation service accounts in name => email format. | object({…}) | | null | -| [subnets](variables.tf#L240) | VPC subnet configurations keyed by network name. | map(list(object({…}))) | | {} | - -## Outputs - -| name | description | sensitive | -|---|---|:---:| -| [host_project_ids](outputs.tf#L62) | Network project ids. | | -| [host_project_numbers](outputs.tf#L67) | Network project numbers. | | -| [tfvars](outputs.tf#L72) | Terraform variables file for the following stages. | ✓ | - diff --git a/fast/stages-aw/2-networking-a-fedramp-high/branch-net-envs.tf b/fast/stages-aw/2-networking-a-fedramp-high/branch-net-envs.tf deleted file mode 100644 index 7173c31bb..000000000 --- a/fast/stages-aw/2-networking-a-fedramp-high/branch-net-envs.tf +++ /dev/null @@ -1,228 +0,0 @@ -/** - * Copyright 2023 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -# tfdoc:file:description Dev spoke VPC and related resources. - -locals { - tenant_subnets_map_of_maps = { - for pairing in setproduct(values(var.tenant_accounts), values(var.regions)) : "${pairing[0].main_project}-${pairing[1]}" => { - "project" = pairing[0].main_project, - "tenant" = pairing[0].tenant, - "admin_principal" = pairing[0].admin_principal - "region" = pairing[1], - "env" = pairing[0].env - } - } -} -module "env-spoke-projects" { - source = "../../../modules/project" - providers = { - google = google.billing - google-beta = google-beta.billing - } - for_each = var.envs_folders - billing_account = var.billing_account.id - name = lower("${each.key}-net-host") - lien_reason = "Protected by default as a core project." - parent = var.folder_ids.networking - prefix = var.prefix - services = concat([ - "container.googleapis.com", - "compute.googleapis.com", - "dns.googleapis.com", - "iap.googleapis.com", - "networkmanagement.googleapis.com", - "servicenetworking.googleapis.com", - "stackdriver.googleapis.com", - "vpcaccess.googleapis.com" - ] - ) - shared_vpc_host_config = { - enabled = true - } - metric_scopes = [module.vdss-host-project.project_id] - iam = { - "roles/dns.admin" = compact([ - try(local.service_accounts.gke-dev, null), - try(local.service_accounts.project-factory-dev, null), - try(local.service_accounts.project-factory-prod, null), - ]) - } - # # allow specific service accounts to assign a set of roles - # iam_bindings = { - # sa_delegated_grants = { - # role = "roles/resourcemanager.projectIamAdmin" - # members = compact([ - # try(local.service_accounts.data-platform-dev, null), - # try(local.service_accounts.project-factory-dev, null), - # try(local.service_accounts.project-factory-prod, null), - # try(local.service_accounts.gke-dev, null), - # ]) - # condition = { - # title = "dev_stage3_sa_delegated_grants" - # description = "Development host project delegated grants." - # expression = format( - # "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])", - # join(",", formatlist("'%s'", local.stage3_sas_delegated_grants)) - # ) - # } - # } - # } -} - - -module "env-spoke-vpc" { - source = "../../../modules/net-vpc" - for_each = var.envs_folders - - project_id = module.env-spoke-projects[each.key].project_id - - name = lower("${each.key}-spoke-0") - mtu = 1500 - dns_policy = { - logging = var.dns.enable_logging - } - delete_default_routes_on_create = true - psa_configs = var.psa_ranges.dev - # Set explicit routes for googleapis; send everything else to NVAs - create_googleapis_routes = { - private = true - restricted = true } - subnets = try(var.subnets[lower(each.key)], []) - subnets_proxy_only = [{ - region = var.regions.primary - active = true - name = lower("proxy-${var.regions.primary}") - ip_cidr_range = var.proxy_subnets[each.key] - }] - - shared_vpc_host = true - shared_vpc_service_projects = [for k, v in var.tenant_accounts : v.main_project if v.env == each.key] - -} - -# resource "google_network_connectivity_internal_range" "reserved_ranges" { -# for_each = var.envs_folders -# name = lower("${each.key}-range") -# project = module.env-spoke-projects[each.key].project_id -# description = "Automatically reserved range for ${each.key}" -# network = module.env-spoke-vpc[each.key].id -# usage = "FOR_VPC" -# peering = "FOR_SELF" -# prefix_length = 22 -# target_cidr_range = ["10.200.0.0/16", ] -# } - -# resource "google_compute_subnetwork" "defaults" { -# for_each = var.envs_folders -# name = lower("${each.key}-default-0") -# project = module.env-spoke-projects[each.key].project_id -# ip_cidr_range = google_network_connectivity_internal_range.reserved_ranges[each.key].ip_cidr_range -# region = var.regions.primary -# network = module.env-spoke-vpc[each.key].id -# } - -module "env-spoke-firewall" { - source = "../../../modules/net-vpc-firewall" - for_each = var.envs_folders - - project_id = module.env-spoke-projects[each.key].project_id - network = module.env-spoke-vpc[each.key].name - default_rules_config = { - disabled = true - } - named_ranges = var.cidrs - ingress_rules = try(var.firewall_rules[lower(each.key)].ingress, {}) - egress_rules = try(var.firewall_rules[lower(each.key)].egress, {}) -} - -resource "time_sleep" "peering_delay" { - for_each = var.envs_folders - - create_duration = "${index(keys(var.envs_folders), each.key) * 30}s" - - depends_on = [module.env-spoke-vpc] -} - -module "peering-envs" { - source = "../../../modules/net-vpc-peering" - for_each = var.envs_folders - - prefix = lower("${each.key}-peering-0") - local_network = module.env-spoke-vpc[each.key].self_link - peer_network = module.vdss-vpc.self_link - routes_config = { - local = { - public_import = true - } - peer = { - public_export = true - } - } - - depends_on = [ - time_sleep.peering_delay - ] -} - -# DNS -# GCP-specific environment zone - -module "env-dns-priv-example" { - source = "../../../modules/dns" - for_each = var.envs_folders - - project_id = module.env-spoke-projects[each.key].project_id - name = lower("${each.key}-org-domain") - zone_config = { - domain = lower("${each.key}.${var.organization.domain}.") - private = { - client_networks = [module.vdss-vpc.self_link] - } - } - recordsets = { - "A localhost" = { records = ["127.0.0.1"] } - } -} - -# root zone peering to landing to centralize configuration; remove if unneeded - -module "env-dns-peer-landing-root" { - source = "../../../modules/dns" - for_each = var.envs_folders - project_id = module.env-spoke-projects[each.key].project_id - name = lower("${each.key}-root-dns-peering") - zone_config = { - domain = "." - peering = { - client_networks = [module.env-spoke-vpc[each.key].self_link] - peer_network = module.vdss-vpc.self_link - } - } -} - -resource "google_compute_subnetwork_iam_member" "allow-admin-principals" { - for_each = local.tenant_subnets_map_of_maps - project = module.env-spoke-projects[each.value.env].project_id - region = each.value.region - subnetwork = module.env-spoke-vpc[each.value.env].subnet_ids[ - "${each.value.region}/${one([ - for s in try(var.subnets[lower(each.value.env)], []) : s.name if s.tenant == each.value.tenant - ])}" - ] - role = "roles/compute.networkUser" - member = each.value.admin_principal -} diff --git a/fast/stages-aw/2-networking-a-fedramp-high/connectivity-tests.tf b/fast/stages-aw/2-networking-a-fedramp-high/connectivity-tests.tf deleted file mode 100644 index e4552381a..000000000 --- a/fast/stages-aw/2-networking-a-fedramp-high/connectivity-tests.tf +++ /dev/null @@ -1,110 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -locals { -} -resource "google_network_management_connectivity_test" "landing-test" { - for_each = var.regions - - name = "landing-subnet-test-${each.key}" - project = module.vdss-host-project.project_id - - source { - ip_address = google_compute_address.source-addr[each.key].address - project_id = module.vdss-host-project.project_id - network = module.vdss-vpc.id - network_type = "GCP_NETWORK" - } - destination { - ip_address = "8.8.8.8" - port = 443 - } - - protocol = "TCP" - labels = { - env = "vdss" - } -} - -resource "google_compute_address" "source-addr" { - project = module.vdss-host-project.project_id - - for_each = var.regions - name = "landing-test-addr-${each.value}" - subnetwork = try(module.vdss-vpc.subnet_self_links["${each.value}/landing-default"], null) - address_type = "INTERNAL" - region = each.value -} - - -resource "google_network_management_connectivity_test" "env-tests" { - for_each = var.envs_folders - - name = lower("${each.key}-host-project-test") - project = module.env-spoke-projects[each.key].project_id - - source { - ip_address = google_compute_address.env-source-addrs[each.key].address - project_id = module.env-spoke-projects[each.key].project_id - network = module.env-spoke-vpc[each.key].id - network_type = "GCP_NETWORK" - } - destination { - ip_address = "8.8.8.8" - port = 443 - } - - protocol = "TCP" - labels = { - env = lower(each.key) - } -} -resource "google_compute_address" "env-source-addrs" { - for_each = var.envs_folders - - project = module.env-spoke-projects[each.key].project_id - - name = lower("${each.key}-test-addr") - subnetwork = module.env-spoke-vpc[each.key].subnets["${var.regions.primary}/${[for s in try(var.subnets[lower(each.key)], []) : s.name if s.tenant != null][0]}"].self_link - address_type = "INTERNAL" - region = var.regions.primary - depends_on = [module.env-spoke-vpc] -} - - -# # These tests should fail -## This isn't doing what I want it to, but I really like the idea of having something like this to test for route leaking between the envs - -# resource "google_network_management_connectivity_test" "fail-env-tests" { -# for_each = var.envs_folders - -# name = lower("must-fail-${each.key}-prod") -# project = module.env-spoke-projects[each.key].project_id - -# source { -# ip_address = google_compute_address.env-source-addrs[each.key].address -# project_id = module.env-spoke-projects[each.key].project_id -# network = module.env-spoke-vpc[each.key].id -# network_type = "GCP_NETWORK" -# } -# destination { -# ip_address = google_compute_address.env-source-addrs["Prod"].address -# project_id = module.env-spoke-projects["Prod"].project_id -# network = module.env-spoke-vpc["Prod"].id -# port = 443 -# } - -# protocol = "TCP" - -# } \ No newline at end of file diff --git a/fast/stages-aw/2-networking-a-fedramp-high/log-metric-alerts.tf b/fast/stages-aw/2-networking-a-fedramp-high/log-metric-alerts.tf deleted file mode 120000 index 8fab95f87..000000000 --- a/fast/stages-aw/2-networking-a-fedramp-high/log-metric-alerts.tf +++ /dev/null @@ -1 +0,0 @@ -../2-networking-b-il5-ngfw/log-metric-alerts.tf \ No newline at end of file diff --git a/fast/stages-aw/2-networking-a-fedramp-high/main.tf b/fast/stages-aw/2-networking-a-fedramp-high/main.tf deleted file mode 100644 index 4c1adcdec..000000000 --- a/fast/stages-aw/2-networking-a-fedramp-high/main.tf +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Copyright 2023 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -# tfdoc:file:description Networking folder and hierarchical policy. - -locals { - custom_roles = coalesce(var.custom_roles, {}) - service_accounts = { - for k, v in coalesce(var.service_accounts, {}) : - k => "serviceAccount:${v}" if v != null - } -} - -module "folder" { - source = "../../../modules/folder" - parent = "organizations/${var.organization.id}" - name = "Networking" - folder_create = var.folder_ids.networking == null - id = var.folder_ids.networking - contacts = ( - var.essential_contacts == null - ? {} - : { (var.essential_contacts) = ["ALL"] } - ) - firewall_policy = { - name = "default" - policy = module.firewall-policy-default.id - } -} - -module "firewall-policy-default" { - source = "../../../modules/net-firewall-policy" - name = var.factories_config.firewall_policy_name - parent_id = module.folder.id - factories_config = { - cidr_file_path = "${var.factories_config.data_dir}/cidrs.yaml" - ingress_rules_file_path = "${var.factories_config.data_dir}/hierarchical-ingress-rules.yaml" - } -} diff --git a/fast/stages-aw/2-networking-a-fedramp-high/net-vdss.tf b/fast/stages-aw/2-networking-a-fedramp-high/net-vdss.tf deleted file mode 100644 index 53449f5b5..000000000 --- a/fast/stages-aw/2-networking-a-fedramp-high/net-vdss.tf +++ /dev/null @@ -1,158 +0,0 @@ -/** - * Copyright 2024 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -# tfdoc:file:description Landing VPC and related resources. - -module "vdss-host-project" { - source = "../../../modules/project" - providers = { - google = google.billing - google-beta = google-beta.billing - } - billing_account = var.billing_account.id - name = "net-vdss-host" - lien_reason = "Protected by default as a core project." - parent = var.folder_ids.networking - prefix = var.prefix - services = [ - "compute.googleapis.com", - "certificatemanager.googleapis.com", - "dns.googleapis.com", - "iap.googleapis.com", - "networkmanagement.googleapis.com", - "stackdriver.googleapis.com", - "networkservices.googleapis.com", - "cloudkms.googleapis.com" - ] - shared_vpc_host_config = { - enabled = true - } - iam = { - "roles/dns.admin" = compact([ - try(local.service_accounts.project-factory-prod, null) - ]) - (local.custom_roles.service_project_network_admin) = compact([ - try(local.service_accounts.project-factory-prod, null) - ]) - } -} - -resource "google_compute_project_metadata" "metadata-vdss-host-project" { - project = module.vdss-host-project.project_id - metadata = { - block-project-ssh-keys = true # CIS Compliance Benchmark 4.3 - enable-oslogin = true # CIS Compliance Benchmark 4.4 - } -} - -# DMZ (untrusted) VPC - -module "dmz-vpc" { - source = "../../../modules/net-vpc" - project_id = module.vdss-host-project.project_id - name = "vdss-dmz-0" - mtu = 1500 - dns_policy = { - inbound = true - logging = var.dns.enable_logging - } - create_googleapis_routes = null - subnets = try(var.subnets.dmz, []) -} - -module "dmz-firewall" { - source = "../../../modules/net-vpc-firewall" - project_id = module.vdss-host-project.project_id - network = module.dmz-vpc.name - default_rules_config = { - disabled = true - } - named_ranges = var.cidrs - ingress_rules = try(var.firewall_rules.dmz.ingress, {}) - egress_rules = try(var.firewall_rules.dmz.egress, {}) -} - - -# Landing (trusted) VPC -module "vdss-vpc" { - source = "../../../modules/net-vpc" - project_id = module.vdss-host-project.project_id - name = "vdss-landing-0" - delete_default_routes_on_create = true - mtu = 1500 - subnets = try(var.subnets.landing, []) - dns_policy = { - inbound = true - logging = var.dns.enable_logging - } - # Set explicit routes for googleapis in case the default route is deleted - create_googleapis_routes = { - private = true - restricted = true - } -} - -module "vdss-firewall" { - source = "../../../modules/net-vpc-firewall" - project_id = module.vdss-host-project.project_id - network = module.vdss-vpc.name - default_rules_config = { - disabled = true - } - named_ranges = var.cidrs - ingress_rules = try(var.firewall_rules.vdss.ingress, {}) - egress_rules = try(var.firewall_rules.vdss.egress, {}) -} - -# NAT - -module "dmz-nat-primary" { - source = "../../../modules/net-cloudnat" - project_id = module.vdss-host-project.project_id - region = var.regions.primary - name = "nat-${var.regions.primary}" - router_create = true - router_name = "prod-nat-${var.regions.primary}" - router_network = module.dmz-vpc.name -} - -#DNS -module "landing-dns-priv-gcp" { - source = "../../../modules/dns" - project_id = module.vdss-host-project.project_id - name = "org-domain" - zone_config = { - domain = lower("${var.organization.domain}.") - private = { - client_networks = [module.vdss-vpc.self_link] - } - } - recordsets = { - "A localhost" = { records = ["127.0.0.1"] } - } -} - -# Google APIs via response policies - -module "landing-dns-policy-googleapis" { - source = "../../../modules/dns-response-policy" - project_id = module.vdss-host-project.project_id - name = "googleapis" - rules = var.dns_policy_rules - networks = { - landing = module.vdss-vpc.self_link - } -} diff --git a/fast/stages-aw/2-networking-a-fedramp-high/nva.tf b/fast/stages-aw/2-networking-a-fedramp-high/nva.tf deleted file mode 100644 index d16e6a5b0..000000000 --- a/fast/stages-aw/2-networking-a-fedramp-high/nva.tf +++ /dev/null @@ -1,219 +0,0 @@ -/** - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -locals { - # routing_config should be aligned to the NVA network interfaces - i.e. - # local.routing_config[0] sets up the first interface, and so on. - routing_config = [ - { - name = "dmz" - enable_masquerading = true - routes = [ - var.gcp_ranges.gcp_dmz_primary, - ] - }, - { - name = "landing" - routes = [for k, v in var.envs_folders : module.env-spoke-vpc[k].subnets[ - "${var.regions.primary}/${[for s in try(var.subnets[lower(k)], []) : s.name if s.tenant != null][0]}" - ].ip_cidr_range] - }, - ] -} - -# Custom service account with compute engine role -resource "google_service_account" "compute" { - account_id = "nva-sa" - project = module.vdss-host-project.project_id -} - - -# NVA config -module "nva-cloud-config" { - source = "../../../modules/cloud-config-container/simple-nva" - enable_health_checks = true - network_interfaces = local.routing_config -} - -module "nva-template" { - for_each = var.regions - source = "../../../modules/compute-vm" - project_id = module.vdss-host-project.project_id - name = "nva-template-${each.key}" - zone = "${each.value}-b" - instance_type = "n2d-standard-2" - tags = ["nva"] - create_template = true - can_ip_forward = true - network_interfaces = [ - { - network = module.dmz-vpc.self_link - subnetwork = try(module.dmz-vpc.subnet_self_links["${each.value}/dmz-default"], null) - nat = false - addresses = null - }, - { - network = module.vdss-vpc.self_link - subnetwork = try(module.vdss-vpc.subnet_self_links["${each.value}/landing-default"], null) - nat = false - addresses = null - } - ] - boot_disk = { - initialize_params = { - image = "cos-cloud/cos-stable" - } - } - options = { - allow_stopping_for_update = true - deletion_protection = false - spot = true - termination_action = "STOP" - } - metadata = { - user-data = module.nva-cloud-config.cloud_config - block-project-ssh-keys = true # CIS Compliance Benchmark 4.3 - } - - # CIS Compliance Benchmark 4.1 - # CIS Compliance Benchmark 4.2 - service_account = { - email = google_service_account.compute.email - } - - # CIS Compliance Benchmark 4.11 - confidential_compute = true - shielded_config = { - enable_secure_boot = true - enable_vtpm = true - enable_integrity_monitoring = true - } - depends_on = [module.vdss-vpc, module.dmz-vpc] -} - -module "nva-mig" { - for_each = var.regions - source = "../../../modules/compute-mig" - project_id = module.vdss-host-project.project_id - location = each.value - name = "nva-${each.key}" - instance_template = module.nva-template[each.key].template.self_link - target_size = 2 - auto_healing_policies = { - initial_delay_sec = 30 - } - health_check_config = { - enable_logging = true - tcp = { - port = 22 - } - } -} - -module "ilb-nva-dmz" { - for_each = var.regions - source = "../../../modules/net-lb-int" - project_id = module.vdss-host-project.project_id - region = each.value - name = "nva-dmz-${each.key}" - service_label = var.prefix - forwarding_rules_config = { - "" = { - global_access = true - } - } - vpc_config = { - network = module.dmz-vpc.self_link - subnetwork = try(module.dmz-vpc.subnet_self_links["${each.value}/dmz-default"], null) - } - backends = [ - for k, v in module.nva-mig : - { group = v.group_manager.instance_group } - if startswith(k, each.key) - ] - health_check_config = { - enable_logging = true - tcp = { - port = 22 - } - } -} - -module "ilb-nva-vdss" { - for_each = var.regions - source = "../../../modules/net-lb-int" - project_id = module.vdss-host-project.project_id - region = each.value - name = "nva-vdss-${each.key}" - service_label = var.prefix - forwarding_rules_config = { - "" = { - global_access = true - } - } - vpc_config = { - network = module.vdss-vpc.self_link - subnetwork = try(module.vdss-vpc.subnet_self_links["${each.value}/landing-default"], null) - } - backends = [ - for k, v in module.nva-mig : - { group = v.group_manager.instance_group } - if startswith(k, each.key) - ] - health_check_config = { - enable_logging = true - tcp = { - port = 22 - } - } -} - -resource "google_compute_route" "default" { - name = "default-route-nva" - project = module.vdss-host-project.project_id - dest_range = "0.0.0.0/0" - network = module.vdss-vpc.name - next_hop_ilb = module.ilb-nva-vdss["primary"].forwarding_rules[""].id - priority = 100 -} - -# Google KMS Module -module "kms" { - source = "../../../modules/kms" - project_id = module.vdss-host-project.project_id - keys = { - "default" = { - rotation_period = "7776000s" # CIS Compliance Benchmark 1.10 - purpose = "ENCRYPT_DECRYPT" - version_template = { - algorithm = "GOOGLE_SYMMETRIC_ENCRYPTION" - protection_level = "HSM" - } - } - } - - iam = { - "roles/cloudkms.cryptoKeyEncrypterDecrypter" = [ - google_service_account.compute.member, - module.vdss-host-project.service_agents.compute.iam_email - ] - } - keyring = { - location = var.regions.primary - name = "vdss-keyring" - } - -} diff --git a/fast/stages-aw/2-networking-a-fedramp-high/outputs.tf b/fast/stages-aw/2-networking-a-fedramp-high/outputs.tf deleted file mode 100644 index 2c06e801e..000000000 --- a/fast/stages-aw/2-networking-a-fedramp-high/outputs.tf +++ /dev/null @@ -1,76 +0,0 @@ -/** - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -locals { - envs = { for name, v in var.envs_folders : name => { - folder = v - vpc = module.env-spoke-vpc[name].id - region = var.regions.primary - shared_subnet = module.env-spoke-vpc[name].subnet_self_links[ - "${var.regions.primary}/${[for s in try(var.subnets[lower(name)], []) : s.name if s.tenant != null][0]}" - ] - host_project = module.env-spoke-projects[name].project_id - proxy_only = module.env-spoke-vpc[name].subnets_proxy_only["${var.regions.primary}/proxy-${var.regions.primary}"].self_link - } } - vdss = { - landing_host = module.vdss-host-project.project_id - dmz_vpc = module.dmz-vpc.id - landing_vpc = module.vdss-vpc.id - } - host_project_ids = module.env-spoke-vpc - host_project_numbers = { - prod-landing = module.vdss-host-project.number - } - tfvars = { - host_project_ids = local.host_project_ids - host_project_numbers = local.host_project_numbers - envs = local.envs - vdss = local.vdss - } -} - -# generate tfvars file for subsequent stages - -resource "local_file" "tfvars" { - for_each = var.outputs_location == null ? {} : { 1 = 1 } - file_permission = "0644" - filename = "${try(pathexpand(var.outputs_location), "")}/tfvars/2-networking.auto.tfvars.json" - content = jsonencode(local.tfvars) -} - -resource "google_storage_bucket_object" "tfvars" { - bucket = var.automation.outputs_bucket - name = "tfvars/2-networking.auto.tfvars.json" - content = jsonencode(local.tfvars) -} - -# outputs - -output "host_project_ids" { - description = "Network project ids." - value = local.host_project_ids -} - -output "host_project_numbers" { - description = "Network project numbers." - value = local.host_project_numbers -} - -output "tfvars" { - description = "Terraform variables file for the following stages." - sensitive = true - value = local.tfvars -} \ No newline at end of file diff --git a/fast/stages-aw/2-networking-a-fedramp-high/psc.tf b/fast/stages-aw/2-networking-a-fedramp-high/psc.tf deleted file mode 120000 index 3d95a3096..000000000 --- a/fast/stages-aw/2-networking-a-fedramp-high/psc.tf +++ /dev/null @@ -1 +0,0 @@ -../2-networking-b-il5-ngfw/psc.tf \ No newline at end of file diff --git a/fast/stages-aw/2-networking-a-fedramp-high/terraform.tfvars.sample b/fast/stages-aw/2-networking-a-fedramp-high/terraform.tfvars.sample deleted file mode 100644 index cd301b4c0..000000000 --- a/fast/stages-aw/2-networking-a-fedramp-high/terraform.tfvars.sample +++ /dev/null @@ -1,280 +0,0 @@ -# Sample terraform.tfvars file for Stage 2 (Networking - FedRAMP High) -# Replace values with your desired network topologies. - -# VPC Subnetwork Configurations -subnets = { - landing = [ - { - name = "landing-default" - ip_cidr_range = "10.64.0.0/24" - region = "us-central1" - description = "Default subnet for vdss in primary region" - flow_logs_config = { - aggregation_interval = "INTERVAL_5_SEC" - flow_sampling = 1 - metadata = "INCLUDE_ALL_METADATA" - } - } - ] - dmz = [ - { - name = "dmz-default" - ip_cidr_range = "10.64.128.0/24" - region = "us-central1" - description = "Default subnet for landing dmz in primary region" - flow_logs_config = { - aggregation_interval = "INTERVAL_5_SEC" - flow_sampling = 1 - metadata = "INCLUDE_ALL_METADATA" - } - } - ] - prod = [ - { - name = "prod-tenant-1-subnet" - ip_cidr_range = "10.202.0.0/16" - region = "us-central1" - description = "Default subnet for prod environment in primary region" - flow_logs_config = { - aggregation_interval = "INTERVAL_5_SEC" - flow_sampling = 1 - metadata = "INCLUDE_ALL_METADATA" - } - tenant = "ten-1" # Links this subnet to tenant-1 project sharing - }, - { - name = "prod-tenant-2-subnet" - ip_cidr_range = "10.102.0.0/16" - region = "us-central1" - description = "Dedicated subnet for tenant-2 in prod spoke" - flow_logs_config = { - aggregation_interval = "INTERVAL_5_SEC" - flow_sampling = 1 - metadata = "INCLUDE_ALL_METADATA" - } - tenant = "ten-2" # Links this subnet to tenant-2 project sharing - } - ] - int = [ - { - name = "int-tenant-1-subnet" - ip_cidr_range = "10.30.0.0/16" - region = "us-central1" - description = "Default subnet for int environment in primary region" - flow_logs_config = { - aggregation_interval = "INTERVAL_5_SEC" - flow_sampling = 1 - metadata = "INCLUDE_ALL_METADATA" - } - tenant = "ten-1" - }, - { - name = "int-tenant-2-subnet" - ip_cidr_range = "10.31.0.0/16" - region = "us-central1" - description = "Dedicated subnet for tenant-2 in int spoke" - flow_logs_config = { - aggregation_interval = "INTERVAL_5_SEC" - flow_sampling = 1 - metadata = "INCLUDE_ALL_METADATA" - } - tenant = "ten-2" - } - ] - test = [ - { - name = "test-tenant-1-subnet" - ip_cidr_range = "10.203.0.0/16" - region = "us-central1" - description = "Default subnet for test environment in primary region" - flow_logs_config = { - aggregation_interval = "INTERVAL_5_SEC" - flow_sampling = 1 - metadata = "INCLUDE_ALL_METADATA" - } - tenant = "ten-1" - }, - { - name = "test-tenant-2-subnet" - ip_cidr_range = "10.103.0.0/16" - region = "us-central1" - description = "Dedicated subnet for tenant-2 in test spoke" - flow_logs_config = { - aggregation_interval = "INTERVAL_5_SEC" - flow_sampling = 1 - metadata = "INCLUDE_ALL_METADATA" - } - tenant = "ten-2" - } - ] -} - -# Proxy-only Subnet CIDRs (used for regional load balancers) -proxy_subnets = { - Prod = "10.1.1.0/24" - Int = "10.1.2.0/24" - Test = "10.1.3.0/24" -} - -# Named IP Ranges to reference in Firewall Rules -cidrs = { - healthchecks = [ - "35.191.0.0/16", - "130.211.0.0/22", - "209.85.152.0/22", - "209.85.204.0/22" - ] - rfc1918 = [ - "10.0.0.0/8", - "172.16.0.0/12", - "192.168.0.0/16" - ] - iap = [ - "35.235.240.0/20" - ] - tenants = [ - "10.200.0.0/16" - ] -} - -# Custom Firewall Rules for each VPC / Spoke Spoke -firewall_rules = { - vdss = { - ingress = { - allow-iap-ssh-landing = { - description = "Allow traffic from Google IAP over SSH" - source_ranges = ["iap"] - rules = [ - { - protocol = "tcp" - ports = ["22"] - } - ] - } - allow-hc-nva-ssh-landing = { - description = "Allow traffic from Google healthchecks to NVA appliances" - source_ranges = ["healthchecks"] - rules = [ - { - protocol = "tcp" - ports = ["22"] - } - ] - } - allow-traffic-internal = { - description = "Allow traffic from inside the the networks" - targets = ["nva"] - source_ranges = ["10.0.0.0/8"] - } - } - } - dmz = { - ingress = { - allow-iap-ssh-dmz = { - description = "Allow traffic from Google IAP over SSH" - source_ranges = ["iap"] - rules = [ - { - protocol = "tcp" - ports = ["22"] - } - ] - } - allow-hc-nva-ssh-dmz = { - description = "Allow traffic from Google healthchecks to NVA appliances" - source_ranges = ["healthchecks"] - rules = [ - { - protocol = "tcp" - ports = ["22"] - } - ] - } - } - } - prod = { - ingress = { - allow-iap-ssh = { - description = "Allow traffic from Google IAP over SSH" - source_ranges = ["iap"] - rules = [ - { - protocol = "tcp" - ports = ["22"] - } - ] - } - } - } - int = { - ingress = { - allow-iap-ssh = { - description = "Allow traffic from Google IAP over SSH" - source_ranges = ["iap"] - rules = [ - { - protocol = "tcp" - ports = ["22"] - } - ] - } - } - } - test = { - ingress = { - allow-iap-ssh = { - description = "Allow traffic from Google IAP over SSH" - source_ranges = ["iap"] - rules = [ - { - protocol = "tcp" - ports = ["22"] - } - ] - } - } - } -} - -# Private DNS Zone Response Policy Rules -dns_policy_rules = { - accounts = { dns_name = "accounts.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - aiplatform-notebook-cloud-all = { dns_name = "*.aiplatform-notebook.cloud.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - aiplatform-notebook-gu-all = { dns_name = "*.aiplatform-notebook.googleusercontent.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - backupdr-cloud = { dns_name = "backupdr.cloud.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - backupdr-cloud-all = { dns_name = "*.backupdr.cloud.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - backupdr-gu = { dns_name = "backupdr.googleusercontent.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - backupdr-gu-all = { dns_name = "*.backupdr.googleusercontent.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - cloudfunctions = { dns_name = "*.cloudfunctions.net.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - cloudproxy = { dns_name = "*.cloudproxy.app.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - composer-cloud-all = { dns_name = "*.composer.cloud.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - composer-gu-all = { dns_name = "*.composer.googleusercontent.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - datafusion-all = { dns_name = "*.datafusion.cloud.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - datafusion-gu-all = { dns_name = "*.datafusion.googleusercontent.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - dataproc = { dns_name = "dataproc.cloud.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - dataproc-all = { dns_name = "*.dataproc.cloud.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - dataproc-gu = { dns_name = "dataproc.googleusercontent.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - dataproc-gu-all = { dns_name = "*.dataproc.googleusercontent.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - dl = { dns_name = "dl.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - gcr = { dns_name = "gcr.io.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - gcr-all = { dns_name = "*.gcr.io.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - gke-all = { dns_name = "*.gke.goog.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - googleapis-all = { dns_name = "*.googleapis.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - googleapis-private = { dns_name = "private.googleapis.com.", local_data = { A = { rrdatas = ["199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11"] } } } - googleapis-restricted = { dns_name = "restricted.googleapis.com.", local_data = { A = { rrdatas = ["199.36.153.4", "199.36.153.5", "199.36.153.6", "199.36.153.7"] } } } - gstatic-all = { dns_name = "*.gstatic.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - kernels-gu = { dns_name = "kernels.googleusercontent.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - kernels-gu-all = { dns_name = "*.kernels.googleusercontent.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - ltsapis-all = { dns_name = "*.ltsapis.goog.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - notebooks-all = { dns_name = "*.notebooks.cloud.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - notebooks-gu-all = { dns_name = "*.notebooks.googleusercontent.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - packages-cloud = { dns_name = "packages.cloud.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - packages-cloud-all = { dns_name = "*.packages.cloud.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - pkgdev = { dns_name = "pkg.dev.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - pkgdev-all = { dns_name = "*.pkg.dev.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - pkigoog = { dns_name = "pki.goog.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - pkigoog-all = { dns_name = "*.pki.goog.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - run-all = { dns_name = "*.run.app.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - source = { dns_name = "source.developers.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - storage = { dns_name = "storage.cloud.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } -} diff --git a/fast/stages-aw/2-networking-a-fedramp-high/variables.tf b/fast/stages-aw/2-networking-a-fedramp-high/variables.tf deleted file mode 100644 index 40aaf03f8..000000000 --- a/fast/stages-aw/2-networking-a-fedramp-high/variables.tf +++ /dev/null @@ -1,323 +0,0 @@ -/** - * Copyright 2024 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -variable "alert_email" { - description = "Email to receive log alerts." - type = string -} - -variable "automation" { - # tfdoc:variable:source 0-bootstrap - description = "Automation resources created by the bootstrap stage." - type = object({ - outputs_bucket = string - }) -} - -variable "billing_account" { - # tfdoc:variable:source 0-bootstrap - description = "Billing account id. If billing account is not part of the same org set `is_org_level` to false." - type = object({ - id = string - is_org_level = optional(bool, true) - }) - validation { - condition = var.billing_account.is_org_level != null - error_message = "Invalid `null` value for `billing_account.is_org_level`." - } -} - -variable "custom_roles" { - description = "Custom roles defined at the org level, in key => id format." - type = object({ - service_project_network_admin = string - }) - default = null -} - -variable "dns" { - description = "DNS configuration." - type = object({ - enable_logging = optional(bool, true) # CIS Compliance Benchmark 2.12 - resolvers = optional(list(string), []) - }) - default = {} - nullable = false -} - -variable "envs_folders" { - description = "List of environments to be created for projects to go into." - type = map(object({ - admin = string - })) -} - -variable "essential_contacts" { - description = "Email used for essential contacts, unset if null." - type = string - default = null -} - -variable "factories_config" { - description = "Configuration for network resource factories." - type = object({ - data_dir = optional(string, "data") - dns_policy_rules_file = optional(string, "data/dns-policy-rules.yaml") - firewall_policy_name = optional(string, "net-default") - }) - default = { - data_dir = "data" - } - nullable = false - validation { - condition = var.factories_config.data_dir != null - error_message = "Data folder needs to be non-null." - } - validation { - condition = var.factories_config.firewall_policy_name != null - error_message = "Firewall policy name needs to be non-null." - } -} - -variable "folder_ids" { - # tfdoc:variable:source 1-resman - description = "Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created." - type = object({ - networking = string - envs = optional(map(string)) - }) -} - -variable "gcp_ranges" { - description = "GCP address ranges in name => range format." - type = map(string) - default = { - gcp_dev_primary = "10.68.0.0/16" - gcp_landing_landing_primary = "10.200.0.0/16" - gcp_dmz_primary = "10.64.128.0/24" - gcp_prod_primary = "10.72.0.0/16" - } -} - -variable "organization" { - # tfdoc:variable:source 0-bootstrap - description = "Organization details." - type = object({ - domain = string - id = number - customer_id = string - }) -} - -variable "outputs_location" { - description = "Path where providers and tfvars files for the following stages are written. Leave empty to disable." - type = string - default = null -} - -variable "prefix" { - # tfdoc:variable:source 0-bootstrap - description = "Prefix used for resources that need unique names. Use 9 characters or less." - type = string - - validation { - condition = try(length(var.prefix), 0) < 10 - error_message = "Use a maximum of 9 characters for prefix." - } -} - -variable "psa_ranges" { - description = "IP ranges used for Private Service Access (e.g. CloudSQL). Ranges is in name => range format." - type = object({ - dev = optional(list(object({ - ranges = map(string) - export_routes = optional(bool, false) - import_routes = optional(bool, false) - peered_domains = optional(list(string), []) - })), []) - prod = optional(list(object({ - ranges = map(string) - export_routes = optional(bool, false) - import_routes = optional(bool, false) - peered_domains = optional(list(string), []) - })), []) - }) - nullable = false - default = {} -} - -variable "regions" { - # tfdoc:variable:source 0-bootstrap - description = "Region definitions. Inherited from 0-bootstrap outputs. Must be specified in bootstrap terraform.tfvars." - type = object({ - primary = string - }) - nullable = false -} - -variable "service_accounts" { - # tfdoc:variable:source 1-resman - description = "Automation service accounts in name => email format." - type = object({ - data-platform-dev = string - data-platform-prod = string - gke-dev = string - gke-prod = string - project-factory-dev = string - project-factory-prod = string - }) - default = null -} - -variable "tenant_accounts" { - # tfdoc:variable:soruce 1-resman - description = "Base Tenant accounts that are created for each folder, provided as a combination of environment and tenant." - type = map(object({ - tenant = string - env = string - main_project = string - admin_principal = string - })) -} - -variable "billing_override" { - description = "Optional billing override configuration. If set, disables service account impersonation for project billing linkage and runs under the user account using the specified quota projects." - type = object({ - project = string - billing_project = string - }) - default = null -} - -variable "assured_workloads" { - description = "Assured Workloads configuration." - type = any - default = null -} - -variable "common_services_folder" { - description = "Common services folder ID." - type = string - default = null -} - -variable "logging" { - description = "Logging configuration." - type = any - default = null -} - -variable "fast_features" { - description = "FAST features enabled." - type = any - default = null -} - -variable "groups" { - description = "IAM groups mapping." - type = any - default = null -} - -variable "regime_mapping" { - description = "Compliance regime shorthand mapping." - type = any - default = null -} - -variable "subnets" { - description = "VPC subnet configurations keyed by network name." - type = map(list(object({ - name = string - ip_cidr_range = string - region = string - description = optional(string) - enable_private_access = optional(bool, true) - allow_subnet_cidr_routes_overlap = optional(bool) - flow_logs_config = optional(object({ - aggregation_interval = optional(string) - filter_expression = optional(string) - flow_sampling = optional(number) - metadata = optional(string) - metadata_fields = optional(list(string)) - })) - secondary_ip_ranges = optional(map(string)) - iam = optional(map(list(string)), {}) - tenant = optional(string) - }))) - default = {} - nullable = false -} - -variable "proxy_subnets" { - description = "VPC proxy-only subnet CIDRs keyed by environment." - type = map(string) - default = {} - nullable = false -} - -variable "dns_policy_rules" { - description = "DNS response policy rules in name => rule format." - type = map(object({ - dns_name = string - behavior = optional(string, "bypassResponsePolicy") - local_data = optional(map(object({ - ttl = optional(number) - rrdatas = optional(list(string), []) - })), {}) - })) - default = {} - nullable = false -} - -variable "cidrs" { - description = "Named CIDR ranges to use in firewall rules." - type = map(list(string)) - default = {} - nullable = false -} - -variable "firewall_rules" { - description = "Firewall rules for each VPC / environment spoke." - type = map(object({ - ingress = optional(map(object({ - description = optional(string) - deny = optional(bool, false) - source_ranges = optional(list(string)) - sources = optional(list(string)) - targets = optional(list(string)) - use_service_accounts = optional(bool, false) - rules = optional(list(object({ - protocol = string - ports = optional(list(string)) - }))) - })), {}) - egress = optional(map(object({ - description = optional(string) - deny = optional(bool, true) - destination_ranges = optional(list(string)) - targets = optional(list(string)) - use_service_accounts = optional(bool, false) - rules = optional(list(object({ - protocol = string - ports = optional(list(string)) - }))) - })), {}) - })) - default = {} - nullable = false -} - - diff --git a/fast/stages-aw/2-networking-b-il5-ngfw/branch-net-envs.tf b/fast/stages-aw/2-networking-b-il5-ngfw/branch-net-envs.tf deleted file mode 100644 index 3824c2d09..000000000 --- a/fast/stages-aw/2-networking-b-il5-ngfw/branch-net-envs.tf +++ /dev/null @@ -1,228 +0,0 @@ -/** - * Copyright 2023 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -# tfdoc:file:description Dev spoke VPC and related resources. - -locals { - tenant_subnets_map_of_maps = { - for pairing in setproduct(values(var.tenant_accounts), values(var.regions)) : "${pairing[0].main_project}-${pairing[1]}" => { - "project" = pairing[0].main_project, - "tenant" = pairing[0].tenant, - "admin_principal" = pairing[0].admin_principal - "region" = pairing[1], - "env" = pairing[0].env - } - } -} -module "env-spoke-projects" { - source = "../../../modules/project" - providers = { - google = google.billing - google-beta = google-beta.billing - } - for_each = var.envs_folders - billing_account = var.billing_account.id - name = lower("${each.key}-net-host") - lien_reason = "Protected by default as a core project." - parent = var.folder_ids.networking - prefix = var.prefix - services = concat([ - "container.googleapis.com", - "compute.googleapis.com", - "dns.googleapis.com", - "iap.googleapis.com", - "networkmanagement.googleapis.com", - "servicenetworking.googleapis.com", - "stackdriver.googleapis.com", - "vpcaccess.googleapis.com" - ] - ) - shared_vpc_host_config = { - enabled = true - } - metric_scopes = [module.vdss-host-project.project_id] - iam = { - "roles/dns.admin" = compact([ - try(local.service_accounts.gke-dev, null), - try(local.service_accounts.project-factory-dev, null), - try(local.service_accounts.project-factory-prod, null), - ]) - } - # # allow specific service accounts to assign a set of roles - # iam_bindings = { - # sa_delegated_grants = { - # role = "roles/resourcemanager.projectIamAdmin" - # members = compact([ - # try(local.service_accounts.data-platform-dev, null), - # try(local.service_accounts.project-factory-dev, null), - # try(local.service_accounts.project-factory-prod, null), - # try(local.service_accounts.gke-dev, null), - # ]) - # condition = { - # title = "dev_stage3_sa_delegated_grants" - # description = "Development host project delegated grants." - # expression = format( - # "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])", - # join(",", formatlist("'%s'", local.stage3_sas_delegated_grants)) - # ) - # } - # } - # } -} - - -module "env-spoke-vpc" { - source = "../../../modules/net-vpc" - for_each = var.envs_folders - - project_id = module.env-spoke-projects[each.key].project_id - - name = lower("${each.key}-spoke-0") - mtu = 1500 - dns_policy = { - logging = var.dns.enable_logging - } - delete_default_routes_on_create = true - psa_configs = var.psa_ranges.dev - # Set explicit routes for googleapis; send everything else to NVAs - create_googleapis_routes = { - private = true - restricted = true } - subnets = try(var.subnets[lower(each.key)], []) - subnets_proxy_only = [{ - region = var.regions.primary - active = true - name = lower("proxy-${var.regions.primary}") - ip_cidr_range = var.proxy_subnets[each.key] - }] - - shared_vpc_host = true - shared_vpc_service_projects = [for k, v in var.tenant_accounts : v.main_project if v.env == each.key] - -} - -# resource "google_network_connectivity_internal_range" "reserved_ranges" { -# for_each = var.envs_folders -# name = lower("${each.key}-range") -# project = module.env-spoke-projects[each.key].project_id -# description = "Automatically reserved range for ${each.key}" -# network = module.env-spoke-vpc[each.key].id -# usage = "FOR_VPC" -# peering = "FOR_SELF" -# prefix_length = 22 -# target_cidr_range = ["10.200.0.0/16", ] -# } - -# resource "google_compute_subnetwork" "defaults" { -# for_each = var.envs_folders -# name = lower("${each.key}-default-0") -# project = module.env-spoke-projects[each.key].project_id -# ip_cidr_range = google_network_connectivity_internal_range.reserved_ranges[each.key].ip_cidr_range -# region = var.regions.primary -# network = module.env-spoke-vpc[each.key].id -# } - -module "env-spoke-firewall" { - source = "../../../modules/net-vpc-firewall" - for_each = var.envs_folders - - project_id = module.env-spoke-projects[each.key].project_id - network = module.env-spoke-vpc[each.key].name - default_rules_config = { - disabled = true - } - named_ranges = var.cidrs - ingress_rules = try(var.firewall_rules[lower(each.key)].ingress, {}) - egress_rules = try(var.firewall_rules[lower(each.key)].egress, {}) -} - -resource "time_sleep" "peering_delay" { - for_each = var.envs_folders - - create_duration = "${index(keys(var.envs_folders), each.key) * 30}s" - - depends_on = [module.env-spoke-vpc] -} - -module "peering-envs" { - source = "../../../modules/net-vpc-peering" - for_each = var.envs_folders - - prefix = lower("${each.key}-peering-0") - local_network = module.env-spoke-vpc[each.key].self_link - peer_network = module.vdss-vpc.self_link - routes_config = { - local = { - public_import = true - } - peer = { - public_export = true - } - } - - depends_on = [ - time_sleep.peering_delay - ] -} - -# DNS -# GCP-specific environment zone - -module "env-dns-priv-example" { - source = "../../../modules/dns" - for_each = var.envs_folders - - project_id = module.env-spoke-projects[each.key].project_id - name = lower("${each.key}-org-domain") - zone_config = { - domain = lower("${each.key}.${var.organization.domain}.") - private = { - client_networks = [module.vdss-vpc.self_link] - } - } - recordsets = { - "A localhost" = { records = ["127.0.0.1"] } - } -} - -# root zone peering to landing to centralize configuration; remove if unneeded - -module "env-dns-peer-landing-root" { - source = "../../../modules/dns" - for_each = var.envs_folders - project_id = module.env-spoke-projects[each.key].project_id - name = lower("${each.key}-root-dns-peering") - zone_config = { - domain = "." - peering = { - client_networks = [module.env-spoke-vpc[each.key].self_link] - peer_network = module.vdss-vpc.self_link - } - } -} - -resource "google_compute_subnetwork_iam_member" "allow-admin-principals" { - for_each = local.tenant_subnets_map_of_maps - project = module.env-spoke-projects[each.value.env].project_id - region = each.value.region - subnetwork = module.env-spoke-vpc[each.value.env].subnet_ids[ - "${each.value.region}/${one([ - for s in try(var.subnets[lower(each.value.env)], []) : s.name if s.tenant == each.value.tenant - ])}" - ] - role = "roles/compute.networkUser" - member = each.value.admin_principal -} \ No newline at end of file diff --git a/fast/stages-aw/2-networking-b-il5-ngfw/main.tf b/fast/stages-aw/2-networking-b-il5-ngfw/main.tf deleted file mode 100644 index d7c771e52..000000000 --- a/fast/stages-aw/2-networking-b-il5-ngfw/main.tf +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright 2023 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -# tfdoc:file:description Networking folder and hierarchical policy. - -locals { - service_accounts = { - for k, v in coalesce(var.service_accounts, {}) : - k => "serviceAccount:${v}" if v != null - } -} - -module "folder" { - source = "../../../modules/folder" - parent = "organizations/${var.organization.id}" - name = "Networking" - folder_create = var.folder_ids.networking == null - id = var.folder_ids.networking - contacts = ( - var.essential_contacts == null - ? {} - : { (var.essential_contacts) = ["ALL"] } - ) - firewall_policy = { - name = "default" - policy = module.firewall-policy-default.id - } -} - -module "firewall-policy-default" { - source = "../../../modules/net-firewall-policy" - name = var.factories_config.firewall_policy_name - parent_id = module.folder.id - factories_config = { - cidr_file_path = "${var.factories_config.data_dir}/cidrs.yaml" - ingress_rules_file_path = "${var.factories_config.data_dir}/hierarchical-ingress-rules.yaml" - } -} diff --git a/fast/stages-aw/2-networking-b-il5-ngfw/net-vdss.tf b/fast/stages-aw/2-networking-b-il5-ngfw/net-vdss.tf deleted file mode 100644 index b86eb27a4..000000000 --- a/fast/stages-aw/2-networking-b-il5-ngfw/net-vdss.tf +++ /dev/null @@ -1,204 +0,0 @@ -/** - * Copyright 2024 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -# tfdoc:file:description Landing VPC and related resources. - -module "vdss-host-project" { - source = "../../../modules/project" - providers = { - google = google.billing - google-beta = google-beta.billing - } - billing_account = var.billing_account.id - name = "net-vdss-host" - lien_reason = "Protected by default as a core project." - parent = var.folder_ids.networking - prefix = var.prefix - services = [ - "compute.googleapis.com", - "certificatemanager.googleapis.com", - "dns.googleapis.com", - "iap.googleapis.com", - "networkmanagement.googleapis.com", - "stackdriver.googleapis.com", - "networkservices.googleapis.com", - "cloudkms.googleapis.com" - ] - shared_vpc_host_config = { - enabled = true - } - iam = { - "roles/dns.admin" = compact([ - try(local.service_accounts.project-factory-prod, null) - ]) - } -} - -resource "google_compute_project_metadata" "metadata-vdss-host-project" { - project = module.vdss-host-project.project_id - metadata = { - block-project-ssh-keys = true # CIS Compliance Benchmark 4.3 - enable-oslogin = true # CIS Compliance Benchmark 4.4 - } -} - -# DMZ (untrusted) VPC -module "dmz-vpc" { - source = "../../../modules/net-vpc" - project_id = module.vdss-host-project.project_id - name = "vdss-dmz-0" - mtu = 1500 - dns_policy = { - inbound = true - logging = var.dns.enable_logging - } - create_googleapis_routes = null - subnets = try(var.subnets.dmz, []) -} - -module "dmz-firewall" { - source = "../../../modules/net-vpc-firewall" - project_id = module.vdss-host-project.project_id - network = module.dmz-vpc.name - default_rules_config = { - disabled = true - } - named_ranges = var.cidrs - ingress_rules = try(var.firewall_rules.dmz.ingress, {}) - egress_rules = try(var.firewall_rules.dmz.egress, {}) -} - - -# Landing (trusted) VPC -module "vdss-vpc" { - source = "../../../modules/net-vpc" - project_id = module.vdss-host-project.project_id - name = "vdss-landing-0" - delete_default_routes_on_create = true - mtu = 1500 - subnets = try(var.subnets.landing, []) - dns_policy = { - inbound = true - logging = var.dns.enable_logging - } - # Set explicit routes for googleapis in case the default route is deleted - create_googleapis_routes = { - private = true - restricted = true - } -} - -module "vdss-firewall" { - source = "../../../modules/net-vpc-firewall" - project_id = module.vdss-host-project.project_id - network = module.vdss-vpc.name - default_rules_config = { - disabled = true - } - named_ranges = var.cidrs - ingress_rules = try(var.firewall_rules.vdss.ingress, {}) - egress_rules = try(var.firewall_rules.vdss.egress, {}) -} - -# Mgmt (trusted) VPC -module "mgmt-vpc" { - source = "../../../modules/net-vpc" - project_id = module.vdss-host-project.project_id - name = "vdss-mgmt-0" - delete_default_routes_on_create = true - mtu = 1500 - subnets = try(var.subnets.mgmt, []) - dns_policy = { - inbound = true - logging = var.dns.enable_logging - } - # Set explicit routes for googleapis in case the default route is deleted - create_googleapis_routes = { - private = true - restricted = true - } -} - -module "mgmt-firewall" { - source = "../../../modules/net-vpc-firewall" - project_id = module.vdss-host-project.project_id - network = module.mgmt-vpc.name - default_rules_config = { - disabled = true - } - named_ranges = var.cidrs - ingress_rules = try(var.firewall_rules.mgmt.ingress, {}) - egress_rules = try(var.firewall_rules.mgmt.egress, {}) -} - - -# NAT -module "dmz-nat-primary" { - source = "../../../modules/net-cloudnat" - project_id = module.vdss-host-project.project_id - region = var.regions.primary - name = "nat-${var.regions.primary}" - router_create = true - router_name = "prod-nat-${var.regions.primary}" - router_network = module.dmz-vpc.name -} - -resource "google_compute_route" "mgmt-default" { - name = "default-route-mgmt" - project = module.vdss-host-project.project_id - dest_range = "0.0.0.0/0" - network = module.mgmt-vpc.name - next_hop_gateway = "default-internet-gateway" - priority = 100 -} - -module "dmz-nat-mgmt" { - source = "../../../modules/net-cloudnat" - project_id = module.vdss-host-project.project_id - region = var.regions.primary - name = "nat-mgmt-${var.regions.primary}" - router_create = true - router_name = "prod-nat-mgmt-${var.regions.primary}" - router_network = module.mgmt-vpc.name -} - -#DNS -module "landing-dns-priv-gcp" { - source = "../../../modules/dns" - project_id = module.vdss-host-project.project_id - name = "org-domain" - zone_config = { - domain = lower("${var.organization.domain}.") - private = { - client_networks = [module.vdss-vpc.self_link] - } - } - recordsets = { - "A localhost" = { records = ["127.0.0.1"] } - } -} - -# Google APIs via response policies - -module "landing-dns-policy-googleapis" { - source = "../../../modules/dns-response-policy" - project_id = module.vdss-host-project.project_id - name = "googleapis" - rules = var.dns_policy_rules - networks = { - landing = module.vdss-vpc.self_link - } -} diff --git a/fast/stages-aw/2-networking-b-il5-ngfw/ngfw.tf b/fast/stages-aw/2-networking-b-il5-ngfw/ngfw.tf deleted file mode 100644 index 05d91f6cd..000000000 --- a/fast/stages-aw/2-networking-b-il5-ngfw/ngfw.tf +++ /dev/null @@ -1,394 +0,0 @@ -/** - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -locals { - # routing_config should be aligned to the NVA network interfaces - i.e. - # local.routing_config[0] sets up the first interface, and so on. - # tflint-ignore: terraform_unused_declarations - nva_zones = { for k, v in var.regions : k => slice(data.google_compute_zones.available[k].names, 0, 2) } - cidr_ranges = var.cidrs -} - -data "google_storage_project_service_account" "gcs_account" { - project = module.vdss-host-project.project_id - depends_on = [module.vdss-host-project] -} - -data "google_compute_image" "vmseries" { - filter = "name=vmseries-flex-byol-1120 AND family=${var.vmseries_image}" - most_recent = true - project = "paloaltonetworksgcp-public" -} - -data "google_compute_zones" "available" { - for_each = var.regions - region = each.value - project = module.vdss-host-project.project_id - status = "UP" - - depends_on = [module.vdss-host-project] -} - -resource "tls_private_key" "ngfw-ssh" { - algorithm = "RSA" - rsa_bits = "4096" -} - -# Shell out to openssl to get the password hash -resource "random_password" "password" { - length = 16 - special = true - override_special = "!#$%&*()-_=+[]{}<>:?" -} - -# Shell out to openssl to get the password hash -resource "random_password" "salt" { - length = 8 - special = false -} - -resource "google_project_iam_custom_role" "ngfw-custom-role" { - role_id = "ngfw.appliance" - title = "NGFW Appliance" - project = module.vdss-host-project.project_id - - description = "Many of the permissions required for the Palo Alto NGFW, not including compute.viewer" - permissions = [ - "storage.buckets.get", - "logging.buckets.write", - "opsconfigmonitoring.resourceMetadata.write", - "autoscaling.sites.writeMetrics", - "monitoring.metricDescriptors.create", - "monitoring.metricDescriptors.get", - "monitoring.metricDescriptors.list", - "monitoring.monitoredResourceDescriptors.get", - "monitoring.monitoredResourceDescriptors.list", - "monitoring.timeSeries.create", - ] -} - -module "ngfw-service-account" { - name = "ngfw-compute" - source = "../../../modules/iam-service-account" - project_id = module.vdss-host-project.project_id - iam_project_roles = { - (module.vdss-host-project.project_id) = [ - "projects/${module.vdss-host-project.project_id}/roles/ngfw.appliance", - "roles/compute.viewer" - ] - } - depends_on = [module.vdss-host-project, google_project_iam_custom_role.ngfw-custom-role] -} - -data "external" "openssl" { - program = ["bash", "${path.module}/openssl-helper.sh"] - query = { - # arbitrary map from strings to strings, passed - # to the external program as the data query. - algo = "5" - salt = random_password.salt.result - plaintext = random_password.password.result - } -} - -# Google Cloud Storage Module -module "ngfw-bootstrap-bucket" { - source = "../../../modules/gcs" - for_each = var.regions - prefix = var.prefix - project_id = module.vdss-host-project.project_id - encryption_key = module.kms.keys.default.id - storage_class = "REGIONAL" - name = "ngfw-bootstrap-${each.value}" - location = upper(each.value) - depends_on = [module.kms] -} - -resource "google_storage_bucket_iam_binding" "binding" { - bucket = module.ngfw-bootstrap-bucket[each.key].name - for_each = var.regions - role = "roles/storage.objectUser" - members = [ - "serviceAccount:service-${module.vdss-host-project.number}@compute-system.iam.gserviceaccount.com", - module.ngfw-service-account.service_account.member - ] -} - -# I don't think we need this anymore, but who knows -# resource "time_sleep" "wait_180_seconds" { -# depends_on = [module.vdss-host-project] -# create_duration = "180s" -# } - -resource "google_storage_bucket_object" "config_folders" { - for_each = var.regions - name = "config/" - bucket = module.ngfw-bootstrap-bucket[each.key].name - content = " " -} - -resource "google_storage_bucket_object" "content_folders" { - for_each = var.regions - name = "content/" - bucket = module.ngfw-bootstrap-bucket[each.key].name - content = " " -} - -resource "google_storage_bucket_object" "software_folders" { - for_each = var.regions - name = "software/" - bucket = module.ngfw-bootstrap-bucket[each.key].name - content = " " -} - -resource "google_storage_bucket_object" "license_folders" { - for_each = var.regions - name = "license/" - bucket = module.ngfw-bootstrap-bucket[each.key].name - content = " " -} - -resource "google_storage_bucket_object" "bootstrap-xml" { - name = "config/bootstrap.xml" - for_each = var.regions - content = templatefile("./templates/bootstrap.xml.tpl", { - password_hash = data.external.openssl.result.hash - ssh_pubkey = tls_private_key.ngfw-ssh.public_key_openssh - healthcheck_cidrs = local.cidr_ranges["healthchecks"] - iap_cidrs = local.cidr_ranges["iap"] - tenants_subnets = { for k, v in var.envs_folders : k => module.env-spoke-vpc[k].subnets[ - "${var.regions.primary}/${[for s in try(var.subnets[lower(k)], []) : s.name if s.tenant != null][0]}" - ].ip_cidr_range } - lz_gateway_ip = module.vdss-vpc.subnets["us-east4/landing-default"].gateway_address # This doesn't support dual region yet - - }) - bucket = module.ngfw-bootstrap-bucket[each.key].name -} - -resource "google_storage_bucket_object" "init-cfg" { - name = "config/init-cfg.txt" - for_each = var.regions - - content = templatefile("./templates/init-cfg.txt.tpl", { - op-command-modes = "mgmt-interface-swap" - }) - bucket = module.ngfw-bootstrap-bucket[each.key].name -} - -resource "google_compute_region_instance_template" "ngfw-template" { - for_each = var.regions - project = module.vdss-host-project.project_id - - name_prefix = "ngfw-template-${each.key}-" - description = "This template is used to create and configure Palo Alto NGFW instances." - - tags = ["nva"] - region = var.regions["primary"] - machine_type = "n2d-standard-4" - can_ip_forward = true - - scheduling { - automatic_restart = true - on_host_maintenance = "MIGRATE" - } - - // Create a new boot disk from an image - disk { - source_image = data.google_compute_image.vmseries.id - disk_size_gb = 60 - type = "PERSISTENT" - disk_encryption_key { - kms_key_self_link = module.kms.keys.default.id - } - } - - network_interface { - network = module.dmz-vpc.self_link - subnetwork = try(module.dmz-vpc.subnet_self_links["${each.value}/dmz-default"], null) - } - - network_interface { - network = module.mgmt-vpc.self_link - subnetwork = try( - module.mgmt-vpc.subnet_self_links["${each.value}/mgmt-default"], null - ) - } - network_interface { - network = module.vdss-vpc.self_link - subnetwork = try(module.vdss-vpc.subnet_self_links["${each.value}/landing-default"], null) - } - - metadata = { - mgmt-interface-swap = "enable" - type = "dhcp-client" - op-command-modes = "mgmt-interface-swap" - dhcp-accept-server-domain = "yes" - dhcp-accept-server-hostname = "yes" - ssh-keys = "admin:${tls_private_key.ngfw-ssh.public_key_openssh}" - serial-port-enable = true - serial-port-logging-enable = true - vmseries-bootstrap-gce-storagebucket = module.ngfw-bootstrap-bucket[each.key].name - bootstrap-xml-md5 = google_storage_bucket_object.bootstrap-xml[each.key].md5hash # Roll out a new template when our bootstrap.xml file changes - } - - service_account { - # Google recommends custom service accounts that have cloud-platform scope and permissions granted via IAM Roles. - email = module.ngfw-service-account.email - scopes = ["cloud-platform"] - } - # CIS Compliance Benchmark 4.11 - # Palo Alto VM images aren't UEFI and can't secureboot - # confidential_instance_config { - # enable_confidential_compute = true - # } - # shielded_instance_config { - # enable_secure_boot = true - # enable_vtpm = true - # enable_integrity_monitoring = true - # } - lifecycle { - create_before_destroy = true - } -} - -module "ngfw-mig" { - for_each = var.regions - source = "../../../modules/compute-mig" - project_id = module.vdss-host-project.project_id - location = each.value - name = "nva-ngfw-${each.key}" - distribution_policy = { - target_shape = "EVEN" - zones = local.nva_zones[each.key] - } - - instance_template = google_compute_region_instance_template.ngfw-template[each.key].self_link - target_size = 2 - auto_healing_policies = { - initial_delay_sec = 900 - } - health_check_config = { - tcp = { - port = 22 - } - } - update_policy = { - minimal_action = "REPLACE" - type = "PROACTIVE" - min_ready_sec = 300 - max_surge = { - fixed = length(local.nva_zones[each.key]) - } - max_unavailable = { - fixed = 0 - } - } - -} - -module "ilb-nva-dmz" { - for_each = var.regions - source = "../../../modules/net-lb-int" - project_id = module.vdss-host-project.project_id - region = each.value - name = "nva-dmz-${each.key}" - service_label = var.prefix - forwarding_rules_config = { - "" = { - global_access = true - } - } - vpc_config = { - network = module.dmz-vpc.self_link - subnetwork = try(module.dmz-vpc.subnet_self_links["${each.value}/dmz-default"], null) - } - backends = [ - for k, v in module.ngfw-mig : - { group = v.group_manager.instance_group } - if startswith(k, each.key) - ] - health_check_config = { - enable_logging = true - tcp = { - port = 22 - } - } -} - -module "ilb-nva-vdss" { - for_each = var.regions - source = "../../../modules/net-lb-int" - project_id = module.vdss-host-project.project_id - region = each.value - name = "nva-vdss-${each.key}" - service_label = var.prefix - forwarding_rules_config = { - "" = { - global_access = true - } - } - vpc_config = { - network = module.vdss-vpc.self_link - subnetwork = try(module.vdss-vpc.subnet_self_links["${each.value}/landing-default"], null) - } - backends = [ - for k, v in module.ngfw-mig : - { group = v.group_manager.instance_group } - if startswith(k, each.key) - ] - health_check_config = { - enable_logging = true - tcp = { - port = 22 - } - } -} - -resource "google_compute_route" "default" { - name = "default-route-nva" - project = module.vdss-host-project.project_id - dest_range = "0.0.0.0/0" - network = module.vdss-vpc.name - next_hop_ilb = module.ilb-nva-vdss["primary"].forwarding_rules[""].id - priority = 100 -} - -# Google KMS Module -module "kms" { - source = "../../../modules/kms" - project_id = module.vdss-host-project.project_id - keys = { - "default" = { - rotation_period = "7776000s" # CIS Compliance Benchmark 1.10 - purpose = "ENCRYPT_DECRYPT" - version_template = { - algorithm = "GOOGLE_SYMMETRIC_ENCRYPTION" - protection_level = "HSM" - } - } - } - - iam = { - "roles/cloudkms.cryptoKeyEncrypterDecrypter" = [ - module.vdss-host-project.service_agents.compute.iam_email, - "serviceAccount:${data.google_storage_project_service_account.gcs_account.email_address}" - ] - } - keyring = { - location = var.regions.primary - name = "vdss-keyring" - } -} diff --git a/fast/stages-aw/2-networking-b-il5-ngfw/outputs.tf b/fast/stages-aw/2-networking-b-il5-ngfw/outputs.tf deleted file mode 100644 index 77da4a04b..000000000 --- a/fast/stages-aw/2-networking-b-il5-ngfw/outputs.tf +++ /dev/null @@ -1,92 +0,0 @@ -/** - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -locals { - envs = { for name, v in var.envs_folders : name => { - folder = v - vpc = module.env-spoke-vpc[name].id - region = var.regions.primary - shared_subnet = module.env-spoke-vpc[name].subnet_self_links[ - "${var.regions.primary}/${[for s in try(var.subnets[lower(name)], []) : s.name if s.tenant != null][0]}" - ] - host_project = module.env-spoke-projects[name].project_id - proxy_only = module.env-spoke-vpc[name].subnets_proxy_only[lower("${var.regions.primary}/proxy-${var.regions.primary}")].self_link - } } - vdss = { - landing_host = module.vdss-host-project.project_id - dmz_vpc = module.dmz-vpc.id - landing_vpc = module.vdss-vpc.id - } - host_project_ids = module.env-spoke-vpc - host_project_numbers = { - prod-landing = module.vdss-host-project.number - } - tfvars = { - host_project_ids = local.host_project_ids - host_project_numbers = local.host_project_numbers - envs = local.envs - vdss = local.vdss - } -} - -# generate tfvars file for subsequent stages - -resource "local_file" "tfvars" { - for_each = var.outputs_location == null ? {} : { 1 = 1 } - file_permission = "0644" - filename = "${try(pathexpand(var.outputs_location), "")}/tfvars/2-networking.auto.tfvars.json" - content = jsonencode(local.tfvars) -} - -resource "google_storage_bucket_object" "tfvars" { - bucket = var.automation.outputs_bucket - name = "tfvars/2-networking.auto.tfvars.json" - content = jsonencode(local.tfvars) -} - -# outputs - -output "host_project_ids" { - description = "Network project ids." - value = local.host_project_ids -} - -output "host_project_numbers" { - description = "Network project numbers." - value = local.host_project_numbers -} - -resource "local_file" "rsa-out" { - content = nonsensitive(tls_private_key.ngfw-ssh.private_key_openssh) - filename = "${path.module}/id_rsa" -} - -resource "local_file" "rsa-pub-out" { - content = nonsensitive(tls_private_key.ngfw-ssh.public_key_openssh) - filename = "${path.module}/id_rsa.pub" -} - -output "ngfw_password" { - description = "Password for authenticating to the NGFW." - sensitive = true - value = random_password.password -} - -output "tfvars" { - description = "Terraform variables file for the following stages." - sensitive = true - value = local.tfvars -} diff --git a/fast/stages-aw/2-networking-b-il5-ngfw/psc.tf b/fast/stages-aw/2-networking-b-il5-ngfw/psc.tf deleted file mode 100644 index 3d19fd9bb..000000000 --- a/fast/stages-aw/2-networking-b-il5-ngfw/psc.tf +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -resource "google_compute_global_address" "private_service_connect_ip" { - for_each = var.envs_folders - - project = module.env-spoke-vpc[each.key].project_id - name = "default-peering" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 22 - network = module.env-spoke-vpc[each.key].self_link -} - -resource "google_service_networking_connection" "default" { - for_each = var.envs_folders - network = module.env-spoke-vpc[each.key].self_link - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_service_connect_ip[each.key].name] -} diff --git a/fast/stages-aw/2-networking-b-il5-ngfw/templates/bootstrap.xml.tpl b/fast/stages-aw/2-networking-b-il5-ngfw/templates/bootstrap.xml.tpl deleted file mode 100644 index 057275f46..000000000 --- a/fast/stages-aw/2-networking-b-il5-ngfw/templates/bootstrap.xml.tpl +++ /dev/null @@ -1,534 +0,0 @@ - - - - - - ${ password_hash } - - - yes - - - ${ ssh_pubkey } - - - * - - - - localhost.localdomain - - - - - - - yes - 12 - - - - - - - - - - - - yes - 5 - - - yes - 5 - - - yes - 5 - - - yes - 10 - - - yes - 5 - - - - yes - - - - 10 - 10 - - 100 - 50 - - - - 10 - 10 - - 100 - 50 - - - - - - 100 - yes - - - - - - - - - - - - no - - - - no - - - no - no - - - no - - - ssh-healthcheck - - - - - - no - - - - no - - - no - no - - - no - - - no - - ssh-https-ping - - - - - - - - 3 - 5 - wait-recover - - - - - no - yes - yes - yes - - - - %{ for cidr in healthcheck_cidrs ~} - - %{ endfor ~} - %{ for cidr in iap_cidrs ~} - - %{ endfor ~} - - yes - - - - - - - - - aes-128-cbc - 3des - - - sha1 - - - group2 - - - 8 - - - - - aes-128-cbc - - - sha256 - - - group19 - - - 8 - - - - - aes-256-cbc - - - sha384 - - - group20 - - - 8 - - - - - - - - aes-128-cbc - 3des - - - sha1 - - - group2 - - 1 - - - - - - aes-128-gcm - - - none - - - group19 - - 1 - - - - - - aes-256-gcm - - - none - - - group20 - - 1 - - - - - - - aes-128-cbc - - - sha1 - - - - - - - - - - - - - real-time - - - high - - - high - - - medium - - - medium - - - low - - - low - - - low - - - - - - - - - - - - no - - - 1.25 - 0.5 - 900 - 300 - 900 - yes - - - - - yes - - - - - no - - - no - - - no - - - - - - - - - ethernet1/1 - ethernet1/2 - - - - - %{ for key, value in tenants_subnets ~} - - - ${lz_gateway_ip} - - - None - - ethernet1/2 - 10 - ${value} - - - - - %{ endfor } - - - - - - - - - - - yes - yes - yes - yes - - - updates.paloaltonetworks.com - - - - - wednesday - 01:02 - download-only - - - - - US/Pacific - - yes - yes - - PA-VM - - no - no - no - Americas - - - - - yes - - - FQDN - - mgmt-interface-swap,jumbo-frame - - - yes - yes - yes - yes - - - ${ ssh_pubkey } - - - - - - - yes - - - - - - - - - - - - - ethernet1/2 - - - - - - - ethernet1/1 - - - - - - - - - - - - - Untrust - - - Trust - - - any - - - any - - - any - - - any - - - any - - - application-default - - - any - - - any - - allow - - - - - - - - - - ethernet1/1 - - - - - Untrust - - - Trust - - - any - - - any - - any - - - - - - - - ethernet1/1 - ethernet1/2 - - - -
- - - - - - diff --git a/fast/stages-aw/2-networking-b-il5-ngfw/templates/init-cfg.txt.tpl b/fast/stages-aw/2-networking-b-il5-ngfw/templates/init-cfg.txt.tpl deleted file mode 100644 index 033c138dc..000000000 --- a/fast/stages-aw/2-networking-b-il5-ngfw/templates/init-cfg.txt.tpl +++ /dev/null @@ -1,6 +0,0 @@ -type=dhcp-client -op-command-modes=${op-command-modes} -dhcp-send-hostname=yes -dhcp-send-client-id=yes -dhcp-accept-server-hostname=yes -dhcp-accept-server-domain=yes \ No newline at end of file diff --git a/fast/stages-aw/2-networking-b-il5-ngfw/terraform.tfvars.sample b/fast/stages-aw/2-networking-b-il5-ngfw/terraform.tfvars.sample deleted file mode 100644 index de444b2ea..000000000 --- a/fast/stages-aw/2-networking-b-il5-ngfw/terraform.tfvars.sample +++ /dev/null @@ -1,319 +0,0 @@ -# Sample terraform.tfvars file for Stage 2 (Networking - IL5 NGFW) -# Replace values with your desired network topologies. - -# VPC Subnetwork Configurations -subnets = { - landing = [ - { - name = "landing-default" - ip_cidr_range = "10.64.0.0/24" - region = "us-central1" - description = "Default subnet for vdss in primary region" - flow_logs_config = { - aggregation_interval = "INTERVAL_5_SEC" - flow_sampling = 1 - metadata = "INCLUDE_ALL_METADATA" - } - } - ] - dmz = [ - { - name = "dmz-default" - ip_cidr_range = "10.64.128.0/24" - region = "us-central1" - description = "Default subnet for landing dmz in primary region" - flow_logs_config = { - aggregation_interval = "INTERVAL_5_SEC" - flow_sampling = 1 - metadata = "INCLUDE_ALL_METADATA" - } - } - ] - mgmt = [ - { - name = "mgmt-default" - ip_cidr_range = "10.64.129.0/24" - region = "us-central1" - description = "Default subnet for landing mgmt in primary region" - flow_logs_config = { - aggregation_interval = "INTERVAL_5_SEC" - flow_sampling = 1 - metadata = "INCLUDE_ALL_METADATA" - } - } - ] - prod = [ - { - name = "prod-tenant-1-subnet" - ip_cidr_range = "10.201.0.0/16" - region = "us-central1" - description = "Default subnet for prod environment in primary region" - flow_logs_config = { - aggregation_interval = "INTERVAL_5_SEC" - flow_sampling = 1 - metadata = "INCLUDE_ALL_METADATA" - } - tenant = "ten-1" # Links this subnet to tenant-1 project sharing - }, - { - name = "prod-tenant-2-subnet" - ip_cidr_range = "10.200.0.0/16" - region = "us-central1" - description = "Dedicated subnet for tenant-2 in prod spoke" - flow_logs_config = { - aggregation_interval = "INTERVAL_5_SEC" - flow_sampling = 1 - metadata = "INCLUDE_ALL_METADATA" - } - tenant = "ten-2" # Links this subnet to tenant-2 project sharing - } - ] - int = [ - { - name = "int-tenant-1-subnet" - ip_cidr_range = "10.150.0.0/16" - region = "us-central1" - description = "Default subnet for int environment in primary region" - flow_logs_config = { - aggregation_interval = "INTERVAL_5_SEC" - flow_sampling = 1 - metadata = "INCLUDE_ALL_METADATA" - } - tenant = "ten-1" - }, - { - name = "int-tenant-2-subnet" - ip_cidr_range = "10.151.0.0/16" - region = "us-central1" - description = "Dedicated subnet for tenant-2 in int spoke" - flow_logs_config = { - aggregation_interval = "INTERVAL_5_SEC" - flow_sampling = 1 - metadata = "INCLUDE_ALL_METADATA" - } - tenant = "ten-2" - } - ] - test = [ - { - name = "test-tenant-1-subnet" - ip_cidr_range = "10.100.0.0/16" - region = "us-central1" - description = "Default subnet for test environment in primary region" - flow_logs_config = { - aggregation_interval = "INTERVAL_5_SEC" - flow_sampling = 1 - metadata = "INCLUDE_ALL_METADATA" - } - tenant = "ten-1" - }, - { - name = "test-tenant-2-subnet" - ip_cidr_range = "10.101.0.0/16" - region = "us-central1" - description = "Dedicated subnet for tenant-2 in test spoke" - flow_logs_config = { - aggregation_interval = "INTERVAL_5_SEC" - flow_sampling = 1 - metadata = "INCLUDE_ALL_METADATA" - } - tenant = "ten-2" - } - ] -} - -# Proxy-only Subnet CIDRs (used for regional load balancers) -proxy_subnets = { - Prod = "10.1.1.0/24" - Int = "10.1.2.0/24" - Test = "10.1.3.0/24" -} - -# Named IP Ranges to reference in Firewall Rules -cidrs = { - healthchecks = [ - "35.191.0.0/16", - "130.211.0.0/22", - "209.85.152.0/22", - "209.85.204.0/22" - ] - rfc1918 = [ - "10.0.0.0/8", - "172.16.0.0/12", - "192.168.0.0/16" - ] - iap = [ - "35.235.240.0/20" - ] - internal = [ - "10.0.0.0/8" - ] -} - -# Custom Firewall Rules for each VPC / Spoke Spoke -firewall_rules = { - vdss = { - ingress = { - allow-iap-ssh-landing = { - description = "Allow traffic from Google IAP over SSH" - source_ranges = ["iap"] - rules = [ - { - protocol = "tcp" - ports = ["22"] - } - ] - } - allow-hc-nva-ssh-landing = { - description = "Allow traffic from Google healthchecks to NVA appliances" - source_ranges = ["healthchecks"] - rules = [ - { - protocol = "tcp" - ports = ["22"] - } - ] - } - allow-traffic-internal = { - description = "Allow traffic from inside the the networks" - targets = ["nva"] - source_ranges = ["10.0.0.0/8"] - } - } - } - dmz = { - ingress = { - allow-iap-ssh-dmz = { - description = "Allow traffic from Google IAP over SSH" - source_ranges = ["iap"] - rules = [ - { - protocol = "tcp" - ports = ["22"] - } - ] - } - allow-hc-nva-ssh-dmz = { - description = "Allow traffic from Google healthchecks to NVA appliances" - source_ranges = ["healthchecks"] - rules = [ - { - protocol = "tcp" - ports = ["22"] - } - ] - } - } - } - mgmt = { - ingress = { - allow-hc-nva-ssh-mgmt = { - description = "Allow traffic from Google healthchecks to NVA appliances" - source_ranges = ["healthchecks", "iap"] - rules = [ - { - protocol = "tcp" - ports = ["22"] - } - ] - } - allow-ssh-bastion-nva-mgmt = { - description = "We expect the bastion host to be able to SSH into the NGFWs" - sources = ["bastion"] - source_ranges = ["internal"] - targets = ["nva"] - rules = [ - { - protocol = "tcp" - ports = ["22", "443"] - } - ] - } - } - } - prod = { - ingress = { - allow-iap-ssh = { - description = "Allow traffic from Google IAP over SSH" - source_ranges = ["iap"] - rules = [ - { - protocol = "tcp" - ports = ["22"] - } - ] - } - } - } - int = { - ingress = { - allow-iap-ssh = { - description = "Allow traffic from Google IAP over SSH" - source_ranges = ["iap"] - rules = [ - { - protocol = "tcp" - ports = ["22"] - } - ] - } - } - } - test = { - ingress = { - allow-iap-ssh = { - description = "Allow traffic from Google IAP over SSH" - source_ranges = ["iap"] - rules = [ - { - protocol = "tcp" - ports = ["22"] - } - ] - } - } - } -} - -# Private DNS Zone Response Policy Rules -dns_policy_rules = { - accounts = { dns_name = "accounts.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - aiplatform-notebook-cloud-all = { dns_name = "*.aiplatform-notebook.cloud.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - aiplatform-notebook-gu-all = { dns_name = "*.aiplatform-notebook.googleusercontent.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - backupdr-cloud = { dns_name = "backupdr.cloud.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - backupdr-cloud-all = { dns_name = "*.backupdr.cloud.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - backupdr-gu = { dns_name = "backupdr.googleusercontent.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - backupdr-gu-all = { dns_name = "*.backupdr.googleusercontent.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - cloudfunctions = { dns_name = "*.cloudfunctions.net.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - cloudproxy = { dns_name = "*.cloudproxy.app.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - composer-cloud-all = { dns_name = "*.composer.cloud.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - composer-gu-all = { dns_name = "*.composer.googleusercontent.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - datafusion-all = { dns_name = "*.datafusion.cloud.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - datafusion-gu-all = { dns_name = "*.datafusion.googleusercontent.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - dataproc = { dns_name = "dataproc.cloud.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - dataproc-all = { dns_name = "*.dataproc.cloud.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - dataproc-gu = { dns_name = "dataproc.googleusercontent.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - dataproc-gu-all = { dns_name = "*.dataproc.googleusercontent.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - dl = { dns_name = "dl.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - gcr = { dns_name = "gcr.io.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - gcr-all = { dns_name = "*.gcr.io.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - gke-all = { dns_name = "*.gke.goog.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - googleapis-all = { dns_name = "*.googleapis.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - googleapis-private = { dns_name = "private.googleapis.com.", local_data = { A = { rrdatas = ["199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11"] } } } - googleapis-restricted = { dns_name = "restricted.googleapis.com.", local_data = { A = { rrdatas = ["199.36.153.4", "199.36.153.5", "199.36.153.6", "199.36.153.7"] } } } - gstatic-all = { dns_name = "*.gstatic.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - kernels-gu = { dns_name = "kernels.googleusercontent.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - kernels-gu-all = { dns_name = "*.kernels.googleusercontent.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - ltsapis-all = { dns_name = "*.ltsapis.goog.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - notebooks-all = { dns_name = "*.notebooks.cloud.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - notebooks-gu-all = { dns_name = "*.notebooks.googleusercontent.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - packages-cloud = { dns_name = "packages.cloud.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - packages-cloud-all = { dns_name = "*.packages.cloud.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - pkgdev = { dns_name = "pkg.dev.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - pkgdev-all = { dns_name = "*.pkg.dev.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - pkigoog = { dns_name = "pki.goog.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - pkigoog-all = { dns_name = "*.pki.goog.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - run-all = { dns_name = "*.run.app.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - source = { dns_name = "source.developers.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } - storage = { dns_name = "storage.cloud.google.com.", local_data = { CNAME = { rrdatas = ["private.googleapis.com."] } } } -} diff --git a/fast/stages-aw/1-resman/IAM.md b/fast/stages-aw/2-resman/IAM.md similarity index 96% rename from fast/stages-aw/1-resman/IAM.md rename to fast/stages-aw/2-resman/IAM.md index 6619a2534..583898bd0 100644 --- a/fast/stages-aw/1-resman/IAM.md +++ b/fast/stages-aw/2-resman/IAM.md @@ -1,3 +1,19 @@ + + # IAM bindings reference Legend: + additive, conditional. diff --git a/fast/stages-aw/1-resman/README.md b/fast/stages-aw/2-resman/README.md similarity index 74% rename from fast/stages-aw/1-resman/README.md rename to fast/stages-aw/2-resman/README.md index 0004ce023..c1085f82f 100644 --- a/fast/stages-aw/1-resman/README.md +++ b/fast/stages-aw/2-resman/README.md @@ -1,3 +1,19 @@ + + # Resource Hierarchy This stage provisions Int, Test, and Prod Google Cloud Folders, and Google Cloud Projects contained within, for tenants. In addition, it lays the framework for the subsequent network and security stages by creating the Google Cloud Folder structure for both. There is substantial modification from the original CFF structure, as all Google Cloud Projects MUST reside within the scope of an Assured Workloads Google Cloud Folder. @@ -13,17 +29,18 @@ This stage provisions Int, Test, and Prod Google Cloud Folders, and Google Cloud - [Team Google Cloud Folders](#team-google-cloud-folders) - [IAM](#iam) - [Additional Google Cloud Folders](#additional-google-cloud-folders) + - [Tenant Log Sinks](#tenant-log-sinks) - [Variables](#variables) - [Outputs](#outputs) ## Design Overview and Choices -The design of this stage ensures that all parts of a Stellar Engine deployment reside within an Assured Workloads Google Cloud Folder; this prevents things like logs from living outside a compliant domain. +The design of this stage ensures that all parts of a Stellar Engine Landing Zone deployment reside within an Assured Workloads Google Cloud Folder; this prevents things like logs from living outside a compliant domain. ## How to Run This Stage -For detailed information on prerequisites and steps to deploy this stage, please see the latest [Detailed Deployment Guide (DDG)](/docs/ddg.md) If you do not have access, you will have to request it. +For detailed information on prerequisites and steps to deploy this stage, please see the latest [stellar-engine Cloud Engineer Development Guide](https://docs.google.com/document/d/1o39QZ-K5CTP8FdTs9Jgz3JRF7HZ8in-1QoM0SCcIEAk/edit?tab=t.0#heading=h.tvlxzbk3nqgs) and scroll down to stellar-engine - Automation section. If you do not have access, you will have to request it. ### Impersonating the Automation Service Account @@ -31,7 +48,7 @@ The preconfigured provider file uses impersonation to run with this stage's auto ### Lightweight multitenancy -If the organization needs to support tenants without the full complexity and separation offered by our [full multitenant support](../../stages-multitenant/), this stage offers a simplified setup which is suitable for cases where tenants have less autonomy, and don't need to implement FAST stages inside their reserved partition. +If the organization needs to support tenants without the full complexity and separation offered by our [full multitenant support](../5-tenants/), this stage offers a simplified setup which is suitable for cases where tenants have less autonomy, and don't need to implement FAST stages inside their reserved partition. This mode is activated by defining tenants in the `tenants` variable, while IAM configurations that apply to every tenant can be optionally set in the `tenants_config` variable. @@ -122,7 +139,7 @@ This is a list of the variables that need edited to set the Tenant name. ```tfvars tenants = { -{{EDIT_THIS_VARIABLE_TO_THE_FIRST_TENANT_NAME}} = { +{{EDIT_THIS_VARIABLE_TO_THE_FIRST_TENANT_NAME}} = admin_principal = "group:gcp-devops@example.com" descriptive_name = "{{EDIT_THIS_VARIABLE_TO_THE_FIRST_TENANT_DESCRIPTION}}" locations = { @@ -130,7 +147,7 @@ tenants = { kms = "us-east4" # Must match GCS Region } }, - {{EDIT_THIS_VARIABLE_TO_THE_SECOND_TENANT_NAME}} = { + {{EDIT_THIS_VARIABLE_TO_THE_SECOND_TENANT_NAME}} = admin_principal = "group:gcp-devops@example.com" descriptive_name = "{{EDIT_THIS_VARIABLE_TO_THE_SECOND_TENANT_DESCRIPTION}}" locations = { @@ -145,7 +162,7 @@ This is an example that shows a configured variable block with two example Tenan ```tfvars tenants = { -wingarch = { +wingarch = admin_principal = "group:gcp-devops@example.com" descriptive_name = "Wing Architect Research Group" locations = { @@ -153,7 +170,7 @@ wingarch = { kms = "us-east4" # Must match GCS Region } }, - fuselagerd = { + fuselagerd = admin_principal = "group:gcp-devops@example.com" descriptive_name = "Fuselage Research & Development Group" locations = { @@ -212,56 +229,59 @@ This allows to centralize the minimum set of resources to delegate control of ea ### IAM -The `folder_iam` variable can be used to manage authoritative bindings for all top-level Google Cloud Folders. For additional control, IAM roles can be easily edited in the relevant `branch-xxx.tf` file, following the best practice outlined in the [bootstrap stage](../0-bootstrap#customizations) documentation of separating user-level and service-account level IAM policies throuth the IAM-related variables (`iam`, `iam_bindings`, `iam_bindings_additive`) of the relevant modules. +The `folder_iam` variable can be used to manage authoritative bindings for all top-level Google Cloud Folders. For additional control, IAM roles can be easily edited in the relevant `branch-xxx.tf` file, following the best practice outlined in the [bootstrap stage](../1-assured-workload#customizations) documentation of separating user-level and service-account level IAM policies through the IAM-related variables (`iam`, `iam_bindings`, `iam_bindings_additive`) of the relevant modules. -A full reference of IAM roles managed by this stage [is available here](./IAM.md). +A full reference of IAM roles managed by this stage [is available here](#). ### Additional Google Cloud Folders Due to its simplicity, this stage lends itself easily to customizations: adding a new top-level branch (e.g. for shared GKE clusters) is as easy as cloning one of the `branch-xxx.tf` files, and changing names. +### Tenant Log Sinks + +Organization-level logging sinks for tenants creates a centralize log route from tenant folders to dedicated log buckets during the stage they are created. This customization is integrated from the bootstrap stage where outputs are staged. It captures logs from the tenant folders, projects, and all their related activities including automated tenant mappings for routing purposes. + --- ## Variables | name | description | type | required | default | |---|---|:---:|:---:|:---:| -| [alert_email](variables.tf#L18) | Email to receive log alerts. | string | ✓ | | -| [automation](variables.tf#L34) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | -| [billing_account](variables.tf#L57) | Billing account id. If billing account is not part of the same org set `is_org_level` to `false`. To disable handling of billing IAM roles set `no_iam` to `true`. | object({…}) | ✓ | | -| [common_services_folder](variables.tf#L162) | Common services folder where non-tenant related resources should be kept. | string | ✓ | | -| [envs_folders](variables.tf#L179) | List of environments to be created for projects to go into. | map(object({…})) | ✓ | | +| [automation](variables.tf#L30) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | +| [billing_account](variables.tf#L58) | Billing account id. If billing account is not part of the same org set `is_org_level` to `false`. To disable handling of billing IAM roles set `no_iam` to `true`. | object({…}) | ✓ | | +| [common_services_folder](variables.tf#L169) | Common services folder where non-tenant related resources should be kept. | string | ✓ | | | [organization](variables.tf#L263) | Organization details. | object({…}) | ✓ | | | [prefix](variables.tf#L279) | Prefix used for resources that need unique names. Use 7 characters or less. | string | ✓ | | | [regime_mapping](variables.tf#L290) | Mapping of compliance regime names to short codes. | map(string) | ✓ | | -| [assured_workloads](variables.tf#L23) | Configuration for Assured Workloads. | object({…}) | | {} | -| [cicd_repositories](variables.tf#L68) | CI/CD repository configuration. Identity providers reference keys in the `automation.federated_identity_providers` variable. Set to null to disable, or set individual repositories to null if not needed. | object({…}) | | null | -| [custom_roles](variables.tf#L167) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | +| [shared_services_project_id](variables.tf#L295) | The project ID for shared services inherited from Stage 1. | string | ✓ | | +| [tenant_environments](variables.tf#L316) | List of environments to be created for projects to go into. | map(object({…})) | ✓ | | +| [top_level_folder](variables.tf#L323) | Top Level Folder Details. | object({…}) | ✓ | | +| [assured_workloads](variables.tf#L19) | Configuration for Assured Workloads. | object({…}) | | {} | +| [cicd_repositories](variables.tf#L69) | CI/CD repository configuration. Identity providers reference keys in the `automation.federated_identity_providers` variable. Set to null to disable, or set individual repositories to null if not needed. | object({…}) | | null | +| [custom_roles](variables.tf#L174) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | | [factories_config](variables.tf#L186) | Configuration for the resource factories or external data. | object({…}) | | {} | | [fast_features](variables.tf#L195) | Selective control for top-level FAST features. | object({…}) | | {} | | [folder_iam](variables.tf#L211) | Authoritative IAM for top-level folders. | object({…}) | | {} | | [groups](variables.tf#L228) | Group names or IAM-format principals to grant organization-level permissions. If just the name is provided, the 'group:' principal and organization domain are interpolated. | object({…}) | | {} | -| [locations](variables.tf#L243) | Optional locations for GCS, BigQuery, and logging buckets created here. | object({…}) | | {…} | +| [locations](variables.tf#L243) | Optional locations for GCS, BigQuery, and logging buckets created here. | object({…}) | | {…} | | [outputs_location](variables.tf#L273) | Enable writing provider, tfvars and CI/CD workflow files to local filesystem. Leave null to disable. | string | | null | -| [team_folders](variables.tf#L295) | Team folders to be created. Format is described in a code comment. | map(object({…})) | | null | -| [tenants](variables.tf#L311) | Lightweight tenant definitions. | map(object({…})) | | {} | -| [tenants_config](variables.tf#L340) | Lightweight tenants shared configuration. Roles will be assigned to tenant admin group and service accounts. | object({…}) | | {} | +| [team_folders](variables.tf#L300) | Team folders to be created. Format is described in a code comment. | map(object({…})) | | null | ## Outputs | name | description | sensitive | |---|---|:---:| -| [cicd_repositories](outputs.tf#L396) | WIF configuration for CI/CD repositories. | | -| [dataplatform](outputs.tf#L410) | Data for the Data Platform stage. | | -| [envs](outputs.tf#L426) | Environments folders created for the tenants. | | -| [gcve](outputs.tf#L431) | Data for the GCVE stage. | | -| [gke_multitenant](outputs.tf#L452) | Data for the GKE multitenant stage. | | -| [networking](outputs.tf#L473) | Data for the networking stage. | | -| [project_factories](outputs.tf#L482) | Data for the project factories stage. | | -| [providers](outputs.tf#L497) | Terraform provider files for this stage and dependent stages. | ✓ | -| [sandbox](outputs.tf#L504) | Data for the sandbox stage. | | -| [security](outputs.tf#L518) | Data for the networking stage. | | -| [team_cicd_repositories](outputs.tf#L528) | WIF configuration for Team CI/CD repositories. | | -| [teams](outputs.tf#L542) | Data for the teams stage. | | -| [tfvars](outputs.tf#L554) | Terraform variable files for the following stages. | ✓ | +| [cicd_repositories](outputs.tf#L440) | WIF configuration for CI/CD repositories. | | +| [dataplatform](outputs.tf#L454) | Data for the Data Platform stage. | | +| [gcve](outputs.tf#L470) | Data for the GCVE stage. | | +| [gke_multitenant](outputs.tf#L491) | Data for the GKE multitenant stage. | | +| [networking](outputs.tf#L512) | Data for the networking stage. | | +| [project_factories](outputs.tf#L521) | Data for the project factories stage. | | +| [providers](outputs.tf#L536) | Terraform provider files for this stage and dependent stages. | ✓ | +| [sandbox](outputs.tf#L543) | Data for the sandbox stage. | | +| [security](outputs.tf#L557) | Data for the networking stage. | | +| [shared_services](outputs.tf#L567) | Data for the shared-services stage. | | +| [team_cicd_repositories](outputs.tf#L575) | WIF configuration for Team CI/CD repositories. | | +| [teams](outputs.tf#L589) | Data for the teams stage. | | +| [tfvars](outputs.tf#L601) | Terraform variable files for the following stages. | ✓ | diff --git a/fast/stages-aw/1-resman/billing.tf b/fast/stages-aw/2-resman/billing.tf similarity index 98% rename from fast/stages-aw/1-resman/billing.tf rename to fast/stages-aw/2-resman/billing.tf index 64b87c265..cd17783da 100644 --- a/fast/stages-aw/1-resman/billing.tf +++ b/fast/stages-aw/2-resman/billing.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Billing resources for external billing use cases. locals { @@ -43,6 +42,7 @@ locals { # standalone billing account + resource "google_billing_account_iam_member" "billing_ext_admin" { for_each = toset( local.billing_mode == "resource" ? local.billing_ext_users : [] @@ -59,4 +59,4 @@ resource "google_billing_account_iam_member" "billing_ext_costsmanager" { billing_account_id = var.billing_account.id role = "roles/billing.costsManager" member = each.key -} +} \ No newline at end of file diff --git a/fast/stages-aw/1-resman/branch-data-platform.tf b/fast/stages-aw/2-resman/branch-data-platform.tf similarity index 98% rename from fast/stages-aw/1-resman/branch-data-platform.tf rename to fast/stages-aw/2-resman/branch-data-platform.tf index dc967621f..d629f22de 100644 --- a/fast/stages-aw/1-resman/branch-data-platform.tf +++ b/fast/stages-aw/2-resman/branch-data-platform.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Data Platform stages resources. module "branch-dp-folder" { @@ -160,7 +159,7 @@ module "branch-dp-dev-gcs" { project_id = var.automation.project_id name = "dev-resman-dp-0" prefix = var.prefix - location = var.regions.primary + location = local.primary_location_gcs storage_class = local.gcs_storage_class versioning = true iam = { @@ -175,7 +174,7 @@ module "branch-dp-prod-gcs" { project_id = var.automation.project_id name = "prod-resman-dp-0" prefix = var.prefix - location = var.regions.primary + location = local.primary_location_gcs storage_class = local.gcs_storage_class versioning = true iam = { diff --git a/fast/stages-aw/2-resman/branch-envs.tf b/fast/stages-aw/2-resman/branch-envs.tf new file mode 100644 index 000000000..2c0b9a2d0 --- /dev/null +++ b/fast/stages-aw/2-resman/branch-envs.tf @@ -0,0 +1,30 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# tfdoc:file:description Team stage resources. +module "branch-envs-sa" { + source = "../../../modules/iam-service-account" + count = var.fast_features.envs ? 1 : 0 + project_id = var.automation.project_id + name = "prod-resman-envs-0" + display_name = "Terraform resman envs service account." + prefix = var.prefix + iam_project_roles = { + (var.automation.project_id) = ["roles/serviceusage.serviceUsageConsumer"] + } + iam_storage_roles = { + (var.automation.outputs_bucket) = ["roles/storage.objectAdmin"] + } +} diff --git a/fast/stages-aw/1-resman/branch-gcve.tf b/fast/stages-aw/2-resman/branch-gcve.tf similarity index 98% rename from fast/stages-aw/1-resman/branch-gcve.tf rename to fast/stages-aw/2-resman/branch-gcve.tf index 26cffea5d..4365c2b8e 100644 --- a/fast/stages-aw/1-resman/branch-gcve.tf +++ b/fast/stages-aw/2-resman/branch-gcve.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description GCVE stage resources. module "branch-gcve-folder" { @@ -161,7 +160,7 @@ module "branch-gcve-dev-gcs" { project_id = var.automation.project_id name = "dev-resman-gcve-0" prefix = var.prefix - location = var.regions.primary + location = local.primary_location_gcs storage_class = local.gcs_storage_class versioning = true iam = { @@ -176,7 +175,7 @@ module "branch-gcve-prod-gcs" { project_id = var.automation.project_id name = "prod-resman-gcve-0" prefix = var.prefix - location = var.regions.primary + location = local.primary_location_gcs storage_class = local.gcs_storage_class versioning = true iam = { diff --git a/fast/stages-aw/1-resman/branch-gke.tf b/fast/stages-aw/2-resman/branch-gke.tf similarity index 98% rename from fast/stages-aw/1-resman/branch-gke.tf rename to fast/stages-aw/2-resman/branch-gke.tf index c7b830a45..2aea41597 100644 --- a/fast/stages-aw/1-resman/branch-gke.tf +++ b/fast/stages-aw/2-resman/branch-gke.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description GKE multitenant stage resources. module "branch-gke-folder" { @@ -161,7 +160,7 @@ module "branch-gke-dev-gcs" { project_id = var.automation.project_id name = "dev-resman-gke-0" prefix = var.prefix - location = var.regions.primary + location = local.primary_location_gcs storage_class = local.gcs_storage_class versioning = true iam = { @@ -176,7 +175,7 @@ module "branch-gke-prod-gcs" { project_id = var.automation.project_id name = "prod-resman-gke-0" prefix = var.prefix - location = var.regions.primary + location = local.primary_location_gcs storage_class = local.gcs_storage_class versioning = true iam = { diff --git a/fast/stages-aw/1-resman/branch-networking.tf b/fast/stages-aw/2-resman/branch-networking.tf similarity index 80% rename from fast/stages-aw/1-resman/branch-networking.tf rename to fast/stages-aw/2-resman/branch-networking.tf index 61ef77e08..2ab54c653 100644 --- a/fast/stages-aw/1-resman/branch-networking.tf +++ b/fast/stages-aw/2-resman/branch-networking.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Networking stage resources. locals { @@ -50,6 +49,7 @@ module "branch-network-folder" { "roles/editor", ] } + org_policies = yamldecode(file("./data/allow_ncc.yaml")) iam = local._network_folder_iam tag_bindings = null } @@ -64,17 +64,25 @@ module "branch-network-sa" { prefix = var.prefix iam = { "roles/iam.serviceAccountTokenCreator" = compact([ - try(module.branch-network-sa-cicd[0].iam_email, null) + try(module.branch-network-sa-cicd[0].iam_email, null), + try(module.branch-network-r-sa-cicd[0].iam_email, null) ]) } iam_project_roles = { - (var.automation.project_id) = ["roles/serviceusage.serviceUsageConsumer"] + (var.automation.project_id) = ["roles/serviceusage.serviceUsageConsumer"], + (var.shared_services_project_id) = ["roles/networkconnectivity.spokeAdmin"] } iam_storage_roles = { (var.automation.outputs_bucket) = ["roles/storage.objectAdmin"] } } + +resource "google_billing_account_iam_member" "networking_billing_admins" { + billing_account_id = var.billing_account.id + role = "roles/billing.admin" + member = "serviceAccount:${module.branch-network-sa.email}" +} # automation read-only service account module "branch-network-r-sa" { @@ -101,17 +109,15 @@ module "branch-network-r-sa" { module "branch-network-gcs" { source = "../../../modules/gcs" project_id = var.automation.project_id - name = "prod-resman-net-0" + name = lower("${replace(lookup(var.regime_mapping, var.assured_workloads.regime, var.assured_workloads.regime), "_", " ")}-prod-resman-net-0") prefix = var.prefix - location = var.regions.primary + location = local.primary_location_gcs storage_class = local.gcs_storage_class versioning = true - force_destroy = true iam = { "roles/storage.objectAdmin" = [module.branch-network-sa.iam_email] "roles/storage.objectViewer" = [module.branch-network-r-sa.iam_email] } - encryption_key = "projects/${var.automation.project_id}/locations/${var.regions.primary}/keyRings/gcs/cryptoKeys/gcs" - depends_on = [google_kms_crypto_key_iam_member.resman_bootstrap_kms] + encryption_key = "projects/${var.automation.project_id}/locations/${local.primary_location_gcs}/keyRings/gcs-${local.primary_location_kms}/cryptoKeys/gcs" } diff --git a/fast/stages-aw/1-resman/branch-project-factory.tf b/fast/stages-aw/2-resman/branch-project-factory.tf similarity index 97% rename from fast/stages-aw/1-resman/branch-project-factory.tf rename to fast/stages-aw/2-resman/branch-project-factory.tf index b4ea2d136..49c705d4d 100644 --- a/fast/stages-aw/1-resman/branch-project-factory.tf +++ b/fast/stages-aw/2-resman/branch-project-factory.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Project factory stage resources. # automation service accounts @@ -108,7 +107,7 @@ module "branch-pf-dev-gcs" { project_id = var.automation.project_id name = "dev-resman-pf-0" prefix = var.prefix - location = var.regions.primary + location = local.primary_location_gcs storage_class = local.gcs_storage_class versioning = true iam = { @@ -123,7 +122,7 @@ module "branch-pf-prod-gcs" { project_id = var.automation.project_id name = "prod-resman-pf-0" prefix = var.prefix - location = var.regions.primary + location = local.primary_location_gcs storage_class = local.gcs_storage_class versioning = true iam = { diff --git a/fast/stages-aw/1-resman/branch-sandbox.tf b/fast/stages-aw/2-resman/branch-sandbox.tf similarity index 97% rename from fast/stages-aw/1-resman/branch-sandbox.tf rename to fast/stages-aw/2-resman/branch-sandbox.tf index 2866612cc..9bc095b3c 100644 --- a/fast/stages-aw/1-resman/branch-sandbox.tf +++ b/fast/stages-aw/2-resman/branch-sandbox.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Sandbox stage resources. locals { @@ -54,7 +53,7 @@ module "branch-sandbox-gcs" { project_id = var.automation.project_id name = "dev-resman-sbox-0" prefix = var.prefix - location = var.regions.primary + location = local.primary_location_gcs storage_class = local.gcs_storage_class versioning = true iam = { diff --git a/fast/stages-aw/1-resman/branch-security.tf b/fast/stages-aw/2-resman/branch-security.tf similarity index 84% rename from fast/stages-aw/1-resman/branch-security.tf rename to fast/stages-aw/2-resman/branch-security.tf index 79f72594f..69fa34744 100644 --- a/fast/stages-aw/1-resman/branch-security.tf +++ b/fast/stages-aw/2-resman/branch-security.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Security stage resources. locals { @@ -63,7 +62,8 @@ module "branch-security-sa" { prefix = var.prefix iam = { "roles/iam.serviceAccountTokenCreator" = compact([ - try(module.branch-security-sa-cicd[0].iam_email, null) + try(module.branch-security-sa-cicd[0].iam_email, null), + try(module.branch-security-r-sa-cicd[0].iam_email, null) ]) } iam_project_roles = { @@ -74,6 +74,13 @@ module "branch-security-sa" { } } + +resource "google_billing_account_iam_member" "security_billing_admins" { + billing_account_id = var.billing_account.id + role = "roles/billing.admin" + member = "serviceAccount:${module.branch-security-sa.email}" +} + # automation read-only service account module "branch-security-r-sa" { @@ -100,18 +107,16 @@ module "branch-security-r-sa" { module "branch-security-gcs" { source = "../../../modules/gcs" project_id = var.automation.project_id - name = "prod-resman-sec-0" + name = lower("${replace(lookup(var.regime_mapping, var.assured_workloads.regime, var.assured_workloads.regime), "_", " ")}-prod-resman-sec") prefix = var.prefix - location = var.regions.primary + location = local.primary_location_gcs storage_class = local.gcs_storage_class versioning = true - force_destroy = true iam = { "roles/storage.objectAdmin" = [module.branch-security-sa.iam_email] "roles/storage.objectViewer" = [module.branch-security-r-sa.iam_email] } - encryption_key = "projects/${var.automation.project_id}/locations/${var.regions.primary}/keyRings/gcs/cryptoKeys/gcs" - depends_on = [google_kms_crypto_key_iam_member.resman_bootstrap_kms] + encryption_key = "projects/${var.automation.project_id}/locations/${local.primary_location_kms}/keyRings/gcs-${local.primary_location_kms}/cryptoKeys/gcs" } diff --git a/fast/stages-aw/2-resman/branch-shared-services.tf b/fast/stages-aw/2-resman/branch-shared-services.tf new file mode 100644 index 000000000..85ae4f95c --- /dev/null +++ b/fast/stages-aw/2-resman/branch-shared-services.tf @@ -0,0 +1,77 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# tfdoc:file:description Shared services stage resources. + +# automation service account + +module "branch-shared-services-sa" { + source = "../../../modules/iam-service-account" + project_id = var.automation.project_id + name = "resman-shdsvc-0" + display_name = "Terraform resman shared-services service account." + prefix = var.prefix + iam = { + "roles/iam.serviceAccountTokenCreator" = compact([ + try(module.branch-shared-services-sa-cicd[0].iam_email, null), + try(module.branch-shared-services-r-sa-cicd[0].iam_email, null) + ]) + } + iam_project_roles = { + (var.automation.project_id) = ["roles/serviceusage.serviceUsageConsumer"] + (var.shared_services_project_id) = ["roles/owner"] + } + iam_storage_roles = { + (var.automation.outputs_bucket) = ["roles/storage.objectAdmin"] + } + iam_folder_roles = { + (var.common_services_folder) = ["roles/compute.xpnAdmin"] + } +} + +# automation read-only service account + +module "branch-shared-services-r-sa" { + source = "../../../modules/iam-service-account" + project_id = var.automation.project_id + name = "resman-shdsvc-0r" + display_name = "Terraform resman shared-services service account (read-only)." + prefix = var.prefix + iam = {} + iam_project_roles = { + (var.automation.project_id) = ["roles/serviceusage.serviceUsageConsumer"] + } + iam_storage_roles = { + (var.automation.outputs_bucket) = [var.custom_roles["storage_viewer"]] + } +} + +# automation bucket + +module "branch-shared-services-gcs" { + source = "../../../modules/gcs" + project_id = var.automation.project_id + name = lower("${replace(lookup(var.regime_mapping, var.assured_workloads.regime, var.assured_workloads.regime), "_", " ")}-resman-shdsvc") + prefix = var.prefix + location = local.primary_location_gcs + storage_class = local.gcs_storage_class + versioning = true + iam = { + "roles/storage.objectAdmin" = [module.branch-shared-services-sa.iam_email] + "roles/storage.objectViewer" = [module.branch-shared-services-r-sa.iam_email] + } + + encryption_key = "projects/${var.automation.project_id}/locations/${local.primary_location_kms}/keyRings/gcs-${local.primary_location_kms}/cryptoKeys/gcs" +} diff --git a/fast/stages-aw/1-resman/branch-teams.tf b/fast/stages-aw/2-resman/branch-teams.tf similarity index 97% rename from fast/stages-aw/1-resman/branch-teams.tf rename to fast/stages-aw/2-resman/branch-teams.tf index 34a3b08d8..91425fe98 100644 --- a/fast/stages-aw/1-resman/branch-teams.tf +++ b/fast/stages-aw/2-resman/branch-teams.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Team stage resources. +# TODO(ludo): add support for CI/CD locals { # FAST-specific IAM _teams_folder_fast_iam = !var.fast_features.teams ? {} : { @@ -65,7 +65,7 @@ module "branch-teams-gcs" { project_id = var.automation.project_id name = "prod-resman-teams-0" prefix = var.prefix - location = var.regions.primary + location = local.primary_location_gcs storage_class = local.gcs_storage_class versioning = true iam = { @@ -89,6 +89,7 @@ module "branch-teams-team-folder" { iam_by_principals = each.value.iam_by_principals == null ? {} : each.value.iam_by_principals } +# TODO: move into team's own IaC project module "branch-teams-team-sa" { source = "../../../modules/iam-service-account" @@ -115,7 +116,7 @@ module "branch-teams-team-gcs" { project_id = var.automation.project_id name = "prod-teams-${each.key}-0" prefix = var.prefix - location = var.regions.primary + location = local.primary_location_gcs storage_class = local.gcs_storage_class versioning = true iam = { diff --git a/fast/stages-aw/2-resman/changelog b/fast/stages-aw/2-resman/changelog new file mode 100644 index 000000000..470510af1 --- /dev/null +++ b/fast/stages-aw/2-resman/changelog @@ -0,0 +1,5 @@ +2606091411 +2606091512 +2606101328 +2606111153 + diff --git a/fast/stages-aw/1-resman/checklist.tf b/fast/stages-aw/2-resman/checklist.tf similarity index 99% rename from fast/stages-aw/1-resman/checklist.tf rename to fast/stages-aw/2-resman/checklist.tf index 55b57bc8c..cf0da45d4 100644 --- a/fast/stages-aw/1-resman/checklist.tf +++ b/fast/stages-aw/2-resman/checklist.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { # parse raw data from JSON files if they exist _cl_data_raw = ( diff --git a/fast/stages-aw/1-resman/cicd-data-platform.tf b/fast/stages-aw/2-resman/cicd-data-platform.tf similarity index 99% rename from fast/stages-aw/1-resman/cicd-data-platform.tf rename to fast/stages-aw/2-resman/cicd-data-platform.tf index a544f5c36..870e3f5fe 100644 --- a/fast/stages-aw/1-resman/cicd-data-platform.tf +++ b/fast/stages-aw/2-resman/cicd-data-platform.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description CI/CD resources for the data platform branch. # source repositories diff --git a/fast/stages-aw/1-resman/cicd-gcve.tf b/fast/stages-aw/2-resman/cicd-gcve.tf similarity index 99% rename from fast/stages-aw/1-resman/cicd-gcve.tf rename to fast/stages-aw/2-resman/cicd-gcve.tf index 119ae8bba..e6cd0b5a9 100644 --- a/fast/stages-aw/1-resman/cicd-gcve.tf +++ b/fast/stages-aw/2-resman/cicd-gcve.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description CI/CD resources for the GCVE branch. # source repositories diff --git a/fast/stages-aw/1-resman/cicd-gke.tf b/fast/stages-aw/2-resman/cicd-gke.tf similarity index 99% rename from fast/stages-aw/1-resman/cicd-gke.tf rename to fast/stages-aw/2-resman/cicd-gke.tf index 4125104bb..9cbf88e0a 100644 --- a/fast/stages-aw/1-resman/cicd-gke.tf +++ b/fast/stages-aw/2-resman/cicd-gke.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description CI/CD resources for the GKE multitenant branch. # source repositories diff --git a/fast/stages-aw/1-resman/cicd-networking.tf b/fast/stages-aw/2-resman/cicd-networking.tf similarity index 92% rename from fast/stages-aw/1-resman/cicd-networking.tf rename to fast/stages-aw/2-resman/cicd-networking.tf index 2215e9baa..501dc6956 100644 --- a/fast/stages-aw/1-resman/cicd-networking.tf +++ b/fast/stages-aw/2-resman/cicd-networking.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description CI/CD resources for the networking branch. # source repository @@ -32,7 +31,7 @@ module "branch-network-cicd-repo" { "roles/source.reader" = [module.branch-network-sa-cicd[0].iam_email] } triggers = { - fast-02-networking = { + fast-03-networking = { filename = ".cloudbuild/workflow.yaml" included_files = ["**/*tf", ".cloudbuild/workflow.yaml"] service_account = module.branch-network-sa-cicd[0].id @@ -86,10 +85,14 @@ module "branch-network-sa-cicd" { } ) iam_project_roles = { - (var.automation.project_id) = ["roles/logging.logWriter"] + (var.automation.project_id) = [ + "roles/logging.logWriter", + "roles/iam.serviceAccountTokenCreator" + ] } iam_storage_roles = { (var.automation.outputs_bucket) = ["roles/storage.objectViewer"] + (var.automation.config_bucket) = ["roles/storage.objectViewer"] } } @@ -126,5 +129,6 @@ module "branch-network-r-sa-cicd" { } iam_storage_roles = { (var.automation.outputs_bucket) = ["roles/storage.objectViewer"] + (var.automation.config_bucket) = ["roles/storage.objectViewer"] } } diff --git a/fast/stages-aw/1-resman/cicd-project-factory.tf b/fast/stages-aw/2-resman/cicd-project-factory.tf similarity index 99% rename from fast/stages-aw/1-resman/cicd-project-factory.tf rename to fast/stages-aw/2-resman/cicd-project-factory.tf index 009199c2e..dbe76d9de 100644 --- a/fast/stages-aw/1-resman/cicd-project-factory.tf +++ b/fast/stages-aw/2-resman/cicd-project-factory.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description CI/CD resources for the teams branch. # source repositories diff --git a/fast/stages-aw/1-resman/cicd-security.tf b/fast/stages-aw/2-resman/cicd-security.tf similarity index 95% rename from fast/stages-aw/1-resman/cicd-security.tf rename to fast/stages-aw/2-resman/cicd-security.tf index d0dab9236..a44a581d4 100644 --- a/fast/stages-aw/1-resman/cicd-security.tf +++ b/fast/stages-aw/2-resman/cicd-security.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description CI/CD resources for the security branch. # source repository @@ -32,7 +31,7 @@ module "branch-security-cicd-repo" { "roles/source.reader" = [module.branch-security-sa-cicd[0].iam_email] } triggers = { - fast-03-security = { + fast-04-security = { filename = ".cloudbuild/workflow.yaml" included_files = ["**/*tf", ".cloudbuild/workflow.yaml"] service_account = module.branch-security-sa-cicd[0].id @@ -90,6 +89,7 @@ module "branch-security-sa-cicd" { } iam_storage_roles = { (var.automation.outputs_bucket) = ["roles/storage.objectViewer"] + (var.automation.config_bucket) = ["roles/storage.objectViewer"] } } @@ -126,5 +126,6 @@ module "branch-security-r-sa-cicd" { } iam_storage_roles = { (var.automation.outputs_bucket) = ["roles/storage.objectViewer"] + (var.automation.config_bucket) = ["roles/storage.objectViewer"] } } diff --git a/fast/stages-aw/2-resman/cicd-shared-services.tf b/fast/stages-aw/2-resman/cicd-shared-services.tf new file mode 100644 index 000000000..0d6a08232 --- /dev/null +++ b/fast/stages-aw/2-resman/cicd-shared-services.tf @@ -0,0 +1,131 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# tfdoc:file:description CI/CD resources for the shared-services branch. + +# source repository + +module "branch-shared-services-cicd-repo" { + source = "../../../modules/source-repository" + for_each = ( + try(local.cicd_repositories.shared_services.type, null) == "sourcerepo" + ? { 0 = local.cicd_repositories.shared_services } + : {} + ) + project_id = var.automation.project_id + name = each.value.name + iam = { + "roles/source.admin" = [module.branch-shared-services-sa.iam_email] + "roles/source.reader" = [module.branch-shared-services-sa-cicd[0].iam_email] + } + triggers = { + fast-shared-services = { + filename = ".cloudbuild/workflow.yaml" + included_files = ["**/*tf", ".cloudbuild/workflow.yaml"] + service_account = module.branch-shared-services-sa-cicd[0].id + substitutions = {} + template = { + project_id = null + branch_name = each.value.branch + repo_name = each.value.name + tag_name = null + } + } + } + depends_on = [module.branch-shared-services-sa-cicd] +} + +# read-write (apply) SA used by CI/CD workflows to impersonate automation SA + +module "branch-shared-services-sa-cicd" { + source = "../../../modules/iam-service-account" + for_each = ( + try(local.cicd_repositories.shared_services.name, null) != null + ? { 0 = local.cicd_repositories.shared_services } + : {} + ) + project_id = var.automation.project_id + name = "resman-shdsvc-1" + display_name = "Terraform CI/CD stage 2 shared-services service account." + prefix = var.prefix + iam = ( + each.value.type == "sourcerepo" + # used directly from the cloud build trigger for source repos + ? { + "roles/iam.serviceAccountUser" = local.automation_resman_sa_iam + } + # impersonated via workload identity federation for external repos + : { + "roles/iam.workloadIdentityUser" = [ + each.value.branch == null + ? format( + local.identity_providers[each.value.identity_provider].principal_repo, + var.automation.federated_identity_pool, + each.value.name + ) + : format( + local.identity_providers[each.value.identity_provider].principal_branch, + var.automation.federated_identity_pool, + each.value.name, + each.value.branch + ) + ] + } + ) + iam_project_roles = { + (var.automation.project_id) = ["roles/logging.logWriter"] + } + iam_storage_roles = { + (var.automation.outputs_bucket) = ["roles/storage.objectViewer"] + (var.automation.config_bucket) = ["roles/storage.objectViewer"] + } +} + +# read-only (plan) SA used by CI/CD workflows to impersonate automation SA + +module "branch-shared-services-r-sa-cicd" { + source = "../../../modules/iam-service-account" + for_each = ( + try(local.cicd_repositories.shared_services.name, null) != null + ? { 0 = local.cicd_repositories.shared_services } + : {} + ) + project_id = var.automation.project_id + name = "resman-shdsvc-1r" + display_name = "Terraform CI/CD shared-services service account (read-only)." + prefix = var.prefix + iam = ( + each.value.type == "sourcerepo" + # build trigger for read-only SA is optionally defined by users + ? {} + # impersonated via workload identity federation for external repos + : { + "roles/iam.workloadIdentityUser" = [ + format( + local.identity_providers[each.value.identity_provider].principal_repo, + var.automation.federated_identity_pool, + each.value.name + ) + ] + } + ) + iam_project_roles = { + (var.automation.project_id) = ["roles/logging.logWriter"] + } + iam_storage_roles = { + (var.automation.outputs_bucket) = ["roles/storage.objectViewer"] + (var.automation.config_bucket) = ["roles/storage.objectViewer"] + } +} diff --git a/fast/stages-aw/1-resman/cicd-teams.tf b/fast/stages-aw/2-resman/cicd-teams.tf similarity index 99% rename from fast/stages-aw/1-resman/cicd-teams.tf rename to fast/stages-aw/2-resman/cicd-teams.tf index 67e04c109..dd652f174 100644 --- a/fast/stages-aw/1-resman/cicd-teams.tf +++ b/fast/stages-aw/2-resman/cicd-teams.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description CI/CD resources for individual teams. # source repository diff --git a/fast/stages-aw/2-resman/data/allow_ncc.yaml b/fast/stages-aw/2-resman/data/allow_ncc.yaml new file mode 100644 index 000000000..1bcfaec02 --- /dev/null +++ b/fast/stages-aw/2-resman/data/allow_ncc.yaml @@ -0,0 +1,27 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This constraint defines the set of Google Cloud resource services that can be +# used within an organization, folder, or project, such as compute.googleapis.com +# and storage.googleapis.com. By default, all Google Cloud resource services are +# allowed. For more information, see +# https://cloud.google.com/resource-manager/help/organization-policy/restricting-resources. +# COULD HAVE + +gcp.restrictServiceUsage: + inherit_from_parent: true + rules: + - allow: + values: + - networkconnectivity.googleapis.com diff --git a/fast/stages-aw/1-resman/diagram.png b/fast/stages-aw/2-resman/diagram.png similarity index 100% rename from fast/stages-aw/1-resman/diagram.png rename to fast/stages-aw/2-resman/diagram.png diff --git a/fast/stages-aw/1-resman/diagram.svg b/fast/stages-aw/2-resman/diagram.svg similarity index 100% rename from fast/stages-aw/1-resman/diagram.svg rename to fast/stages-aw/2-resman/diagram.svg diff --git a/fast/stages-aw/1-resman/main.tf b/fast/stages-aw/2-resman/main.tf similarity index 87% rename from fast/stages-aw/1-resman/main.tf rename to fast/stages-aw/2-resman/main.tf index 293f75c77..6b58c8c30 100644 --- a/fast/stages-aw/1-resman/main.tf +++ b/fast/stages-aw/2-resman/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -77,27 +77,29 @@ locals { } cicd_workflow_var_files = { stage_2 = [ - "0-bootstrap.auto.tfvars.json", - "1-resman.auto.tfvars.json", - "0-globals.auto.tfvars.json" + "1-assured-workload.auto.tfvars.json", + "2-resman.auto.tfvars.json", + "1-globals.auto.tfvars.json" ] stage_3 = [ - "0-bootstrap.auto.tfvars.json", - "1-resman.auto.tfvars.json", - "0-globals.auto.tfvars.json", - "2-networking.auto.tfvars.json", - "3-security.auto.tfvars.json" + "1-assured-workload.auto.tfvars.json", + "2-resman.auto.tfvars.json", + "1-globals.auto.tfvars.json", + "3-networking.auto.tfvars.json", + "4-security.auto.tfvars.json" ] } custom_roles = coalesce(var.custom_roles, {}) gcs_storage_class = ( - length(split("-", var.regions.primary)) < 2 + length(split("-", local.primary_location_gcs)) < 2 ? "MULTI_REGIONAL" : "REGIONAL" ) identity_providers = coalesce( try(var.automation.federated_identity_providers, null), {} ) + primary_location_gcs = element(var.locations.gcs, 0) + primary_location_kms = element(var.locations.kms, 0) principals = { for k, v in var.groups : k => ( can(regex("^[a-zA-Z]+:", v)) diff --git a/fast/stages-aw/1-resman/organization-iam.tf b/fast/stages-aw/2-resman/organization-iam.tf similarity index 77% rename from fast/stages-aw/1-resman/organization-iam.tf rename to fast/stages-aw/2-resman/organization-iam.tf index c99df3a47..54b07fce9 100644 --- a/fast/stages-aw/1-resman/organization-iam.tf +++ b/fast/stages-aw/2-resman/organization-iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Organization-level IAM bindings locals. locals { @@ -36,6 +35,18 @@ locals { member = module.branch-security-sa.iam_email role = "roles/accesscontextmanager.policyAdmin" } + sa_net_compute_net_admin = { + member = module.branch-network-sa.iam_email + role = "roles/compute.networkAdmin" + } + net_sa_org_policy_admin = { + member = module.branch-network-sa.iam_email + role = "roles/orgpolicy.policyAdmin" + } + ten_sa_org_policy_admin = { + member = "serviceAccount:${var.automation.service_accounts.tenant}" + role = "roles/orgpolicy.policyAdmin" + } }, # optional billing roles for network and security local.billing_mode != "org" ? {} : { @@ -89,30 +100,5 @@ locals { role = "roles/billing.costsManager" } }, - # lightweight tenant roles - { - for k, v in var.tenants : "oslogin_ext_user-tenant_${k}" => { - member = "domain:${v.organization.domain}" - role = "roles/compute.osLoginExternalUser" - } if v.organization != null - }, - { - for k, v in var.tenants : "org-viewer-tenant_${k}_domain" => { - member = "domain:${v.organization.domain}" - role = "roles/resourcemanager.organizationViewer" - } if v.organization != null - }, - { - for k, v in var.tenants : "org-viewer-tenant_${k}_admin" => { - member = v.admin_principal - role = "roles/resourcemanager.organizationViewer" - } - }, - local.billing_mode != "org" ? {} : { - for k, v in var.tenants : "billing_user-tenant_${k}_billing_admin" => { - member = v.admin_principal - role = "roles/billing.user" - } - }, ) } diff --git a/fast/stages-aw/2-resman/organization.tf b/fast/stages-aw/2-resman/organization.tf new file mode 100644 index 000000000..bed7a410a --- /dev/null +++ b/fast/stages-aw/2-resman/organization.tf @@ -0,0 +1,49 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# tfdoc:file:description Organization policies. + +locals { + _org_only_roles = [ + "roles/billing.user", + "roles/cloudasset.viewer", + "roles/compute.orgFirewallPolicyAdmin", + "roles/orgpolicy.policyAdmin" + ] + folder_iam_bindings_additive = { + for k, v in local.iam_bindings_additive : k => v + if !contains(local._org_only_roles, v.role) + } + org_iam_bindings_additive = { + for k, v in local.iam_bindings_additive : k => v + if contains(local._org_only_roles, v.role) + } +} + +module "organization" { + source = "../../../modules/organization-se" + organization_id = "organizations/${var.organization.id}" + # additive bindings via delegated IAM grant set in stage 0 + iam_bindings_additive = local.org_iam_bindings_additive +} + +module "top-level-folder" { + source = "../../../modules/folder" + folder_create = false + id = "folders/${var.top_level_folder.id}" + parent = "organizations/${var.organization.id}" + # additive bindings, used for roles co-managed by different stages + iam_bindings_additive = local.folder_iam_bindings_additive +} \ No newline at end of file diff --git a/fast/stages-aw/1-resman/outputs-files.tf b/fast/stages-aw/2-resman/outputs-files.tf similarity index 94% rename from fast/stages-aw/1-resman/outputs-files.tf rename to fast/stages-aw/2-resman/outputs-files.tf index 2f13adfc5..4a7dfc300 100644 --- a/fast/stages-aw/1-resman/outputs-files.tf +++ b/fast/stages-aw/2-resman/outputs-files.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Output files persistence to local filesystem. locals { @@ -30,7 +29,7 @@ resource "local_file" "providers" { resource "local_file" "tfvars" { for_each = var.outputs_location == null ? {} : { 1 = 1 } file_permission = "0644" - filename = "${local.outputs_location}/tfvars/1-resman.auto.tfvars.json" + filename = "${local.outputs_location}/tfvars/2-resman.auto.tfvars.json" content = jsonencode(local.tfvars) } diff --git a/fast/stages-aw/1-resman/outputs-gcs.tf b/fast/stages-aw/2-resman/outputs-gcs.tf similarity index 64% rename from fast/stages-aw/1-resman/outputs-gcs.tf rename to fast/stages-aw/2-resman/outputs-gcs.tf index 8e102a410..e2e49dfce 100644 --- a/fast/stages-aw/1-resman/outputs-gcs.tf +++ b/fast/stages-aw/2-resman/outputs-gcs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Output files persistence to automation GCS bucket. resource "google_storage_bucket_object" "providers" { @@ -23,9 +22,23 @@ resource "google_storage_bucket_object" "providers" { content = each.value } +resource "google_storage_bucket_object" "tenant-providers" { + bucket = var.automation.outputs_bucket + name = "providers/5-tenant-providers.tf" + content = local.tenant_resman_providers +} + +resource "google_storage_bucket_object" "tenant_outputs" { + bucket = var.automation.outputs_bucket + name = "stage_2_tenant_outputs.json" + content = jsonencode({ + tenant_environments = var.tenant_environments + }) +} + resource "google_storage_bucket_object" "tfvars" { bucket = var.automation.outputs_bucket - name = "tfvars/1-resman.auto.tfvars.json" + name = "tfvars/2-resman.auto.tfvars.json" content = jsonencode(local.tfvars) } @@ -35,3 +48,9 @@ resource "google_storage_bucket_object" "workflows" { name = "workflows/${replace(each.key, "_", "-")}-workflow.yaml" content = each.value } + +resource "google_storage_bucket_object" "tfvars_user_definitions" { + bucket = var.automation.inputs_bucket + name = "stage-2/stage-2-inputs.auto.tfvars.json" + content = local.tfvars_content +} diff --git a/fast/stages-aw/1-resman/outputs.tf b/fast/stages-aw/2-resman/outputs.tf similarity index 73% rename from fast/stages-aw/1-resman/outputs.tf rename to fast/stages-aw/2-resman/outputs.tf index 4a6f8679a..758be9b7a 100644 --- a/fast/stages-aw/1-resman/outputs.tf +++ b/fast/stages-aw/2-resman/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _tpl_providers = "${path.module}/templates/providers.tf.tpl" cicd_workflow_attrs = { @@ -89,8 +88,8 @@ locals { plan = try(module.branch-network-r-sa-cicd[0].email, null) } tf_providers_files = { - apply = "2-networking-providers.tf" - plan = "2-networking-r-providers.tf" + apply = "3-networking-providers.tf" + plan = "3-networking-r-providers.tf" } tf_var_files = local.cicd_workflow_var_files.stage_2 } @@ -122,8 +121,19 @@ locals { plan = try(module.branch-security-r-sa-cicd[0].email, null) } tf_providers_files = { - apply = "3-security-providers.tf" - plan = "3-security-r-providers.tf" + apply = "4-security-providers.tf" + plan = "4-security-r-providers.tf" + } + tf_var_files = local.cicd_workflow_var_files.stage_2 + } + shared_services = { + service_accounts = { + apply = try(module.branch-shared-services-sa-cicd[0].email, null) + plan = try(module.branch-shared-services-r-sa-cicd[0].email, null) + } + tf_providers_files = { + apply = "shared-services-providers.tf" + plan = "shared-services-r-providers.tf" } tf_var_files = local.cicd_workflow_var_files.stage_2 } @@ -143,7 +153,6 @@ locals { }) ) } - env_folder_ids = { for k, v in module.branch-envs-folders : k => try(v.folder.id, null) } folder_ids = merge( { data-platform-dev = try(module.branch-dp-dev-folder[0].id, null) @@ -156,7 +165,6 @@ locals { sandbox = try(module.branch-sandbox-folder[0].id, null) security = try(module.branch-security-folder.id, null) teams = try(module.branch-teams-folder[0].id, null) - envs = try(local.env_folder_ids, null) }, { for k, v in module.branch-teams-team-folder : @@ -171,155 +179,189 @@ locals { "team-${k}-prod" => v.id } ) - providers_raw = merge( + providers = merge( { - "2-networking" = { - bucket = module.branch-network-gcs.name - name = "networking" - sa = module.branch-network-sa.email - bootstrap_project = var.automation.project_id - } - "2-networking-r" = { - bucket = module.branch-network-gcs.name - name = "networking" - sa = module.branch-network-r-sa.email - bootstrap_project = var.automation.project_id - } - "3-security" = { - bucket = module.branch-security-gcs.name - name = "security" - sa = module.branch-security-sa.email - bootstrap_project = var.automation.project_id - } - "3-security-r" = { - bucket = module.branch-security-gcs.name - name = "security" - sa = module.branch-security-r-sa.email - bootstrap_project = var.automation.project_id - } + "3-networking" = templatefile(local._tpl_providers, { + backend_extra = null + bucket = module.branch-network-gcs.name + name = "networking" + sa = module.branch-network-sa.email + }) + "3-networking-r" = templatefile(local._tpl_providers, { + backend_extra = null + bucket = module.branch-network-gcs.name + name = "networking" + sa = module.branch-network-r-sa.email + }) + "3-vpn" = templatefile(local._tpl_providers, { + backend_extra = "prefix = \"vpn\"" + bucket = module.branch-network-gcs.name + name = "networking-vpn" + sa = module.branch-network-sa.email + }) + "4-security" = templatefile(local._tpl_providers, { + backend_extra = null + bucket = module.branch-security-gcs.name + name = "security" + sa = module.branch-security-sa.email + }) + "4-security-r" = templatefile(local._tpl_providers, { + backend_extra = null + bucket = module.branch-security-gcs.name + name = "security" + sa = module.branch-security-r-sa.email + }) + "shared-services" = templatefile(local._tpl_providers, { + backend_extra = null + bucket = module.branch-shared-services-gcs.name + name = "shared-services" + sa = module.branch-shared-services-sa.email + }) + "shared-services-r" = templatefile(local._tpl_providers, { + backend_extra = null + bucket = module.branch-shared-services-gcs.name + name = "shared-services" + sa = module.branch-shared-services-r-sa.email + }) }, !var.fast_features.data_platform ? {} : { - "3-data-platform-dev" = { + "3-data-platform-dev" = templatefile(local._tpl_providers, { + backend_extra = null bucket = module.branch-dp-dev-gcs[0].name name = "dp-dev" sa = module.branch-dp-dev-sa[0].email - } - "3-data-platform-dev-r" = { + }) + "3-data-platform-dev-r" = templatefile(local._tpl_providers, { + backend_extra = null bucket = module.branch-dp-dev-gcs[0].name name = "dp-dev" sa = module.branch-dp-dev-r-sa[0].email - } - "3-data-platform-prod" = { + }) + "3-data-platform-prod" = templatefile(local._tpl_providers, { + backend_extra = null bucket = module.branch-dp-prod-gcs[0].name name = "dp-prod" sa = module.branch-dp-prod-sa[0].email - } - "3-data-platform-prod-r" = { + }) + "3-data-platform-prod-r" = templatefile(local._tpl_providers, { + backend_extra = null bucket = module.branch-dp-prod-gcs[0].name name = "dp-prod" sa = module.branch-dp-prod-r-sa[0].email - } + }) }, !var.fast_features.gke ? {} : { - "3-gke-dev" = { + "3-gke-dev" = templatefile(local._tpl_providers, { + backend_extra = null bucket = module.branch-gke-dev-gcs[0].name name = "gke-dev" sa = module.branch-gke-dev-sa[0].email - } - "3-gke-dev-r" = { + }) + "3-gke-dev-r" = templatefile(local._tpl_providers, { + backend_extra = null bucket = module.branch-gke-dev-gcs[0].name name = "gke-dev" sa = module.branch-gke-dev-r-sa[0].email - } - "3-gke-prod" = { + }) + "3-gke-prod" = templatefile(local._tpl_providers, { + backend_extra = null bucket = module.branch-gke-prod-gcs[0].name name = "gke-prod" sa = module.branch-gke-prod-sa[0].email - } - "3-gke-prod-r" = { + }) + "3-gke-prod-r" = templatefile(local._tpl_providers, { + backend_extra = null bucket = module.branch-gke-prod-gcs[0].name name = "gke-prod" sa = module.branch-gke-prod-r-sa[0].email - } + }) }, !var.fast_features.gcve ? {} : { - "3-gcve-dev" = { + "3-gcve-dev" = templatefile(local._tpl_providers, { + backend_extra = null bucket = module.branch-gcve-dev-gcs[0].name name = "gcve-dev" sa = module.branch-gcve-dev-sa[0].email - } - "3-gcve-dev-r" = { + }) + "3-gcve-dev-r" = templatefile(local._tpl_providers, { + backend_extra = null bucket = module.branch-gcve-dev-gcs[0].name name = "gcve-dev" sa = module.branch-gcve-dev-r-sa[0].email - } - "3-gcve-prod" = { + }) + "3-gcve-prod" = templatefile(local._tpl_providers, { + backend_extra = null bucket = module.branch-gcve-prod-gcs[0].name name = "gcve-prod" sa = module.branch-gcve-prod-sa[0].email - } - "3-gcve-prod-r" = { + }) + "3-gcve-prod-r" = templatefile(local._tpl_providers, { + backend_extra = null bucket = module.branch-gcve-prod-gcs[0].name name = "gcve-prod" sa = module.branch-gcve-prod-r-sa[0].email - } + }) }, !var.fast_features.project_factory ? {} : { - "3-project-factory-dev" = { + "3-project-factory-dev" = templatefile(local._tpl_providers, { + backend_extra = null bucket = module.branch-pf-dev-gcs[0].name name = "team-dev" sa = module.branch-pf-dev-sa[0].email - } - "3-project-factory-dev-r" = { + }) + "3-project-factory-dev-r" = templatefile(local._tpl_providers, { + backend_extra = null bucket = module.branch-pf-dev-gcs[0].name name = "team-dev" sa = module.branch-pf-dev-r-sa[0].email - } - "3-project-factory-prod" = { + }) + "3-project-factory-prod" = templatefile(local._tpl_providers, { + backend_extra = null bucket = module.branch-pf-prod-gcs[0].name name = "team-prod" sa = module.branch-pf-prod-sa[0].email - } - "3-project-factory-prod-r" = { + }) + "3-project-factory-prod-r" = templatefile(local._tpl_providers, { + backend_extra = null bucket = module.branch-pf-prod-gcs[0].name name = "team-prod" sa = module.branch-pf-prod-r-sa[0].email - } + }) }, !var.fast_features.sandbox ? {} : { - "9-sandbox" = { + "9-sandbox" = templatefile(local._tpl_providers, { + backend_extra = null bucket = module.branch-sandbox-gcs[0].name name = "sandbox" sa = module.branch-sandbox-sa[0].email - } + }) }, !var.fast_features.teams ? {} : merge( { - "3-teams" = { + "3-teams" = templatefile(local._tpl_providers, { + backend_extra = null bucket = module.branch-teams-gcs[0].name name = "teams" sa = module.branch-teams-sa[0].email - } + }) }, { for k, v in module.branch-teams-team-sa : - "3-teams-${k}" => { + "3-teams-${k}" => templatefile(local._tpl_providers, { + backend_extra = null bucket = module.branch-teams-team-gcs[k].name name = "teams" sa = v.email - } + }) } ) ) - providers = { - for k, v in local.providers_raw : k => templatefile(local._tpl_providers, merge( - { - backend_extra = null - bootstrap_project = null - }, - v - )) - } + tenant_resman_providers = templatefile(local._tpl_providers, { + bucket = var.automation.tenant_bucket + backend_extra = null + name = "tenants" + sa = var.automation.service_accounts.tenant + }) service_accounts = merge( { data-platform-dev = try(module.branch-dp-dev-sa[0].email, null) @@ -343,6 +385,8 @@ locals { sandbox = try(module.branch-sandbox-sa[0].email, null) security = module.branch-security-sa.email security-r = module.branch-security-r-sa.email + shared-services = module.branch-shared-services-sa.email + shared-services-r = module.branch-shared-services-r-sa.email teams = try(module.branch-teams-sa[0].email, null) }, { @@ -368,19 +412,28 @@ locals { tf_var_files = local.cicd_workflow_var_files.stage_3 } } - tenant_accounts = { for k, v in local.tenant_envs : k => { - main_project = module.tenant-self-main-projects[k].id - env = v.env - tenant = v.tenant - admin_principal = var.tenants[v.tenant].admin_principal - } } + # tenant_accounts = { for k, v in local.tenant_envs : k => { + # main_project = module.tenant-self-main-projects[k].id + # env = v.env + # tenant = v.tenant + # admin_principal = var.tenants[v.tenant].admin_principal + # } } tfvars = { - folder_ids = local.folder_ids - envs_folders = var.envs_folders - service_accounts = local.service_accounts - tenant_accounts = local.tenant_accounts - billing_override = var.billing_override + checklist_hierarchy = local.checklist.hierarchy + folder_ids = local.folder_ids + tenant_environments = var.tenant_environments + service_accounts = local.service_accounts + # tenant_accounts = local.tenant_accounts + # tenant_folder_ids = { + # for k, v in local.tenant_envs : k => module.tenant-top-folders[k].id + # } } + + inputs_tfvars = { + fast_features = var.fast_features + tenant_environments = var.tenant_environments + } + tfvars_content = jsonencode(local.inputs_tfvars) } output "cicd_repositories" { @@ -413,11 +466,6 @@ output "dataplatform" { } } -output "envs" { - description = "Environments folders created for the tenants." - value = try(module.branch-envs-folders, null) -} - output "gcve" { # tfdoc:output:consumers 03-gke-multitenant description = "Data for the GCVE stage." @@ -485,7 +533,7 @@ output "project_factories" { # ready to use provider configurations for subsequent stages output "providers" { - # tfdoc:output:consumers 02-networking 03-security 03-dataplatform xx-sandbox xx-teams + # tfdoc:output:consumers 03-networking 04-security 03-dataplatform xx-sandbox xx-teams shared-services description = "Terraform provider files for this stage and dependent stages." sensitive = true value = local.providers @@ -506,7 +554,7 @@ output "sandbox" { } output "security" { - # tfdoc:output:consumers 03-security + # tfdoc:output:consumers 04-security description = "Data for the networking stage." value = { folder = module.branch-security-folder.id @@ -515,6 +563,14 @@ output "security" { } } +output "shared_services" { + description = "Data for the shared-services stage." + value = { + gcs_bucket = module.branch-shared-services-gcs.name + service_account = module.branch-shared-services-sa.iam_email + } +} + output "team_cicd_repositories" { description = "WIF configuration for Team CI/CD repositories." value = { diff --git a/fast/stages-aw/0-bootstrap/templates/providers.tf.tpl b/fast/stages-aw/2-resman/templates/providers.tf.tpl similarity index 52% rename from fast/stages-aw/0-bootstrap/templates/providers.tf.tpl rename to fast/stages-aw/2-resman/templates/providers.tf.tpl index 65491ce50..d1c224c5c 100644 --- a/fast/stages-aw/0-bootstrap/templates/providers.tf.tpl +++ b/fast/stages-aw/2-resman/templates/providers.tf.tpl @@ -30,22 +30,4 @@ provider "google-beta" { impersonate_service_account = "${sa}" } -%{~ if try(bootstrap_project, null) != null ~} -# Billing-specific providers (Conditional Impersonation) -provider "google" { - alias = "billing" - impersonate_service_account = try(var.billing_override, null) != null ? null : "${sa}" - project = try(var.billing_override.project, "${bootstrap_project}") - billing_project = try(var.billing_override.billing_project, "${bootstrap_project}") - user_project_override = true -} -provider "google-beta" { - alias = "billing" - impersonate_service_account = try(var.billing_override, null) != null ? null : "${sa}" - project = try(var.billing_override.project, "${bootstrap_project}") - billing_project = try(var.billing_override.billing_project, "${bootstrap_project}") - user_project_override = true -} -%{~ endif ~} - # end provider.tf for ${name} diff --git a/fast/stages-aw/0-bootstrap/templates/workflow-github.yaml b/fast/stages-aw/2-resman/templates/workflow-github.yaml similarity index 98% rename from fast/stages-aw/0-bootstrap/templates/workflow-github.yaml rename to fast/stages-aw/2-resman/templates/workflow-github.yaml index 70ccfc50f..f6aa53cd7 100644 --- a/fast/stages-aw/0-bootstrap/templates/workflow-github.yaml +++ b/fast/stages-aw/2-resman/templates/workflow-github.yaml @@ -1,10 +1,10 @@ -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + name: "FAST ${stage_name} stage" on: diff --git a/fast/stages-aw/1-resman/templates/workflow-gitlab.yaml b/fast/stages-aw/2-resman/templates/workflow-gitlab.yaml similarity index 93% rename from fast/stages-aw/1-resman/templates/workflow-gitlab.yaml rename to fast/stages-aw/2-resman/templates/workflow-gitlab.yaml index c50f8e58e..289cbcd34 100644 --- a/fast/stages-aw/1-resman/templates/workflow-gitlab.yaml +++ b/fast/stages-aw/2-resman/templates/workflow-gitlab.yaml @@ -1,10 +1,10 @@ -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + variables: GOOGLE_CREDENTIALS: cicd-sa-credentials.json FAST_OUTPUTS_BUCKET: ${outputs_bucket} @@ -28,13 +29,13 @@ workflow: variables: COMMAND: apply FAST_SERVICE_ACCOUNT: ${service_accounts.apply} - TF_PROVIDERS_FILE: 0-bootstrap-providers.tf + TF_PROVIDERS_FILE: 1-assured-workload-providers.tf # pr / plan - if: $CI_PIPELINE_SOURCE == 'merge_request_event' variables: COMMAND: plan FAST_SERVICE_ACCOUNT: ${service_accounts.plan} - TF_PROVIDERS_FILE: 0-bootstrap-r-providers.tf + TF_PROVIDERS_FILE: 1-assured-workload-r-providers.tf stages: - gcp-setup diff --git a/fast/stages-aw/1-resman/templates/workflow-sourcerepo.yaml b/fast/stages-aw/2-resman/templates/workflow-sourcerepo.yaml similarity index 97% rename from fast/stages-aw/1-resman/templates/workflow-sourcerepo.yaml rename to fast/stages-aw/2-resman/templates/workflow-sourcerepo.yaml index 012ff93e7..fe3cea3f8 100644 --- a/fast/stages-aw/1-resman/templates/workflow-sourcerepo.yaml +++ b/fast/stages-aw/2-resman/templates/workflow-sourcerepo.yaml @@ -1,10 +1,10 @@ -# Copyright 2024 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + steps: - name: alpine:3 id: tf-download diff --git a/fast/stages-aw/2-resman/terraform.tfvars.sample b/fast/stages-aw/2-resman/terraform.tfvars.sample new file mode 100644 index 000000000..b995053c3 --- /dev/null +++ b/fast/stages-aw/2-resman/terraform.tfvars.sample @@ -0,0 +1,43 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +fast_features = { + envs = true +} + +tenant_environments = { + dev = { + admin = "gcp-organization-admins@domain.com" + }, + prod = { + admin = "gcp-organization-admins@domain.com" + } +} + +cicd_repositories = { + networking = { + name = "google-cloud/project" + type = "gitlab" + identity_provider = "gitlab-fed" + branch = "main" + } + security = { + name = "google-cloud/project" + type = "gitlab" + identity_provider = "gitlab-fed" + branch = "main" + } +} diff --git a/fast/stages-aw/1-resman/variables.tf b/fast/stages-aw/2-resman/variables.tf similarity index 81% rename from fast/stages-aw/1-resman/variables.tf rename to fast/stages-aw/2-resman/variables.tf index 8dce6d8c9..422e1a542 100644 --- a/fast/stages-aw/1-resman/variables.tf +++ b/fast/stages-aw/2-resman/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,10 +15,6 @@ */ # defaults for variables marked with global tfdoc annotations, can be set via # the tfvars file generated in stage 00 and stored in its outputs -variable "alert_email" { - description = "Email to receive log alerts." - type = string -} variable "assured_workloads" { description = "Configuration for Assured Workloads." @@ -32,9 +28,11 @@ variable "assured_workloads" { } variable "automation" { - # tfdoc:variable:source 0-bootstrap + # tfdoc:variable:source 1-assured-workload description = "Automation resources created by the bootstrap stage." type = object({ + config_bucket = string + inputs_bucket = string outputs_bucket = string project_id = string project_number = string @@ -50,12 +48,15 @@ variable "automation" { service_accounts = object({ resman = string resman-r = string + tenant = string + tenant-r = string }) + tenant_bucket = string }) } variable "billing_account" { - # tfdoc:variable:source 0-bootstrap + # tfdoc:variable:source 1-assured-workload description = "Billing account id. If billing account is not part of the same org set `is_org_level` to `false`. To disable handling of billing IAM roles set `no_iam` to `true`." type = object({ id = string @@ -128,6 +129,12 @@ variable "cicd_repositories" { branch = optional(string) identity_provider = optional(string) })) + shared_services = optional(object({ + name = string + type = string + branch = optional(string) + identity_provider = optional(string) + })) }) default = null validation { @@ -165,7 +172,7 @@ variable "common_services_folder" { } variable "custom_roles" { - # tfdoc:variable:source 0-bootstrap + # tfdoc:variable:source 1-assured-workload description = "Custom roles defined at the org level, in key => id format." type = object({ gcve_network_admin = string @@ -176,13 +183,6 @@ variable "custom_roles" { default = null } -variable "envs_folders" { - description = "List of environments to be created for projects to go into." - type = map(object({ - admin = string - })) -} - variable "factories_config" { description = "Configuration for the resource factories or external data." type = object({ @@ -193,7 +193,7 @@ variable "factories_config" { } variable "fast_features" { - # tfdoc:variable:source 0-0-bootstrap + # tfdoc:variable:source 0-1-assured-workload description = "Selective control for top-level FAST features." type = object({ data_platform = optional(bool, false) @@ -226,7 +226,7 @@ variable "folder_iam" { } variable "groups" { - # tfdoc:variable:source 0-bootstrap + # tfdoc:variable:source 1-assured-workload # https://cloud.google.com/docs/enterprise/setup-checklist description = "Group names or IAM-format principals to grant organization-level permissions. If just the name is provided, the 'group:' principal and organization domain are interpolated." type = object({ @@ -240,17 +240,28 @@ variable "groups" { default = {} } -variable "regions" { - # tfdoc:variable:source 0-bootstrap - description = "Region definitions. Inherited from 0-bootstrap outputs. Must be specified in bootstrap terraform.tfvars." +variable "locations" { + # tfdoc:variable:source 1-assured-workload + description = "Optional locations for GCS, BigQuery, and logging buckets created here." type = object({ - primary = string + bq = string + gcs = list(string) + logging = list(string) + pubsub = list(string) + kms = list(string) }) + default = { + bq = "US" + gcs = ["US"] + kms = ["nam9"] + logging = ["us"] + pubsub = [] + } nullable = false } variable "organization" { - # tfdoc:variable:source 0-bootstrap + # tfdoc:variable:source 1-assured-workload description = "Organization details." type = object({ domain = string @@ -266,12 +277,12 @@ variable "outputs_location" { } variable "prefix" { - # tfdoc:variable:source 0-bootstrap + # tfdoc:variable:source 1-assured-workload description = "Prefix used for resources that need unique names. Use 7 characters or less." type = string validation { - condition = try(length(var.prefix), 0) < 8 + condition = try(length(var.prefix), 0) <= 10 error_message = "Use a maximum of 7 characters for prefix." } } @@ -281,6 +292,11 @@ variable "regime_mapping" { type = map(string) } +variable "shared_services_project_id" { + description = "The project ID for shared services inherited from Stage 1." + type = string +} + variable "team_folders" { description = "Team folders to be created. Format is described in a code comment." type = map(object({ @@ -297,51 +313,17 @@ variable "team_folders" { default = null } -variable "tenants" { - description = "Lightweight tenant definitions." +variable "tenant_environments" { + description = "List of environments to be created for projects to go into." type = map(object({ - admin_principal = string - descriptive_name = string - billing_account = optional(string) - compliance = optional(object({ - regime = string - location = string - })) - locations = optional(object({ - gcs = string - kms = string - })) - organization = optional(object({ - customer_id = string - domain = string - id = number - })) + admin = string })) - nullable = false - default = {} - - validation { - condition = alltrue([for k, _ in var.tenants : length(k) < 7]) - error_message = "Tenant keys must be less than 7 characters." - } -} - -variable "tenants_config" { - description = "Lightweight tenants shared configuration. Roles will be assigned to tenant admin group and service accounts." - type = object({ - core_folder_roles = optional(list(string), []) - tenant_folder_roles = optional(list(string), []) - top_folder_roles = optional(list(string), []) - }) - nullable = false - default = {} } -variable "billing_override" { - description = "Optional billing override configuration. If set, disables service account impersonation for project billing linkage and runs under the user account using the specified quota projects." +variable "top_level_folder" { + description = "Top Level Folder Details." type = object({ - project = string - billing_project = string + name = string + id = string }) - default = null } diff --git a/fast/stages-aw/2-networking-b-il5-ngfw/README.md b/fast/stages-aw/3-networking/README.md similarity index 70% rename from fast/stages-aw/2-networking-b-il5-ngfw/README.md rename to fast/stages-aw/3-networking/README.md index adefeab19..84c0368ec 100644 --- a/fast/stages-aw/2-networking-b-il5-ngfw/README.md +++ b/fast/stages-aw/3-networking/README.md @@ -1,3 +1,19 @@ + + # Networking with Network Virtual Appliance This stage sets up the shared network infrastructure for the whole Google Cloud Organization. @@ -63,11 +79,11 @@ The final number of subnets, and their IP addressing will depend on the user-spe ### Palo Alto NGFW -In order to support full NGFW capabilities, including IDS/IPS and TLS break-and-inspect, the team has chosen to implement Palo Alto NGFWs. While there are other vendor products that can support these requirements, our team has the most experience getting accreditations using Palo Alto NGFW. In future iterations of this codebase, we intend on expanding this capability to include: GCP Cloud NGFW, Barracuda, and Cisco. +In order to support full NGFW capabilities, including IDS/IPS and TLS break-and-inspect, the team has chosen to implement Palo Alto NGFWs. While there are other vendor products that can support these requirements, our team has the most experience getting accreditation using Palo Alto NGFW. In future iterations of this codebase, we intend on expanding this capability to include: GCP Cloud NGFW, Barracuda, and Cisco. ### Multi-regional deployment -The stage can optionally deploy the infrastructure into one or two regions. Due to current restrictions for the IL5 overlay, the two available regions are typically us-east4 and us-central1 (nam4). Regional resources include NVAs (templates, MIGs, LBs) and test VMs. The specific regions can be configured via the `regions` variable. +The stage can optionally deploy the the infrastructure into one or two regions. Due to current restrictions for the IL5 overlay, the two available regions are us-east4 and us-central1 (nam4). By default just us-east4. Regional resources include NVAs (templates, MIGs, LBs) and test VMs. As part of your design, you should weigh the additional maintenance cost of operating in two regions against your availability requirements to decide what is best for your deployment. ### VPC design @@ -87,7 +103,7 @@ By default, the design assumes the following: - cross-environment traffic and traffic from any dmz network to any landing network (and vice versa) pass through the NVAs. For demo purposes, the current NVA performs simple routing/natting only - any traffic from a landing network to an dmz network (e.g. Internet) is natted by the NVAs. Users can configure further exclusions -The landing landing VPC acts as a hub: it bridges internal resources with the outside world and it hosts the shared services consumed by the spoke VPCs, connected to the hub through VPC network peerings. Spokes are used to partition the environments. These environments are inherited from the `0-bootstrap` and `1-resman` stages. +The landing landing VPC acts as a hub: it bridges internal resources with the outside world and it hosts the shared services consumed by the spoke VPCs, connected to the hub through VPC network peerings. Spokes are used to partition the environments. These environments are inherited from the `1-assured-workload` and `2-resman` stages. Each virtual network is a [shared VPC](https://cloud.google.com/vpc/docs/shared-vpc): shared VPCs are managed in dedicated *host Google Cloud Project* and shared with other *service Google Cloud Projects* that consume the network resources. Shared VPC lets Google Cloud Organization administrators delegate administrative responsibilities, such as creating and managing instances, to Service Google Cloud Projects Admins while maintaining centralized control over network resources like subnets, routes, and firewalls. @@ -102,10 +118,10 @@ Internal connectivity (e.g. between the landing landing VPC and the spokes) is r This is an options summary -- [VPC Peering](https://cloud.google.com/vpc/docs/vpc-peering) (used here to connect the landing landing VPC with the spokes, also used by [02-networking-vpn](../2-networking-b-vpn/)) +- [VPC Peering](https://cloud.google.com/vpc/docs/vpc-peering) (used here to connect the landing landing VPC with the spokes, also used by [03-networking-vpn](../3-vpn/)) - Pros: no additional costs, full bandwidth with no configurations, no extra latency - Cons: no transitivity (e.g. to GKE masters, Cloud SQL, etc.), no selective exchange of routes, several quotas and limits shared between VPCs in a peering group -- [Multi-NIC appliances](https://cloud.google.com/architecture/best-practices-vpc-design#multi-nic) (used here to connect the landing landing and dmz VPCs) and multi-NIC appliances with NCC/BGP support implemented [here](../2-networking-e-nva-bgp/) +- [Multi-NIC appliances](https://cloud.google.com/architecture/best-practices-vpc-design#multi-nic) (used here to connect the landing landing and dmz VPCs) and multi-NIC appliances with NCC/BGP support implemented [here](../3-networking/) - Pros: provides additional security features (e.g. IPS), potentially better integration with on-prem systems by using the same vendor - Cons: complex HA/failover setup, limited by VM bandwidth and scale, additional costs for VMs and licenses, out of band management of a critical cloud component @@ -113,9 +129,9 @@ This is an options summary Minimizing the number of routes (and subnets) in the cloud environment is important, as it simplifies management and it avoids hitting [Cloud Router](https://cloud.google.com/network-connectivity/docs/router/quotas) and [VPC](https://cloud.google.com/vpc/docs/quota) quotas and limits. For this reason, we recommend to carefully plan the IP space used in your cloud environment. This allows the use of larger IP CIDR blocks in routes, whenever possible. -This stage uses a dedicated `/11` block (`10.64.0.0/11`), which should be sized to the own needs. The subnets created in each VPC derive from this range. +This stage uses a dedicated `/16` block (`10.84.0.0/16`), which should be sized to the own needs. The subnets created in each VPC derive from this range. -The `/11` block is evenly split in eight, smaller `/16` blocks, assigned to different areas of the Google Cloud network across the configured regions: *landing dmz primary-region*, *landing dmz secondary-region*, *landing landing primary-region*, *landing dmz secondary-region*, *development primary-region*, *development secondary-region*, *production primary-region*, *production secondary-region*. +The `/16` block is evenly split in smaller `/24` blocks, assigned to different areas of the Google Cloud network: *landing dmz us-east4*, *landing landing us-east4*, *landing mgmt us-east4*, *connectivity us-east4*. The first `/24` range in every area is allocated for a default subnet, which can be removed or modified as needed. The last three `/24` ranges can be used for [PSA (Private Service Access)](https://cloud.google.com/vpc/docs/private-services-access)via the `psa_ranges` variable, or for [Internal Application Load Balancers (L7 LBs)](https://cloud.google.com/load-balancing/docs/l7-internal) subnets via the factory. @@ -127,15 +143,15 @@ This is a summary of the VPC Networks deployed into the `-net-vdss-host` | `vdss-dmz-0` | The Internet facing network for the DMZ | | `vdss-landing-0` | The landing network on the "trust" side of the Palo Alto NGFW deployments | -Additionally, a VPC is created for each of the `net--net-host` Google Cloud Project deployed in `1-resman`, and those are all peered to the `landing-vdss-0` VPC. +Additionally, a VPC is created for each of the `net--net-host` Google Cloud Project deployed in `2-resman`, and those are all peered to the `landing-vdss-0` VPC. This is a summary of the subnets allocated by default in this setup: | name | region | VPC network | description | CIDR | |---|---|---|---|---| -| `mgmt-default` | `` | `prod-mgmt-0` | `10.64.128.0/24` | -| `dmz-default` | `` | `prod-dmz-0` | `10.64.128.0/24` | -| `landing-default` | `` | `prod-landing-0` | `10.64.0.0/24` | +| `mgmt-default` | `us-east4` | `vdss-mgmt-0` | `10.84.129.0/24` | +| `dmz-default` | `us-east4` | `vdss-dmz-0` | `10.84.128.0/24` | +| `landing-default` | `us-east4` | `vdss-landing-0` | `10.84.0.0/24` | Within each environment, there is a shared-subnet deployed and a proxy-only subnet deployed. @@ -207,7 +223,7 @@ These files contain different resources: ### VPNs -The connectivity between on-premises and GCP (the landing landing VPC) is implemented with Cloud HA VPN ([`net-vpn`](../../../modules/net-vpn-ha)) and defined in [`vpn-onprem.tf`](./vpn-onprem.tf). The file implements a single logical connection between on-premises and the landing landing VPC, both in `us-east4` and `us-central1`. The relevant parameters for its configuration are found in the variables `vpn_onprem_primary_config` and `vpn_onprem_secondary_config`. +The connectivity between on-premises and GCP (the landing landing VPC) is implemented with Cloud HA VPN ([`net-vpn`](../../../modules/net-vpn-ha)) and defined in [`vpn-onprem.tf`](./vpc.tf). The file implements a single logical connection between on-premises and the landing landing VPC, both in `us-east4` and `us-central1`. The relevant parameters for its configuration are found in the variables `vpn_onprem_primary_config` and `vpn_onprem_secondary_config`. ### Routing and BGP @@ -220,15 +236,15 @@ BGP sessions for landing landing to on-premises are configured through the varia ### Firewall **VPC firewall rules** ([`net-vpc-firewall`](../../../modules/net-vpc-firewall)) are defined per-vpc on each `vpc-*.tf` file and leverage a resource factory to massively create rules. -To add a new firewall rule, create a new file or edit an existing one in the `data_folder` directory defined in the module `net-vpc-firewall`, following the examples of the "[Rules factory](../../../modules/net-vpc-firewall#rules-factory)" section of the module documentation. Sample firewall rules are shipped in [data/firewall-rules/dmz](./data/firewall-rules/dmz) and in [data/firewall-rules/landing](./data/firewall-rules/landing), and can be easily customized. +To add a new firewall rule, create a new file or edit an existing one in the `data_folder` directory defined in the module `net-vpc-firewall`, following the examples of the "[Rules factory](../../../modules/net-vpc-firewall#rules-factory)" section of the module documentation. Sample firewall rules are shipped in [data/firewall-rules/dmz](./data/firewall-rules/dmz) and in [data/firewall-rules/landing](./data), and can be easily customized. -**Hierarchical firewall policies** ([`folder`](../../../modules/folder)) are defined in `main.tf` and managed through a policy factory implemented by the `net-firewall-policy` module, which is then applied to the `Networking` folder containing all the core networking infrastructure. Policies are defined in the `rules_file` file, to define a new one simply use the [firewall policy module documentation](../../../modules/net-firewall-policy/README.md#factory)". Sample hierarchical firewall rules are shipped in [data/hierarchical-ingress-rules.yaml](./data/hierarchical-ingress-rules.yaml) and can be easily customised. +**Hierarchical firewall policies** ([`folder`](../../../modules/folder)) are defined in `main.tf` and managed through a policy factory implemented by the `net-firewall-policy` module, which is then applied to the `Networking` folder containing all the core networking infrastructure. Policies are defined in the `rules_file` file, to define a new one simply use the [firewall policy module documentation](../../../modules/net-firewall-policy/README.md#factory)". Sample hierarchical firewall rules are shipped in [data/hierarchical-ingress-rules.yaml](./data/hierarchical-ingress-rules.yaml) and can be easily customized. ### DNS architecture The DNS ([`dns`](../../../modules/dns)) infrastructure is defined in [`dns-*.tf`] files. -Cloud DNS manages onprem forwarding, the main GCP zone (in this example `gcp.example.com`) and environment-specific zones (i.e. `dev.gcp.example.com` and `prod.gcp.example.com`). +Cloud DNS manages on prem forwarding, the main GCP zone (in this example `gcp.example.com`) and environment-specific zones (i.e. `dev.gcp.example.com` and `prod.gcp.example.com`). #### Cloud environment @@ -237,7 +253,7 @@ The spokes can optionally define private zones (e.g. `prod-dns-private-zone`). G ## How to run this stage -This stage is meant to be executed after the [resource management](../1-resman) stage has run, as it leverages the automation service account and bucket created there, and additional resources configured in the [bootstrap](../0-bootstrap) stage. +This stage is meant to be executed after the [resource management](../2-resman) stage has run, as it leverages the automation service account and bucket created there, and additional resources configured in the [bootstrap](../1-assured-workload) stage. It's of course possible to run this stage in isolation, but that's outside the scope of this document, and you would need to refer to the code for the previous stages for the environmental requirements. @@ -245,7 +261,7 @@ Before running this stage, you need to make sure you have the correct credential ### Provider and Terraform variables -As all other FAST stages, the [mechanism used to pass variable values and pre-built provider files from one stage to the next](../0-bootstrap/README.md#output-files-and-cross-stage-variables) is also leveraged here. +As all other FAST stages, the [mechanism used to pass variable values and pre-built provider files from one stage to the next](../1-assured-workload/README.md#output-files-and-cross-stage-variables) is also leveraged here. The commands to link or copy the provider and terraform variable files can be easily derived from the `stage-links.sh` script in the FAST root git folder, passing it a single argument with the local output files git folder (if configured) or the Google Cloud output bucket in the automation Google Cloud Projects (derived from stage 0 outputs). The following examples demonstrate both cases, and the resulting commands that then need to be copy/pasted and run. @@ -253,13 +269,13 @@ The commands to link or copy the provider and terraform variable files can be ea ../../stage-links.sh gs://xxx-prod-iac-core-outputs-0 ``` -_copy and paste the following commands for '`2-networking-a-peering`'_ +_copy and paste the following commands for '`3-networking-a-peering`'_ ``` -gcloud alpha storage cp gs://xxx-prod-iac-core-outputs-0/providers/2-networking-providers.tf ./ -gcloud alpha storage cp gs://xxx-prod-iac-core-outputs-0/tfvars/0-globals.auto.tfvars.json ./ -gcloud alpha storage cp gs://xxx-prod-iac-core-outputs-0/tfvars/0-bootstrap.auto.tfvars.json ./ -gcloud alpha storage cp gs://xxx-prod-iac-core-outputs-0/tfvars/1-resman.auto.tfvars.json ./ +gcloud alpha storage cp gs://xxx-prod-iac-core-outputs-0/providers/3-networking-providers.tf ./ +gcloud alpha storage cp gs://xxx-prod-iac-core-outputs-0/tfvars/1-globals.auto.tfvars.json ./ +gcloud alpha storage cp gs://xxx-prod-iac-core-outputs-0/tfvars/1-assured-workload.auto.tfvars.json ./ +gcloud alpha storage cp gs://xxx-prod-iac-core-outputs-0/tfvars/2-resman.auto.tfvars.json ./ ``` ### Impersonating the automation service account @@ -268,12 +284,12 @@ The preconfigured provider file uses impersonation to run with this stage's auto ### Setting default Google Cloud Projects for manual run -**Important**: Before running this, make sure that if you are running these stages manually from the command line, that your default Google Cloud Projects is set to the 'automation' Google Cloud Projects created in 0-bootstrap. +**Important**: Before running this, make sure that if you are running these stages manually from the command line, that your default Google Cloud Projects is set to the 'automation' Google Cloud Projects created in 1-assured-workload. To find the 'automation' Google Cloud Projects ```bash -cd ../0-bootstrap +cd ../1-assured-workload terraform output project_ids ``` And to set the gcloud Google Cloud Projects default in your CLI @@ -285,20 +301,20 @@ gcloud config set project -prod-iac-core-0 Return to the Networking directory ```bash -cd ../2-networking-b-il5-ngfw +cd ../3-networking ``` ### Variable configuration Variables in this stage -- like most other FAST stages -- are broadly divided into three separate sets: -- variables which refer to global values for the whole organization (org id, billing account id, prefix, etc.), which are pre-populated via the `0-globals.auto.tfvars.json` file linked or copied above -- variables which refer to resources managed by previous stage, which are prepopulated here via the `0-bootstrap.auto.tfvars.json` and `1-resman.auto.tfvars.json` files linked or copied above -- and finally variables that optionally control this stage's behaviour and customizations, and can to be set in a custom `terraform.tfvars` file +- variables which refer to global values for the whole organization (org id, billing account id, prefix, etc.), which are pre-populated via the `1-globals.auto.tfvars.json` file linked or copied above +- variables which refer to resources managed by previous stage, which are prepopulated here via the `1-assured-workload.auto.tfvars.json` and `2-resman.auto.tfvars.json` files linked or copied above +- and finally variables that optionally control this stage's behavior and customizations, and can to be set in a custom `terraform.tfvars` file The latter set is explained in the [Customization](#customizations) sections below, and the full list can be found in the [Variables](#variables) table at the bottom of this document. -Note that the `outputs_location` variable is disabled by default, you need to explicitly set it in your `terraform.tfvars` file if you want output files to be generated by this stage. This is a sample `terraform.tfvars` that configures it, refer to the [bootstrap stage documentation](../0-bootstrap/README.md#output-files-and-cross-stage-variables) for more details: +Note that the `outputs_location` variable is disabled by default, you need to explicitly set it in your `terraform.tfvars` file if you want output files to be generated by this stage. This is a sample `terraform.tfvars` that configures it, refer to the [bootstrap stage documentation](../1-assured-workload/README.md#output-files-and-cross-stage-variables) for more details: ```tfvars outputs_location = "~/fast-config" @@ -308,7 +324,7 @@ outputs_location = "~/fast-config" This configuration is possible but unsupported and only exists for development purposes, use at your own risk: -- temporarily switch `billing_account.id` to `null` in `0-globals.auto.tfvars.json` +- temporarily switch `billing_account.id` to `null` in `1-globals.auto.tfvars.json` - for each Google Cloud Projects resources in the Google Cloud Projects modules used in this stage (`dev-spoke-project`, `landing-project`, `prod-spoke-project`) - apply using `-target`, for example `terraform apply -target 'module.landing-project.google_project.project[0]'` @@ -350,15 +366,13 @@ Regions are defined via the `regions` variable which sets up a mapping between t ### Reaching the Management Console -In order to access the Palo Alto managment console, you will need 3 things +In order to access the Palo Alto management console, you will need 3 things 1. The admin password is stored in the terraform state file, use this command to get it `terraform output -json | jq ".ngfw_password.value.result"` 2. The terraform code should have automatically created a small VM on the mgmt network that will work as a bastion. You may have to start it, if it is not already running. 3. Each NGFW instance will have at least 3 interfaces, but only the second one, connected to `prod-mgmt-0` is usable for administration. -Use the following command to access the web portal `gcloud compute ssh management-bastion --zone --tunnel-through-iap -- -L 8443::443`. From here, you should be able to access the management interface at the url https://localhost:8443/ and log in with the username `admin` and the password you found using in the terraform output command. - -*Note*: Replace `` with the zone where your management bastion host was deployed. You can find this in the Terraform outputs or by running `terraform show | grep zone`. +Use the following command to access the web portal `gcloud compute ssh management-bastion --zone us-east4-a --tunnel-through-iap -- -L 8443::443`. From here, you should be able to access the management interface at the url https://localhost:8443/ and log in with the username `admin` and the password you found using in the terraform output command. *Note*: You may need to change the zone in the above command if your management bastion host wasn't deployed in `us-east4-a`. If you wish to ssh into the NGFWs, you can copy the `id_rsa` and `id_rsa.pub` files that are output by the terraform process over to the `.ssh/` folder on the bastion host. @@ -381,41 +395,39 @@ If you are redeploying this stage with the same prefix, please run "pre-redeploy | name | description | type | required | default | |---|---|:---:|:---:|:---:| -| [alert_email](variables.tf#L16) | Email to receive log alerts. | string | ✓ | | -| [automation](variables.tf#L21) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | -| [billing_account](variables.tf#L29) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | object({…}) | ✓ | | -| [envs_folders](variables.tf#L52) | List of environments to be created for projects to go into. | map(object({…})) | ✓ | | -| [folder_ids](variables.tf#L86) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | -| [organization](variables.tf#L95) | Organization details. | object({…}) | ✓ | | -| [prefix](variables.tf#L111) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | -| [regions](variables.tf#L142) | Region definitions. Inherited from 0-bootstrap outputs. Must be specified in bootstrap terraform.tfvars. | object({…}) | ✓ | | -| [tenant_accounts](variables.tf#L164) | Base Tenant accounts that are created for each folder, provided as a combination of environment and tenant. | map(object({…})) | ✓ | | -| [assured_workloads](variables.tf#L193) | Assured Workloads configuration. | any | | null | -| [billing_override](variables.tf#L184) | Optional billing override configuration. If set, disables service account impersonation for project billing linkage and runs under the user account using the specified quota projects. | object({…}) | | null | -| [cidrs](variables.tf#L274) | Named CIDR ranges to use in firewall rules. | map(list(string)) | | {} | -| [common_services_folder](variables.tf#L199) | Common services folder ID. | string | | null | -| [dns](variables.tf#L42) | DNS configuration. | object({…}) | | {} | -| [dns_policy_rules](variables.tf#L260) | DNS response policy rules in name => rule format. | map(object({…})) | | {} | -| [essential_contacts](variables.tf#L59) | Email used for essential contacts, unset if null. | string | | null | -| [factories_config](variables.tf#L65) | Configuration for network resource factories. | object({…}) | | {…} | -| [fast_features](variables.tf#L211) | FAST features enabled. | any | | null | -| [firewall_rules](variables.tf#L281) | Firewall rules for each VPC / environment spoke. | map(object({…})) | | {} | -| [groups](variables.tf#L217) | IAM groups mapping. | any | | null | -| [logging](variables.tf#L205) | Logging configuration. | any | | null | -| [outputs_location](variables.tf#L105) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | -| [proxy_subnets](variables.tf#L253) | VPC proxy-only subnet CIDRs keyed by environment. | map(string) | | {} | -| [psa_ranges](variables.tf#L122) | IP ranges used for Private Service Access (e.g. CloudSQL). Ranges is in name => range format. | object({…}) | | {} | -| [regime_mapping](variables.tf#L223) | Compliance regime shorthand mapping. | any | | null | -| [service_accounts](variables.tf#L150) | Automation service accounts in name => email format. | object({…}) | | null | -| [subnets](variables.tf#L229) | VPC subnet configurations keyed by network name. | map(list(object({…}))) | | {} | -| [vmseries_image](variables.tf#L178) | The image name from which to boot an instance, including a license type (bundle/flex) and version. | string | | "vmseries-112" | +| [alert_email](variables.tf#L17) | Email to receive log alerts. | string | ✓ | | +| [automation](variables.tf#L39) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | +| [billing_account](variables.tf#L67) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | object({…}) | ✓ | | +| [folder_ids](variables.tf#L136) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | +| [locations](variables.tf#L154) | Locations for different GCP services. | object({…}) | ✓ | | +| [logging](variables.tf#L165) | Logging configuration. | object({…}) | ✓ | | +| [organization](variables.tf#L181) | Organization details. | object({…}) | ✓ | | +| [prefix](variables.tf#L197) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | +| [regime_mapping](variables.tf#L234) | Mapping of compliance regime names to short codes. | map(string) | ✓ | | +| [shared_services_project_id](variables.tf#L266) | The project ID for shared services inherited from Stage 1. | string | ✓ | | +| [tenant_environments](variables.tf#L280) | List of environments to be created for projects to go into. | map(object({…})) | ✓ | | +| [assured_workloads](variables.tf#L22) | Configuration for Assured Workloads. | object({…}) | | {} | +| [auth_code](variables.tf#L33) | Optional Palo Alto auth-code for BYOL license activation. | string | | "" | +| [common_services_folder](variables.tf#L81) | Folder ID for common services. | string | | null | +| [custom_roles](variables.tf#L87) | Custom roles for the organization. | map(string) | | {} | +| [dns](variables.tf#L93) | DNS configuration. | object({…}) | | {} | +| [essential_contacts](variables.tf#L103) | Email used for essential contacts, unset if null. | string | | null | +| [factories_config](variables.tf#L109) | Configuration for network resource factories. | object({…}) | | {…} | +| [fast_features](variables.tf#L130) | Enable/disable FAST features. | map(bool) | | {} | +| [groups](variables.tf#L148) | GCP groups for the organization. | map(string) | | {} | +| [network_quota_preferred_value](variables.tf#L175) | The preferred target value for the Google Cloud network quota preference. | number | | 50 | +| [outputs_location](variables.tf#L191) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | +| [psa_ranges](variables.tf#L208) | IP ranges used for Private Service Access (e.g. CloudSQL). Ranges is in name => range format. | object({…}) | | {} | +| [regions](variables.tf#L239) | Region definitions. | object({…}) | | {…} | +| [service_accounts](variables.tf#L251) | Automation service accounts in name => email format. | object({…}) | | null | +| [tenant_accounts](variables.tf#L274) | Tenant accounts configuration. | any | | {} | ## Outputs | name | description | sensitive | |---|---|:---:| -| [host_project_ids](outputs.tf#L62) | Network project ids. | | -| [host_project_numbers](outputs.tf#L67) | Network project numbers. | | -| [ngfw_password](outputs.tf#L82) | Password for authenticating to the NGFW. | ✓ | -| [tfvars](outputs.tf#L88) | Terraform variables file for the following stages. | ✓ | +| [external_lb_ip](outputs.tf#L105) | The public IP of the external load balancer. | | +| [host_project_numbers](outputs.tf#L115) | Network project numbers. | | +| [ngfw_password](outputs.tf#L120) | Password for authenticating to the NGFW. | ✓ | +| [tfvars](outputs.tf#L131) | Terraform variables file for the following stages. | ✓ | diff --git a/fast/stages-aw/2-networking-b-il5-ngfw/bastion.tf b/fast/stages-aw/3-networking/bastion.tf similarity index 64% rename from fast/stages-aw/2-networking-b-il5-ngfw/bastion.tf rename to fast/stages-aw/3-networking/bastion.tf index c2b9819f5..8f2229782 100644 --- a/fast/stages-aw/2-networking-b-il5-ngfw/bastion.tf +++ b/fast/stages-aw/3-networking/bastion.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Google Compute Shielded VM Module module "bastion-vm" { @@ -33,7 +35,7 @@ module "bastion-vm" { ) }] encryption = { - kms_key_self_link = module.kms.keys.default.id + kms_key_self_link = module.kms[var.regions.primary].keys.default.id } attached_disks = [ { @@ -43,7 +45,7 @@ module "bastion-vm" { initialize_params = { image = "projects/cos-cloud/global/images/family/cos-stable" } - kms_key_self_link = module.kms.keys.default.id + kms_key_self_link = module.kms[var.regions.primary].keys.default.id } ] diff --git a/fast/stages-aw/3-networking/changelog b/fast/stages-aw/3-networking/changelog new file mode 100644 index 000000000..6c5339eb4 --- /dev/null +++ b/fast/stages-aw/3-networking/changelog @@ -0,0 +1,6 @@ +2606091411 +2606091512 +2606101328 +2606111153 +2606161610 +2606162340 diff --git a/fast/stages-aw/3-networking/create-subnet-plan-il5.sh b/fast/stages-aw/3-networking/create-subnet-plan-il5.sh new file mode 100644 index 000000000..6da9c7162 --- /dev/null +++ b/fast/stages-aw/3-networking/create-subnet-plan-il5.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +json_file="2-resman.auto.tfvars.json" +subnet_plan="data/subnet_plan.yaml" +env_names=$(jq -r '.tenant_environments | keys[]' "$json_file") + +base_ip="10.1.0.0" +base_octet=$(echo "$base_ip" | cut -d '.' -f 2) + +echo "---" > "$subnet_plan" +echo "tenant_environments_subnets:" >> "$subnet_plan" +counter=0 +while IFS= read -r env_names; do + incremented_octet=$((base_octet + counter)) + cidr="10.${incremented_octet}.0.0/16" + echo " ${env_names}: \"${cidr}\"" >> "$subnet_plan" + ((counter++)) +done <<< "$env_names" diff --git a/fast/stages-aw/3-networking/data/allowed_apis.yaml b/fast/stages-aw/3-networking/data/allowed_apis.yaml new file mode 100644 index 000000000..ba6d318c0 --- /dev/null +++ b/fast/stages-aw/3-networking/data/allowed_apis.yaml @@ -0,0 +1,48 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#testing purposes API's that already match existing list in the org. +allowed_apis: + - artifactregistry.googleapis.com + - bigquery.googleapis.com + - bigquerydatatransfer.googleapis.com + - privateca.googleapis.com + - cloudbuild.googleapis.com + - composer.googleapis.com + - datafusion.googleapis.com + - dns.googleapis.com + - cloudidentity.googleapis.com + - cloudkms.googleapis.com + - logging.googleapis.com + - monitoring.googleapis.com + - run.googleapis.com + - spanner.googleapis.com + - sqladmin.googleapis.com + - storage.googleapis.com + - cloudtasks.googleapis.com + - vision.googleapis.com + - workstations.googleapis.com + - compute.googleapis.com + - dataflow.googleapis.com + - dataproc.googleapis.com + - eventarc.googleapis.com + - gkehub.googleapis.com + - container.googleapis.com + - iam.googleapis.com + - redis.googleapis.com + - pubsub.googleapis.com + - secretmanager.googleapis.com + - dlp.googleapis.com + - speech.googleapis.com + - datapipelines.googleapis.com diff --git a/fast/stages-aw/3-networking/data/cidrs.yaml b/fast/stages-aw/3-networking/data/cidrs.yaml new file mode 100644 index 000000000..81219b8c4 --- /dev/null +++ b/fast/stages-aw/3-networking/data/cidrs.yaml @@ -0,0 +1,72 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# skip boilerplate check +--- +# Terraform will be unable to decode this file if it does not contain valid YAML +# You can retain `---` (start of the document) to indicate an empty document. + +healthchecks: + - 35.191.0.0/16 + - 130.211.0.0/22 + - 209.85.152.0/22 + - 209.85.204.0/22 + - 169.254.169.254/32 + +rfc1918: + - 10.0.0.0/8 + - 172.16.0.0/12 + - 192.168.0.0/16 + +iap: + - 35.235.240.0/20 + +internal: + - 10.84.0.0/14 + - 10.88.0.0/14 + - 10.92.0.0/14 + - 10.96.0.0/14 + +core: + - 10.84.0.0/14 + +dev: + - 10.88.0.0/14 + +test: + - 10.92.0.0/14 + +prod: + - 10.96.0.0/14 + +#bcap: +# - 10.84.253.0/24 + +#interconnect: +# - 10.84.252.0/24 + +test_landing: + - 10.84.3.0/25 + +prod_landing: + - 10.84.4.0/25 + +bcap_landing: + - 10.84.5.0/25 + +interconnect_landing: + - 10.84.6.0/25 + +csp_landing: + - 10.84.7.0/25 \ No newline at end of file diff --git a/fast/stages-aw/3-networking/data/dns-policy-rules.yaml b/fast/stages-aw/3-networking/data/dns-policy-rules.yaml new file mode 100644 index 000000000..8f793c56b --- /dev/null +++ b/fast/stages-aw/3-networking/data/dns-policy-rules.yaml @@ -0,0 +1,143 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# skip boilerplate check +--- +# start of document (---) avoids errors if the file only contains comments + +# yaml-language-server: $schema=../schemas/dns-response-policy-rules.json + +accounts: + dns_name: "accounts.google.com." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +aiplatform-notebook-cloud-all: + dns_name: "*.aiplatform-notebook.cloud.google.com." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +aiplatform-notebook-gu-all: + dns_name: "*.aiplatform-notebook.googleusercontent.com." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +backupdr-cloud: + dns_name: "backupdr.cloud.google.com." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +backupdr-cloud-all: + dns_name: "*.backupdr.cloud.google.com." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +backupdr-gu: + dns_name: "backupdr.googleusercontent.google.com." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +backupdr-gu-all: + dns_name: "*.backupdr.googleusercontent.google.com." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +cloudfunctions: + dns_name: "*.cloudfunctions.net." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +cloudproxy: + dns_name: "*.cloudproxy.app." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +composer-cloud-all: + dns_name: "*.composer.cloud.google.com." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +composer-gu-all: + dns_name: "*.composer.googleusercontent.com." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +datafusion-all: + dns_name: "*.datafusion.cloud.google.com." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +datafusion-gu-all: + dns_name: "*.datafusion.googleusercontent.com." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +dataproc: + dns_name: "dataproc.cloud.google.com." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +dataproc-all: + dns_name: "*.dataproc.cloud.google.com." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +dataproc-gu: + dns_name: "dataproc.googleusercontent.com." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +dataproc-gu-all: + dns_name: "*.dataproc.googleusercontent.com." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +dl: + dns_name: "dl.google.com." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +gcr: + dns_name: "gcr.io." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +gcr-all: + dns_name: "*.gcr.io." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +gke-all: + dns_name: "*.gke.goog." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +googleapis-all: + dns_name: "*.googleapis.com." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +googleapis-private: + dns_name: "private.googleapis.com." + local_data: + A: + rrdatas: + - 10.84.255.255 +googleapis-restricted: + dns_name: "restricted.googleapis.com." + local_data: + A: + rrdatas: + - 10.84.255.255 +gstatic-all: + dns_name: "*.gstatic.com." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +kernels-gu: + dns_name: "kernels.googleusercontent.com." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +kernels-gu-all: + dns_name: "*.kernels.googleusercontent.com." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +ltsapis-all: + dns_name: "*.ltsapis.goog." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +notebooks-all: + dns_name: "*.notebooks.cloud.google.com." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +notebooks-gu-all: + dns_name: "*.notebooks.googleusercontent.com." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +packages-cloud: + dns_name: "packages.cloud.google.com." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +packages-cloud-all: + dns_name: "*.packages.cloud.google.com." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +pkgdev: + dns_name: "pkg.dev." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +pkgdev-all: + dns_name: "*.pkg.dev." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +pkigoog: + dns_name: "pki.goog." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +pkigoog-all: + dns_name: "*.pki.goog." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +run-all: + dns_name: "*.run.app." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +source: + dns_name: "source.developers.google.com." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} +storage: + dns_name: "storage.cloud.google.com." + local_data: {CNAME: {rrdatas: ["private.googleapis.com."]}} diff --git a/fast/stages-aw/3-networking/data/firewall-rules/bcap/rules.yaml b/fast/stages-aw/3-networking/data/firewall-rules/bcap/rules.yaml new file mode 100644 index 000000000..1864d7ef6 --- /dev/null +++ b/fast/stages-aw/3-networking/data/firewall-rules/bcap/rules.yaml @@ -0,0 +1,18 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# skip boilerplate check +--- +ingress: + \ No newline at end of file diff --git a/fast/stages-aw/3-networking/data/firewall-rules/csp/rules.yaml b/fast/stages-aw/3-networking/data/firewall-rules/csp/rules.yaml new file mode 100644 index 000000000..da104fda1 --- /dev/null +++ b/fast/stages-aw/3-networking/data/firewall-rules/csp/rules.yaml @@ -0,0 +1,20 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# skip boilerplate check +--- +# Terraform will be unable to decode this file if it does not contain valid YAML +# You can retain `---` (start of the document) to indicate an empty document. + +ingress: diff --git a/fast/stages-aw/3-networking/data/firewall-rules/dmz/rules.yaml b/fast/stages-aw/3-networking/data/firewall-rules/dmz/rules.yaml new file mode 100644 index 000000000..67e94c676 --- /dev/null +++ b/fast/stages-aw/3-networking/data/firewall-rules/dmz/rules.yaml @@ -0,0 +1,40 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# skip boilerplate check +--- +# Terraform will be unable to decode this file if it does not contain valid YAML +# You can retain `---` (start of the document) to indicate an empty document. + +ingress: +# allow-hc-nva-ssh-dmz: +# description: "Allow traffic from Google healthchecks to NVA appliances" +# targets: ["nva"] +# source_ranges: +# - healthchecks +# rules: +# - protocol: tcp +# ports: +# - 443 +# - 80 + allow-elb-to-nva-dmz: + description: "Allow traffic from internet via ELB to NVA appliances" + targets: ["nva"] + source_ranges: + - 0.0.0.0/0 + rules: + - protocol: tcp + ports: + - 80 + - 443 \ No newline at end of file diff --git a/fast/stages-aw/3-networking/data/firewall-rules/interconnect/rules.yaml b/fast/stages-aw/3-networking/data/firewall-rules/interconnect/rules.yaml new file mode 100644 index 000000000..954c88cd5 --- /dev/null +++ b/fast/stages-aw/3-networking/data/firewall-rules/interconnect/rules.yaml @@ -0,0 +1,17 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# skip boilerplate check +--- +ingress: diff --git a/fast/stages-aw/3-networking/data/firewall-rules/mgmt/rules.yaml b/fast/stages-aw/3-networking/data/firewall-rules/mgmt/rules.yaml new file mode 100644 index 000000000..864cc36a2 --- /dev/null +++ b/fast/stages-aw/3-networking/data/firewall-rules/mgmt/rules.yaml @@ -0,0 +1,60 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# skip boilerplate check +--- +# Terraform will be unable to decode this file if it does not contain valid YAML +# You can retain `---` (start of the document) to indicate an empty document. + +ingress: + allow-iap-ssh-mgmt: + description: "Allow traffic from Google IAP over SSH" + source_ranges: + - iap + rules: + - protocol: tcp + ports: + - 22 + #allow-hc-nva-ssh-mgmt: + # description: "Allow traffic from Google healthchecks to NVA appliances" + #targets: ["nva"] + #source_ranges: + # - healthchecks + # - iap + # rules: + # - protocol: tcp + # ports: + # - 22 + # - 443 + allow-ssh-bastion-nva-mgmt: + description: "We expect the bastion host to be able to SSH into the NGFWs" + sources: + - bastion + source_ranges: + - internal + targets: + - nva + rules: + - protocol: tcp + ports: + - 22 + - 443 + allow-iap-https-mgmt: + description: "Allow traffic from Google IAP over HTTPS" + source_ranges: + - iap + rules: + - protocol: tcp + ports: + - 443 \ No newline at end of file diff --git a/fast/stages-aw/3-networking/data/firewall-rules/sharedsvcs/rules.yaml b/fast/stages-aw/3-networking/data/firewall-rules/sharedsvcs/rules.yaml new file mode 100644 index 000000000..1eb68479b --- /dev/null +++ b/fast/stages-aw/3-networking/data/firewall-rules/sharedsvcs/rules.yaml @@ -0,0 +1,20 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# skip boilerplate check +--- +# Terraform will be unable to decode this file if it does not contain valid YAML +# You can retain `---` (start of the document) to indicate an empty document. + +ingress: diff --git a/fast/stages-aw/3-networking/data/firewall-rules/transit/rules.yaml b/fast/stages-aw/3-networking/data/firewall-rules/transit/rules.yaml new file mode 100644 index 000000000..da104fda1 --- /dev/null +++ b/fast/stages-aw/3-networking/data/firewall-rules/transit/rules.yaml @@ -0,0 +1,20 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# skip boilerplate check +--- +# Terraform will be unable to decode this file if it does not contain valid YAML +# You can retain `---` (start of the document) to indicate an empty document. + +ingress: diff --git a/fast/stages-aw/3-networking/data/firewall-rules/vdss/rules.yaml b/fast/stages-aw/3-networking/data/firewall-rules/vdss/rules.yaml new file mode 100644 index 000000000..04c069cd4 --- /dev/null +++ b/fast/stages-aw/3-networking/data/firewall-rules/vdss/rules.yaml @@ -0,0 +1,20 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# skip boilerplate check +--- +# Terraform will be unable to decode this file if it does not contain valid YAML +# You can retain `---` (start of the document) to indicate an empty document. + +ingress: \ No newline at end of file diff --git a/fast/stages-aw/3-networking/data/hierarchical-ingress-rules.yaml b/fast/stages-aw/3-networking/data/hierarchical-ingress-rules.yaml new file mode 100644 index 000000000..b2b4c3c5b --- /dev/null +++ b/fast/stages-aw/3-networking/data/hierarchical-ingress-rules.yaml @@ -0,0 +1,76 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +# data/hierarchical-ingress-rules.yaml +# Consolidates administrative, health check, and internal routing access for NVAs at the Folder level. + +allow-iap-to-nva: + description: "Allow traffic from Google IAP (SSH/HTTPS) to NVA appliances" + priority: 1000 + action: "allow" + direction: "INGRESS" + target_service_accounts: + - "ngfw-compute@prod-il5-vdss-host.iam.gserviceaccount.com" + match: + source_ranges: + - iap + layer4_configs: + - protocol: tcp + ports: + - "22" + - "443" + +allow-hc-to-nva: + description: "Allow traffic from Google health checks to NVA appliances" + priority: 1010 + action: "allow" + direction: "INGRESS" + target_service_accounts: + - "ngfw-compute@prod-il5-vdss-host.iam.gserviceaccount.com" + match: + source_ranges: + - healthchecks + layer4_configs: + - protocol: tcp + ports: + - "80" + - "443" + +allow-internal-to-nva: + description: "Allow internal East-West traffic (RFC1918) to reach the NVAs for inspection" + priority: 1020 + action: "allow" + direction: "INGRESS" + target_service_accounts: + - "ngfw-compute@prod-il5-vdss-host.iam.gserviceaccount.com" + match: + source_ranges: + - "10.0.0.0/8" + layer4_configs: + - protocol: tcp + - protocol: icmp + +allow-ssh-from-iap: + description: "Allow SSH from IAP" + priority: 1030 + action: "allow" + direction: "INGRESS" + match: + source_ranges: + - "35.235.240.0/20" + layer4_configs: + - protocol: tcp + ports: + - "22" \ No newline at end of file diff --git a/fast/stages-aw/3-networking/data/hierarchical-ingress-rules.yaml.tmpl b/fast/stages-aw/3-networking/data/hierarchical-ingress-rules.yaml.tmpl new file mode 100644 index 000000000..8c8a92ce1 --- /dev/null +++ b/fast/stages-aw/3-networking/data/hierarchical-ingress-rules.yaml.tmpl @@ -0,0 +1,49 @@ +--- +# data/hierarchical-ingress-rules.yaml +# Consolidates administrative, health check, and internal routing access for NVAs at the Folder level. + +allow-iap-to-nva: + description: "Allow traffic from Google IAP (SSH/HTTPS) to NVA appliances" + priority: 1000 + action: "allow" + direction: "INGRESS" + target_service_accounts: + - "ngfw-compute@${vdss-project-id}.iam.gserviceaccount.com" + match: + source_ranges: + - iap + layer4_configs: + - protocol: tcp + ports: + - "22" + - "443" + +allow-hc-to-nva: + description: "Allow traffic from Google health checks to NVA appliances" + priority: 1010 + action: "allow" + direction: "INGRESS" + target_service_accounts: + - "ngfw-compute@${vdss-project-id}.iam.gserviceaccount.com" + match: + source_ranges: + - healthchecks + layer4_configs: + - protocol: tcp + ports: + - "80" + - "443" + +allow-internal-to-nva: + description: "Allow internal East-West traffic (RFC1918) to reach the NVAs for inspection" + priority: 1020 + action: "allow" + direction: "INGRESS" + target_service_accounts: + - "ngfw-compute@${vdss-project-id}.iam.gserviceaccount.com" + match: + source_ranges: + - "10.0.0.0/8" + layer4_configs: + - protocol: tcp + - protocol: icmp \ No newline at end of file diff --git a/fast/stages-aw/3-networking/data/lz_exceptions.yaml b/fast/stages-aw/3-networking/data/lz_exceptions.yaml new file mode 100644 index 000000000..3e801ebce --- /dev/null +++ b/fast/stages-aw/3-networking/data/lz_exceptions.yaml @@ -0,0 +1,43 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# lz_exceptions.yaml +# Combined list of Category 1 and Category 2 API exceptions for LZ Infrastructure +# These APIs are authorized for use in Core LZ projects only. +COA2: +# Category 1: IL5 Authorized / compliance Catalog Update Pending +#category_1_exceptions: + - accesscontextmanager.googleapis.com + - cloudasset.googleapis.com + - cloudbilling.googleapis.com + - networkconnectivity.googleapis.com + - servicedirectory.googleapis.com +# Category 2: Management/Enabling APIs Not Listed in compliance Catalog +# category_2_exceptions: + - assuredworkloads.googleapis.com + - bigqueryreservation.googleapis.com + - bigquerystorage.googleapis.com + - billingbudgets.googleapis.com + - cloudquotas.googleapis.com + - cloudresourcemanager.googleapis.com + - essentialcontacts.googleapis.com + - iamcredentials.googleapis.com + - iap.googleapis.com + - networksecurity.googleapis.com + - orgpolicy.googleapis.com + - servicenetworking.googleapis.com + - serviceusage.googleapis.com + - stackdriver.googleapis.com + - storage-component.googleapis.com + - sts.googleapis.com \ No newline at end of file diff --git a/fast/stages-aw/3-networking/data/subnet_plan.yaml b/fast/stages-aw/3-networking/data/subnet_plan.yaml new file mode 100644 index 000000000..173c89ae6 --- /dev/null +++ b/fast/stages-aw/3-networking/data/subnet_plan.yaml @@ -0,0 +1,19 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +tenant_environments_subnets: + dev: "10.88.0.0/14" + test: "10.92.0.0/14" + prod: "10.96.0.0/14" diff --git a/fast/stages-aw/3-networking/data/subnets/bcap/bcap-east4.yaml b/fast/stages-aw/3-networking/data/subnets/bcap/bcap-east4.yaml new file mode 100644 index 000000000..cfa41726f --- /dev/null +++ b/fast/stages-aw/3-networking/data/subnets/bcap/bcap-east4.yaml @@ -0,0 +1,23 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Subnet for bcap landing +name: bcap-landing +region: us-east4 +ip_cidr_range: 10.84.5.0/29 +description: Landing subnet for bcap environment +flow_logs_config: + aggregation_interval: "INTERVAL_5_SEC" + flow_sampling: 1 + metadata: "INCLUDE_ALL_METADATA" diff --git a/fast/stages-aw/3-networking/data/subnets/csp/csp-east4.yaml b/fast/stages-aw/3-networking/data/subnets/csp/csp-east4.yaml new file mode 100644 index 000000000..c52ccc1ba --- /dev/null +++ b/fast/stages-aw/3-networking/data/subnets/csp/csp-east4.yaml @@ -0,0 +1,23 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Subnet for AWS/Azure VPN landing +name: csp-landing +region: us-east4 +ip_cidr_range: 10.84.7.0/29 +description: Subnet for external VPN connectivity (AWS/Azure) +flow_logs_config: + aggregation_interval: "INTERVAL_5_SEC" + flow_sampling: 1 + metadata: "INCLUDE_ALL_METADATA" diff --git a/fast/stages-aw/0-bootstrap/audit-logging.tf b/fast/stages-aw/3-networking/data/subnets/dmz/dmz-east4.yaml similarity index 61% rename from fast/stages-aw/0-bootstrap/audit-logging.tf rename to fast/stages-aw/3-networking/data/subnets/dmz/dmz-east4.yaml index 727077593..bf746c4d9 100644 --- a/fast/stages-aw/0-bootstrap/audit-logging.tf +++ b/fast/stages-aw/3-networking/data/subnets/dmz/dmz-east4.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,17 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. -# CIS Compliance Benchmark 2.1 -resource "google_organization_iam_audit_config" "organization" { - org_id = var.organization.id - service = "allServices" - audit_log_config { - log_type = "ADMIN_READ" - } - audit_log_config { - log_type = "DATA_WRITE" - } - audit_log_config { - log_type = "DATA_READ" - } -} +# skip boilerplate check + +name: dmz-default +region: us-east4 +ip_cidr_range: 10.84.128.0/24 +description: Default us-east4 subnet for landing dmz +flow_logs_config: # CIS Compliance Benchmark 3.8 + aggregation_interval: "INTERVAL_5_SEC" + flow_sampling: 1 + metadata: "INCLUDE_ALL_METADATA" diff --git a/fast/stages-aw/3-networking/data/subnets/interconnect/interconnect-east4.yaml b/fast/stages-aw/3-networking/data/subnets/interconnect/interconnect-east4.yaml new file mode 100644 index 000000000..524a2ecd8 --- /dev/null +++ b/fast/stages-aw/3-networking/data/subnets/interconnect/interconnect-east4.yaml @@ -0,0 +1,23 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Subnet for interconnect landing +name: interconnect-landing +region: us-east4 +ip_cidr_range: 10.84.6.0/29 +description: Landing subnet for interconnect environment +flow_logs_config: + aggregation_interval: "INTERVAL_5_SEC" + flow_sampling: 1 + metadata: "INCLUDE_ALL_METADATA" diff --git a/fast/stages-aw/3-networking/data/subnets/landing/vdms-east4.yaml b/fast/stages-aw/3-networking/data/subnets/landing/vdms-east4.yaml new file mode 100644 index 000000000..a0c9e0834 --- /dev/null +++ b/fast/stages-aw/3-networking/data/subnets/landing/vdms-east4.yaml @@ -0,0 +1,24 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# skip boilerplate check +--- +name: vdms-default +region: us-east4 +ip_cidr_range: 10.84.1.0/24 +description: Subnet for VDMS +flow_logs_config: # CIS Compliance Benchmark 3.8 + aggregation_interval: "INTERVAL_5_SEC" + flow_sampling: 1 + metadata: "INCLUDE_ALL_METADATA" diff --git a/fast/stages-aw/3-networking/data/subnets/landing/vdss-shared-default-east4.yaml b/fast/stages-aw/3-networking/data/subnets/landing/vdss-shared-default-east4.yaml new file mode 100644 index 000000000..07a96982d --- /dev/null +++ b/fast/stages-aw/3-networking/data/subnets/landing/vdss-shared-default-east4.yaml @@ -0,0 +1,24 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# skip boilerplate check +--- +name: landing-default +region: us-east4 +ip_cidr_range: 10.84.0.0/24 +description: Default us-east4 subnet for vdss +flow_logs_config: # CIS Compliance Benchmark 3.8 + aggregation_interval: "INTERVAL_5_SEC" + flow_sampling: 1 + metadata: "INCLUDE_ALL_METADATA" diff --git a/fast/stages-aw/3-networking/data/subnets/mgmt/mgmt-east4.yaml b/fast/stages-aw/3-networking/data/subnets/mgmt/mgmt-east4.yaml new file mode 100644 index 000000000..2a9d62da6 --- /dev/null +++ b/fast/stages-aw/3-networking/data/subnets/mgmt/mgmt-east4.yaml @@ -0,0 +1,24 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# skip boilerplate check + +name: mgmt-default +region: us-east4 +ip_cidr_range: 10.84.129.0/24 +description: Default us-east4 subnet for landing mgmt +flow_logs_config: # CIS Compliance Benchmark 3.8 + aggregation_interval: "INTERVAL_5_SEC" + flow_sampling: 1 + metadata: "INCLUDE_ALL_METADATA" diff --git a/fast/stages-aw/3-networking/data/subnets/proxy-subnets.yaml b/fast/stages-aw/3-networking/data/subnets/proxy-subnets.yaml new file mode 100644 index 000000000..6d379803b --- /dev/null +++ b/fast/stages-aw/3-networking/data/subnets/proxy-subnets.yaml @@ -0,0 +1,16 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +tenant_environments_proxy_subnets: + sharedsvcs: "10.84.8.0/23" diff --git a/fast/stages-aw/3-networking/data/subnets/sharedsvcs/sharedsvcs.yaml b/fast/stages-aw/3-networking/data/subnets/sharedsvcs/sharedsvcs.yaml new file mode 100644 index 000000000..928730865 --- /dev/null +++ b/fast/stages-aw/3-networking/data/subnets/sharedsvcs/sharedsvcs.yaml @@ -0,0 +1,23 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Subnet for shared svcs +name: shared-services +region: us-east4 +ip_cidr_range: 10.96.0.0/22 +description: Subnet for Shared Services +flow_logs_config: + aggregation_interval: "INTERVAL_5_SEC" + flow_sampling: 1 + metadata: "INCLUDE_ALL_METADATA" diff --git a/fast/stages-aw/3-networking/data/subnets/transit/tenant-transit-us-east4.yaml b/fast/stages-aw/3-networking/data/subnets/transit/tenant-transit-us-east4.yaml new file mode 100644 index 000000000..390e33cdf --- /dev/null +++ b/fast/stages-aw/3-networking/data/subnets/transit/tenant-transit-us-east4.yaml @@ -0,0 +1,23 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Subnet for dev landing +name: tenant-transit +region: us-east4 +ip_cidr_range: 10.84.2.0/29 +description: Landing subnet for dev environment +flow_logs_config: + aggregation_interval: "INTERVAL_5_SEC" + flow_sampling: 1 + metadata: "INCLUDE_ALL_METADATA" diff --git a/fast/stages-aw/3-networking/dns.tf b/fast/stages-aw/3-networking/dns.tf new file mode 100644 index 000000000..b78a882c2 --- /dev/null +++ b/fast/stages-aw/3-networking/dns.tf @@ -0,0 +1,44 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# tfdoc:file:description DNS zones and policies. + +module "landing-dns-zone-private" { + source = "../../../modules/dns" + project_id = module.vdss-host-project.project_id + name = lower("${var.prefix}-${replace(lookup(var.regime_mapping, var.assured_workloads.regime, var.assured_workloads.regime), "_", " ")}-vdss-org-domain-private") + zone_config = { + domain = lower("${var.prefix}-${replace(lookup(var.regime_mapping, var.assured_workloads.regime, var.assured_workloads.regime), "_", " ")}-vdss.private.${var.organization.domain}.") + private = { + client_networks = [module.vdss-vpc.self_link] + } + } + recordsets = { + "A localhost" = { records = ["127.0.0.1"] } + } +} + +module "landing-dns-policy-googleapis" { + source = "../../../modules/dns-response-policy" + project_id = module.vdss-host-project.project_id + name = "googleapis" + factories_config = { + rules = var.factories_config.dns_policy_rules_file + } + networks = { + landing = module.vdss-vpc.self_link + } +} + diff --git a/fast/stages-aw/2-networking-b-il5-ngfw/log-metric-alerts.tf b/fast/stages-aw/3-networking/log-metric-alerts.tf similarity index 72% rename from fast/stages-aw/2-networking-b-il5-ngfw/log-metric-alerts.tf rename to fast/stages-aw/3-networking/log-metric-alerts.tf index 5cf9731e2..e143ee944 100644 --- a/fast/stages-aw/2-networking-b-il5-ngfw/log-metric-alerts.tf +++ b/fast/stages-aw/3-networking/log-metric-alerts.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # CIS Compliance Benchmark 2.4 # CIS Compliance Benchmark 2.5 diff --git a/fast/stages-aw/3-networking/main.tf b/fast/stages-aw/3-networking/main.tf new file mode 100644 index 000000000..959ad1cd3 --- /dev/null +++ b/fast/stages-aw/3-networking/main.tf @@ -0,0 +1,96 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# tfdoc:file:description Networking folder and hierarchical policy. + +locals { + service_accounts = { + for k, v in coalesce(var.service_accounts, {}) : + k => "serviceAccount:${v}" if v != null + } + proxy_subnets = yamldecode(file("./data/subnets/proxy-subnets.yaml")).tenant_environments_proxy_subnets + + # The following section maps project names for stage 3 using the projects-config.yml inside of the root directory + formatted_regime = lower(replace(lookup(var.regime_mapping, var.assured_workloads.regime, var.assured_workloads.regime), "_", " ")) + project_config_yaml = yamldecode(file("../../../project-config.yml")) + project_map = { + for p in local.project_config_yaml.projects : p.name => + replace(replace(p.project_name, "", var.prefix), "", local.formatted_regime) + } + allowed_api_data = yamldecode(file("./data/allowed_apis.yaml")) + lz_data = yamldecode(file("./data/lz_exceptions.yaml")) + + coa2_allowed_apis = concat( + local.allowed_api_data.allowed_apis, + local.lz_data.COA2 + ) + +} +module "folder" { + source = "../../../modules/folder" + parent = "organizations/${var.organization.id}" + name = "Networking" + folder_create = var.folder_ids.networking == null + id = var.folder_ids.networking + contacts = ( + var.essential_contacts == null + ? {} + : { (var.essential_contacts) = ["ALL"] } + ) + firewall_policy = { + name = "default" + policy = module.firewall-policy-default.id + } +} + +resource "local_file" "generated_ingress_rule" { + content = templatefile("${var.factories_config.data_dir}/hierarchical-ingress-rules.yaml.tmpl", { + vdss-project-id = local.project_map["vdss-host-project"] + }) + + filename = "${var.factories_config.data_dir}/hierarchical-ingress-rules.yaml" +} + +module "firewall-policy-default" { + source = "../../../modules/net-firewall-policy" + name = "${var.prefix}-${var.factories_config.firewall_policy_name}-${replace(lower(lookup(var.regime_mapping, var.assured_workloads.regime, var.assured_workloads.regime)), "_", "-")}" + parent_id = module.folder.id + factories_config = { + cidr_file_path = "${var.factories_config.data_dir}/cidrs.yaml" + ingress_rules_file_path = "${var.factories_config.data_dir}/hierarchical-ingress-rules.yaml" + } +} + +resource "google_project_organization_policy" "net_vdss_host_policy" { + project = module.vdss-host-project.project_id + constraint = "constraints/gcp.restrictServiceUsage" + + list_policy { + allow { + values = local.coa2_allowed_apis + } + } +} + +resource "google_project_organization_policy" "shared_svcs_project_policy" { + project = var.shared_services_project_id + constraint = "constraints/gcp.restrictServiceUsage" + + list_policy { + allow { + values = local.coa2_allowed_apis + } + } +} \ No newline at end of file diff --git a/fast/stages-aw/3-networking/ncc.tf b/fast/stages-aw/3-networking/ncc.tf new file mode 100644 index 000000000..ae7d04b77 --- /dev/null +++ b/fast/stages-aw/3-networking/ncc.tf @@ -0,0 +1,112 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# tfdoc:file:description Networking Hub and Spokes configuration using Network Connectivity Center. + +# main hub +resource "google_network_connectivity_hub" "main" { + name = "main-hub" + project = module.vdss-host-project.project_id + description = "Main NCC Hub for Landings and Spokes" + preset_topology = "STAR" + export_psc = true +} + +# Hub groups with auto-accept for cross-project spokes +resource "google_network_connectivity_group" "groups" { + for_each = toset(["center", "edge"]) + hub = google_network_connectivity_hub.main.id + name = each.key + project = module.vdss-host-project.project_id + auto_accept { + auto_accept_projects = ["*"] # Allow all projects in the organization + } +} + +# center spokes +resource "google_network_connectivity_spoke" "landing" { + name = "landing-vpc-spoke" + hub = google_network_connectivity_hub.main.id + location = "global" + project = module.vdss-host-project.project_id + group = google_network_connectivity_group.groups["center"].id + linked_vpc_network { + uri = module.vdss-vpc.self_link + } + depends_on = [google_network_connectivity_hub.main] +} + +resource "google_network_connectivity_spoke" "sharedsvcs" { + name = "shared-services-spoke" + hub = google_network_connectivity_hub.main.id + location = "global" + project = module.vdss-host-project.project_id + group = google_network_connectivity_group.groups["center"].id + linked_vpc_network { + uri = module.shared-services-vpc.self_link + exclude_export_ranges = ["10.84.8.0/23"] + } + depends_on = [google_network_connectivity_hub.main] +} + +#Tenant Transit Spoke +resource "google_network_connectivity_spoke" "tenant_spoke" { + name = "tenant-transit-vpc-spoke" + hub = google_network_connectivity_hub.main.id + location = "global" + project = module.vdss-host-project.project_id + group = google_network_connectivity_group.groups["center"].id + + linked_vpc_network { + uri = module.tenant-transit-vpc.self_link + } +} + +# edge spokes +resource "google_network_connectivity_spoke" "csp_spoke" { + name = "csp-vpc-spoke" + hub = google_network_connectivity_hub.main.id + location = "global" + project = module.vdss-host-project.project_id + group = google_network_connectivity_group.groups["edge"].id + linked_vpc_network { + uri = module.csp-landing-vpc.self_link + exclude_export_ranges = ["10.84.7.0/24"] + } +} + +resource "google_network_connectivity_spoke" "bcap_spoke" { + name = "bcap-vpc-spoke" + hub = google_network_connectivity_hub.main.id + location = "global" + project = module.vdss-host-project.project_id + group = google_network_connectivity_group.groups["edge"].id + linked_vpc_network { + uri = module.bcap-spoke-vpc.self_link + exclude_export_ranges = ["10.84.5.0/24"] + } +} + +resource "google_network_connectivity_spoke" "interconnect_spoke" { + name = "interconnect-vpc-spoke" + hub = google_network_connectivity_hub.main.id + location = "global" + project = module.vdss-host-project.project_id + group = google_network_connectivity_group.groups["edge"].id + linked_vpc_network { + uri = module.interconnect-spoke-vpc.self_link + exclude_export_ranges = ["10.84.6.0/24"] + } +} diff --git a/fast/stages-aw/3-networking/ngfw.tf b/fast/stages-aw/3-networking/ngfw.tf new file mode 100644 index 000000000..2bd6dce88 --- /dev/null +++ b/fast/stages-aw/3-networking/ngfw.tf @@ -0,0 +1,618 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +locals { + # routing_config should be aligned to the NVA network interfaces - i.e. + # local.routing_config[0] sets up the first interface, and so on. + # tflint-ignore: terraform_unused_declarations + nva_zones = { for k, v in toset([var.regions.primary]) : k => slice(data.google_compute_zones.available[k].names, 0, 2) } + cidr_ranges = yamldecode(file("${path.module}/data/cidrs.yaml")) + all_regions = flatten([var.regions.primary, var.regions.secondary]) + auth_code = var.auth_code != "" ? var.auth_code : trimspace(file("${path.module}/templates/authcodes")) + + bootstrap-xml-local = { + for reg in toset([var.regions.primary]) : reg => templatefile("${path.module}/templates/bootstrap.xml.tpl", { + password_hash = data.external.openssl.result.hash + ssh_pubkey = tls_private_key.ngfw-ssh.public_key_openssh + healthcheck_cidrs = local.cidr_ranges["healthchecks"] + iap_cidrs = local.cidr_ranges["iap"] + lz_gateway_ip = module.vdss-vpc.subnets["${reg}/landing-default"].gateway_address + dmz_gateway_ip = module.dmz-vpc.subnets["${reg}/dmz-default"].gateway_address + tenant_gateway_ip = module.tenant-transit-vpc.subnets["${reg}/tenant-transit"].gateway_address + bcap_gateway_ip = module.bcap-spoke-vpc.subnets["${reg}/bcap-landing"].gateway_address + interconnect_gateway_ip = module.interconnect-spoke-vpc.subnets["${reg}/interconnect-landing"].gateway_address + lz_subnet_cidr = module.vdss-vpc.subnets["${reg}/landing-default"].ip_cidr_range + vdss_internal_cidr = "10.84.0.0/14" + elb_frontend_ip = google_compute_address.elb_dmz_ip[reg].address + ilb_frontend_ip = google_compute_address.ilb_vdss_ip[reg].address + tt_frontend_ip = google_compute_address.ilb_tt_ip[reg].address + bcap_frontend_ip = google_compute_address.ilb_bcap_ip[reg].address + interconnect_frontend_ip = google_compute_address.ilb_interconnect_ip[reg].address + }) + } + init-cfg-local = { + for reg in toset([var.regions.primary]) : reg => templatefile("${path.module}/templates/init-cfg.txt.tpl", { + op-command-modes = "mgmt-interface-swap" + auth_code = local.auth_code + redis_endpoint = "${google_redis_instance.session_resiliency.host}:6379" + redis_auth = random_password.redis_auth.result + }) + } +} + +data "google_storage_project_service_account" "gcs_account" { + project = module.vdss-host-project.project_id + depends_on = [module.vdss-host-project] +} + +data "google_compute_image" "vmseries" { + filter = "name=vmseries-flex-byol-1120" + most_recent = true + project = "paloaltonetworksgcp-public" +} + +data "google_compute_zones" "available" { + for_each = toset([var.regions.primary]) + region = each.value + project = module.vdss-host-project.project_id + status = "UP" + + depends_on = [module.vdss-host-project] +} + +resource "tls_private_key" "ngfw-ssh" { + algorithm = "RSA" + rsa_bits = "4096" +} + +# Shell out to openssl to get the password hash +resource "random_password" "password" { + length = 16 + special = true + override_special = "!#$%&*()-_=+[]{}<>:?" +} + +# Regional Secret Manager resource tracking the random password +resource "google_secret_manager_regional_secret" "ngfw_password" { + secret_id = "ngfw-admin-password" + project = module.vdss-host-project.project_id + location = var.regions.primary + customer_managed_encryption { + kms_key_name = module.kms[var.regions.primary].keys["default"].id + } +} + +resource "google_secret_manager_regional_secret_version" "ngfw_password_version" { + secret = google_secret_manager_regional_secret.ngfw_password.id + secret_data = random_password.password.result +} + +# Shell out to openssl to get the password hash +resource "random_password" "salt" { + length = 8 + special = false +} + +resource "google_project_iam_custom_role" "ngfw-custom-role" { + role_id = "ngfw.appliance" + title = "NGFW Appliance" + project = module.vdss-host-project.project_id + + description = "Many of the permissions required for the Palo Alto NGFW, not including compute.viewer" + permissions = [ + "storage.buckets.get", + "logging.buckets.write", + "opsconfigmonitoring.resourceMetadata.write", + "autoscaling.sites.writeMetrics", + "monitoring.metricDescriptors.create", + "monitoring.metricDescriptors.get", + "monitoring.metricDescriptors.list", + "monitoring.monitoredResourceDescriptors.get", + "monitoring.monitoredResourceDescriptors.list", + "monitoring.timeSeries.create", + ] +} + +module "ngfw-service-account" { + name = "ngfw-compute" + source = "../../../modules/iam-service-account" + project_id = module.vdss-host-project.project_id + iam_project_roles = { + (module.vdss-host-project.project_id) = [ + "projects/${module.vdss-host-project.project_id}/roles/ngfw.appliance", + "roles/compute.viewer" + ] + } + iam = { + "roles/iam.serviceAccountUser" = [ + # FIX un-hardcode the prefix + "serviceAccount:${var.automation.service_accounts.resman}" + ] + } + depends_on = [module.vdss-host-project, google_project_iam_custom_role.ngfw-custom-role] +} + +data "external" "openssl" { + program = ["bash", "${path.module}/openssl-helper.sh"] + query = { + # arbitrary map from strings to strings, passed + # to the external program as the data query. + algo = "5" + salt = random_password.salt.result + plaintext = random_password.password.result + } +} + +# Google Cloud Storage Module +module "ngfw-bootstrap-bucket" { + source = "../../../modules/gcs" + for_each = toset([var.regions.primary]) + prefix = var.prefix + project_id = module.vdss-host-project.project_id + encryption_key = module.kms[each.value].keys.default.id + storage_class = "REGIONAL" + name = "ngfw-bootstrap-${each.value}" + location = upper(each.value) + depends_on = [module.kms] +} + +resource "google_storage_bucket_iam_binding" "binding" { + bucket = module.ngfw-bootstrap-bucket[each.key].name + for_each = toset([var.regions.primary]) + role = "roles/storage.objectUser" + members = [ + "serviceAccount:service-${module.vdss-host-project.number}@compute-system.iam.gserviceaccount.com", + module.ngfw-service-account.service_account.member + ] +} + +resource "google_storage_bucket_object" "config_folders" { + for_each = toset([var.regions.primary]) + name = "config/" + bucket = module.ngfw-bootstrap-bucket[each.key].name + content = " " +} + +resource "google_storage_bucket_object" "content_folders" { + for_each = toset([var.regions.primary]) + name = "content/" + bucket = module.ngfw-bootstrap-bucket[each.key].name + content = " " +} + +resource "google_storage_bucket_object" "software_folders" { + for_each = toset([var.regions.primary]) + name = "software/" + bucket = module.ngfw-bootstrap-bucket[each.key].name + content = " " +} + +resource "google_storage_bucket_object" "authcodes" { + for_each = toset([var.regions.primary]) + name = "license/authcodes" + bucket = module.ngfw-bootstrap-bucket[each.key].name + source = "${path.module}/templates/authcodes" +} +resource "google_compute_address" "elb_dmz_ip" { + for_each = toset([var.regions.primary]) + name = "elb-dmz-ip-${each.key}" + project = module.vdss-host-project.project_id + region = each.value + address_type = "EXTERNAL" +} + +resource "google_compute_address" "ilb_vdss_ip" { + for_each = toset([var.regions.primary]) + name = "ilb-vdss-ip-${each.key}" + project = module.vdss-host-project.project_id + region = each.value + address_type = "INTERNAL" + subnetwork = try(module.vdss-vpc.subnet_self_links["${each.value}/landing-default"], null) +} + +resource "google_compute_address" "ilb_tt_ip" { + for_each = toset([var.regions.primary]) + name = "ilb-tt-ip-${each.key}" + project = module.vdss-host-project.project_id + region = each.value + address_type = "INTERNAL" + subnetwork = try(module.tenant-transit-vpc.subnet_self_links["${each.value}/tenant-transit"], null) +} + +resource "google_compute_address" "ilb_bcap_ip" { + for_each = toset([var.regions.primary]) + name = "ilb-bcap-ip-${each.key}" + project = module.vdss-host-project.project_id + region = each.value + address_type = "INTERNAL" + subnetwork = try(module.bcap-spoke-vpc.subnet_self_links["${each.value}/bcap-landing"], null) + + lifecycle { + create_before_destroy = false + } +} + +resource "google_compute_address" "ilb_interconnect_ip" { + for_each = toset([var.regions.primary]) + name = "ilb-interconnect-ip-${each.key}" + project = module.vdss-host-project.project_id + region = each.value + address_type = "INTERNAL" + subnetwork = try(module.interconnect-spoke-vpc.subnet_self_links["${each.value}/interconnect-landing"], null) + + lifecycle { + create_before_destroy = false + } +} + +resource "google_storage_bucket_object" "bootstrap-xml" { + name = "config/bootstrap.xml" + for_each = toset([var.regions.primary]) + content = local.bootstrap-xml-local[each.key] + bucket = module.ngfw-bootstrap-bucket[each.key].name +} + +resource "google_storage_bucket_object" "init-cfg" { + name = "config/init-cfg.txt" + for_each = toset([var.regions.primary]) + content = local.init-cfg-local[each.key] + bucket = module.ngfw-bootstrap-bucket[each.key].name +} + +resource "google_compute_region_instance_template" "ngfw-template" { + for_each = toset([var.regions.primary]) + project = module.vdss-host-project.project_id + + name_prefix = "ngfw-template-${each.key}-" + description = "This template is used to create and configure Palo Alto NGFW instances." + + tags = ["nva"] + region = each.value + machine_type = "n2d-standard-8" + can_ip_forward = true + + scheduling { + automatic_restart = true + on_host_maintenance = "MIGRATE" + } + + // Create a new boot disk from an image + disk { + source_image = data.google_compute_image.vmseries.id + disk_size_gb = 60 + type = "PERSISTENT" + disk_encryption_key { + kms_key_self_link = module.kms[each.value].keys.default.id + } + } + + network_interface { + network = module.dmz-vpc.self_link + subnetwork = try(module.dmz-vpc.subnet_self_links["${each.value}/dmz-default"], null) + } + + network_interface { + network = module.mgmt-vpc.self_link + subnetwork = try( + module.mgmt-vpc.subnet_self_links["${each.value}/mgmt-default"], null + ) + } + network_interface { + network = module.vdss-vpc.self_link + subnetwork = try(module.vdss-vpc.subnet_self_links["${each.value}/landing-default"], null) + } + + network_interface { + network = module.tenant-transit-vpc.self_link + subnetwork = try(module.tenant-transit-vpc.subnet_self_links["${each.value}/tenant-transit"], null) + } + + network_interface { + network = module.bcap-spoke-vpc.self_link + subnetwork = try(module.bcap-spoke-vpc.subnet_self_links["${each.value}/bcap-landing"], null) + } + + network_interface { + network = module.interconnect-spoke-vpc.self_link + subnetwork = try(module.interconnect-spoke-vpc.subnet_self_links["${each.value}/interconnect-landing"], null) + } + + metadata = { + mgmt-interface-swap = "enable" + type = "dhcp-client" + op-command-modes = "mgmt-interface-swap" + dhcp-accept-server-domain = "yes" + dhcp-accept-server-hostname = "yes" + ssh-keys = "admin:${tls_private_key.ngfw-ssh.public_key_openssh}" + serial-port-enable = true + serial-port-logging-enable = true + vmseries-bootstrap-gce-storagebucket = module.ngfw-bootstrap-bucket[each.key].name + bootstrap-xml-md5 = google_storage_bucket_object.bootstrap-xml[each.key].md5hash # Roll out a new template when our bootstrap.xml file changes + init-cfg-md5 = google_storage_bucket_object.init-cfg[each.key].md5hash + authcodes-md5 = google_storage_bucket_object.authcodes[each.key].md5hash + } + lifecycle { + create_before_destroy = false + } + service_account { + # Google recommends custom service accounts that have cloud-platform scope and permissions granted via IAM Roles. + email = module.ngfw-service-account.email + scopes = ["cloud-platform"] + } + # CIS Compliance Benchmark 4.11 + # Palo Alto VM images aren't UEFI and can't secureboot + # confidential_instance_config { + # enable_confidential_compute = true + # } + # shielded_instance_config { + # enable_secure_boot = true + # enable_vtpm = true + # enable_integrity_monitoring = true + # } +} + +resource "google_compute_region_health_check" "ngfw" { + for_each = toset([var.regions.primary]) + name = "ngfw-health-check-${each.key}" + project = module.vdss-host-project.project_id + region = each.value + + https_health_check { + port = 443 + request_path = "/unauth/php/health.php" + } + + log_config { + enable = true + } +} + +module "ngfw-mig" { + for_each = toset([var.regions.primary]) + source = "../../../modules/compute-mig" + project_id = module.vdss-host-project.project_id + location = each.key + name = "nva-ngfw-${each.key}" + update_policy = { + type = "PROACTIVE" + minimal_action = "REPLACE" + most_disruptive_allowed_action = "REPLACE" + max_surge = { + fixed = 3 + } + max_unavailable = { + fixed = 0 + } + } + distribution_policy = { + target_shape = "EVEN" + zones = local.nva_zones[each.key] + } + + instance_template = google_compute_region_instance_template.ngfw-template[each.key].self_link + target_size = 2 + auto_healing_policies = { + initial_delay_sec = 900 + health_check = google_compute_region_health_check.ngfw[each.key].id + } + + health_check_config = null +} + +module "ilb-nva-vdss" { + for_each = toset([var.regions.primary]) + source = "../../../modules/net-lb-int" + project_id = module.vdss-host-project.project_id + region = each.value + name = "nva-vdss-${each.key}" + service_label = var.prefix + forwarding_rules_config = { + "" = { + address = google_compute_address.ilb_vdss_ip[each.key].address + global_access = true + } + } + backend_service_config = { + connection_tracking = { + persist_conn_on_unhealthy = "NEVER_PERSIST" + } + } + vpc_config = { + network = module.vdss-vpc.self_link + subnetwork = try(module.vdss-vpc.subnet_self_links["${each.value}/landing-default"], null) + } + backends = [ + for k, v in module.ngfw-mig : + { group = v.group_manager.instance_group } + if startswith(k, each.key) + ] + health_check = google_compute_region_health_check.ngfw[each.key].id + health_check_config = null +} + +module "ilb-nva-tenant-transit" { + for_each = toset([var.regions.primary]) + source = "../../../modules/net-lb-int" + project_id = module.vdss-host-project.project_id + region = each.value + name = "nva-tenant-transit-${each.key}" + service_label = "${var.prefix}-tenant-transit" + forwarding_rules_config = { + "" = { + address = google_compute_address.ilb_tt_ip[each.key].address + global_access = true + } + } + backend_service_config = { + connection_tracking = { + persist_conn_on_unhealthy = "NEVER_PERSIST" + } + } + vpc_config = { + network = module.tenant-transit-vpc.self_link + subnetwork = try(module.tenant-transit-vpc.subnet_self_links["${each.value}/tenant-transit"], null) + } + backends = [ + for k, v in module.ngfw-mig : + { group = v.group_manager.instance_group } + if startswith(k, each.key) + ] + health_check = google_compute_region_health_check.ngfw[each.key].id + health_check_config = null +} + +module "ilb-nva-bcap" { + for_each = toset([var.regions.primary]) + source = "../../../modules/net-lb-int" + project_id = module.vdss-host-project.project_id + region = each.value + name = "nva-bcap-${each.key}" + service_label = "${var.prefix}-bcap" + forwarding_rules_config = { + "" = { + address = google_compute_address.ilb_bcap_ip[each.key].address + global_access = true + } + } + backend_service_config = { + connection_tracking = { + persist_conn_on_unhealthy = "NEVER_PERSIST" + } + } + vpc_config = { + network = module.bcap-spoke-vpc.self_link + subnetwork = try(module.bcap-spoke-vpc.subnet_self_links["${each.value}/bcap-landing"], null) + } + backends = [ + for k, v in module.ngfw-mig : + { group = v.group_manager.instance_group } + if startswith(k, each.key) + ] + health_check = google_compute_region_health_check.ngfw[each.key].id + health_check_config = null +} + +module "ilb-nva-interconnect" { + for_each = toset([var.regions.primary]) + source = "../../../modules/net-lb-int" + project_id = module.vdss-host-project.project_id + region = each.value + name = "nva-interconnect-${each.key}" + service_label = "${var.prefix}-interconnect" + forwarding_rules_config = { + "" = { + address = google_compute_address.ilb_interconnect_ip[each.key].address + global_access = true + } + } + backend_service_config = { + connection_tracking = { + persist_conn_on_unhealthy = "NEVER_PERSIST" + } + } + vpc_config = { + network = module.interconnect-spoke-vpc.self_link + subnetwork = try(module.interconnect-spoke-vpc.subnet_self_links["${each.value}/interconnect-landing"], null) + } + backends = [ + for k, v in module.ngfw-mig : + { group = v.group_manager.instance_group } + if startswith(k, each.key) + ] + health_check = google_compute_region_health_check.ngfw[each.key].id + health_check_config = null +} + +module "elb-nva-dmz" { + for_each = toset([var.regions.primary]) + source = "../../../modules/net-lb-ext" + project_id = module.vdss-host-project.project_id + region = each.value + name = "elb-dmz-${each.key}" + + forwarding_rules_config = { + "" = { + address = google_compute_address.elb_dmz_ip[each.key].address + ip_protocol = "L3_DEFAULT" + all_ports = true + } + } + + backends = [ + for k, v in module.ngfw-mig : + { group = v.group_manager.instance_group } + if startswith(k, each.key) + ] + health_check = google_compute_region_health_check.ngfw[each.key].id + health_check_config = null +} + +resource "google_compute_route" "default" { + name = "default-route-nva" + project = module.vdss-host-project.project_id + dest_range = "0.0.0.0/0" + network = module.vdss-vpc.name + next_hop_ilb = module.ilb-nva-vdss[var.regions.primary].forwarding_rules[""].id + priority = 100 +} + +# Google KMS Module +module "kms" { + source = "../../../modules/kms" + project_id = module.vdss-host-project.project_id + for_each = toset(local.all_regions) + keys = { + "default" = { + rotation_period = "7776000s" # CIS Compliance Benchmark 1.10 + purpose = "ENCRYPT_DECRYPT" + version_template = { + algorithm = "GOOGLE_SYMMETRIC_ENCRYPTION" + protection_level = "HSM" + } + } + "ntp" = { + rotation_period = "7776000s" + labels = { service = "ntp" } + purpose = "ENCRYPT_DECRYPT" + version_template = { + algorithm = "GOOGLE_SYMMETRIC_ENCRYPTION" + protection_level = "HSM" + } + } + "smtp" = { + rotation_period = "7776000s" + labels = { service = "smtp" } + purpose = "ENCRYPT_DECRYPT" + version_template = { + algorithm = "GOOGLE_SYMMETRIC_ENCRYPTION" + protection_level = "HSM" + } + } + } + + iam = { + "roles/cloudkms.cryptoKeyEncrypterDecrypter" = [ + module.vdss-host-project.service_agents.compute.iam_email, + "serviceAccount:${data.google_storage_project_service_account.gcs_account.email_address}", + # Fix make dynamic, number is {PREFIX}-{COMPLIANCE}-net-vdss-host project number + "serviceAccount:service-${module.vdss-host-project.number}@compute-system.iam.gserviceaccount.com", + "serviceAccount:service-${module.vdss-host-project.number}@gcp-sa-secretmanager.iam.gserviceaccount.com" + ] + } + keyring = { + location = each.value + name = "vdss-keyring-${each.value}" + } +} diff --git a/fast/stages-aw/2-networking-b-il5-ngfw/openssl-helper.sh b/fast/stages-aw/3-networking/openssl-helper.sh similarity index 90% rename from fast/stages-aw/2-networking-b-il5-ngfw/openssl-helper.sh rename to fast/stages-aw/3-networking/openssl-helper.sh index 516274f1c..cc9770270 100644 --- a/fast/stages-aw/2-networking-b-il5-ngfw/openssl-helper.sh +++ b/fast/stages-aw/3-networking/openssl-helper.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. - # Exit if any of the intermediate steps fail set -e @@ -24,7 +23,7 @@ set -e eval "$(jq -r '@sh "ALGO=\(.algo) PLAINTEXT=\(.plaintext) SALT=\(.salt)"')" # Placeholder for whatever data-fetching logic your script implements -hash=$(openssl passwd "-${ALGO}" -salt "${SALT}" "${PLAINTEXT}") +hash=$(printf "%s" "${PLAINTEXT}" | openssl passwd "-${ALGO}" -salt "${SALT}" -stdin) # Safely produce a JSON object containing the result value. # jq will ensure that the value is properly quoted diff --git a/fast/stages-aw/3-networking/outputs-gcs.tf b/fast/stages-aw/3-networking/outputs-gcs.tf new file mode 100644 index 000000000..6fbf4c2b0 --- /dev/null +++ b/fast/stages-aw/3-networking/outputs-gcs.tf @@ -0,0 +1,27 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +resource "google_storage_bucket_object" "tenant_outputs" { + bucket = var.automation.outputs_bucket + name = "stage_3_tenant_outputs.json" + content = jsonencode({ + edge_group_id = google_network_connectivity_group.groups["edge"].id + hub_id = google_network_connectivity_hub.main.id + ilb_ips = { + transit = module.ilb-nva-tenant-transit[var.regions.primary].forwarding_rule_addresses[""] + } + }) +} diff --git a/fast/stages-aw/3-networking/outputs.tf b/fast/stages-aw/3-networking/outputs.tf new file mode 100644 index 000000000..6a3a22b77 --- /dev/null +++ b/fast/stages-aw/3-networking/outputs.tf @@ -0,0 +1,134 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +locals { + # Map environments to their tenants and their respective networking details + envs = { for env_name, env_v in var.tenant_environments : env_name => { + folder = env_v + } } + + vdss = { + landing_host = module.vdss-host-project.project_id + dmz_vpc = module.dmz-vpc.id + landing_vpc = module.vdss-vpc.id + external_lb_ip = module.elb-nva-dmz[var.regions.primary].forwarding_rules[""].ip_address + self_link = module.vdss-vpc.self_link + } + + host_project_ids = {} + host_project_numbers = { + prod-landing = module.vdss-host-project.number + } + env_spoke = {} + tfvars = { + host_project_ids = local.host_project_ids + host_project_numbers = local.host_project_numbers + envs = local.envs + vdss = local.vdss + env_spoke = local.env_spoke + hub_id = google_network_connectivity_hub.main.id + edge_group_id = google_network_connectivity_group.groups["edge"].id + ilb_ips = { + transit = module.ilb-nva-tenant-transit[var.regions.primary].forwarding_rule_addresses[""] + } + kms_keys = { + for region, kms in module.kms : region => kms.key_ids + } + } + tfvars_shared_services = { + bcap = { + network_name = module.bcap-spoke-vpc.name + subnetwork_name = module.bcap-spoke-vpc.subnets["${var.regions.primary}/bcap-landing"].name + subnetwork_region = module.bcap-spoke-vpc.subnets["${var.regions.primary}/bcap-landing"].region + } + hub_project_id = module.vdss-host-project.name, + host_project_id = module.vdss-host-project.name, + network = module.shared-services-vpc.self_link, + subnetwork = module.shared-services-vpc.subnets["${var.regions.primary}/shared-services"].self_link, # TODO swap in actual subnet self_link + encryption_key = module.kms[var.regions.primary].keys["ntp"].id + smtp_encryption_key = module.kms[var.regions.primary].keys["smtp"].id + vpc_self_links = { + csp_landing = module.csp-landing-vpc.self_link + landing = module.vdss-vpc.self_link + shared_services = module.shared-services-vpc.self_link + tenant_transit = module.tenant-transit-vpc.self_link + } + } +} + +# generate tfvars file for subsequent stages + +resource "local_file" "tfvars" { + for_each = var.outputs_location == null ? {} : { 1 = 1 } + file_permission = "0644" + filename = "${try(pathexpand(var.outputs_location), "")}/tfvars/3-networking.auto.tfvars.json" + content = jsonencode(local.tfvars) +} + +resource "google_storage_bucket_object" "tfvars" { + bucket = var.automation.outputs_bucket + name = "tfvars/3-networking.auto.tfvars.json" + content = jsonencode(local.tfvars) +} + +resource "google_storage_bucket_object" "tfvars_shared_services" { + bucket = var.automation.outputs_bucket + name = "tfvars/3-networking-shared-services.auto.tfvars.json" + content = jsonencode(local.tfvars_shared_services) +} + +resource "local_file" "rsa-out" { + content = nonsensitive(tls_private_key.ngfw-ssh.private_key_openssh) + filename = "${path.module}/id_rsa" +} + +resource "local_file" "rsa-pub-out" { + content = nonsensitive(tls_private_key.ngfw-ssh.public_key_openssh) + filename = "${path.module}/id_rsa.pub" +} + +# outputs + +output "external_lb_ip" { + description = "The public IP of the external load balancer." + value = module.elb-nva-dmz[var.regions.primary].forwarding_rules[""].ip_address +} + +# output "host_project_ids" { +# description = "Network project ids." +# value = local.host_project_ids +# } + +output "host_project_numbers" { + description = "Network project numbers." + value = local.host_project_numbers +} + +output "ngfw_password" { + description = "Password for authenticating to the NGFW." + sensitive = true + value = random_password.password +} + +# output "test_vm_ips" { +# description = "Internal IP addresses of the test web servers." +# value = { for k, v in module.test-vms : k => v.internal_ip } +# } + +output "tfvars" { + description = "Terraform variables file for the following stages." + sensitive = true + value = local.tfvars +} \ No newline at end of file diff --git a/fast/stages-aw/3-networking/projects.tf b/fast/stages-aw/3-networking/projects.tf new file mode 100644 index 000000000..f25fca1ef --- /dev/null +++ b/fast/stages-aw/3-networking/projects.tf @@ -0,0 +1,132 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# tfdoc:file:description Host projects. + +# VDSS Host Project +module "vdss-host-project" { + source = "../../../modules/project" + billing_account = var.billing_account.id + name = local.project_map["vdss-host-project"] + parent = var.folder_ids.networking + services = [ + "compute.googleapis.com", + "certificatemanager.googleapis.com", + "dns.googleapis.com", + "iap.googleapis.com", + "networkmanagement.googleapis.com", + "stackdriver.googleapis.com", + "networkservices.googleapis.com", + "cloudkms.googleapis.com", + "storage.googleapis.com", + "redis.googleapis.com", + "servicenetworking.googleapis.com", + "networkconnectivity.googleapis.com", + "secretmanager.googleapis.com", + "servicedirectory.googleapis.com" + ] + shared_vpc_host_config = { + enabled = true + } + iam = { + "roles/dns.admin" = compact([ + try(local.service_accounts.project-factory-prod, null), + try(local.service_accounts.shared-services, null), + ]) + "roles/networkconnectivity.serviceAgent" = [ + "serviceAccount:service-${module.vdss-host-project.number}@gcp-sa-networkconnectivity.iam.gserviceaccount.com" + ] + } + iam_bindings_additive = try(local.service_accounts.shared-services, null) == null ? {} : { + shared-services-compute-network = { + role = "roles/compute.networkAdmin" + member = local.service_accounts.shared-services + } + shared-services-compute-security = { + role = "roles/compute.securityAdmin" + member = local.service_accounts.shared-services + } + shared-services-compute-instance = { + role = "roles/compute.instanceAdmin.v1" + member = local.service_accounts.shared-services + } + shared-services-sa-admin = { + role = "roles/iam.serviceAccountAdmin" + member = local.service_accounts.shared-services + } + shared-services-sa-user = { + role = "roles/iam.serviceAccountUser" + member = local.service_accounts.shared-services + } + } +} + +resource "google_compute_project_metadata" "metadata-vdss-host-project" { + project = module.vdss-host-project.project_id + metadata = { + block-project-ssh-keys = true # CIS Compliance Benchmark 4.3 + enable-oslogin = true # CIS Compliance Benchmark 4.4 + } +} + +# resource "google_cloud_quotas_quota_preference" "network_quota" { +# parent = "projects/${module.vdss-host-project.number}" +# name = "networks-increase-v2" +# service = "compute.googleapis.com" +# quota_id = "NETWORKS-per-project" +# quota_config { +# preferred_value = var.network_quota_preferred_value +# } +# justification = "Required for multiple VPC networks in VDSS project." +# contact_email = var.alert_email +# } + +# Environment-level host projects (Shared VPC Hosts) +module "env-spoke-projects" { + source = "../../../modules/project" + billing_account = var.billing_account.id + for_each = var.tenant_environments + name = local.project_map["${each.key}-net-host"] + parent = var.folder_ids.networking + services = concat([ + "container.googleapis.com", + "compute.googleapis.com", + "dns.googleapis.com", + "iap.googleapis.com", + "networkmanagement.googleapis.com", + "servicenetworking.googleapis.com", + "stackdriver.googleapis.com", + "vpcaccess.googleapis.com", + "networkconnectivity.googleapis.com" + ] + ) + shared_vpc_host_config = { + enabled = true + } + metric_scopes = [module.vdss-host-project.project_id] + iam = { + "roles/dns.admin" = compact([ + try(local.service_accounts.gke-dev, null), + try(local.service_accounts.project-factory-dev, null), + try(local.service_accounts.project-factory-prod, null), + ]) + } + iam_bindings_additive = { + vdss_ncc_sa = { + role = "roles/networkconnectivity.serviceAgent" + member = "serviceAccount:service-${module.vdss-host-project.number}@gcp-sa-networkconnectivity.iam.gserviceaccount.com" + } + } +} diff --git a/fast/stages-aw/3-networking/redis.tf b/fast/stages-aw/3-networking/redis.tf new file mode 100644 index 000000000..49c118c88 --- /dev/null +++ b/fast/stages-aw/3-networking/redis.tf @@ -0,0 +1,55 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# tfdoc:file:description Redis and encryption. + +resource "random_password" "redis_auth" { + length = 32 + special = false +} + +resource "google_kms_crypto_key_iam_member" "redis_kms" { + crypto_key_id = module.kms[var.regions.primary].keys.default.id + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + member = "serviceAccount:service-${module.vdss-host-project.number}@cloud-redis.iam.gserviceaccount.com" +} + +resource "google_redis_instance" "session_resiliency" { + name = "${var.prefix}-sess-res" + tier = "STANDARD_HA" + memory_size_gb = 1 + region = var.regions.primary + location_id = "${var.regions.primary}-a" + alternative_location_id = "${var.regions.primary}-b" + + authorized_network = module.mgmt-vpc.id + connect_mode = "PRIVATE_SERVICE_ACCESS" + + redis_version = "REDIS_7_0" + display_name = "Session Resiliency for NGFW" + + auth_enabled = true + transit_encryption_mode = "SERVER_AUTHENTICATION" + + customer_managed_key = module.kms[var.regions.primary].keys.default.id + + project = module.vdss-host-project.project_id + + depends_on = [ + module.mgmt-vpc, + google_kms_crypto_key_iam_member.redis_kms + ] +} + diff --git a/fast/stages-aw/3-networking/templates/authcodes b/fast/stages-aw/3-networking/templates/authcodes new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/fast/stages-aw/3-networking/templates/authcodes @@ -0,0 +1 @@ + diff --git a/fast/stages-aw/3-networking/templates/bootstrap.xml.tpl b/fast/stages-aw/3-networking/templates/bootstrap.xml.tpl new file mode 100644 index 000000000..068e36045 --- /dev/null +++ b/fast/stages-aw/3-networking/templates/bootstrap.xml.tpl @@ -0,0 +1,1168 @@ + + + + + + ${ password_hash } + + + yes + + + ${ ssh_pubkey } + + + * + + + + localhost.localdomain + + + + + + + yes + 16 + + + + + + + + + + + + yes + 5 + + + yes + 5 + + + yes + 5 + + + yes + 10 + + + yes + 5 + + + + yes + + + + 10 + 10 + + 100 + 50 + + + + 10 + 10 + + 100 + 50 + + + + + + 100 + yes + + + + + + + + + + + + no + + + + no + + + no + no + + + no + + + allow-ping + + + + + + no + + + + no + + + no + no + + + no + + + no + + allow-ping + + + + + + no + + + + no + + + no + no + + + no + + + no + + allow-ping + + + + + + no + + + + no + + + no + no + + + no + + + no + + allow-ping + + + + + + no + + + + no + + + no + no + + + no + + + no + + allow-ping + + + + + + no + + + + no + + + no + no + + + no + + + no + + allow-ping + + + + + + no + + + + no + + + no + no + + + no + + + no + + allow-ping + + + + + + + + no + + + + + allow-health-check + + + + no + + + + + allow-health-check + + + + + + + + 3 + 5 + wait-recover + + + + + no + no + no + yes + + + + + + + + + + yes + no + yes + + + + + + + + + aes-256-cbc + aes-128-cbc + + + sha256 + + + group14 + + + 8 + + + + + aes-128-cbc + + + sha256 + + + group19 + + + 8 + + + + + aes-256-cbc + + + sha384 + + + group20 + + + 8 + + + + + + + + aes-256-cbc + aes-128-cbc + + + sha256 + + + group14 + + 1 + + + + + + aes-128-gcm + + + none + + + group19 + + 1 + + + + + + aes-256-gcm + + + none + + + group20 + + 1 + + + + + + + + + + + + + + real-time + + + high + + + high + + + medium + + + medium + + + low + + + low + + + low + + + + + + + + + + + + no + + + 1.25 + 0.5 + 900 + 300 + 900 + yes + + + + + yes + + + + + no + + + no + + + no + + + + + + + yes + yes + 4 + yes + + + ethernet1/1 + ethernet1/2 + ethernet1/6 + ethernet1/7 + loopback.1 + + + + + + + ${dmz_gateway_ip} + + + None + + ethernet1/1 + 100 + 0.0.0.0/0 + + + + + + + ${lz_gateway_ip} + + + None + + ethernet1/2 + 10 + 10.84.0.0/16 + + + + + + + ${dmz_gateway_ip} + + + None + + ethernet1/1 + 10 + 35.191.0.0/16 + + + + ${dmz_gateway_ip} + + + None + + ethernet1/1 + 10 + 130.211.0.0/22 + + + + ${lz_gateway_ip} + + + None + + ethernet1/2 + 10 + 35.191.0.0/16 + + + + + + + env-router + + + None + + 10 + 10.88.0.0/13 + + + + + + + env-router + + + None + + 10 + 10.96.0.0/16 + + + + + + + + + + + + + + yes + yes + 4 + + + + + + yes + + + no + + + no + + + no + + + no + + + + ethernet1/3 + ethernet1/4 + ethernet1/5 + loopback.2 + + + + + + + ${tenant_gateway_ip} + + + None + + ethernet1/3 + 10 + 35.191.0.0/16 + + + + + + + ${tenant_gateway_ip} + + + None + + ethernet1/3 + 10 + 130.211.0.0/22 + + + + + + + ${bcap_gateway_ip} + + + None + + ethernet1/4 + 10 + 35.191.0.0/16 + + + + + + + ${bcap_gateway_ip} + + + None + + ethernet1/4 + 10 + 130.211.0.0/22 + + + + + + + ${interconnect_gateway_ip} + + + None + + ethernet1/5 + 10 + 35.191.0.0/16 + + + + + + + ${interconnect_gateway_ip} + + + None + + ethernet1/5 + 10 + 130.211.0.0/22 + + + + + + + default + + + None + + 100 + 0.0.0.0/0 + + + + + + + ${tenant_gateway_ip} + + + None + + ethernet1/3 + 10 + 10.88.0.0/13 + + + + + + + ${tenant_gateway_ip} + + + None + + ethernet1/3 + 10 + 10.96.0.0/16 + + + + + + + + + + + + + + + yes + yes + yes + yes + + + updates.paloaltonetworks.com + + + + + wednesday + 01:02 + download-only + + + + + US/Pacific + + yes + yes + + PA-VM + + no + no + no + + + + + yes + + + FQDN + + mgmt-interface-swap + + + yes + yes + yes + yes + + + ${ ssh_pubkey } + + + + + + + yes + + + + + + + + + + + + + ethernet1/2 + + + + + + + ethernet1/1 + + + + + + + ethernet1/3 + + + + + + + ethernet1/4 + + + + + + + ethernet1/5 + + + + + + + loopback.1 + loopback.2 + + + + + + + + + + + + + lb-checks + + + any + + + lb-checks + + + any + + + any + + + any + + + any + + + any + + + ssl + web-browsing + + + application-default + + + any + + + any + + allow + no + yes + + + + any + + + any + + + any + + + any + + + any + + + any + + + ssl + web-browsing + ssh + ping + dns + ntp + + + application-default + + + any + + + any + + allow + + any + + + any + + no + yes + + + + + + + + + + ethernet1/1 + + + + + Untrust + + + VDSS + + + any + + + any + + any + no + + + + loopback + + + Untrust + + + Untrust + + + lb-checks + + + any + + any + ethernet1/1 + + + + loopback + + + VDSS + + + VDSS + + + lb-checks + + + any + + any + ethernet1/2 + + + + loopback2 + + + Tenant + + + Tenant + + + lb-checks + + + any + + any + ethernet1/3 + + + + loopback2 + + + BCAP + + + BCAP + + + lb-checks + + + any + + any + ethernet1/4 + + + + loopback2 + + + Interconnect + + + Interconnect + + + lb-checks + + + any + + any + ethernet1/5 + + + + + + + + + + allow + no + yes + + + deny + no + yes + + + + + + + + ethernet1/1 + ethernet1/2 + ethernet1/3 + ethernet1/4 + ethernet1/5 + ethernet1/6 + ethernet1/7 + loopback.1 + loopback.2 + + + +
+ + 169.254.169.254 + + google-ip + + + + 35.191.0.0/16 + + google-ip + + + + 130.211.0.0/22 + + google-ip + + + + 209.85.152.0/22 + + google-ip + + + + 209.85.204.0/22 + + google-ip + + + + 100.64.0.1 + + internal-ip + + + + 100.64.0.2 + + internal-ip + + +
+ + + + google-ip + + + google-metadata-server + lb-check-1 + lb-check-2 + lb-check-3 + lb-check-4 + + + + + + + +
+
+
+
+
\ No newline at end of file diff --git a/fast/stages-aw/3-networking/templates/init-cfg.txt.tpl b/fast/stages-aw/3-networking/templates/init-cfg.txt.tpl new file mode 100644 index 000000000..2f23b69be --- /dev/null +++ b/fast/stages-aw/3-networking/templates/init-cfg.txt.tpl @@ -0,0 +1,14 @@ +type=dhcp-client +panorama-server=140.20.252.10 +vm-auth-key=2:vHlDEPkyRvqgUJ4td20I5Qam_2h6NEvdkUWwdFrafrSzm9eOXV2n3NM3RPbEtLYFNgb8XkqQ16s8D7W93sKLcQ +op-command-modes=${op-command-modes} +dhcp-send-hostname=yes +dhcp-send-client-id=yes +dhcp-accept-server-hostname=yes +dhcp-accept-server-domain=yes +fips-cc-mode=yes +plugin-op-commands=set-sess-res:True +auth-code=${auth_code} +redis-endpoint=${redis_endpoint} +redis-auth=${redis_auth} +redis-certificate= \ No newline at end of file diff --git a/fast/stages-aw/3-networking/terraform.tfvars.sample b/fast/stages-aw/3-networking/terraform.tfvars.sample new file mode 100644 index 000000000..c51896c63 --- /dev/null +++ b/fast/stages-aw/3-networking/terraform.tfvars.sample @@ -0,0 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +active_tenants = [ + "tenant_name" +] \ No newline at end of file diff --git a/fast/stages-aw/2-networking-b-il5-ngfw/variables.tf b/fast/stages-aw/3-networking/variables.tf similarity index 53% rename from fast/stages-aw/2-networking-b-il5-ngfw/variables.tf rename to fast/stages-aw/3-networking/variables.tf index 1b6c21114..1f39888a9 100644 --- a/fast/stages-aw/2-networking-b-il5-ngfw/variables.tf +++ b/fast/stages-aw/3-networking/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,27 +18,77 @@ variable "alert_email" { type = string } +variable "assured_workloads" { + description = "Configuration for Assured Workloads." + type = object({ + regime = optional(string) + location = optional(string) + folder = optional(string) + }) + nullable = false + default = {} +} + +variable "auth_code" { + description = "Optional Palo Alto auth-code for BYOL license activation." + type = string + default = "" +} + variable "automation" { - # tfdoc:variable:source 0-bootstrap + # tfdoc:variable:source 1-assured-workload description = "Automation resources created by the bootstrap stage." type = object({ - outputs_bucket = string + config_bucket = optional(string) + inputs_bucket = optional(string) + outputs_bucket = string + tenant_bucket = optional(string) + project_id = string + project_number = string + federated_identity_pool = optional(string) + federated_identity_providers = map(object({ + audiences = list(string) + issuer = string + issuer_uri = string + name = string + principal_branch = string + principal_repo = string + })) + service_accounts = object({ + bootstrap = string + bootstrap-r = string + resman = string + resman-r = string + }) }) } variable "billing_account" { - # tfdoc:variable:source 0-bootstrap + # tfdoc:variable:source 1-assured-workload description = "Billing account id. If billing account is not part of the same org set `is_org_level` to false." type = object({ id = string is_org_level = optional(bool, true) + no_iam = optional(bool, false) }) validation { condition = var.billing_account.is_org_level != null error_message = "Invalid `null` value for `billing_account.is_org_level`." } } +/* +variable "common_services_folder" { + description = "Folder ID for common services." + type = string + default = null +} +variable "custom_roles" { + description = "Custom roles for the organization." + type = map(string) + default = {} +} +*/ variable "dns" { description = "DNS configuration." type = object({ @@ -49,13 +99,6 @@ variable "dns" { nullable = false } -variable "envs_folders" { - description = "List of environments to be created for projects to go into." - type = map(object({ - admin = string - })) -} - variable "essential_contacts" { description = "Email used for essential contacts, unset if null." type = string @@ -82,18 +125,60 @@ variable "factories_config" { error_message = "Firewall policy name needs to be non-null." } } - +/* +variable "fast_features" { + description = "Enable/disable FAST features." + type = map(bool) + default = {} +} +*/ variable "folder_ids" { - # tfdoc:variable:source 1-resman + # tfdoc:variable:source 2-resman description = "Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created." type = object({ networking = string envs = optional(map(string)) + security = optional(string) }) } + +/* +variable "groups" { + description = "GCP groups for the organization." + type = map(string) + default = {} +} + +variable "locations" { + description = "Locations for different GCP services." + type = object({ + bq = optional(string, "US") + gcs = optional(list(string), ["US"]) + logging = optional(list(string), ["global"]) + pubsub = optional(list(string), []) + kms = optional(list(string), ["US"]) + }) +} + +variable "logging" { + description = "Logging configuration." + type = object({ + project_id = string + project_number = string + writer_identities = map(string) + }) +} + + +variable "network_quota_preferred_value" { + description = "The preferred target value for the Google Cloud network quota preference." + type = number + default = 50 +} +*/ variable "organization" { - # tfdoc:variable:source 0-bootstrap + # tfdoc:variable:source 1-assured-workload description = "Organization details." type = object({ domain = string @@ -109,16 +194,16 @@ variable "outputs_location" { } variable "prefix" { - # tfdoc:variable:source 0-bootstrap + # tfdoc:variable:source 1-assured-workload description = "Prefix used for resources that need unique names. Use 9 characters or less." type = string validation { - condition = try(length(var.prefix), 0) < 10 + condition = try(length(var.prefix), 0) <= 10 error_message = "Use a maximum of 9 characters for prefix." } } - +/* variable "psa_ranges" { description = "IP ranges used for Private Service Access (e.g. CloudSQL). Ranges is in name => range format." type = object({ @@ -128,6 +213,12 @@ variable "psa_ranges" { import_routes = optional(bool, false) peered_domains = optional(list(string), []) })), []) + test = optional(list(object({ + ranges = map(string) + export_routes = optional(bool, false) + import_routes = optional(bool, false) + peered_domains = optional(list(string), []) + })), []) prod = optional(list(object({ ranges = map(string) export_routes = optional(bool, false) @@ -138,17 +229,26 @@ variable "psa_ranges" { nullable = false default = {} } +*/ +variable "regime_mapping" { + description = "Mapping of compliance regime names to short codes." + type = map(string) +} variable "regions" { - description = "Region definitions. Inherited from 0-bootstrap outputs. Must be specified in bootstrap terraform.tfvars." + description = "Region definitions." type = object({ - primary = string + primary = string + secondary = list(string) }) - nullable = false + default = { + primary = "us-east4" + secondary = [""] + } } variable "service_accounts" { - # tfdoc:variable:source 1-resman + # tfdoc:variable:source 2-resman description = "Automation service accounts in name => email format." type = object({ data-platform-dev = string @@ -157,155 +257,29 @@ variable "service_accounts" { gke-prod = string project-factory-dev = string project-factory-prod = string + shared-services = optional(string) }) default = null } -variable "tenant_accounts" { - # tfdoc:variable:soruce 1-resman - description = "Base Tenant accounts that are created for each folder, provided as a combination of environment and tenant." - type = map(object({ - tenant = string - env = string - main_project = string - admin_principal = string - })) +variable "shared_services_project_id" { + description = "The project ID for shared services inherited from Stage 1." + type = string } # To get a list of available official images, please run the following command: # `gcloud compute images list --filter="family ~ vmseries" --project paloaltonetworksgcp-public --no-standard-images` - -variable "vmseries_image" { - description = "The image name from which to boot an instance, including a license type (bundle/flex) and version." - default = "vmseries-112" - type = string -} - -variable "billing_override" { - description = "Optional billing override configuration. If set, disables service account impersonation for project billing linkage and runs under the user account using the specified quota projects." - type = object({ - project = string - billing_project = string - }) - default = null -} - -variable "assured_workloads" { - description = "Assured Workloads configuration." - type = any - default = null -} - -variable "common_services_folder" { - description = "Common services folder ID." - type = string - default = null -} - -variable "logging" { - description = "Logging configuration." - type = any - default = null -} - -variable "fast_features" { - description = "FAST features enabled." - type = any - default = null -} - -variable "groups" { - description = "IAM groups mapping." - type = any - default = null -} - -variable "regime_mapping" { - description = "Compliance regime shorthand mapping." +/* +variable "tenant_accounts" { + description = "Tenant accounts configuration." type = any - default = null -} - -variable "subnets" { - description = "VPC subnet configurations keyed by network name." - type = map(list(object({ - name = string - ip_cidr_range = string - region = string - description = optional(string) - enable_private_access = optional(bool, true) - allow_subnet_cidr_routes_overlap = optional(bool) - flow_logs_config = optional(object({ - aggregation_interval = optional(string) - filter_expression = optional(string) - flow_sampling = optional(number) - metadata = optional(string) - metadata_fields = optional(list(string)) - })) - secondary_ip_ranges = optional(map(string)) - iam = optional(map(list(string)), {}) - tenant = optional(string) - }))) - default = {} - nullable = false -} - -variable "proxy_subnets" { - description = "VPC proxy-only subnet CIDRs keyed by environment." - type = map(string) default = {} - nullable = false -} - -variable "dns_policy_rules" { - description = "DNS response policy rules in name => rule format." - type = map(object({ - dns_name = string - behavior = optional(string, "bypassResponsePolicy") - local_data = optional(map(object({ - ttl = optional(number) - rrdatas = optional(list(string), []) - })), {}) - })) - default = {} - nullable = false } - -variable "cidrs" { - description = "Named CIDR ranges to use in firewall rules." - type = map(list(string)) - default = {} - nullable = false -} - -variable "firewall_rules" { - description = "Firewall rules for each VPC / environment spoke." +*/ +variable "tenant_environments" { + description = "List of environments to be created for projects to go into." type = map(object({ - ingress = optional(map(object({ - description = optional(string) - deny = optional(bool, false) - source_ranges = optional(list(string)) - sources = optional(list(string)) - targets = optional(list(string)) - use_service_accounts = optional(bool, false) - rules = optional(list(object({ - protocol = string - ports = optional(list(string)) - }))) - })), {}) - egress = optional(map(object({ - description = optional(string) - deny = optional(bool, true) - destination_ranges = optional(list(string)) - targets = optional(list(string)) - use_service_accounts = optional(bool, false) - rules = optional(list(object({ - protocol = string - ports = optional(list(string)) - }))) - })), {}) + admin = string })) - default = {} - nullable = false } diff --git a/fast/stages-aw/3-networking/vpc.tf b/fast/stages-aw/3-networking/vpc.tf new file mode 100644 index 000000000..019fac810 --- /dev/null +++ b/fast/stages-aw/3-networking/vpc.tf @@ -0,0 +1,357 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# tfdoc:file:description VPCs, Firewalls, NATs, and Routes. + +# DMZ (untrusted) VPC +module "dmz-vpc" { + source = "../../../modules/net-vpc" + project_id = module.vdss-host-project.project_id + name = "vdss-dmz-0" + mtu = 1500 + dns_policy = { + inbound = true + logging = var.dns.enable_logging + } + create_googleapis_routes = null + factories_config = { + context = { regions = var.regions } + subnets_folder = "${var.factories_config.data_dir}/subnets/dmz" + } +} + +module "dmz-firewall" { + source = "../../../modules/net-vpc-firewall" + project_id = module.vdss-host-project.project_id + network = module.dmz-vpc.name + default_rules_config = { + disabled = true + } + factories_config = { + cidr_tpl_file = "${var.factories_config.data_dir}/cidrs.yaml" + rules_folder = "${var.factories_config.data_dir}/firewall-rules/dmz" + } +} + +# Landing (trusted) VPC +module "vdss-vpc" { + source = "../../../modules/net-vpc" + project_id = module.vdss-host-project.project_id + name = "vdss-landing-0" + delete_default_routes_on_create = true + mtu = 1500 + factories_config = { + context = { regions = var.regions } + subnets_folder = "${var.factories_config.data_dir}/subnets/landing" + } + dns_policy = { + inbound = true + logging = var.dns.enable_logging + } + create_googleapis_routes = null +} + +module "vdss-firewall" { + source = "../../../modules/net-vpc-firewall" + project_id = module.vdss-host-project.project_id + network = module.vdss-vpc.name + default_rules_config = { + disabled = true + } + factories_config = { + cidr_tpl_file = "${var.factories_config.data_dir}/cidrs.yaml" + rules_folder = "${var.factories_config.data_dir}/firewall-rules/vdss" + } +} + +# Mgmt (trusted) VPC +module "mgmt-vpc" { + source = "../../../modules/net-vpc" + project_id = module.vdss-host-project.project_id + name = "vdss-mgmt-0" + delete_default_routes_on_create = true + mtu = 1500 + factories_config = { + context = { regions = var.regions } + subnets_folder = "${var.factories_config.data_dir}/subnets/mgmt" + } + dns_policy = { + inbound = true + logging = var.dns.enable_logging + } + psa_configs = [{ + ranges = { + redis = "10.84.130.0/24" + } + }] + create_googleapis_routes = null +} + +module "mgmt-firewall" { + source = "../../../modules/net-vpc-firewall" + project_id = module.vdss-host-project.project_id + network = module.mgmt-vpc.name + default_rules_config = { + disabled = true + } + factories_config = { + cidr_tpl_file = "${var.factories_config.data_dir}/cidrs.yaml" + rules_folder = "${var.factories_config.data_dir}/firewall-rules/mgmt" + } +} + +# CSP Landing VPC +module "csp-landing-vpc" { + source = "../../../modules/net-vpc" + project_id = module.vdss-host-project.project_id + name = "csp-landing" + delete_default_routes_on_create = true + mtu = 1500 + factories_config = { + context = { regions = var.regions } + subnets_folder = "${var.factories_config.data_dir}/subnets/csp" + } +} + +module "csp-spoke-firewall" { + source = "../../../modules/net-vpc-firewall" + project_id = module.vdss-host-project.project_id + network = module.csp-landing-vpc.name + default_rules_config = { + disabled = true + } + factories_config = { + cidr_tpl_file = "${var.factories_config.data_dir}/cidrs.yaml" + rules_folder = "${var.factories_config.data_dir}/firewall-rules/csp" + } +} + +# BCAP Spoke VPC +module "bcap-spoke-vpc" { + source = "../../../modules/net-vpc" + project_id = module.vdss-host-project.project_id + name = "bcap-landing" + delete_default_routes_on_create = true + mtu = 1500 + factories_config = { + context = { regions = var.regions } + subnets_folder = "${var.factories_config.data_dir}/subnets/bcap" + } +} + +module "bcap-spoke-firewall" { + source = "../../../modules/net-vpc-firewall" + project_id = module.vdss-host-project.project_id + network = module.bcap-spoke-vpc.name + default_rules_config = { + disabled = true + } + factories_config = { + cidr_tpl_file = "${var.factories_config.data_dir}/cidrs.yaml" + rules_folder = "${var.factories_config.data_dir}/firewall-rules/bcap" + } +} + +# Interconnect Spoke VPC +module "interconnect-spoke-vpc" { + source = "../../../modules/net-vpc" + project_id = module.vdss-host-project.project_id + name = "interconnect-landing" + delete_default_routes_on_create = true + mtu = 1500 + factories_config = { + context = { regions = var.regions } + subnets_folder = "${var.factories_config.data_dir}/subnets/interconnect" + } +} + +module "interconnect-spoke-firewall" { + source = "../../../modules/net-vpc-firewall" + project_id = module.vdss-host-project.project_id + network = module.interconnect-spoke-vpc.name + default_rules_config = { + disabled = true + } + factories_config = { + cidr_tpl_file = "${var.factories_config.data_dir}/cidrs.yaml" + rules_folder = "${var.factories_config.data_dir}/firewall-rules/interconnect" + } +} + +# --- Hub VPCs (Internal Environment Hubs) --- + +# Dev Hub VPC +module "tenant-transit-vpc" { + source = "../../../modules/net-vpc" + project_id = module.vdss-host-project.project_id + name = "tenant-transit" + delete_default_routes_on_create = true + mtu = 1500 + factories_config = { + context = { regions = var.regions } + subnets_folder = "${var.factories_config.data_dir}/subnets/transit" + } +} + +module "tenant-transit-firewall" { + source = "../../../modules/net-vpc-firewall" + project_id = module.vdss-host-project.project_id + network = module.tenant-transit-vpc.name + default_rules_config = { + disabled = true + } + factories_config = { + cidr_tpl_file = "${var.factories_config.data_dir}/cidrs.yaml" + rules_folder = "${var.factories_config.data_dir}/firewall-rules/transit" + } +} + +# Shared Services VPC +module "shared-services-vpc" { + source = "../../../modules/net-vpc" + project_id = module.vdss-host-project.project_id + name = "shared-services" + delete_default_routes_on_create = true + mtu = 1500 + factories_config = { + context = { regions = var.regions } + subnets_folder = "${var.factories_config.data_dir}/subnets/sharedsvcs" + } + subnets_proxy_only = [{ + region = var.regions.primary + active = true + name = lower("sharedsvcs-${var.regions.primary}-proxy-0") + ip_cidr_range = local.proxy_subnets["sharedsvcs"] + }] +} + +module "shared-services-firewall" { + source = "../../../modules/net-vpc-firewall" + project_id = module.vdss-host-project.project_id + network = module.shared-services-vpc.name + default_rules_config = { + disabled = true + } + factories_config = { + cidr_tpl_file = "${var.factories_config.data_dir}/cidrs.yaml" + rules_folder = "${var.factories_config.data_dir}/firewall-rules/sharedsvcs" + } +} + +resource "google_compute_route" "shared_svcs_default_route_nva" { + name = "shared-svcs-default-route-nva" + project = module.vdss-host-project.project_id + dest_range = "0.0.0.0/0" + network = module.shared-services-vpc.self_link + + next_hop_ilb = module.ilb-nva-vdss[var.regions.primary].forwarding_rules[""].ip_address + priority = 100 + + depends_on = [ + google_network_connectivity_spoke.landing, + google_network_connectivity_spoke.sharedsvcs + ] +} + +# --- Routes --- + +resource "google_compute_route" "mgmt-default" { + name = "default-route-mgmt" + project = module.vdss-host-project.project_id + dest_range = "0.0.0.0/0" + network = module.mgmt-vpc.name + next_hop_gateway = "default-internet-gateway" + priority = 100 +} + +resource "google_compute_route" "csp_spoke_default" { + name = "csp-spoke-default-route-nva" + project = module.vdss-host-project.project_id + dest_range = "0.0.0.0/0" + network = module.csp-landing-vpc.self_link + next_hop_ilb = module.ilb-nva-vdss[var.regions.primary].forwarding_rules[""].ip_address + priority = 10 + depends_on = [ + google_network_connectivity_spoke.landing, + google_network_connectivity_spoke.csp_spoke + ] +} + +resource "google_compute_route" "bcap_spoke_default" { + name = "bcap-spoke-default-route-nva" + project = module.vdss-host-project.project_id + dest_range = "0.0.0.0/0" + network = module.bcap-spoke-vpc.self_link + next_hop_ilb = module.ilb-nva-bcap[var.regions.primary].forwarding_rules[""].id + priority = 10 + depends_on = [ + google_network_connectivity_spoke.landing, + google_network_connectivity_spoke.bcap_spoke + ] +} + +resource "google_compute_route" "interconnect_spoke_default" { + name = "interconnect-spoke-default-route-nva" + project = module.vdss-host-project.project_id + dest_range = "0.0.0.0/0" + network = module.interconnect-spoke-vpc.self_link + next_hop_ilb = module.ilb-nva-interconnect[var.regions.primary].forwarding_rules[""].id + priority = 10 + depends_on = [ + google_network_connectivity_spoke.landing, + google_network_connectivity_spoke.interconnect_spoke + ] +} + +# --- NAT --- + +module "dmz-nat-primary" { + source = "../../../modules/net-cloudnat" + project_id = module.vdss-host-project.project_id + region = var.regions.primary + name = "nat-${var.regions.primary}" + router_create = true + router_name = "prod-nat-${var.regions.primary}" + router_network = module.dmz-vpc.name +} + +module "dmz-nat-mgmt" { + source = "../../../modules/net-cloudnat" + project_id = module.vdss-host-project.project_id + region = var.regions.primary + name = "nat-mgmt-${var.regions.primary}" + router_create = true + router_name = "prod-nat-mgmt-${var.regions.primary}" + router_network = module.mgmt-vpc.name +} + +# --- PSC & Service Networking --- +resource "google_compute_global_address" "psc_googleapis" { + name = "psc-googleapis" + project = module.vdss-host-project.project_id + address_type = "INTERNAL" + purpose = "PRIVATE_SERVICE_CONNECT" + network = module.vdss-vpc.self_link + address = "10.84.255.255" +} + +resource "google_compute_global_forwarding_rule" "psc_googleapis" { + name = "pscapis" + project = module.vdss-host-project.project_id + target = "vpc-sc" + network = module.vdss-vpc.self_link + ip_address = google_compute_global_address.psc_googleapis.id + load_balancing_scheme = "" +} diff --git a/fast/stages-aw/3-security/validation.sh b/fast/stages-aw/3-security/validation.sh deleted file mode 100755 index 587a37f26..000000000 --- a/fast/stages-aw/3-security/validation.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -echo "--- Verifying Deployment Service Account Status ---" -echo "" - -# Discover the Infrastructure-as-Code (IaC) core project -IAC_PROJECT=$(gcloud projects list --filter="projectId~'-prod-iac-core-0$'" --format="value(projectId)") - -# Check if a unique project was found -if [ -z "$IAC_PROJECT" ]; then - echo "⚠️ WARNING: No IaC core project found ending in '-prod-iac-core-0'." - exit 1 -elif [ $(echo "$IAC_PROJECT" | wc -l) -ne 1 ]; then - echo "⚠️ WARNING: Multiple possible IaC core projects found. Please verify manually:" - echo "$IAC_PROJECT" - exit 1 -fi - -echo "✅ Found IaC Core Project: $IAC_PROJECT" - -# Find and check the status of each key service account -SA_LIST=$(gcloud iam service-accounts list --project="$IAC_PROJECT" \ - --filter="email ~ '(bootstrap-0|resman-0|prod-resman-net-0|security-0)@'" \ - --format="value(email)") - -if [ -z "$SA_LIST" ]; then - echo "⚠️ WARNING: No standard deployment service accounts found in $IAC_PROJECT." -else - for sa in $SA_LIST; do - STATUS=$(gcloud iam service-accounts describe "$sa" --project="$IAC_PROJECT" --format="value(disabled)") - if [ "$STATUS" == "True" ]; then - echo "✅ SUCCESS: $sa is disabled." - else - echo "❌ FAILED: $sa is still enabled." - fi - done -fi - -echo "" -echo "--- Verification Complete ---" diff --git a/fast/stages-aw/3-vpn/README.md b/fast/stages-aw/3-vpn/README.md new file mode 100644 index 000000000..94878afd9 --- /dev/null +++ b/fast/stages-aw/3-vpn/README.md @@ -0,0 +1,139 @@ + + +# VPN Connectivity + +This stage provisions hybrid cloud connectivity between Google Cloud, AWS, Azure, and on-premises environments via Panorama. It establishes HA VPN Gateways, External VPN Gateways, and BGP peering to ensure resilient, encrypted communication across the multi-cloud footprint. + +# Table of Contents + + +- [Table of Contents](#table-of-contents) +- [Design Overview and choices](#design-overview-and-choices) + - [HA VPN Architecture](#ha-vpn-architecture) + - [CNSA-Compliant Security](#cnsa-compliant-security) + - [Multi-Cloud Connectivity](#multi-cloud-connectivity) + - [Dynamic Routing and BGP](#dynamic-routing-and-bgp) +- [How to Run This Stage](#how-to-run-this-stage) + - [Running the stage](#running-the-stage) +- [Variables](#variables) +- [Outputs](#outputs) + + +## Design Overview and choices + +### HA VPN Architecture +The team has chosen to implement Google Cloud HA VPN to provide a 99.99% service availability SLA. This architecture requires two interfaces on the GCP side, each with a distinct public IP address, connecting to a redundant peer gateway. This setup ensures that connectivity remains active even during maintenance or single-zone failures. + +### CNSA-Compliant Security +In order to support high-security requirements, the default configuration utilizes CNSA-compliant cipher suites. By default, tunnels use AES-GCM-256 for encryption and Group 20 Diffie-Hellman for key exchange. These settings ensure that data in transit meets federal and enterprise security standards. + +### Multi-Cloud Connectivity +The stage is designed to bridge disparate cloud ecosystems: + +AWS: Implements a four-tunnel design to support maximum throughput and AWS's requirement for redundant tunnels across multiple peer IPs. + +Azure: Utilizes a two-tunnel design matching Azure's standard VPN Gateway redundancy model. + +Panorama: Specifically designed for security management and logging traffic, allowing administrative tools to reach the cloud environment securely. + +### Dynamic Routing and BGP +Minimizing manual route management is critical for operational stability. This stage leverages Cloud Routers to establish BGP sessions with all peers. + +BGP Masking: Uses a dynamic mask length variable (defaulting to /30) for transit subnets. + +Custom Advertisements: Cloud Routers are configured to advertise specific IP ranges while excluding the default advertisement of all VPC ranges to stay within route quotas. + +## How to Run This Stage + +### Running the stage + +Once provider and variable values are in place and the correct user is configured, the stage can be run: + +```bash +terraform init +terraform plan +terraform apply +``` + +--- + +## Variables + +| name | description | type | required | default | +|---|---|:---:|:---:|:---:| +| [gcp_bgp_asn](variables.tf#L123) | BGP Autonomous System Number for the GCP Cloud Router. | number | ✓ | | +| [gcp_network_name](variables.tf#L138) | The name of your existing GCP VPC network. | string | ✓ | | +| [project_id](variables.tf#L233) | The GCP Project ID where the resources will be created. | string | ✓ | | +| [region](variables.tf#L238) | The GCP region where the resources will be created. | string | ✓ | | +| [aws_bgp_asn](variables.tf#L1) | BGP Autonomous System Number for AWS side. | number | | 64512 | +| [aws_redundancy_type](variables.tf#L7) | Redundancy type for the AWS external VPN gateway. | string | | "FOUR_IPS_REDUNDANCY" | +| [aws_secret_version](variables.tf#L13) | The version of the secret to pull from Secret Manager for AWS VPN PSKs. | string | | "latest" | +| [aws_tunnel_cipher_suite](variables.tf#L19) | The CNSA-compliant cipher suite for the AWS VPN tunnels. If null, the global tunnel_cipher_suite is used. | object({…}) | | null | +| [aws_tunnel_details](variables.tf#L37) | Explicit configuration for the AWS tunnel peers. | map(object({…})) | | null | +| [azure_bgp_asn](variables.tf#L47) | BGP Autonomous System Number for Azure side. | number | | 65515 | +| [azure_gateway_ip_0](variables.tf#L53) | The first public IP address of the Azure VPN gateway. | string | | null | +| [azure_gateway_ip_1](variables.tf#L59) | The second public IP address of the Azure VPN gateway. | string | | null | +| [azure_gcp_bgp_apipa_ip_0](variables.tf#L65) | GCP-side internal BGP IP for the first Azure tunnel. | string | | "169.254.21.1" | +| [azure_gcp_bgp_apipa_ip_1](variables.tf#L71) | GCP-side internal BGP IP for the second Azure tunnel. | string | | "169.254.21.5" | +| [azure_peer_bgp_apipa_ip_0](variables.tf#L77) | Azure-side internal BGP IP for the first Azure tunnel. | string | | "169.254.21.2" | +| [azure_peer_bgp_apipa_ip_1](variables.tf#L83) | Azure-side internal BGP IP for the second Azure tunnel. | string | | "169.254.21.6" | +| [azure_redundancy_type](variables.tf#L89) | Redundancy type for the Azure external VPN gateway. | string | | "TWO_IPS_REDUNDANCY" | +| [create_gcp_vpn_tunnels_aws](variables.tf#L95) | Determines if the GCP VPN tunnels and BGP peering sessions for AWS should be created (gateways remain active). | bool | | true | +| [enable_azure_vpn](variables.tf#L101) | Set to false to destroy the Azure-related VPN tunnels and BGP peering sessions (leaving the gateways intact). | bool | | true | +| [enable_panorama_vpn](variables.tf#L107) | Set to false to destroy the Panorama-related VPN tunnels and BGP peering sessions (leaving the gateways and router intact). | bool | | true | +| [gateway_ip_version](variables.tf#L113) | The IP family of the gateway IPs for the HA-VPN gateway interfaces. Possible values: IPV4, IPV6. | string | | "IPV4" | +| [gcp_bgp_identifier_range](variables.tf#L132) | Explicitly specifies a range of valid BGP Identifiers for this Router. It is provided as a link-local IPv4 range (from 169.254.0.0/16), of size at least /30. If null, GCP will auto-assign. | string | | null | +| [gcp_router_name](variables.tf#L143) | The name of the GCP Cloud Router. | string | | null | +| [ike_version](variables.tf#L149) | The IKE protocol version used for the VPN tunnels. | number | | 2 | +| [mgmt_bgp_asn](variables.tf#L155) | MGMT router ASN. | number | | 65200 | +| [name_prefix](variables.tf#L161) | A prefix to use for resource names. | string | | "ha-vpn" | +| [panorama_bgp_asn](variables.tf#L167) | BGP Autonomous System Number for Panorama side. | number | | 65516 | +| [panorama_gateway_ip_0](variables.tf#L173) | The first public IP address of the Panorama VPN gateway. | string | | null | +| [panorama_gateway_ip_1](variables.tf#L179) | The second public IP address of the Panorama VPN gateway. | string | | null | +| [panorama_gcp_bgp_apipa_ip_0](variables.tf#L185) | GCP-side internal BGP IP for the first Panorama tunnel. | string | | "169.254.22.1" | +| [panorama_gcp_bgp_apipa_ip_1](variables.tf#L191) | GCP-side internal BGP IP for the second Panorama tunnel. | string | | "169.254.22.5" | +| [panorama_peer_bgp_apipa_ip_0](variables.tf#L197) | Panorama-side internal BGP IP for the first Panorama tunnel. | string | | "169.254.22.2" | +| [panorama_peer_bgp_apipa_ip_1](variables.tf#L203) | Panorama-side internal BGP IP for the second Panorama tunnel. | string | | "169.254.22.6" | +| [panorama_project_id](variables.tf#L209) | The GCP Project ID where Panorama resources will be created (if different from global project_id). | string | | null | +| [panorama_redundancy_type](variables.tf#L215) | Redundancy type for the Panorama external VPN gateway. | string | | "TWO_IPS_REDUNDANCY" | +| [panorama_router_name](variables.tf#L221) | The name of the Cloud Router for Panorama (if different from global gcp_router_name). | string | | null | +| [panorama_vpc_name](variables.tf#L227) | The name of the VPC network for Panorama (if different from global gcp_network_name). | string | | null | +| [secret_name_aws_conn1_tun1](variables.tf#L243) | Secret Manager secret name for AWS Connection 1 Tunnel 1 PSK. | string | | null | +| [secret_name_aws_conn1_tun2](variables.tf#L249) | Secret Manager secret name for AWS Connection 1 Tunnel 2 PSK. | string | | null | +| [secret_name_aws_conn2_tun1](variables.tf#L255) | Secret Manager secret name for AWS Connection 2 Tunnel 1 PSK. | string | | null | +| [secret_name_aws_conn2_tun2](variables.tf#L261) | Secret Manager secret name for AWS Connection 2 Tunnel 2 PSK. | string | | null | +| [secret_name_azure_tunnel0](variables.tf#L267) | Secret Manager secret name for Azure Tunnel 0 PSK. | string | | null | +| [secret_name_azure_tunnel1](variables.tf#L273) | Secret Manager secret name for Azure Tunnel 1 PSK. | string | | null | +| [secret_name_panorama_tunnel0](variables.tf#L279) | Secret Manager secret name for Panorama Tunnel 0 PSK. | string | | null | +| [secret_name_panorama_tunnel1](variables.tf#L285) | Secret Manager secret name for Panorama Tunnel 1 PSK. | string | | null | +| [stack_type](variables.tf#L291) | The stack type for this VPN gateway. Possible values: IPV4_ONLY, IPV4_IPV6, IPV6_ONLY. | string | | "IPV4_ONLY" | +| [tunnel_cipher_suite](variables.tf#L301) | The CNSA-compliant cipher suite for the VPN tunnels. Phase 1 and Phase 2 configurations. | object({…}) | | {…} | +| [vpn_bgp_mask](variables.tf#L331) | The subnet mask length for the BGP APIPA IP ranges. | number | | 30 | + +## Outputs + +| name | description | sensitive | +|---|---|:---:| +| [aws_gcp_ha_gateway_name](outputs.tf#L3) | The name of the GCP HA VPN Gateway for AWS. | | +| [aws_tunnel_details](outputs.tf#L8) | Detailed mapping for AWS VPN tunnels. | | +| [azure_gcp_ha_gateway_name](outputs.tf#L30) | The name of the GCP HA VPN Gateway for Azure. | | +| [azure_tunnel_details](outputs.tf#L35) | Detailed mapping for Azure VPN tunnels. | | +| [panorama_gcp_ha_gateway_name](outputs.tf#L71) | The name of the GCP HA VPN Gateway for Panorama. | | +| [panorama_tunnel_details](outputs.tf#L76) | Detailed mapping for Panorama VPN tunnels. | | +| [vpn_network_config](outputs.tf#L112) | Network-wide BGP and redundancy parameters. | | +| [vpn_security_config](outputs.tf#L122) | Security parameters used for all VPN tunnels. | | + diff --git a/fast/stages-aw/3-vpn/aws.tf b/fast/stages-aw/3-vpn/aws.tf new file mode 100644 index 000000000..10d671f38 --- /dev/null +++ b/fast/stages-aw/3-vpn/aws.tf @@ -0,0 +1,175 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +# GCP-side Resources for AWS VPN connectivity + +# PSK Data Sources from GCP Secret Manager +data "google_secret_manager_regional_secret_version" "aws_psk_c1t1" { + count = (var.create_gcp_vpn_tunnels_aws && var.secret_name_aws_conn1_tun1 != null) ? 1 : 0 + secret = var.secret_name_aws_conn1_tun1 + version = var.aws_secret_version + project = var.project_id + location = var.region +} + +data "google_secret_manager_regional_secret_version" "aws_psk_c1t2" { + count = (var.create_gcp_vpn_tunnels_aws && var.secret_name_aws_conn1_tun2 != null) ? 1 : 0 + secret = var.secret_name_aws_conn1_tun2 + version = var.aws_secret_version + project = var.project_id + location = var.region +} + +data "google_secret_manager_regional_secret_version" "aws_psk_tenant1" { + count = (var.create_gcp_vpn_tunnels_aws && var.secret_name_aws_conn2_tun1 != null) ? 1 : 0 + secret = var.secret_name_aws_conn2_tun1 + version = var.aws_secret_version + project = var.project_id + location = var.region +} + +data "google_secret_manager_regional_secret_version" "aws_psk_tenant2" { + count = (var.create_gcp_vpn_tunnels_aws && var.secret_name_aws_conn2_tun2 != null) ? 1 : 0 + secret = var.secret_name_aws_conn2_tun2 + version = var.aws_secret_version + project = var.project_id + location = var.region +} + +locals { + aws_tunnels = { + "tun1" = { + gcp_iface_index = 0 + aws_peer_iface_index = 0 + aws_psk = length(data.google_secret_manager_regional_secret_version.aws_psk_c1t1) > 0 ? data.google_secret_manager_regional_secret_version.aws_psk_c1t1[0].secret_data : try(var.secret_name_aws_conn1_tun1, null) + external_ip = try(var.aws_tunnel_details["tun1"].external_ip, null) + gcp_bgp_ip = try(var.aws_tunnel_details["tun1"].gcp_bgp_ip, null) + aws_bgp_ip = try(var.aws_tunnel_details["tun1"].aws_bgp_ip, null) + }, + "tun2" = { + gcp_iface_index = 0 + aws_peer_iface_index = 1 + aws_psk = length(data.google_secret_manager_regional_secret_version.aws_psk_c1t2) > 0 ? data.google_secret_manager_regional_secret_version.aws_psk_c1t2[0].secret_data : try(var.secret_name_aws_conn1_tun2, null) + external_ip = try(var.aws_tunnel_details["tun2"].external_ip, null) + gcp_bgp_ip = try(var.aws_tunnel_details["tun2"].gcp_bgp_ip, null) + aws_bgp_ip = try(var.aws_tunnel_details["tun2"].aws_bgp_ip, null) + }, + "tun3" = { + gcp_iface_index = 1 + aws_peer_iface_index = 2 + aws_psk = length(data.google_secret_manager_regional_secret_version.aws_psk_tenant1) > 0 ? data.google_secret_manager_regional_secret_version.aws_psk_tenant1[0].secret_data : try(var.secret_name_aws_conn2_tun1, null) + external_ip = try(var.aws_tunnel_details["tun3"].external_ip, null) + gcp_bgp_ip = try(var.aws_tunnel_details["tun3"].gcp_bgp_ip, null) + aws_bgp_ip = try(var.aws_tunnel_details["tun3"].aws_bgp_ip, null) + }, + "tun4" = { + gcp_iface_index = 1 + aws_peer_iface_index = 3 + aws_psk = length(data.google_secret_manager_regional_secret_version.aws_psk_tenant2) > 0 ? data.google_secret_manager_regional_secret_version.aws_psk_tenant2[0].secret_data : try(var.secret_name_aws_conn2_tun2, null) + external_ip = try(var.aws_tunnel_details["tun4"].external_ip, null) + gcp_bgp_ip = try(var.aws_tunnel_details["tun4"].gcp_bgp_ip, null) + aws_bgp_ip = try(var.aws_tunnel_details["tun4"].aws_bgp_ip, null) + } + } +} + +resource "google_compute_ha_vpn_gateway" "aws_ha_gw" { + count = 1 + project = var.project_id + region = var.region + name = "${var.name_prefix}-aws-ha-gw" + network = data.google_compute_network.existing.self_link + stack_type = var.stack_type + gateway_ip_version = var.gateway_ip_version +} + +resource "google_compute_external_vpn_gateway" "aws_peer_gw" { + count = 1 + + project = var.project_id + name = "${var.name_prefix}-aws-peer-gw" + redundancy_type = var.aws_redundancy_type + + dynamic "interface" { + for_each = local.aws_tunnels + content { + id = interface.value.aws_peer_iface_index + ip_address = interface.value.external_ip + } + } +} + +resource "google_compute_vpn_tunnel" "aws_tunnel" { + for_each = var.create_gcp_vpn_tunnels_aws ? local.aws_tunnels : {} + + project = var.project_id + region = var.region + name = "${var.name_prefix}-aws-tun-${each.key}" + vpn_gateway = google_compute_ha_vpn_gateway.aws_ha_gw[0].self_link + vpn_gateway_interface = each.value.gcp_iface_index + peer_external_gateway = google_compute_external_vpn_gateway.aws_peer_gw[0].self_link + peer_external_gateway_interface = each.value.aws_peer_iface_index + + shared_secret = each.value.aws_psk + router = google_compute_router.gcp_router.self_link + ike_version = var.ike_version + + dynamic "cipher_suite" { + for_each = (var.aws_tunnel_cipher_suite != null ? var.aws_tunnel_cipher_suite : var.tunnel_cipher_suite) != null ? [var.aws_tunnel_cipher_suite != null ? var.aws_tunnel_cipher_suite : var.tunnel_cipher_suite] : [] + content { + dynamic "phase1" { + for_each = cipher_suite.value.phase1 != null ? [cipher_suite.value.phase1] : [] + content { + encryption = length(phase1.value.encryption) > 0 ? phase1.value.encryption : null + integrity = length(phase1.value.integrity) > 0 ? phase1.value.integrity : null + prf = length(phase1.value.prf) > 0 ? phase1.value.prf : null + dh = length(phase1.value.dh) > 0 ? phase1.value.dh : null + } + } + dynamic "phase2" { + for_each = cipher_suite.value.phase2 != null ? [cipher_suite.value.phase2] : [] + content { + encryption = length(phase2.value.encryption) > 0 ? phase2.value.encryption : null + integrity = length(phase2.value.integrity) > 0 ? phase2.value.integrity : null + pfs = length(phase2.value.pfs) > 0 ? phase2.value.pfs : null + } + } + } + } +} + +resource "google_compute_router_interface" "aws_if" { + for_each = var.create_gcp_vpn_tunnels_aws ? local.aws_tunnels : {} + + project = var.project_id + region = var.region + name = "${var.name_prefix}-aws-if-${each.key}" + router = google_compute_router.gcp_router.name + ip_range = each.value.gcp_bgp_ip + vpn_tunnel = google_compute_vpn_tunnel.aws_tunnel[each.key].name +} + +resource "google_compute_router_peer" "aws_peer" { + for_each = var.create_gcp_vpn_tunnels_aws ? local.aws_tunnels : {} + + project = var.project_id + region = var.region + name = "${var.name_prefix}-aws-peer-${each.key}" + router = google_compute_router.gcp_router.name + interface = google_compute_router_interface.aws_if[each.key].name + peer_ip_address = each.value.aws_bgp_ip + peer_asn = var.aws_bgp_asn +} diff --git a/fast/stages-aw/3-vpn/azure.tf b/fast/stages-aw/3-vpn/azure.tf new file mode 100644 index 000000000..7f2f92e0d --- /dev/null +++ b/fast/stages-aw/3-vpn/azure.tf @@ -0,0 +1,150 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +# PSK Data Sources from GCP Secret Manager +data "google_secret_manager_regional_secret_version" "azure_psk_tun0" { + count = (var.enable_azure_vpn && var.secret_name_azure_tunnel0 != null) ? 1 : 0 + secret = var.secret_name_azure_tunnel0 + project = var.project_id + location = var.region +} + +data "google_secret_manager_regional_secret_version" "azure_psk_tun1" { + count = (var.enable_azure_vpn && var.secret_name_azure_tunnel1 != null) ? 1 : 0 + secret = var.secret_name_azure_tunnel1 + project = var.project_id + location = var.region +} + +locals { + azure_ip_0 = var.azure_gateway_ip_0 != null ? var.azure_gateway_ip_0 : null + azure_ip_1 = var.azure_gateway_ip_1 != null ? var.azure_gateway_ip_1 : null + + azure_tunnels = { + "tun0" = { + gcp_iface_index = 0 + peer_iface_index = 0 + psk = length(data.google_secret_manager_regional_secret_version.azure_psk_tun0) > 0 ? data.google_secret_manager_regional_secret_version.azure_psk_tun0[0].secret_data : try(var.secret_name_azure_tunnel0, null) + external_ip = local.azure_ip_0 + gcp_bgp_ip = "${var.azure_gcp_bgp_apipa_ip_0}/${var.vpn_bgp_mask}" + peer_bgp_ip = var.azure_peer_bgp_apipa_ip_0 + }, + "tun1" = { + gcp_iface_index = 1 + peer_iface_index = 1 + psk = length(data.google_secret_manager_regional_secret_version.azure_psk_tun1) > 0 ? data.google_secret_manager_regional_secret_version.azure_psk_tun1[0].secret_data : try(var.secret_name_azure_tunnel1, null) + external_ip = local.azure_ip_1 + gcp_bgp_ip = "${var.azure_gcp_bgp_apipa_ip_1}/${var.vpn_bgp_mask}" + peer_bgp_ip = var.azure_peer_bgp_apipa_ip_1 + } + } +} + +# GCP Resources for Azure VPN + +resource "google_compute_ha_vpn_gateway" "azure_ha_gw" { + count = 1 + project = var.project_id + region = var.region + name = "${var.name_prefix}-azure-ha-gw" + network = var.gcp_network_name + stack_type = var.stack_type + gateway_ip_version = var.gateway_ip_version +} + +resource "google_compute_external_vpn_gateway" "azure_peer_gw" { + count = 1 + project = var.project_id + name = "${var.name_prefix}-azure-vpn-gw" + redundancy_type = var.azure_redundancy_type + + dynamic "interface" { + for_each = local.azure_tunnels + content { + id = interface.value.peer_iface_index + ip_address = interface.value.external_ip + } + } + + lifecycle { + precondition { + condition = local.azure_ip_0 != null && local.azure_ip_1 != null + error_message = "Both var.azure_gateway_ip_0 and var.azure_gateway_ip_1 must be explicitly provided." + } + } +} + +resource "google_compute_vpn_tunnel" "azure_tunnel" { + for_each = var.enable_azure_vpn ? local.azure_tunnels : {} + + project = var.project_id + region = var.region + name = "${var.name_prefix}-azure-${each.key}" + vpn_gateway = google_compute_ha_vpn_gateway.azure_ha_gw[0].self_link + vpn_gateway_interface = each.value.gcp_iface_index + peer_external_gateway = google_compute_external_vpn_gateway.azure_peer_gw[0].self_link + peer_external_gateway_interface = each.value.peer_iface_index + + shared_secret = each.value.psk + router = google_compute_router.gcp_router.self_link + ike_version = var.ike_version + + dynamic "cipher_suite" { + for_each = var.tunnel_cipher_suite != null ? [var.tunnel_cipher_suite] : [] + content { + dynamic "phase1" { + for_each = cipher_suite.value.phase1 != null ? [cipher_suite.value.phase1] : [] + content { + encryption = length(phase1.value.encryption) > 0 ? phase1.value.encryption : null + integrity = length(phase1.value.integrity) > 0 ? phase1.value.integrity : null + prf = length(phase1.value.prf) > 0 ? phase1.value.prf : null + dh = length(phase1.value.dh) > 0 ? phase1.value.dh : null + } + } + dynamic "phase2" { + for_each = cipher_suite.value.phase2 != null ? [cipher_suite.value.phase2] : [] + content { + encryption = length(phase2.value.encryption) > 0 ? phase2.value.encryption : null + integrity = length(phase2.value.integrity) > 0 ? phase2.value.integrity : null + pfs = length(phase2.value.pfs) > 0 ? phase2.value.pfs : null + } + } + } + } +} + +resource "google_compute_router_interface" "azure_if" { + for_each = var.enable_azure_vpn ? local.azure_tunnels : {} + + project = var.project_id + region = var.region + name = "${var.name_prefix}-azure-if-${each.key}" + router = google_compute_router.gcp_router.name + ip_range = each.value.gcp_bgp_ip + vpn_tunnel = google_compute_vpn_tunnel.azure_tunnel[each.key].name +} + +resource "google_compute_router_peer" "azure_peer" { + for_each = var.enable_azure_vpn ? local.azure_tunnels : {} + + project = var.project_id + region = var.region + name = "${var.name_prefix}-azure-peer-${each.key}" + router = google_compute_router.gcp_router.name + interface = google_compute_router_interface.azure_if[each.key].name + peer_ip_address = each.value.peer_bgp_ip + peer_asn = var.azure_bgp_asn +} diff --git a/fast/stages-aw/3-vpn/changelog b/fast/stages-aw/3-vpn/changelog new file mode 100644 index 000000000..483fb78bc --- /dev/null +++ b/fast/stages-aw/3-vpn/changelog @@ -0,0 +1,6 @@ +2606091411 +2606091512 +2606101328 +2606171321 +2606261323 +2606261551 \ No newline at end of file diff --git a/fast/stages-aw/3-vpn/gcp_common.tf b/fast/stages-aw/3-vpn/gcp_common.tf new file mode 100644 index 000000000..aab399acc --- /dev/null +++ b/fast/stages-aw/3-vpn/gcp_common.tf @@ -0,0 +1,41 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +data "google_compute_network" "existing" { + name = var.gcp_network_name + project = var.project_id +} + +resource "google_compute_router" "gcp_router" { + project = var.project_id + region = var.region + name = coalesce(var.gcp_router_name, "${var.name_prefix}-router") + network = data.google_compute_network.existing.self_link + bgp { + asn = var.gcp_bgp_asn + identifier_range = var.gcp_bgp_identifier_range + advertise_mode = "CUSTOM" + advertised_groups = ["ALL_SUBNETS"] + # 35.199.192.0/19 is the source IP range Cloud DNS uses for forwarding + # queries. Without this advertisement, DNS responses from Azure cannot + # route back through the VPN tunnel, causing silent SERVFAIL. + # https://cloud.google.com/dns/docs/zones/forwarding-zones + advertised_ip_ranges { + range = "35.199.192.0/19" + description = "Cloud DNS forwarding range" + } + } +} diff --git a/fast/stages-aw/3-vpn/outputs.tf b/fast/stages-aw/3-vpn/outputs.tf new file mode 100644 index 000000000..ee1f9f020 --- /dev/null +++ b/fast/stages-aw/3-vpn/outputs.tf @@ -0,0 +1,146 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +# AWS Outputs + +output "aws_gcp_ha_gateway_name" { + description = "The name of the GCP HA VPN Gateway for AWS." + value = try(google_compute_ha_vpn_gateway.aws_ha_gw[0].name, null) +} + +output "aws_tunnel_details" { + description = "Detailed mapping for AWS VPN tunnels." + value = var.create_gcp_vpn_tunnels_aws ? { + for k, t in local.aws_tunnels : k => { + gcp = { + interface_id = t.gcp_iface_index + public_ip = try(google_compute_ha_vpn_gateway.aws_ha_gw[0].vpn_interfaces[t.gcp_iface_index].ip_address, null) + bgp_ip = t.gcp_bgp_ip + asn = var.gcp_bgp_asn + } + aws = { + interface_id = t.aws_peer_iface_index + public_ip = t.external_ip + bgp_ip = t.aws_bgp_ip + asn = var.aws_bgp_asn + } + } + } : null +} + +# Azure Outputs + +output "azure_gcp_ha_gateway_name" { + description = "The name of the GCP HA VPN Gateway for Azure." + value = try(google_compute_ha_vpn_gateway.azure_ha_gw[0].name, null) +} + +output "azure_tunnel_details" { + description = "Detailed mapping for Azure VPN tunnels." + value = var.enable_azure_vpn ? { + tunnel0 = { + gcp = { + interface_id = 0 + public_ip = try(google_compute_ha_vpn_gateway.azure_ha_gw[0].vpn_interfaces[0].ip_address, null) + bgp_ip = var.azure_gcp_bgp_apipa_ip_0 + asn = var.gcp_bgp_asn + } + azure = { + interface_id = 0 + public_ip = var.azure_gateway_ip_0 + bgp_ip = var.azure_peer_bgp_apipa_ip_0 + asn = var.azure_bgp_asn + } + } + tunnel1 = { + gcp = { + interface_id = 1 + public_ip = try(google_compute_ha_vpn_gateway.azure_ha_gw[0].vpn_interfaces[1].ip_address, null) + bgp_ip = var.azure_gcp_bgp_apipa_ip_1 + asn = var.gcp_bgp_asn + } + azure = { + interface_id = 1 + public_ip = var.azure_gateway_ip_1 + bgp_ip = var.azure_peer_bgp_apipa_ip_1 + asn = var.azure_bgp_asn + } + } + } : null +} + +# Panorama Outputs + +output "panorama_gcp_ha_gateway_name" { + description = "The name of the GCP HA VPN Gateway for Panorama." + value = try(google_compute_ha_vpn_gateway.panorama_ha_gw[0].name, null) +} + +output "panorama_tunnel_details" { + description = "Detailed mapping for Panorama VPN tunnels." + value = var.enable_panorama_vpn ? { + tunnel0 = { + gcp = { + interface_id = 0 + public_ip = try(google_compute_ha_vpn_gateway.panorama_ha_gw[0].vpn_interfaces[0].ip_address, null) + bgp_ip = var.panorama_gcp_bgp_apipa_ip_0 + asn = var.gcp_bgp_asn + } + panorama = { + interface_id = 0 + public_ip = var.panorama_gateway_ip_0 + bgp_ip = var.panorama_peer_bgp_apipa_ip_0 + asn = var.panorama_bgp_asn + } + } + tunnel1 = { + gcp = { + interface_id = 1 + public_ip = try(google_compute_ha_vpn_gateway.panorama_ha_gw[0].vpn_interfaces[1].ip_address, null) + bgp_ip = var.panorama_gcp_bgp_apipa_ip_1 + asn = var.gcp_bgp_asn + } + panorama = { + interface_id = 1 + public_ip = var.panorama_gateway_ip_1 + bgp_ip = var.panorama_peer_bgp_apipa_ip_1 + asn = var.panorama_bgp_asn + } + } + } : null +} + +# Variabllized Configurations + +output "vpn_network_config" { + description = "Network-wide BGP and redundancy parameters." + value = { + bgp_mask_length = var.vpn_bgp_mask + aws_redundancy_type = var.aws_redundancy_type + azure_redundancy_type = var.azure_redundancy_type + panorama_redundancy_type = var.panorama_redundancy_type + } +} + +output "vpn_security_config" { + description = "Security parameters used for all VPN tunnels." + value = { + ike_version = var.ike_version + aws_secret_version = var.aws_secret_version + global_cipher_suite = var.tunnel_cipher_suite + aws_cipher_override = var.aws_tunnel_cipher_suite + } +} diff --git a/fast/stages-aw/3-vpn/panorama.tf b/fast/stages-aw/3-vpn/panorama.tf new file mode 100644 index 000000000..3728d4243 --- /dev/null +++ b/fast/stages-aw/3-vpn/panorama.tf @@ -0,0 +1,210 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +# Panorama VPN Resources +data "google_secret_manager_regional_secret_version" "pano_psk_tun0" { + secret = var.secret_name_panorama_tunnel0 + project = local.panorama_project + location = var.region +} + +data "google_secret_manager_regional_secret_version" "pano_psk_tun1" { + secret = var.secret_name_panorama_tunnel1 + project = local.panorama_project + location = var.region +} + +locals { + panorama_ip_0 = var.panorama_gateway_ip_0 != null ? var.panorama_gateway_ip_0 : null + panorama_ip_1 = var.panorama_gateway_ip_1 != null ? var.panorama_gateway_ip_1 : null + panorama_project = coalesce(var.panorama_project_id, var.project_id) + panorama_vpc = coalesce(var.panorama_vpc_name, var.gcp_network_name) +} + +data "google_compute_network" "panorama_vpc" { + count = 1 + name = local.panorama_vpc + project = local.panorama_project +} + +resource "google_compute_router" "panorama_router" { + count = 1 + project = local.panorama_project + region = var.region + name = coalesce(var.panorama_router_name, "${var.name_prefix}-mgmt-router") + network = data.google_compute_network.panorama_vpc[0].self_link + bgp { + asn = var.mgmt_bgp_asn + identifier_range = var.gcp_bgp_identifier_range + } +} + +# GCP Resources for Panorama VPN + +resource "google_compute_ha_vpn_gateway" "panorama_ha_gw" { + count = 1 + project = local.panorama_project + region = var.region + name = "${var.name_prefix}-panorama-ha-gw" + network = data.google_compute_network.panorama_vpc[0].self_link + stack_type = var.stack_type + gateway_ip_version = var.gateway_ip_version +} + +resource "google_compute_external_vpn_gateway" "panorama_peer_gw" { + count = 1 + project = local.panorama_project + name = "${var.name_prefix}-panorama-peer-gw" + redundancy_type = var.panorama_redundancy_type + + interface { + id = 0 + ip_address = local.panorama_ip_0 + } + interface { + id = 1 + ip_address = local.panorama_ip_1 + } + + lifecycle { + precondition { + condition = local.panorama_ip_0 != null && local.panorama_ip_1 != null + error_message = "Both var.panorama_gateway_ip_0 and var.panorama_gateway_ip_1 must be provided." + } + } +} + +# Tunnels +resource "google_compute_vpn_tunnel" "panorama_tunnel0" { + count = var.enable_panorama_vpn ? 1 : 0 + project = local.panorama_project + region = var.region + name = "${var.name_prefix}-panorama-tun0" + vpn_gateway = google_compute_ha_vpn_gateway.panorama_ha_gw[0].self_link + vpn_gateway_interface = 0 + peer_external_gateway = google_compute_external_vpn_gateway.panorama_peer_gw[0].self_link + peer_external_gateway_interface = 0 + + shared_secret = data.google_secret_manager_regional_secret_version.pano_psk_tun0.secret_data + router = google_compute_router.panorama_router[0].self_link + ike_version = var.ike_version + + dynamic "cipher_suite" { + for_each = var.tunnel_cipher_suite != null ? [var.tunnel_cipher_suite] : [] + content { + dynamic "phase1" { + for_each = cipher_suite.value.phase1 != null ? [cipher_suite.value.phase1] : [] + content { + encryption = length(phase1.value.encryption) > 0 ? phase1.value.encryption : null + integrity = length(phase1.value.integrity) > 0 ? phase1.value.integrity : null + prf = length(phase1.value.prf) > 0 ? phase1.value.prf : null + dh = length(phase1.value.dh) > 0 ? phase1.value.dh : null + } + } + dynamic "phase2" { + for_each = cipher_suite.value.phase2 != null ? [cipher_suite.value.phase2] : [] + content { + encryption = length(phase2.value.encryption) > 0 ? phase2.value.encryption : null + integrity = length(phase2.value.integrity) > 0 ? phase2.value.integrity : null + pfs = length(phase2.value.pfs) > 0 ? phase2.value.pfs : null + } + } + } + } +} + +resource "google_compute_vpn_tunnel" "panorama_tunnel1" { + count = var.enable_panorama_vpn ? 1 : 0 + project = local.panorama_project + region = var.region + name = "${var.name_prefix}-panorama-tun1" + vpn_gateway = google_compute_ha_vpn_gateway.panorama_ha_gw[0].self_link + vpn_gateway_interface = 1 + peer_external_gateway = google_compute_external_vpn_gateway.panorama_peer_gw[0].self_link + peer_external_gateway_interface = 1 + + shared_secret = data.google_secret_manager_regional_secret_version.pano_psk_tun1.secret_data + router = google_compute_router.panorama_router[0].self_link + ike_version = var.ike_version + + dynamic "cipher_suite" { + for_each = var.tunnel_cipher_suite != null ? [var.tunnel_cipher_suite] : [] + content { + dynamic "phase1" { + for_each = cipher_suite.value.phase1 != null ? [cipher_suite.value.phase1] : [] + content { + encryption = length(phase1.value.encryption) > 0 ? phase1.value.encryption : null + integrity = length(phase1.value.integrity) > 0 ? phase1.value.integrity : null + prf = length(phase1.value.prf) > 0 ? phase1.value.prf : null + dh = length(phase1.value.dh) > 0 ? phase1.value.dh : null + } + } + dynamic "phase2" { + for_each = cipher_suite.value.phase2 != null ? [cipher_suite.value.phase2] : [] + content { + encryption = length(phase2.value.encryption) > 0 ? phase2.value.encryption : null + integrity = length(phase2.value.integrity) > 0 ? phase2.value.integrity : null + pfs = length(phase2.value.pfs) > 0 ? phase2.value.pfs : null + } + } + } + } +} + +# BGP Interfaces +resource "google_compute_router_interface" "panorama_if0" { + count = var.enable_panorama_vpn ? 1 : 0 + project = local.panorama_project + region = var.region + name = "${var.name_prefix}-panorama-if0" + router = google_compute_router.panorama_router[0].name + ip_range = "${var.panorama_gcp_bgp_apipa_ip_0}/${var.vpn_bgp_mask}" + vpn_tunnel = var.enable_panorama_vpn ? google_compute_vpn_tunnel.panorama_tunnel0[0].name : null +} + +resource "google_compute_router_interface" "panorama_if1" { + count = var.enable_panorama_vpn ? 1 : 0 + project = local.panorama_project + region = var.region + name = "${var.name_prefix}-panorama-if1" + router = google_compute_router.panorama_router[0].name + ip_range = "${var.panorama_gcp_bgp_apipa_ip_1}/${var.vpn_bgp_mask}" + vpn_tunnel = var.enable_panorama_vpn ? google_compute_vpn_tunnel.panorama_tunnel1[0].name : null +} + +# BGP Peers +resource "google_compute_router_peer" "panorama_peer0" { + count = var.enable_panorama_vpn ? 1 : 0 + project = local.panorama_project + region = var.region + name = "${var.name_prefix}-panorama-peer0" + router = google_compute_router.panorama_router[0].name + interface = var.enable_panorama_vpn ? google_compute_router_interface.panorama_if0[0].name : null + peer_ip_address = var.panorama_peer_bgp_apipa_ip_0 + peer_asn = var.panorama_bgp_asn +} + +resource "google_compute_router_peer" "panorama_peer1" { + count = var.enable_panorama_vpn ? 1 : 0 + project = local.panorama_project + region = var.region + name = "${var.name_prefix}-panorama-peer1" + router = google_compute_router.panorama_router[0].name + interface = var.enable_panorama_vpn ? google_compute_router_interface.panorama_if1[0].name : null + peer_ip_address = var.panorama_peer_bgp_apipa_ip_1 + peer_asn = var.panorama_bgp_asn +} + diff --git a/fast/stages-aw/3-vpn/terraform.tfvars.sample b/fast/stages-aw/3-vpn/terraform.tfvars.sample new file mode 100644 index 000000000..6bf168415 --- /dev/null +++ b/fast/stages-aw/3-vpn/terraform.tfvars.sample @@ -0,0 +1,92 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +# Global Configuration +project_id = "my-production-project-123" +region = "us-east4" +name_prefix = "prod-multi-vpn" +gcp_network_name = "prod-vpc-network" +gcp_router_name = "prod-vpc-router-use4" +gcp_bgp_asn = 65514 +ike_version = 2 +vpn_bgp_mask = 30 + +# AWS Specific Configuration +create_gcp_vpn_tunnels_aws = true +aws_bgp_asn = 64512 + +# CNSA-compliant defaults are built into the module, but can be overridden here. +# If you see "NO PROPOSAL CHOSEN", ensure this matches the AWS side exactly. +# Example of a highly compatible suite: +# aws_tunnel_cipher_suite = { +# phase1 = { +# encryption = ["AES-256"] +# integrity = ["SHA2-256"] +# prf = ["PRF-HMAC-SHA2-256"] +# dh = ["Group-14"] +# } +# phase2 = { +# encryption = ["AES-256"] +# integrity = ["SHA2-256"] +# pfs = ["Group-14"] +# } +# } + +aws_tunnel_details = { + tun1 = { external_ip = "203.0.113.1", gcp_bgp_ip = "169.254.21.2/30", aws_bgp_ip = "169.254.21.1" } + tun2 = { external_ip = "203.0.113.2", gcp_bgp_ip = "169.254.22.2/30", aws_bgp_ip = "169.254.22.1" } + tun3 = { external_ip = "203.0.113.3", gcp_bgp_ip = "169.254.23.2/30", aws_bgp_ip = "169.254.23.1" } + tun4 = { external_ip = "203.0.113.4", gcp_bgp_ip = "169.254.24.2/30", aws_bgp_ip = "169.254.24.1" } +} +secret_name_aws_conn1_tun1 = "aws-vpn-psk-c1t1" +secret_name_aws_conn1_tun2 = "aws-vpn-psk-c1t2" +secret_name_aws_conn2_tun1 = "aws-vpn-psk-tenant1" +secret_name_aws_conn2_tun2 = "aws-vpn-psk-tenant2" +aws_secret_version = "latest" +aws_redundancy_type = "FOUR_IPS_REDUNDANCY" + +# Azure Specific Configuration +enable_azure_vpn = true +mgmt_bgp_asn = 65200 +azure_bgp_asn = 65515 +azure_gateway_ip_0 = "203.0.113.10" +azure_gateway_ip_1 = "203.0.113.20" +secret_name_azure_tunnel0 = "azure-vpn-psk-tun0" +secret_name_azure_tunnel1 = "azure-vpn-psk-tun1" +azure_gcp_bgp_apipa_ip_0 = "169.254.22.6" +azure_peer_bgp_apipa_ip_0 = "169.254.22.5" +azure_gcp_bgp_apipa_ip_1 = "169.254.22.10" +azure_peer_bgp_apipa_ip_1 = "169.254.22.9" +azure_redundancy_type = "TWO_IPS_REDUNDANCY" + +# Panorama Specific Configuration +enable_panorama_vpn = true +panorama_project_id = "my-panorama-project-456" +panorama_vpc_name = "my-panorama-vpc" +panorama_bgp_asn = 65516 +panorama_gateway_ip_0 = "203.0.113.30" +panorama_gateway_ip_1 = "203.0.113.40" +secret_name_panorama_tunnel0 = "panorama-vpn-psk-tun0" +secret_name_panorama_tunnel1 = "panorama-vpn-psk-tun1" +panorama_gcp_bgp_apipa_ip_0 = "169.254.23.6" +panorama_peer_bgp_apipa_ip_0 = "169.254.23.5" +panorama_gcp_bgp_apipa_ip_1 = "169.254.23.10" +panorama_peer_bgp_apipa_ip_1 = "169.254.23.9" +panorama_redundancy_type = "TWO_IPS_REDUNDANCY" + +# Advanced configuration (optional) +stack_type = "IPV4_ONLY" +gateway_ip_version = "IPV4" diff --git a/fast/stages-aw/3-vpn/variables.tf b/fast/stages-aw/3-vpn/variables.tf new file mode 100644 index 000000000..92a263d52 --- /dev/null +++ b/fast/stages-aw/3-vpn/variables.tf @@ -0,0 +1,351 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +variable "aws_bgp_asn" { + description = "BGP Autonomous System Number for AWS side." + type = number + default = 64512 +} + +variable "aws_redundancy_type" { + description = "Redundancy type for the AWS external VPN gateway." + type = string + default = "FOUR_IPS_REDUNDANCY" +} + +variable "aws_secret_version" { + description = "The version of the secret to pull from Secret Manager for AWS VPN PSKs." + type = string + default = "latest" +} + +variable "aws_tunnel_cipher_suite" { + description = "The CNSA-compliant cipher suite for the AWS VPN tunnels. If null, the global tunnel_cipher_suite is used." + type = object({ + phase1 = optional(object({ + encryption = optional(list(string)) + integrity = optional(list(string)) + prf = optional(list(string)) + dh = optional(list(string)) + })) + phase2 = optional(object({ + encryption = optional(list(string)) + integrity = optional(list(string)) + pfs = optional(list(string)) + })) + }) + default = null +} + +variable "aws_tunnel_details" { + description = "Explicit configuration for the AWS tunnel peers." + type = map(object({ + external_ip = string + gcp_bgp_ip = string + aws_bgp_ip = string + })) + default = null +} + +variable "azure_bgp_asn" { + description = "BGP Autonomous System Number for Azure side." + type = number + default = 65515 +} + +variable "azure_gateway_ip_0" { + description = "The first public IP address of the Azure VPN gateway." + type = string + default = null +} + +variable "azure_gateway_ip_1" { + description = "The second public IP address of the Azure VPN gateway." + type = string + default = null +} + +variable "azure_gcp_bgp_apipa_ip_0" { + description = "GCP-side internal BGP IP for the first Azure tunnel." + type = string + default = "169.254.21.1" +} + +variable "azure_gcp_bgp_apipa_ip_1" { + description = "GCP-side internal BGP IP for the second Azure tunnel." + type = string + default = "169.254.21.5" +} + +variable "azure_peer_bgp_apipa_ip_0" { + description = "Azure-side internal BGP IP for the first Azure tunnel." + type = string + default = "169.254.21.2" +} + +variable "azure_peer_bgp_apipa_ip_1" { + description = "Azure-side internal BGP IP for the second Azure tunnel." + type = string + default = "169.254.21.6" +} + +variable "azure_redundancy_type" { + description = "Redundancy type for the Azure external VPN gateway." + type = string + default = "TWO_IPS_REDUNDANCY" +} + +variable "create_gcp_vpn_tunnels_aws" { + description = "Determines if the GCP VPN tunnels and BGP peering sessions for AWS should be created (gateways remain active)." + type = bool + default = true +} + +variable "enable_azure_vpn" { + description = "Set to false to destroy the Azure-related VPN tunnels and BGP peering sessions (leaving the gateways intact)." + type = bool + default = true +} + +variable "enable_panorama_vpn" { + description = "Set to false to destroy the Panorama-related VPN tunnels and BGP peering sessions (leaving the gateways and router intact)." + type = bool + default = true +} + +variable "gateway_ip_version" { + description = "The IP family of the gateway IPs for the HA-VPN gateway interfaces. Possible values: IPV4, IPV6." + type = string + default = "IPV4" + validation { + condition = contains(["IPV4", "IPV6"], var.gateway_ip_version) + error_message = "The gateway_ip_version must be one of IPV4, IPV6." + } +} + +variable "gcp_bgp_asn" { + description = "BGP Autonomous System Number for the GCP Cloud Router." + type = number + validation { + condition = var.gcp_bgp_asn >= 0 && var.gcp_bgp_asn <= 4294967295 + error_message = "The GCP BGP ASN must be a valid 32-bit integer." + } +} + +variable "gcp_bgp_identifier_range" { + description = "Explicitly specifies a range of valid BGP Identifiers for this Router. It is provided as a link-local IPv4 range (from 169.254.0.0/16), of size at least /30. If null, GCP will auto-assign." + type = string + default = null +} + +variable "gcp_network_name" { + description = "The name of your existing GCP VPC network." + type = string +} + +variable "gcp_router_name" { + description = "The name of the GCP Cloud Router." + type = string + default = null +} + +variable "ike_version" { + description = "The IKE protocol version used for the VPN tunnels." + type = number + default = 2 +} + +variable "mgmt_bgp_asn" { + description = "MGMT router ASN." + type = number + default = 65200 +} + +variable "name_prefix" { + description = "A prefix to use for resource names." + type = string + default = "ha-vpn" +} + +variable "panorama_bgp_asn" { + description = "BGP Autonomous System Number for Panorama side." + type = number + default = 65516 +} + +variable "panorama_gateway_ip_0" { + description = "The first public IP address of the Panorama VPN gateway." + type = string + default = null +} + +variable "panorama_gateway_ip_1" { + description = "The second public IP address of the Panorama VPN gateway." + type = string + default = null +} + +variable "panorama_gcp_bgp_apipa_ip_0" { + description = "GCP-side internal BGP IP for the first Panorama tunnel." + type = string + default = "169.254.22.1" +} + +variable "panorama_gcp_bgp_apipa_ip_1" { + description = "GCP-side internal BGP IP for the second Panorama tunnel." + type = string + default = "169.254.22.5" +} + +variable "panorama_peer_bgp_apipa_ip_0" { + description = "Panorama-side internal BGP IP for the first Panorama tunnel." + type = string + default = "169.254.22.2" +} + +variable "panorama_peer_bgp_apipa_ip_1" { + description = "Panorama-side internal BGP IP for the second Panorama tunnel." + type = string + default = "169.254.22.6" +} + +variable "panorama_project_id" { + description = "The GCP Project ID where Panorama resources will be created (if different from global project_id)." + type = string + default = null +} + +variable "panorama_redundancy_type" { + description = "Redundancy type for the Panorama external VPN gateway." + type = string + default = "TWO_IPS_REDUNDANCY" +} + +variable "panorama_router_name" { + description = "The name of the Cloud Router for Panorama (if different from global gcp_router_name)." + type = string + default = null +} + +variable "panorama_vpc_name" { + description = "The name of the VPC network for Panorama (if different from global gcp_network_name)." + type = string + default = null +} + +variable "project_id" { + description = "The GCP Project ID where the resources will be created." + type = string +} + +variable "region" { + description = "The GCP region where the resources will be created." + type = string +} + +variable "secret_name_aws_conn1_tun1" { + description = "Secret Manager secret name for AWS Connection 1 Tunnel 1 PSK." + type = string + default = null +} + +variable "secret_name_aws_conn1_tun2" { + description = "Secret Manager secret name for AWS Connection 1 Tunnel 2 PSK." + type = string + default = null +} + +variable "secret_name_aws_conn2_tun1" { + description = "Secret Manager secret name for AWS Connection 2 Tunnel 1 PSK." + type = string + default = null +} + +variable "secret_name_aws_conn2_tun2" { + description = "Secret Manager secret name for AWS Connection 2 Tunnel 2 PSK." + type = string + default = null +} + +variable "secret_name_azure_tunnel0" { + description = "Secret Manager secret name for Azure Tunnel 0 PSK." + type = string + default = null +} + +variable "secret_name_azure_tunnel1" { + description = "Secret Manager secret name for Azure Tunnel 1 PSK." + type = string + default = null +} + +variable "secret_name_panorama_tunnel0" { + description = "Secret Manager secret name for Panorama Tunnel 0 PSK." + type = string + default = null +} + +variable "secret_name_panorama_tunnel1" { + description = "Secret Manager secret name for Panorama Tunnel 1 PSK." + type = string + default = null +} + +variable "stack_type" { + description = "The stack type for this VPN gateway. Possible values: IPV4_ONLY, IPV4_IPV6, IPV6_ONLY." + type = string + default = "IPV4_ONLY" + validation { + condition = contains(["IPV4_ONLY", "IPV4_IPV6", "IPV6_ONLY"], var.stack_type) + error_message = "The stack_type must be one of IPV4_ONLY, IPV4_IPV6, IPV6_ONLY." + } +} + +variable "tunnel_cipher_suite" { + description = "The CNSA-compliant cipher suite for the VPN tunnels. Phase 1 and Phase 2 configurations." + type = object({ + phase1 = optional(object({ + encryption = optional(list(string)) + integrity = optional(list(string)) + prf = optional(list(string)) + dh = optional(list(string)) + })) + phase2 = optional(object({ + encryption = optional(list(string)) + integrity = optional(list(string)) + pfs = optional(list(string)) + })) + }) + default = { + phase1 = { + encryption = ["AES-GCM-16-256"] + integrity = [] + prf = ["PRF-HMAC-SHA2-384"] + dh = ["Group-20"] + } + phase2 = { + encryption = ["AES-GCM-16-256"] + integrity = [] + pfs = ["Group-20"] + } + } +} + +variable "vpn_bgp_mask" { + description = "The subnet mask length for the BGP APIPA IP ranges." + type = number + default = 30 +} \ No newline at end of file diff --git a/fast/stages-aw/3-security/IAM.md b/fast/stages-aw/4-security/IAM.md similarity index 74% rename from fast/stages-aw/3-security/IAM.md rename to fast/stages-aw/4-security/IAM.md index e6c31d31e..1ed909eec 100644 --- a/fast/stages-aw/3-security/IAM.md +++ b/fast/stages-aw/4-security/IAM.md @@ -1,3 +1,19 @@ + + # IAM bindings reference Legend: + additive, conditional. diff --git a/fast/stages-aw/3-security/README.md b/fast/stages-aw/4-security/README.md similarity index 75% rename from fast/stages-aw/3-security/README.md rename to fast/stages-aw/4-security/README.md index 4781b4ac4..e8ea0e6a1 100644 --- a/fast/stages-aw/3-security/README.md +++ b/fast/stages-aw/4-security/README.md @@ -1,3 +1,19 @@ + + # Shared security resources and VPC Service Controls This stage sets up security resources and configurations which impact the whole Google Cloud Organization, or are shared across the hierarchy to other projects and teams. @@ -63,7 +79,7 @@ The VPC SC configuration is controlled via the top-level `vpc_sc` variable, and ## How to run this stage -This stage is meant to be executed after the [resource management](../1-resman) stage has run, as it leverages the automation service account and bucket created there, and additional resources configured in the [bootstrap](../0-bootstrap) stage. +This stage is meant to be executed after the [resource management](../2-resman) stage has run, as it leverages the automation service account and bucket created there, and additional resources configured in the [bootstrap](../1-assured-workload) stage. It's of course possible to run this stage in isolation, but that's outside the scope of this document, and you would need to refer to the code for the previous stages for the environmental requirements. @@ -71,7 +87,7 @@ Before running this stage, you need to make sure you have the correct credential ### Provider and Terraform variables -As all other FAST stages, the [mechanism used to pass variable values and pre-built provider files from one stage to the next](../0-bootstrap/README.md#output-files-and-cross-stage-variables) is also leveraged here. +As all other FAST stages, the [mechanism used to pass variable values and pre-built provider files from one stage to the next](../1-assured-workload/README.md#output-files-and-cross-stage-variables) is also leveraged here. The commands to link or copy the provider and terraform variable files can be easily derived from the `stage-links.sh` script in the FAST root folder, passing it a single argument with the local output files folder (if configured) or the GCS output bucket in the automation project (derived from stage 0 outputs). The following examples demonstrate both cases, and the resulting commands that then need to be copy/pasted and run. @@ -79,13 +95,13 @@ The commands to link or copy the provider and terraform variable files can be ea ../../stage-links.sh gs://xxx-prod-iac-core-outputs-0 ``` -_Copy and paste the following commands for '3-security'_ +_Copy and paste the following commands for '4-security'_ ```bash -gcloud alpha storage cp gs://xxx-prod-iac-core-outputs-0/providers/3-security-providers.tf ./ -gcloud alpha storage cp gs://xxx-prod-iac-core-outputs-0/tfvars/0-globals.auto.tfvars.json ./ -gcloud alpha storage cp gs://xxx-prod-iac-core-outputs-0/tfvars/0-bootstrap.auto.tfvars.json ./ -gcloud alpha storage cp gs://xxx-prod-iac-core-outputs-0/tfvars/1-resman.auto.tfvars.json ./ +gcloud alpha storage cp gs://xxx-prod-iac-core-outputs-0/providers/4-security-providers.tf ./ +gcloud alpha storage cp gs://xxx-prod-iac-core-outputs-0/tfvars/1-globals.auto.tfvars.json ./ +gcloud alpha storage cp gs://xxx-prod-iac-core-outputs-0/tfvars/1-assured-workload-bootstrap.auto.tfvars.json ./ +gcloud alpha storage cp gs://xxx-prod-iac-core-outputs-0/tfvars/2-resman.auto.tfvars.json ./ ``` ### Impersonating the automation service account @@ -94,10 +110,10 @@ The preconfigured provider file uses impersonation to run with this stage's auto Make sure the `network` service account has the `Service Usage Consumer` role. -Find the network service account by changing directories to `1-resman` in order to run Terraform to query the values needed. +Find the network service account by changing directories to `2-resman` in order to run Terraform to query the values needed. ```bash -cd ../1-resman/ +cd ../2-resman/ terraform output security ``` @@ -105,12 +121,12 @@ And make sure it has the "Service Usage Consumer" role in the project that you a ### Setting default project for manual run -**Important**: Before running this, make sure that if you are running these stages manually from the command line, that your default project is set to the 'automation' Google Cloud Project created in 0-bootstrap. +**Important**: Before running this, make sure that if you are running these stages manually from the command line, that your default project is set to the 'automation' Google Cloud Project created in 1-assured-workload. To find the 'automation' project, ```bash -cd ../0-bootstrap +cd ../1-assured-workload terraform output project_ids ``` @@ -122,20 +138,20 @@ gcloud config set project -prod-iac-core-0 Now return to the Security directory. ```bash -cd ../3-security +cd ../4-security ``` ### Variable configuration Variables in this stage -- like most other FAST stages -- are broadly divided into three separate sets: -- variables which refer to global values for the whole Google Cloud Organization (org id, billing account id, prefix, etc.), which are pre-populated via the `0-globals.auto.tfvars.json` file linked or copied above -- variables which refer to resources managed by previous stages, which are prepopulated here via the `0-bootstrap.auto.tfvars.json` and `1-resman.auto.tfvars.json` files linked or copied above +- variables which refer to global values for the whole Google Cloud Organization (org id, billing account id, prefix, etc.), which are pre-populated via the `1-globals.auto.tfvars.json` file linked or copied above +- variables which refer to resources managed by previous stages, which are prepopulated here via the `1-assured-workload.auto.tfvars.json` and `2-resman.auto.tfvars.json` files linked or copied above - and finally variables that optionally control this stage's behavior and customizations, and can to be set in a custom `terraform.tfvars` file The latter set is explained in the [Customization](#customizations) sections below, and the full list can be found in the [Variables](#variables) table at the bottom of this document. -Note that the `outputs_location` variable is disabled by default, you need to explicitly set it in your `terraform.tfvars` file if you want output files to be generated by this stage. This is a sample `terraform.tfvars` that configures it, refer to the [bootstrap stage documentation](../0-bootstrap/README.md#output-files-and-cross-stage-variables) for more details: +Note that the `outputs_location` variable is disabled by default, you need to explicitly set it in your `terraform.tfvars` file if you want output files to be generated by this stage. This is a sample `terraform.tfvars` that configures it, refer to the [bootstrap stage documentation](../1-assured-workload/README.md#output-files-and-cross-stage-variables) for more details: ```tfvars outputs_location = "~/fast-config" @@ -145,7 +161,7 @@ outputs_location = "~/fast-config" This configuration is possible but unsupported and only exists for development purposes, use at your own risk: -- temporarily switch `billing_account.id` to `null` in `0-globals.auto.tfvars.json` +- temporarily switch `billing_account.id` to `null` in `1-globals.auto.tfvars.json` - for each project resources in the project modules used in this stage (`dev-sec-project`, `prod-sec-project`) - apply using `-target`, for example `terraform apply -target 'module.prod-sec-project.google_project.project[0]'` @@ -184,7 +200,7 @@ You can also run this script with the following flags Some common troubleshooting steps: - Ensure the file is executable by running - + ```bash chmod +x sa_lockdown.sh ``` @@ -192,7 +208,7 @@ chmod +x sa_lockdown.sh ### Deleting the bootstrap project -Once Stellar Engine has been deployed, the bootstrap Google Cloud Project is no longer necessary. You can delete the bootstrap Google Cloud Project by running the following script within the "3-security" directory. Be sure to insert your appropriate boostrap Google Cloud Project ID. +Once Stellar Engine Landing Zone has been deployed, the bootstrap Google Cloud Project is no longer necessary. You can delete the bootstrap Google Cloud Project by running the following script within the "4-security" directory. Be sure to insert your appropriate bootstrap Google Cloud Project ID. ```bash ./delete_gcp_project.sh --project-id= @@ -298,31 +314,20 @@ Some references that might be useful in setting up this stage | name | description | type | required | default | |---|---|:---:|:---:|:---:| | [alert_email](variables.tf#L16) | Email to receive log alerts. | string | ✓ | | -| [automation](variables.tf#L21) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | -| [billing_account](variables.tf#L29) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | object({…}) | ✓ | | -| [folder_ids](variables.tf#L62) | Folder name => id mappings, the 'security' folder name must exist. | object({…}) | ✓ | | -| [organization](variables.tf#L123) | Organization details. | object({…}) | ✓ | | -| [prefix](variables.tf#L139) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | -| [service_accounts](variables.tf#L149) | Automation service accounts that can assign the encrypt/decrypt roles on keys. | object({…}) | ✓ | | -| [assured_workloads](variables.tf#L199) | Assured Workloads configuration. | any | | null | -| [billing_override](variables.tf#L184) | Optional billing override configuration. If set, disables service account impersonation for project billing linkage and runs under the user account using the specified quota projects. | object({…}) | | null | -| [common_services_folder](variables.tf#L259) | Common services folder ID. | any | | null | -| [custom_roles](variables.tf#L193) | Custom IAM roles defined during bootstrap. | any | | null | -| [envs_folders](variables.tf#L235) | Environment folders mappings. | any | | null | -| [essential_contacts](variables.tf#L42) | Email used for essential contacts, unset if null. | string | | null | -| [factories_config](variables.tf#L48) | Paths to folders that enable factory functionality. | object({…}) | | {} | -| [fast_features](variables.tf#L253) | FAST features mapping. | any | | null | -| [federated_identity_providers](variables.tf#L223) | Federated identity providers configuration. | any | | null | -| [gcp_ranges](variables.tf#L229) | GCP address ranges configuration. | any | | null | -| [groups](variables.tf#L211) | IAM groups configuration. | any | | null | -| [kms_keys](variables.tf#L70) | KMS keys to create, keyed by name. | map(object({…})) | | {} | -| [logging](variables.tf#L113) | Log writer identities for organization / folders. | object({…}) | | null | -| [org_policy_classification_tags](variables.tf#L247) | Org policy classification tags configuration. | any | | null | -| [outputs_location](variables.tf#L133) | Path where providers, tfvars files, and lists for the following stages are written. Leave empty to disable. | string | | null | -| [regime_mapping](variables.tf#L217) | Compliance regime shorthand mapping. | any | | null | -| [regions](variables.tf#L205) | GCP regions configuration. | any | | null | -| [tenant_accounts](variables.tf#L241) | Tenant accounts configuration. | any | | null | -| [vpc_sc](variables.tf#L160) | VPC SC configuration. | object({…}) | | {} | +| [automation](variables.tf#L32) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | +| [billing_account](variables.tf#L40) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | object({…}) | ✓ | | +| [folder_ids](variables.tf#L73) | Folder name => id mappings, the 'security' folder name must exist. | object({…}) | ✓ | | +| [organization](variables.tf#L184) | Organization details. | object({…}) | ✓ | | +| [prefix](variables.tf#L200) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | +| [regime_mapping](variables.tf#L210) | Mapping of compliance regime names to short codes. | map(string) | ✓ | | +| [service_accounts](variables.tf#L215) | Automation service accounts that can assign the encrypt/decrypt roles on keys. | object({…}) | ✓ | | +| [assured_workloads](variables.tf#L21) | Configuration for Assured Workloads. | object({…}) | | {} | +| [essential_contacts](variables.tf#L53) | Email used for essential contacts, unset if null. | string | | null | +| [factories_config](variables.tf#L59) | Paths to folders that enable factory functionality. | object({…}) | | {} | +| [kms_keys](variables.tf#L81) | KMS keys to create, keyed by name. | map(object({…})) | | {} | +| [logging](variables.tf#L174) | Log writer identities for organization / folders. | object({…}) | | null | +| [outputs_location](variables.tf#L194) | Path where providers, tfvars files, and lists for the following stages are written. Leave empty to disable. | string | | null | +| [vpc_sc](variables.tf#L226) | VPC SC configuration. | object({…}) | | {} | ## Outputs diff --git a/fast/stages-aw/3-security/core-dev.tf b/fast/stages-aw/4-security/core-dev.tf similarity index 88% rename from fast/stages-aw/3-security/core-dev.tf rename to fast/stages-aw/4-security/core-dev.tf index d51e9b6fb..e587fe8c5 100644 --- a/fast/stages-aw/3-security/core-dev.tf +++ b/fast/stages-aw/4-security/core-dev.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { dev_kms_restricted_admins = [ for sa in distinct(compact([ @@ -25,14 +24,9 @@ locals { } module "dev-sec-project" { - source = "../../../modules/project" - providers = { - google = google.billing - google-beta = google-beta.billing - } - name = "dev-sec-core-0" + source = "../../../modules/project" + name = local.project_map["dev-sec-project"] parent = var.folder_ids.security - prefix = var.prefix billing_account = var.billing_account.id iam = { "roles/cloudkms.viewer" = local.dev_kms_restricted_admins diff --git a/fast/stages-aw/3-security/core-prod.tf b/fast/stages-aw/4-security/core-prod.tf similarity index 87% rename from fast/stages-aw/3-security/core-prod.tf rename to fast/stages-aw/4-security/core-prod.tf index f4d7cb156..57c2ba834 100644 --- a/fast/stages-aw/3-security/core-prod.tf +++ b/fast/stages-aw/4-security/core-prod.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { prod_kms_restricted_admins = [ for sa in distinct(compact([ @@ -24,14 +23,9 @@ locals { } module "prod-sec-project" { - source = "../../../modules/project" - providers = { - google = google.billing - google-beta = google-beta.billing - } - name = "prod-sec-core-0" + source = "../../../modules/project" + name = local.project_map["prod-sec-project"] parent = var.folder_ids.security - prefix = var.prefix billing_account = var.billing_account.id iam = { "roles/cloudkms.viewer" = local.prod_kms_restricted_admins diff --git a/fast/stages-aw/3-security/data/vpc-sc/restricted-services.yaml b/fast/stages-aw/4-security/data/vpc-sc/restricted-services.yaml similarity index 99% rename from fast/stages-aw/3-security/data/vpc-sc/restricted-services.yaml rename to fast/stages-aw/4-security/data/vpc-sc/restricted-services.yaml index 3c070aaca..8aa830e2b 100644 --- a/fast/stages-aw/3-security/data/vpc-sc/restricted-services.yaml +++ b/fast/stages-aw/4-security/data/vpc-sc/restricted-services.yaml @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/fast/stages-aw/3-security/delete_gcp_project.sh b/fast/stages-aw/4-security/delete_gcp_project.sh old mode 100755 new mode 100644 similarity index 99% rename from fast/stages-aw/3-security/delete_gcp_project.sh rename to fast/stages-aw/4-security/delete_gcp_project.sh index 62ab3104a..7720950ca --- a/fast/stages-aw/3-security/delete_gcp_project.sh +++ b/fast/stages-aw/4-security/delete_gcp_project.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. - # Initialize variables PROJECT_ID="" CURRENT_USER="" diff --git a/fast/stages-aw/3-security/diagram.png b/fast/stages-aw/4-security/diagram.png similarity index 100% rename from fast/stages-aw/3-security/diagram.png rename to fast/stages-aw/4-security/diagram.png diff --git a/fast/stages-aw/3-security/log-metric-alerts.tf b/fast/stages-aw/4-security/log-metric-alerts.tf similarity index 64% rename from fast/stages-aw/3-security/log-metric-alerts.tf rename to fast/stages-aw/4-security/log-metric-alerts.tf index 08544731d..95cc69c24 100644 --- a/fast/stages-aw/3-security/log-metric-alerts.tf +++ b/fast/stages-aw/4-security/log-metric-alerts.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # CIS Compliance Benchmark 2.4 # CIS Compliance Benchmark 2.5 diff --git a/fast/stages-aw/3-security/main.tf b/fast/stages-aw/4-security/main.tf similarity index 79% rename from fast/stages-aw/3-security/main.tf rename to fast/stages-aw/4-security/main.tf index a72bd7b78..1f6c49fb9 100644 --- a/fast/stages-aw/3-security/main.tf +++ b/fast/stages-aw/4-security/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { # additive IAM binding for delegated KMS admins kms_restricted_admin_template = { @@ -52,6 +51,14 @@ locals { "secretmanager.googleapis.com", "stackdriver.googleapis.com" ] + + # The following section maps project names for stage 4 using the projects-config.yml inside of the root directory + formatted_regime = lower(replace(lookup(var.regime_mapping, var.assured_workloads.regime, var.assured_workloads.regime), "_", " ")) + project_config_yaml = yamldecode(file("../../../project-config.yml")) + project_map = { + for p in local.project_config_yaml.projects : p.name => + replace(replace(p.project_name, "", var.prefix), "", local.formatted_regime) + } } module "folder" { diff --git a/fast/stages-aw/3-security/outputs.tf b/fast/stages-aw/4-security/outputs.tf similarity index 94% rename from fast/stages-aw/3-security/outputs.tf rename to fast/stages-aw/4-security/outputs.tf index 2561ce215..f5dcd0789 100644 --- a/fast/stages-aw/3-security/outputs.tf +++ b/fast/stages-aw/4-security/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _output_kms_keys = concat( flatten([ @@ -42,13 +41,13 @@ locals { resource "local_file" "tfvars" { for_each = var.outputs_location == null ? {} : { 1 = 1 } file_permission = "0644" - filename = "${pathexpand(var.outputs_location)}/tfvars/3-security.auto.tfvars.json" + filename = "${pathexpand(var.outputs_location)}/tfvars/4-security.auto.tfvars.json" content = jsonencode(local.tfvars) } resource "google_storage_bucket_object" "tfvars" { bucket = var.automation.outputs_bucket - name = "tfvars/3-security.auto.tfvars.json" + name = "tfvars/4-security.auto.tfvars.json" content = jsonencode(local.tfvars) } diff --git a/fast/stages-aw/3-security/sa_lockdown.sh b/fast/stages-aw/4-security/sa_lockdown.sh old mode 100755 new mode 100644 similarity index 87% rename from fast/stages-aw/3-security/sa_lockdown.sh rename to fast/stages-aw/4-security/sa_lockdown.sh index f333c2248..484546293 --- a/fast/stages-aw/3-security/sa_lockdown.sh +++ b/fast/stages-aw/4-security/sa_lockdown.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -13,9 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. - # Default list of service account names -VALID_NAMES=("bootstrap" "resman" "networking" "security") +VALID_NAMES=("bootstrap" "resman" "networking" "security" "tenant") # Initialize variables ACTION="disable" # Default action is to disable @@ -90,14 +89,11 @@ for tfvars_file in *.tfvars.json; do # If service account is found, disable/enable it if [ "$service_account" != "null" ] && [ -n "$service_account" ]; then - # Extract project ID from service account email (format: name@project-id.iam.gserviceaccount.com) - project_id=$(echo "$service_account" | sed -E 's/.*@(.*)\.iam\.gserviceaccount\.com/\1/') - - # echo "$ACTION service account: $service_account in project: $project_id" + # echo "$ACTION service account: $service_account" if [ "$ACTION" == "disable" ]; then - gcloud iam service-accounts disable "$service_account" --project="$project_id" --quiet + gcloud iam service-accounts disable "$service_account" --quiet elif [ "$ACTION" == "enable" ]; then - gcloud iam service-accounts enable "$service_account" --project="$project_id" --quiet + gcloud iam service-accounts enable "$service_account" --quiet else echo "Unknown action: $ACTION" exit 1 diff --git a/fast/stages-aw/3-security/variables.tf b/fast/stages-aw/4-security/variables.tf similarity index 68% rename from fast/stages-aw/3-security/variables.tf rename to fast/stages-aw/4-security/variables.tf index 92fc01acf..41370cbc4 100644 --- a/fast/stages-aw/3-security/variables.tf +++ b/fast/stages-aw/4-security/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,8 +18,19 @@ variable "alert_email" { type = string } +variable "assured_workloads" { + description = "Configuration for Assured Workloads." + type = object({ + regime = optional(string) + location = optional(string) + folder = optional(string) + }) + nullable = false + default = {} +} + variable "automation" { - # tfdoc:variable:source 0-bootstrap + # tfdoc:variable:source 1-assured-workload description = "Automation resources created by the bootstrap stage." type = object({ outputs_bucket = string @@ -27,7 +38,7 @@ variable "automation" { } variable "billing_account" { - # tfdoc:variable:source 0-bootstrap + # tfdoc:variable:source 1-assured-workload description = "Billing account id. If billing account is not part of the same org set `is_org_level` to false." type = object({ id = string @@ -60,7 +71,7 @@ variable "factories_config" { } variable "folder_ids" { - # tfdoc:variable:source 1-resman + # tfdoc:variable:source 2-resman description = "Folder name => id mappings, the 'security' folder name must exist." type = object({ security = string @@ -72,12 +83,62 @@ variable "kms_keys" { type = map(object({ rotation_period = optional(string, "7776000s") # CIS Compliance Benchmark 1.10 labels = optional(map(string)) - # Default locations for IL5/FedRAMP compliance - can be overridden per environment - # Uses primary US regions and zones commonly approved for government workloads locations = optional(list(string), [ - "us", # Multi-region - "us-east4", # Primary region - "us-central1", # Secondary region + "us", + "us-central2", + "us-east5-locations", + "us-central1-b", + "us-central2-d", + "us-west1-c", + "us-east4-a", + "us-west1", + "us-central2-b", + "us-south1-locations", + "us-south1-b", + "us-west2-c", + "us-west1-b", + "us-central2-locations", + "us-east4-d", + "us-east4-locations", + "us-east5-c", + "us-central2-a", + "us-west1-locations", + "us-west4", + "us-west3-b", + "us-west1-a", + "us-west4-a", + "us-west2", + "us-east4-c", + "us-west2-b", + "us-south1-a", + "us-east5-a", + "nam4", + "us-east4-a", + "us-west2-locations", + "us-central1-f", + "us-south1", + "us-west4-c", + "us-west2-a", + "us-west3", + "us-west4-b", + "us-central1", + "us-west3-c", + "us-central1-c", + "us-south1-c", + "us-east4-locations", + "us-east4", + "us-east4-b", + "us-central1-a", + "us-central2-c", + "us-east5-b", + "us-central1-locations", + "us-west4-locations", + "us-east5", + "us-west3-locations", + "us-west3-a", + "us-east4", + "us-east4-b", + "us-east4-c", ]) purpose = optional(string, "ENCRYPT_DECRYPT") skip_initial_version_creation = optional(bool, false) @@ -111,7 +172,7 @@ variable "kms_keys" { } variable "logging" { - # tfdoc:variable:source 0-bootstrap + # tfdoc:variable:source 1-assured-workload description = "Log writer identities for organization / folders." type = object({ project_number = string @@ -121,7 +182,7 @@ variable "logging" { } variable "organization" { - # tfdoc:variable:source 0-bootstrap + # tfdoc:variable:source 1-assured-workload description = "Organization details." type = object({ domain = string @@ -137,17 +198,22 @@ variable "outputs_location" { } variable "prefix" { - # tfdoc:variable:source 0-bootstrap + # tfdoc:variable:source 1-assured-workload description = "Prefix used for resources that need unique names. Use 9 characters or less." type = string validation { - condition = try(length(var.prefix), 0) < 10 + condition = try(length(var.prefix), 0) <= 10 error_message = "Use a maximum of 9 characters for prefix." } } +variable "regime_mapping" { + description = "Mapping of compliance regime names to short codes." + type = map(string) +} + variable "service_accounts" { - # tfdoc:variable:source 1-resman + # tfdoc:variable:source 2-resman description = "Automation service accounts that can assign the encrypt/decrypt roles on keys." type = object({ data-platform-dev = string @@ -179,86 +245,4 @@ variable "vpc_sc" { }) default = {} nullable = false -} - -variable "billing_override" { - description = "Optional billing override configuration. If set, disables service account impersonation for project billing linkage and runs under the user account using the specified quota projects." - type = object({ - project = string - billing_project = string - }) - default = null -} - -variable "custom_roles" { - description = "Custom IAM roles defined during bootstrap." - type = any - default = null -} - -variable "assured_workloads" { - description = "Assured Workloads configuration." - type = any - default = null -} - -variable "regions" { - description = "GCP regions configuration." - type = any - default = null -} - -variable "groups" { - description = "IAM groups configuration." - type = any - default = null -} - -variable "regime_mapping" { - description = "Compliance regime shorthand mapping." - type = any - default = null -} - -variable "federated_identity_providers" { - description = "Federated identity providers configuration." - type = any - default = null -} - -variable "gcp_ranges" { - description = "GCP address ranges configuration." - type = any - default = null -} - -variable "envs_folders" { - description = "Environment folders mappings." - type = any - default = null -} - -variable "tenant_accounts" { - description = "Tenant accounts configuration." - type = any - default = null -} - -variable "org_policy_classification_tags" { - description = "Org policy classification tags configuration." - type = any - default = null -} - -variable "fast_features" { - description = "FAST features mapping." - type = any - default = null -} - -variable "common_services_folder" { - description = "Common services folder ID." - type = any - default = null -} - +} \ No newline at end of file diff --git a/fast/stages-aw/3-security/vpc-sc.tf b/fast/stages-aw/4-security/vpc-sc.tf similarity index 92% rename from fast/stages-aw/3-security/vpc-sc.tf rename to fast/stages-aw/4-security/vpc-sc.tf index f7d7b6f4f..424a7b61d 100644 --- a/fast/stages-aw/3-security/vpc-sc.tf +++ b/fast/stages-aw/4-security/vpc-sc.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { vpc_sc_ingress_policies = var.logging == null ? {} : { fast-org-log-sinks = { @@ -58,6 +57,8 @@ module "vpc-sc-discovery" { include_projects = var.vpc_sc.resource_discovery.include_projects } +# TODO(ludomagno): allow passing in restricted services via variable and factory file +# TODO(ludomagno): implement vpc accessible services via variable or factory file module "vpc-sc" { source = "../../../modules/vpc-sc" @@ -75,7 +76,7 @@ module "vpc-sc" { local.vpc_sc_ingress_policies ) factories_config = var.factories_config.vpc_sc - service_perimeters_regular = { + perimeters = { default = { spec = ( var.vpc_sc.perimeter_default.dry_run ? local.vpc_sc_perimeter : null diff --git a/fast/stages-aw/5-tenants/README.md b/fast/stages-aw/5-tenants/README.md new file mode 100644 index 000000000..78575a59e --- /dev/null +++ b/fast/stages-aw/5-tenants/README.md @@ -0,0 +1,213 @@ + + +# Resource Hierarchy + +This stage provisions an individual tenant's Google Cloud Folders, the Google Cloud projects contained within those folders, the tenant-specific Networking and tenant-specific logging resources. This stage can be used N number of times for N number of tenants without needing multiple folders per tenant. + +# Table of Contents + + +- [Table of Contents](#table-of-contents) +- [Design Overview and Choices](#design-overview-and-choices) +- [How to Run This Stage](#how-to-run-this-stage) + - [Impersonating the Automation Service Account](#impersonating-the-automation-service-account) + - [Lightweight multitenancy](#lightweight-multitenancy) + - [IAM](#iam) + - [Additional Google Cloud Folders](#additional-google-cloud-folders) + - [Tenant Log Sinks](#tenant-log-sinks) +- [Variables](#variables) +- [Outputs](#outputs) + + +## Design Overview and Choices + +The design of this stage ensures that all resources for each tenant resides within a specified `Tenants` Google Cloud Folder within an Assured Workloads Google Cloud Folder; this prevents things like logs from living outside a compliant domain. This stage is designed to deploy a single tenant, but can be used to deploy N number of tenants. This allows each tenant to have its own state file and not utilize a monolithic state file for all tenants. This stage deploys all resources related to the tenant, including the tenant networking, logging and infrastructure. + +## How to Run This Stage + +There is a single providers file for this stage that allows for the backend GCS bucket to be passed in at runtime. To initialize this stage for a specific tenant, run the command `terraform init -backend-config="prefix=" -reconfigure`, where `TENANT_NAME` is the name of the tenant inside the GCS bucket. Once complete, any future Terraform commands will reference the state file located in `gs:///` until the first command is re-ran to point to another tenant. To run terraform for another tenant, you need to run `terraform init -backend-config="prefix=" -reconfigure` with the new tenant's `TENANT_NAME`. + +### Impersonating the Automation Service Account + +The preconfigured provider file uses impersonation to run with this stage's automation service account's credentials. The `gcp-devops` and `organization-admins` groups have the necessary IAM bindings in place to do that, so make sure the current user is a member of one of those groups. + +### Lightweight multitenancy + +If the organization needs to support tenants without the full complexity and separation offered by our [full multitenant support](../5-tenants/), this stage offers a simplified setup which is suitable for cases where tenants have less autonomy, and don't need to implement FAST stages inside their reserved partition. + +This mode is activated by defining tenant in the `tenant` variable, while IAM configurations that apply to every tenant can be optionally set in the `tenant_config` variable. + +The resulting setup provides a new "Tenants" branch in the Google Cloud Folder hierarchy with one second-level Google Cloud Folder for each tenant, and additional Google Cloud Folders inside it to host tenant resources managed from the central team, and tenant resources managed by the tenant itself. Automation resources are provided for both teams. + +The default roles applied on tenant Google Cloud Folders are + +- on the top-level Google Cloud Folder for each tenant + - for the core IaC service account + - `roles/cloudasset.owner` + - `roles/compute.xpnAdmin` + - `roles/logging.admin` + - `roles/resourcemanager.folderAdmin` + - `roles/resourcemanager.projectCreator` + - `roles/resourcemanager.tagUser` +- on the core Google Cloud Folder for each tenant + - for the core IaC service account + - `roles/owner` + - for the tenant admin group and IaC service account + - `roles/viewer` +- on the tenant Google Cloud Folder for each tenant + - for the tenant admin group and IaC service account + - `roles/cloudasset.owner` + - `roles/compute.xpnAdmin` + - `roles/logging.admin` + - `roles/resourcemanager.folderAdmin` + - `roles/resourcemanager.projectCreator` + - `roles/resourcemanager.tagUser` + - `roles/owner` + +Further customization is possible via the `tenants_config` variable. + +This is a high level diagram of the design described above. + +```mermaid +%%{init: {'theme':'base'}}%% +classDiagram + Organization -- Tenants_root~📁~ + Organization -- org_iac + Tenants_root~📁~ -- Tenant_0_root~📁~ + Tenants_root~📁~ -- Tenant_1_root~📁~ + Tenant_0_root~📁~ -- Tenant_0_core~📁~ + Tenant_0_root~📁~ -- Tenant_0_self~📁~ + Tenant_0_self~📁~ -- tenant0_iac + Tenant_1_root~📁~ -- Tenant_1_core~📁~ + Tenant_1_root~📁~ -- Tenant_1_self~📁~ + Tenant_1_self~📁~ -- tenant1_iac + class org_iac["org_iac (from stage 0)"] { + - GCS buckets + - service accounts + } + class Tenants_root~📁~ { + - IAM bindings() + } + class Tenant_0_root~📁~ { + - IAM bindings() + } + class Tenant_0_core~📁~ { + - IAM bindings() + } + class Tenant_0_self~📁~ { + - IAM bindings() + } + class tenant0_iac { + - GCS buckets + - service account + - IAM bindings() + } + class Tenant_1_root~📁~ { + - IAM bindings() + } + class Tenant_1_core~📁~ { + - IAM bindings() + } + class Tenant_1_self~📁~ { + - IAM bindings() + } + class tenant1_iac { + - GCS buckets + - service account + - IAM bindings() + } +``` + +This is a list of the variables that need edited to set the Tenant name. + +```tfvars +tenant = { +{{EDIT_THIS_VARIABLE_TO_THE_FIRST_TENANT_NAME}} = + admin_principal = "group:gcp-devops@example.com" + name = "{{EDIT_THIS_VARIABLE_TO_THE_FIRST_TENANT_DESCRIPTION}}" + locations = { + gcs = "us-east4" + kms = "us-east4" # Must match GCS Region + } + } +} +``` + +This is an example that shows a configured variable block with two example Tenants named `wingarch` and `fuselagerd`. + +```tfvars +tenants = { +wingarch = + admin_principal = "group:gcp-devops@example.com" + name = "Wing Architect Research Group" + locations = { + gcs = "us-east4" + kms = "us-east4" # Must match GCS Region + } + } +} +``` + +Providers and tfvars files will be created for each tenant. + +### IAM + +The `folder_iam` variable can be used to manage authoritative bindings for all top-level Google Cloud Folders. For additional control, IAM roles can be easily edited in the relevant `branch-xxx.tf` file, following the best practice outlined in the [bootstrap stage](../1-assured-workload#customizations) documentation of separating user-level and service-account level IAM policies through the IAM-related variables (`iam`, `iam_bindings`, `iam_bindings_additive`) of the relevant modules. + +A full reference of IAM roles managed by this stage [is available here](#). + +### Additional Google Cloud Folders + +Due to its simplicity, this stage lends itself easily to customizations: adding a new top-level branch (e.g. for shared GKE clusters) is as easy as cloning one of the `branch-xxx.tf` files, and changing names. + +### Tenant Log Sinks + +Tenant-specific folder logging sinks for tenants creates a centralize log route from tenant folders to dedicated log buckets during the stage they are created. This customization is integrated from the bootstrap stage where outputs are staged. It captures logs from the tenant folders, projects, and all their related activities including automated tenant mappings for routing purposes. + +--- + +## Variables + +| name | description | type | required | default | +|---|---|:---:|:---:|:---:| +| [alert_email](variables.tf#L19) | Email to receive log alerts. | string | ✓ | | +| [automation](variables.tf#L24) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | +| [cicd](variables.tf#L50) | Optional CICD variables to add Workload Identity Federation and a GitLab provider. | object({…}) | ✓ | | +| [edge_group_id](variables.tf#L59) | ID of the edge group created in stage 3 for the spoke to join. | string | ✓ | | +| [hub_id](variables.tf#L64) | ID of the hub created in stage 3 so we can add spokes to it. | string | ✓ | | +| [ilb_ips](variables.tf#L69) | ILB IP addresses for each environment. | object({…}) | ✓ | | +| [logging](variables.tf#L97) | Logging resources created by the bootstrap stage. | object({…}) | ✓ | | +| [organization](variables.tf#L111) | Organization details. | object({…}) | ✓ | | +| [prefix](variables.tf#L127) | Prefix used for resources that need unique names. Use 7 characters or less. | string | ✓ | | +| [tenant](variables.tf#L150) | Lightweight tenant definition for a single environment. | object({…}) | ✓ | | +| [tenants_folder_id](variables.tf#L204) | The Overarching Tenant Folder inside of Dev. | string | ✓ | | +| [locations](variables.tf#L77) | Optional locations for GCS, BigQuery, and logging buckets created here. | object({…}) | | {…} | +| [outputs_location](variables.tf#L121) | Enable writing provider, tfvars and CI/CD workflow files to local filesystem. Leave null to disable. | string | | null | +| [regions](variables.tf#L138) | Region definitions. | object({…}) | | {…} | +| [tenant_config](variables.tf#L193) | Lightweight tenants shared configuration. Roles will be assigned to tenant admin group and service accounts. | object({…}) | | {} | + +## Outputs + +| name | description | sensitive | +|---|---|:---:| +| [gcs_iac_bucket](outputs.tf#L1) | IaC buckets. | | +| [projects](outputs.tf#L11) | Tenant projects. | | +| [service_accounts_automation](outputs.tf#L21) | Service accounts for automation. | | +| [service_accounts_cicd](outputs.tf#L32) | Service accounts for CICD. | | +| [vpc_networks](outputs.tf#L43) | Tenant VPC network. | | +| [workload_identity_provider](outputs.tf#L59) | Name of Workload Identity GitLab provider. | | + diff --git a/fast/stages-aw/5-tenants/branch-tenants.tf b/fast/stages-aw/5-tenants/branch-tenants.tf new file mode 100644 index 000000000..4edb15b83 --- /dev/null +++ b/fast/stages-aw/5-tenants/branch-tenants.tf @@ -0,0 +1,439 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +# /** +# * Copyright 2024 Google LLC +# * +# * Licensed under the Apache License, Version 2.0 (the "License"); +# * you may not use this file except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# */ + +# # tfdoc:file:description Lightweight tenant resources. + +# # TODO(ludo): add support for CI/CD + +locals { + + tenant_env_list = [ + for ten_env in var.tenant.tenant_specific_envs : { + key = "${var.tenant.name}-${ten_env}" + tenant = var.tenant.name + tenant_info = var.tenant + parent_id = var.tenants_folder_id + env = ten_env + } + ] + + tenant_envs = { + for item in local.tenant_env_list : item.key => item + } + + tenant_iam = { + for k, v in local.tenant_envs : k => [ + v.tenant_info.admin_principal, + module.tenant-self-iac-sa[k].iam_email + ] + } + + tenant_iam_members = flatten([ + for k, v in local.tenant_iam : v + ]) + + tenant_projects = { + for env_key, env_data in local.tenant_envs : env_key => { + tenant_key = env_key + display_name = "${local.project_map["tenant-projects"]}-${substr(env_data.env, 0, 1)}" + tenant_info = env_data.tenant_info + } + } + + flat_tenant_groups = flatten([ + for name, data in var.tenant.tenant_groups : [ + for role in data.roles : { + role = startswith(role, "roles/") ? role : "roles/${role}" + principal = strcontains(name, "@") ? "group:${name}" : "group:${name}@${var.organization.domain}" + } + ] + ]) + + tenant_role_map = { + for obj in local.flat_tenant_groups : obj.role => obj.principal... + } +} + +# Tenant folders (top, core, self) +module "tenant-top-folders" { + source = "../../../modules/folder" + parent = var.tenants_folder_id + name = local.project_map["tenant-projects"] + iam_by_principals = { + (var.tenant.admin_principal) = ["roles/browser"] + } + logging_sinks = { + for sink, sink_config in local.tenant_log_sinks : sink => { + bq_partitioned_table = sink_config.bq_partitioned_table + destination = sink_config.destination + description = "Tier 1 ${var.tenant.name} logging sink for C5ISR logging." + filter = sink_config.filter + include_children = sink_config.include_children + type = sink_config.type + } + } +} + +# Tenant Projects (Target: D, T, P, and IaC Core) +module "tenant-projects" { + source = "../../../modules/project" + for_each = local.tenant_projects + # Name matches: "Fake Tenant X Proj D" + name = lower(each.value.display_name) + parent = module.tenant-top-folders.id + + iam_by_principals_additive = { + (var.tenant.admin_principal) = [ + "roles/iam.serviceAccountAdmin", + "roles/iam.serviceAccountTokenCreator", + "roles/iam.workloadIdentityPoolAdmin" + ] + "serviceAccount:${var.automation.service_accounts.resman-r}" = [ + "organizations/${var.organization.id}/roles/storageViewer", + "roles/viewer" + ] + } + compute_metadata = { + google-compute-default-region = local.primary_location_gcs + google-compute-default-zone = "${local.primary_location_gcs}-b" # There always seems to be a -b zone + } + services = [ + "accesscontextmanager.googleapis.com", + "bigquery.googleapis.com", + "bigqueryreservation.googleapis.com", + "bigquerystorage.googleapis.com", + "billingbudgets.googleapis.com", + "cloudbilling.googleapis.com", + "cloudbuild.googleapis.com", + "cloudkms.googleapis.com", + "cloudresourcemanager.googleapis.com", + "container.googleapis.com", + "compute.googleapis.com", + "container.googleapis.com", + "essentialcontacts.googleapis.com", + "iam.googleapis.com", + "iamcredentials.googleapis.com", + "logging.googleapis.com", + "monitoring.googleapis.com", + "orgpolicy.googleapis.com", + "pubsub.googleapis.com", + "servicenetworking.googleapis.com", + "serviceusage.googleapis.com", + "stackdriver.googleapis.com", + "storage-component.googleapis.com", + "storage.googleapis.com", + "sts.googleapis.com" + ] +} + +module "network-project" { + source = "../../../modules/project" + count = var.tenant.deploy_network_project != null && var.tenant.deploy_network_project ? 1 : 0 + name = "${var.tenant.macom}-${var.tenant.name}-prod-networking" + parent = module.tenant-top-folders.id + + iam_by_principals_additive = { + (var.tenant.admin_principal) = [ + "roles/iam.serviceAccountAdmin", + "roles/iam.serviceAccountTokenCreator", + "roles/iam.workloadIdentityPoolAdmin" + ] + "serviceAccount:${var.automation.service_accounts.resman-r}" = [ + "organizations/${var.organization.id}/roles/storageViewer", + "roles/viewer" + ] + } + compute_metadata = { + google-compute-default-region = local.primary_location_gcs + google-compute-default-zone = "${local.primary_location_gcs}-b" + } + services = [ + "accesscontextmanager.googleapis.com", + "bigquery.googleapis.com", + "bigqueryreservation.googleapis.com", + "bigquerystorage.googleapis.com", + "billingbudgets.googleapis.com", + "cloudbilling.googleapis.com", + "cloudbuild.googleapis.com", + "cloudkms.googleapis.com", + "cloudresourcemanager.googleapis.com", + "container.googleapis.com", + "compute.googleapis.com", + "container.googleapis.com", + "essentialcontacts.googleapis.com", + "iam.googleapis.com", + "iamcredentials.googleapis.com", + "logging.googleapis.com", + "monitoring.googleapis.com", + "orgpolicy.googleapis.com", + "pubsub.googleapis.com", + "servicenetworking.googleapis.com", + "serviceusage.googleapis.com", + "stackdriver.googleapis.com", + "storage-component.googleapis.com", + "storage.googleapis.com", + "sts.googleapis.com" + ] +} + +resource "google_project_organization_policy" "trusted_image_projects" { + for_each = local.tenant_projects + project = module.tenant-projects[each.key].project_id + constraint = "compute.trustedImageProjects" + + list_policy { + inherit_from_parent = true + allow { + values = ["projects/cis-public"] + } + } +} + +# Automation Service Accounts (One per Tenant-Env) +module "tenant-sa" { + source = "../../../modules/iam-service-account" + for_each = local.tenant_projects + project_id = module.tenant-projects[each.key].project_id + name = lower("tn-${each.value.display_name}-sa") + description = "Terraform service account for tenant ${each.value.display_name}" + prefix = null +} + +module "tenant-top-folders-iam" { + source = "../../../modules/folder" + id = module.tenant-top-folders.id + folder_create = false + tag_bindings = null + iam = merge( + { + "roles/cloudasset.owner" = [module.tenant-core-sa.iam_email] + "roles/compute.xpnAdmin" = [module.tenant-core-sa.iam_email] + "roles/logging.admin" = [module.tenant-core-sa.iam_email] + "roles/resourcemanager.folderAdmin" = [module.tenant-core-sa.iam_email] + "roles/resourcemanager.projectCreator" = [module.tenant-core-sa.iam_email] + "roles/resourcemanager.tagUser" = [module.tenant-core-sa.iam_email] + }, + { + for k in var.tenant_config.top_folder_roles : + k => local.tenant_iam_members + }, + local.tenant_role_map + ) +} + +module "tenant-core-folders-iam" { + source = "../../../modules/folder" + id = module.tenant-top-folders.id + folder_create = false + iam = merge( + { + "roles/owner" = [ + module.tenant-core-sa.iam_email + ] + "roles/viewer" = local.tenant_iam_members + }, + { + for k in var.tenant_config.core_folder_roles : + k => local.tenant_iam_members + } + ) +} + +module "tenant-self-folders-iam" { + source = "../../../modules/folder" + id = module.tenant-top-folders.id + folder_create = false + iam = merge( + { + "roles/cloudasset.owner" = [module.tenant-core-sa.iam_email] + "roles/compute.xpnAdmin" = [module.tenant-core-sa.iam_email] + "roles/resourcemanager.folderAdmin" = [module.tenant-core-sa.iam_email] + "roles/resourcemanager.projectCreator" = [module.tenant-core-sa.iam_email] + "roles/resourcemanager.tagUser" = [module.tenant-core-sa.iam_email] + "roles/owner" = [module.tenant-core-sa.iam_email] + }, + { + for k in var.tenant_config.tenant_folder_roles : + k => local.tenant_iam_members + } + ) +} + +# Deny folicy for crypokeys on each project +resource "google_iam_deny_policy" "tenant_folder_kms_lockdown" { + provider = google-beta + + parent = urlencode("cloudresourcemanager.googleapis.com/${module.tenant-top-folders.id}") + + name = "lockdown-kms-administration" + display_name = "Prevent Tenant Modification of KMS" + + rules { + deny_rule { + # Block everyone... + denied_principals = ["principalSet://goog/public:all"] + + # When we need to create an exception add them here (maybe make this part of tenants.yml) + exception_principals = [ + "principal://iam.googleapis.com/projects/-/serviceAccounts/${var.automation.service_accounts.tenant}" + ] + + # From doing these specific KMS actions + denied_permissions = [ + "cloudkms.googleapis.com/cryptoKeys.setIamPolicy", + "cloudkms.googleapis.com/keyRings.setIamPolicy", + "cloudkms.googleapis.com/cryptoKeyVersions.destroy", + "cloudkms.googleapis.com/cryptoKeys.update" + ] + } + } +} + +# Tenant IaC resources (core) + +module "tenant-core-sa" { + source = "../../../modules/iam-service-account" + # for_each = local.tenant_envs + project_id = var.automation.project_id + name = lower("tn-${var.tenant.name}-prod-0") + description = "Terraform service account for tenant ${var.tenant.name}." + prefix = var.prefix + iam_project_roles = { + (var.automation.project_id) = ["roles/serviceusage.serviceUsageConsumer"] + } +} + +# module "tenant-core-gcs" { +# source = "../../../modules/gcs" +# project_id = var.automation.project_id +# name = lower("tn-${var.tenant.name}") +# prefix = null +# versioning = true +# location = local.primary_location_gcs +# storage_class = ( +# length(split("-", local.primary_location_gcs)) < 2 +# ? "MULTI_REGIONAL" +# : "REGIONAL" +# ) +# # encryption_key = module.tenant-project-keys["${var.tenant.name}-${local.primary_location_kms}"].key_ids["gcs"] +# depends_on = [module.tenant-project-keys, google_kms_crypto_key_iam_member.tenant_kms] +# iam = { +# "roles/storage.objectAdmin" = [module.tenant-core-sa.iam_email] +# } +# } + +module "tenant-self-iac-gcs-outputs" { + source = "../../../modules/gcs" + for_each = local.tenant_projects + project_id = module.tenant-projects[each.key].project_id + location = local.primary_location_gcs + storage_class = ( + length(split("-", local.primary_location_gcs)) < 2 + ? "MULTI_REGIONAL" + : "REGIONAL" + ) + name = lower("${each.value.display_name}-iac-outputs") + prefix = var.prefix + versioning = true + iam = { + "roles/storage.objectAdmin" = [module.tenant-core-sa.iam_email] + } + encryption_key = module.tenant-project-keys["${each.value.tenant_key}-${local.primary_location_kms}"].key_ids["gcs"] + depends_on = [module.tenant-project-keys, google_kms_crypto_key_iam_member.tenant_kms] + +} + +module "tenant-self-iac-gcs-states" { + source = "../../../modules/gcs" + for_each = local.tenant_projects + project_id = module.tenant-projects[each.key].project_id + location = local.primary_location_gcs + storage_class = ( + length(split("-", local.primary_location_gcs)) < 2 + ? "MULTI_REGIONAL" + : "REGIONAL" + ) + name = lower("${each.value.display_name}-iac") + prefix = var.prefix + versioning = true + encryption_key = module.tenant-project-keys["${each.key}-${local.primary_location_kms}"].key_ids["gcs"] + depends_on = [module.tenant-project-keys, google_kms_crypto_key_iam_member.tenant_kms] + + iam = { + "roles/storage.objectAdmin" = [ + module.tenant-core-sa.iam_email, + module.tenant-sa[each.key].iam_email + ] + } +} + +module "tenant-self-iac-sa" { + source = "../../../modules/iam-service-account" + for_each = local.tenant_projects + project_id = module.tenant-projects[each.key].project_id + name = lower("${each.value.display_name}-iac") + description = "Terraform automation service account." + prefix = null + iam = { + "roles/iam.serviceAccountTokenCreator" = compact([ + try(module.automation-tf-cicd-sa[each.key].iam_email, null) + ]) + } + iam_project_roles = { + (module.tenant-projects[each.key].project_id) = [ + "roles/cloudkms.admin", + "roles/iam.serviceAccountCreator", + "roles/iam.serviceAccountUser", + "roles/serviceusage.serviceUsageConsumer", + "roles/browser", + "roles/owner", + "roles/cloudbuild.builds.editor", + "roles/cloudbuild.builds.viewer", + "roles/iam.serviceAccountAdmin", + "roles/iam.serviceAccountViewer", + "roles/iam.workloadIdentityPoolAdmin", + "roles/iam.workloadIdentityPoolViewer", + "roles/source.admin", + "roles/source.reader", + "roles/storage.admin", + "roles/viewer" + ] + } + iam_storage_roles = { + (module.tenant-self-iac-gcs-outputs[each.value.tenant_key].name) = [ + "roles/storage.admin" + ] + (module.tenant-self-iac-gcs-states[each.value.tenant_key].name) = [ + "roles/storage.admin" + ] + } +} diff --git a/fast/stages-aw/5-tenants/cicd-tenants.tf b/fast/stages-aw/5-tenants/cicd-tenants.tf new file mode 100644 index 000000000..d17d3a218 --- /dev/null +++ b/fast/stages-aw/5-tenants/cicd-tenants.tf @@ -0,0 +1,78 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +resource "google_iam_workload_identity_pool" "default" { + provider = google-beta + for_each = var.cicd != null ? local.tenant_projects : {} + project = module.tenant-projects[each.key].project_id + workload_identity_pool_id = "${each.key}-cicd" +} + +resource "google_iam_workload_identity_pool_provider" "default" { + provider = google-beta + for_each = var.cicd != null ? local.tenant_projects : {} + project = module.tenant-projects[each.key].project_id + workload_identity_pool_id = ( + google_iam_workload_identity_pool.default[each.key].workload_identity_pool_id + ) + workload_identity_pool_provider_id = "${each.key}-cicd-gitlab" + attribute_condition = "attribute.project_path == '${var.cicd.gitlab_project_path}'" + attribute_mapping = { + "attribute.environment" = "assertion.environment" + "attribute.environment_protected" = "assertion.environment_protected" + "attribute.namespace_id" = "assertion.namespace_id" + "attribute.namespace_path" = "assertion.namespace_path" + "attribute.pipeline_id" = "assertion.pipeline_id" + "attribute.pipeline_source" = "assertion.pipeline_source" + "attribute.project_id" = "assertion.project_id" + "attribute.project_path" = "assertion.project_path" + "attribute.ref" = "assertion.ref" + "attribute.ref_protected" = "assertion.ref_protected" + "attribute.ref_type" = "assertion.ref_type" + "attribute.repository" = "assertion.project_path" + "attribute.sub" = "assertion.sub" + "google.subject" = "assertion.sub" + } + oidc { + # Setting an empty list configures allowed_audiences to the url of the provider + allowed_audiences = [var.cicd.gitlab_uri] + # If users don't provide an issuer_uri, we set the public one for the platform chosen. + issuer_uri = var.cicd.gitlab_uri + # OIDC JWKs in JSON String format. If no value is provided, they key is + # fetched from the `.well-known` path for the issuer_uri + jwks_json = try(trimspace(var.cicd.jwks_json), "") + } +} + +module "automation-tf-cicd-sa" { + source = "../../../modules/iam-service-account" + for_each = var.cicd != null ? local.tenant_projects : {} + project_id = module.tenant-projects[each.key].project_id + name = "${each.key}-acas-cicd" + display_name = "Terraform CI/CD GitLab service account." + iam = { + "roles/iam.workloadIdentityUser" = [ + format( + "principalSet://iam.googleapis.com/%s/attribute.repository/%s", + google_iam_workload_identity_pool.default[each.key].name, + var.cicd.gitlab_project_path + ) + ] + } + iam_project_roles = { + (module.tenant-projects[each.key].project_id) = ["roles/logging.logWriter"] + } +} \ No newline at end of file diff --git a/fast/stages-aw/5-tenants/data/allowed_apis.yaml b/fast/stages-aw/5-tenants/data/allowed_apis.yaml new file mode 100644 index 000000000..ba6d318c0 --- /dev/null +++ b/fast/stages-aw/5-tenants/data/allowed_apis.yaml @@ -0,0 +1,48 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#testing purposes API's that already match existing list in the org. +allowed_apis: + - artifactregistry.googleapis.com + - bigquery.googleapis.com + - bigquerydatatransfer.googleapis.com + - privateca.googleapis.com + - cloudbuild.googleapis.com + - composer.googleapis.com + - datafusion.googleapis.com + - dns.googleapis.com + - cloudidentity.googleapis.com + - cloudkms.googleapis.com + - logging.googleapis.com + - monitoring.googleapis.com + - run.googleapis.com + - spanner.googleapis.com + - sqladmin.googleapis.com + - storage.googleapis.com + - cloudtasks.googleapis.com + - vision.googleapis.com + - workstations.googleapis.com + - compute.googleapis.com + - dataflow.googleapis.com + - dataproc.googleapis.com + - eventarc.googleapis.com + - gkehub.googleapis.com + - container.googleapis.com + - iam.googleapis.com + - redis.googleapis.com + - pubsub.googleapis.com + - secretmanager.googleapis.com + - dlp.googleapis.com + - speech.googleapis.com + - datapipelines.googleapis.com diff --git a/fast/stages-aw/5-tenants/data/firewall_rules/dev/rules.yaml b/fast/stages-aw/5-tenants/data/firewall_rules/dev/rules.yaml new file mode 100644 index 000000000..3ed0979a6 --- /dev/null +++ b/fast/stages-aw/5-tenants/data/firewall_rules/dev/rules.yaml @@ -0,0 +1,18 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# skip boilerplate check +--- +# Terraform will be unable to decode this file if it does not contain valid YAML +# You can retain `---` (start of the document) to indicate an empty document. \ No newline at end of file diff --git a/fast/stages-aw/5-tenants/data/firewall_rules/prod/rules.yaml b/fast/stages-aw/5-tenants/data/firewall_rules/prod/rules.yaml new file mode 100644 index 000000000..3ed0979a6 --- /dev/null +++ b/fast/stages-aw/5-tenants/data/firewall_rules/prod/rules.yaml @@ -0,0 +1,18 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# skip boilerplate check +--- +# Terraform will be unable to decode this file if it does not contain valid YAML +# You can retain `---` (start of the document) to indicate an empty document. \ No newline at end of file diff --git a/fast/stages-aw/5-tenants/data/firewall_rules/test/rules.yaml b/fast/stages-aw/5-tenants/data/firewall_rules/test/rules.yaml new file mode 100644 index 000000000..3ed0979a6 --- /dev/null +++ b/fast/stages-aw/5-tenants/data/firewall_rules/test/rules.yaml @@ -0,0 +1,18 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# skip boilerplate check +--- +# Terraform will be unable to decode this file if it does not contain valid YAML +# You can retain `---` (start of the document) to indicate an empty document. \ No newline at end of file diff --git a/fast/stages-aw/5-tenants/data/lz_exceptions.yaml b/fast/stages-aw/5-tenants/data/lz_exceptions.yaml new file mode 100644 index 000000000..3e801ebce --- /dev/null +++ b/fast/stages-aw/5-tenants/data/lz_exceptions.yaml @@ -0,0 +1,43 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# lz_exceptions.yaml +# Combined list of Category 1 and Category 2 API exceptions for LZ Infrastructure +# These APIs are authorized for use in Core LZ projects only. +COA2: +# Category 1: IL5 Authorized / compliance Catalog Update Pending +#category_1_exceptions: + - accesscontextmanager.googleapis.com + - cloudasset.googleapis.com + - cloudbilling.googleapis.com + - networkconnectivity.googleapis.com + - servicedirectory.googleapis.com +# Category 2: Management/Enabling APIs Not Listed in compliance Catalog +# category_2_exceptions: + - assuredworkloads.googleapis.com + - bigqueryreservation.googleapis.com + - bigquerystorage.googleapis.com + - billingbudgets.googleapis.com + - cloudquotas.googleapis.com + - cloudresourcemanager.googleapis.com + - essentialcontacts.googleapis.com + - iamcredentials.googleapis.com + - iap.googleapis.com + - networksecurity.googleapis.com + - orgpolicy.googleapis.com + - servicenetworking.googleapis.com + - serviceusage.googleapis.com + - stackdriver.googleapis.com + - storage-component.googleapis.com + - sts.googleapis.com \ No newline at end of file diff --git a/fast/stages-aw/5-tenants/data/subnet_plan.yaml b/fast/stages-aw/5-tenants/data/subnet_plan.yaml new file mode 100644 index 000000000..173c89ae6 --- /dev/null +++ b/fast/stages-aw/5-tenants/data/subnet_plan.yaml @@ -0,0 +1,19 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +tenant_environments_subnets: + dev: "10.88.0.0/14" + test: "10.92.0.0/14" + prod: "10.96.0.0/14" diff --git a/fast/stages-aw/5-tenants/kms.tf b/fast/stages-aw/5-tenants/kms.tf new file mode 100644 index 000000000..e9a9cb597 --- /dev/null +++ b/fast/stages-aw/5-tenants/kms.tf @@ -0,0 +1,78 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +locals { + # Generating a map for each environment (d,t,p) and each location for kms + tenant_envs_kms = { + for pairing in setproduct(keys(local.tenant_projects), var.locations.kms) : + "${pairing[0]}-${pairing[1]}" => { + project_key = pairing[0] + location = pairing[1] + project_id = module.tenant-projects[pairing[0]].project_id + sa_email = module.tenant-sa[pairing[0]].iam_email + } + } +} + +module "tenant-project-keys" { + source = "../../../modules/kms" + for_each = local.tenant_envs_kms + project_id = each.value.project_id + iam = { + "roles/cloudkms.cryptoKeyEncrypterDecrypter" = [ + module.tenant-core-sa.iam_email, + "serviceAccount:service-${module.tenant-projects[each.value.project_key].number}@gs-project-accounts.iam.gserviceaccount.com" + ] + } + keyring = { + name = "${each.value.project_key}-keyring-${each.value.location}" + location = each.value.location + } + keys = { + gcs = { + purpose = "ENCRYPT_DECRYPT" + labels = { service = "gcs" } + rotation_period = "7776000s" # CIS Compliance Benchmark 1.10 + version_template = { + algorithm = "GOOGLE_SYMMETRIC_ENCRYPTION" + protection_level = "HSM" + } + }, + default = { + purpose = "ENCRYPT_DECRYPT" + labels = { service = "iac-core" } + rotation_period = "7776000s" + version_template = { + algorithm = "GOOGLE_SYMMETRIC_ENCRYPTION" + protection_level = "HSM" + } + } + } +} + +resource "google_kms_crypto_key_iam_member" "resman_bootstrap_kms" { + for_each = local.tenant_envs_kms + crypto_key_id = "projects/${var.automation.project_id}/locations/${each.value.location}/keyRings/gcs-${each.value.location}/cryptoKeys/gcs" + member = each.value.sa_email + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" +} + +resource "google_kms_crypto_key_iam_member" "tenant_kms" { + for_each = local.tenant_envs_kms + crypto_key_id = module.tenant-project-keys[each.key].key_ids["gcs"] + member = each.value.sa_email + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" +} diff --git a/fast/stages-aw/5-tenants/log-metric-alerts.tf b/fast/stages-aw/5-tenants/log-metric-alerts.tf new file mode 100644 index 000000000..a819d8d58 --- /dev/null +++ b/fast/stages-aw/5-tenants/log-metric-alerts.tf @@ -0,0 +1,59 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +# CIS Compliance Benchmark 2.4 +# CIS Compliance Benchmark 2.5 +# CIS Compliance Benchmark 2.6 +# CIS Compliance Benchmark 2.7 +# CIS Compliance Benchmark 2.8 +# CIS Compliance Benchmark 2.9 +# CIS Compliance Benchmark 2.10 +# CIS Compliance Benchmark 2.11 + +# module "core_log_metrics" { +# source = "../../../modules/cis-log-metrics" + +# for_each = module.tenant-projects +# project = each.value.id +# } + +module "main_log_metrics" { + source = "../../../modules/cis-log-metrics" + + for_each = module.tenant-projects + project = each.value.id +} + +# Alerts require log-metrics to be configure +resource "time_sleep" "resman_wait_10_seconds" { + depends_on = [module.main_log_metrics] + create_duration = "10s" +} + +module "env_log_alerts" { + source = "../../../modules/cis-log-alerts" + + for_each = module.tenant-projects + project = each.value.project_id + combiner = "OR" + duration = "60s" + comparison = "COMPARISON_GT" + alignment_period = "60s" + per_series_aligner = "ALIGN_RATE" + alert_email = var.alert_email + + depends_on = [time_sleep.resman_wait_10_seconds] +} diff --git a/fast/stages-aw/5-tenants/main.tf b/fast/stages-aw/5-tenants/main.tf new file mode 100644 index 000000000..faf95c2cb --- /dev/null +++ b/fast/stages-aw/5-tenants/main.tf @@ -0,0 +1,58 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +locals { + primary_location_gcs = element(var.locations.gcs, 0) + primary_location_kms = element(var.locations.kms, 0) + primary_location_pubsub = try(element(var.locations.pubsub, 0), null) + + project_config_yaml = yamldecode(file("../../../project-config.yml")) + project_map = { + for p in local.project_config_yaml.projects : p.name => + replace(replace(replace(p.project_name, "", lower(var.tenant.name)), "", lower(substr(split(".", var.organization.domain)[0], 0, 7))), "", lower(var.tenant.macom)) + } + + tenant_subnets_map_of_maps = { + for pairing in setproduct(values(local.tenant_accounts), [var.regions.primary]) : "${pairing[0].main_project}-${pairing[1]}" => { + "project" = pairing[0].main_project, + "tenant" = pairing[0].tenant, + "admin_principal" = pairing[0].admin_principal + "region" = pairing[1], + "env" = pairing[0].env + "tenant_key" = "${pairing[0].env}-${pairing[0].tenant}" + } + } + + allowed_api_data = yamldecode(file("./data/allowed_apis.yaml")) + lz_data = yamldecode(file("./data/lz_exceptions.yaml")) + + coa2_allowed_apis = concat( + local.allowed_api_data.allowed_apis, + local.lz_data.COA2 + ) +} + +resource "google_project_organization_policy" "shared_svcs_project_policy" { + for_each = local.tenant_subnets_map_of_maps + project = each.value.project + constraint = "constraints/gcp.restrictServiceUsage" + + list_policy { + allow { + values = local.coa2_allowed_apis + } + } +} \ No newline at end of file diff --git a/fast/stages-aw/5-tenants/organization-iam.tf b/fast/stages-aw/5-tenants/organization-iam.tf new file mode 100644 index 000000000..b01863d21 --- /dev/null +++ b/fast/stages-aw/5-tenants/organization-iam.tf @@ -0,0 +1,38 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# tfdoc:file:description Organization-level IAM bindings locals. + +locals { + iam_bindings_additive = merge( + # lightweight tenant roles + var.tenant.organization != null ? { + "oslogin_ext_user-tenant_${var.tenant.name}" = { + member = "domain:${var.tenant.organization.domain}" + role = "roles/compute.osLoginExternalUser" + }, + "org-viewer-tenant_${var.tenant.name}_domain" = { + member = "domain:${var.tenant.organization.domain}" + role = "roles/compute.osLoginExternalUser" + } + } : {}, + { + "org-viewer-tenant_${var.tenant.name}_admin" = { + member = var.tenant.admin_principal + role = "roles/resourcemanager.organizationViewer" + } + } + ) +} diff --git a/fast/stages-aw/1-resman/organization.tf b/fast/stages-aw/5-tenants/organization.tf similarity index 96% rename from fast/stages-aw/1-resman/organization.tf rename to fast/stages-aw/5-tenants/organization.tf index f016d78c7..b45ddd344 100644 --- a/fast/stages-aw/1-resman/organization.tf +++ b/fast/stages-aw/5-tenants/organization.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Organization policies. module "organization" { diff --git a/fast/stages-aw/1-resman/outputs-tenants.tf b/fast/stages-aw/5-tenants/outputs-tenants.tf similarity index 52% rename from fast/stages-aw/1-resman/outputs-tenants.tf rename to fast/stages-aw/5-tenants/outputs-tenants.tf index d1105d38e..4bf0936c7 100644 --- a/fast/stages-aw/1-resman/outputs-tenants.tf +++ b/fast/stages-aw/5-tenants/outputs-tenants.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,45 +13,50 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { - tenant_core_providers = { - for k, v in local.tenant_envs : - k => templatefile("${path.module}/templates/providers.tf.tpl", { - bucket = module.tenant-core-gcs[k].name - name = k - sa = module.tenant-core-sa[k].email - backend_extra = null - bootstrap_project = null - }) + tenant_accounts = { + for k, v in local.tenant_envs : k => { + main_project = module.tenant-projects[k].project_id + env = v.env + tenant = v.tenant + admin_principal = var.tenant.admin_principal + } } + # tenant_core_providers = { + # for k, v in local.tenant_envs : + # k => templatefile("${path.module}/templates/providers.tf.tpl", { + # bucket = module.tenant-core-gcs.name + # name = k + # sa = module.tenant-core-sa.email + # prefix = null + # backend_extra = null + # }) + # } tenant_self_providers = { for k, v in local.tenant_envs : k => templatefile("${path.module}/templates/providers.tf.tpl", { - bucket = module.tenant-self-iac-gcs-states[k].name - name = k - sa = module.tenant-self-iac-sa[k].email - backend_extra = null - bootstrap_project = null + bucket = module.tenant-self-iac-gcs-states[k].name + name = k + sa = module.tenant-self-iac-sa[k].email + prefix = null + backend_extra = null }) } tenant_tfvars = { for k, v in local.tenant_envs : k => merge(v, { automation = { - core_bucket = module.tenant-core-gcs[k].name - core_sa = module.tenant-core-sa[k].email + # core_bucket = module.tenant-core-gcs.name + core_sa = module.tenant-core-sa.email outputs_bucket = module.tenant-self-iac-gcs-outputs[k].name - project_id = module.tenant-self-iac-projects[k].project_id sa = module.tenant-self-iac-sa[k].email state_bucket = module.tenant-self-iac-gcs-states[k].name } core = { - billing_account = var.billing_account - organization = var.organization - main_project = module.tenant-self-main-projects[k].id + organization = var.organization + # main_project = module.tenant-self-main-projects.id } folder_ids = { - self = module.tenant-top-folders[k].id + self = module.tenant-top-folders.id } shortname = k prefix = "${var.prefix}-${k}" @@ -60,7 +65,6 @@ locals { } # core tfvars and providers - resource "local_file" "tenant-core-tfvars" { for_each = var.outputs_location == null ? {} : local.tenant_tfvars file_permission = "0644" @@ -70,16 +74,16 @@ resource "local_file" "tenant-core-tfvars" { content = jsonencode(each.value) } -resource "local_file" "tenant-core-providers" { - for_each = ( - var.outputs_location == null ? {} : local.tenant_core_providers - ) - file_permission = "0644" - filename = ( - "${pathexpand(var.outputs_location)}/providers/tenant/${each.key}-providers.tf" - ) - content = each.value -} +# resource "local_file" "tenant-core-providers" { +# for_each = ( +# var.outputs_location == null ? {} : local.tenant_core_providers +# ) +# file_permission = "0644" +# filename = ( +# "${pathexpand(var.outputs_location)}/providers/tenant/${each.key}-providers.tf" +# ) +# content = each.value +# } resource "google_storage_bucket_object" "tenant-core-tfvars" { for_each = local.tenant_tfvars @@ -88,15 +92,14 @@ resource "google_storage_bucket_object" "tenant-core-tfvars" { content = jsonencode(each.value) } -resource "google_storage_bucket_object" "tenant-core-providers" { - for_each = local.tenant_core_providers - bucket = var.automation.outputs_bucket - name = "providers/tenant/${each.key}-providers.tf" - content = each.value -} +# resource "google_storage_bucket_object" "tenant-core-providers" { +# for_each = local.tenant_core_providers +# bucket = var.automation.outputs_bucket +# name = "providers/tenant/${each.key}-providers.tf" +# content = each.value +# } # tenant tfvars and providers - resource "local_file" "tenant-self-providers" { for_each = ( var.outputs_location == null ? {} : local.tenant_self_providers @@ -109,15 +112,15 @@ resource "local_file" "tenant-self-providers" { } resource "google_storage_bucket_object" "tenant-self-tfvars" { - for_each = local.tenant_tfvars - bucket = module.tenant-self-iac-gcs-outputs[each.key].name + for_each = module.tenant-projects + bucket = module.tenant-self-iac-gcs-outputs[each.key].id name = "tfvars/${each.key}.auto.tfvars.json" content = jsonencode(each.value) } -resource "google_storage_bucket_object" "tenant-self-providers" { - for_each = local.tenant_self_providers - bucket = module.tenant-self-iac-gcs-outputs[each.key].name - name = "providers/${each.key}-providers.tf" - content = each.value -} \ No newline at end of file +# resource "google_storage_bucket_object" "tenant-self-providers" { +# for_each = local.tenant_self_providers +# bucket = module.tenant-self-iac-gcs-outputs.name +# name = "providers/${each.key}-providers.tf" +# content = each.value +# } \ No newline at end of file diff --git a/fast/stages-aw/5-tenants/outputs.tf b/fast/stages-aw/5-tenants/outputs.tf new file mode 100644 index 000000000..e7f16fb93 --- /dev/null +++ b/fast/stages-aw/5-tenants/outputs.tf @@ -0,0 +1,83 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +output "gcs_iac_bucket" { + description = "IaC buckets." + value = { + for key, gcs in module.tenant-self-iac-gcs-states : key => { + id = gcs.bucket.id + name = gcs.bucket.name + } + } +} + +output "projects" { + description = "Tenant projects." + value = { + for key, prj in module.tenant-projects : key => { + id = prj.id + name = prj.name + } + } +} + +output "service_accounts_automation" { + description = "Service accounts for automation." + value = { + for key, sa in module.tenant-self-iac-sa : key => { + email = sa.email + id = sa.id + name = sa.name + } + } +} + +output "service_accounts_cicd" { + description = "Service accounts for CICD." + value = { + for key, sa in module.automation-tf-cicd-sa : key => { + email = sa.email + id = sa.id + name = sa.name + } + } +} + +output "vpc_networks" { + description = "Tenant VPC network." + value = { + for key, vpc in module.tenant-vpc : key => { + id = vpc.id + name = vpc.name + subnets = { + for skey, subnet in vpc.subnets : skey => { + id = subnet.id + name = subnet.name + } + } + } + } +} + +output "workload_identity_provider" { + description = "Name of Workload Identity GitLab provider." + value = { + for key, prv in google_iam_workload_identity_pool_provider.default : key => { + id = prv.id + name = prv.name + } + } +} \ No newline at end of file diff --git a/fast/stages-aw/5-tenants/spokes.tf b/fast/stages-aw/5-tenants/spokes.tf new file mode 100644 index 000000000..71882b7ef --- /dev/null +++ b/fast/stages-aw/5-tenants/spokes.tf @@ -0,0 +1,64 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# tfdoc:file:description VPC and spoke creation. + +# VPC network for each tenant environment +module "tenant-vpc" { + source = "../../../modules/net-vpc" + for_each = local.tenant_subnets_map_of_maps + project_id = each.value.project + name = "${each.value.tenant_key}-vpc" + mtu = 1500 + delete_default_routes_on_create = true + + subnets = [ + { + name = "${each.value.tenant_key}-${each.value.region}-subnet" + ip_cidr_range = var.tenant.spoke_subnets[each.value.env] + region = each.value.region + } + ] + dns_policy = { + inbound = true + logging = true + } + create_googleapis_routes = null + +} + +# NCC spoke for each tenant environment +resource "google_network_connectivity_spoke" "tenant_spoke" { + for_each = local.tenant_subnets_map_of_maps + name = "${each.value.env}-${each.value.tenant}-spoke" + hub = var.hub_id + location = "global" + project = each.value.project + group = var.edge_group_id + linked_vpc_network { + uri = module.tenant-vpc[each.key].self_link + } +} + +# Default route for each tenant environment VPC +resource "google_compute_route" "tenant_default_route" { + for_each = local.tenant_subnets_map_of_maps + name = "${each.value.tenant_key}-default-route" + project = each.value.project + dest_range = "0.0.0.0/0" + network = module.tenant-vpc[each.key].self_link + next_hop_ilb = var.ilb_ips["transit"] + priority = 100 +} diff --git a/fast/stages-aw/5-tenants/templates/providers.tf.tpl b/fast/stages-aw/5-tenants/templates/providers.tf.tpl new file mode 100644 index 000000000..210bd5ea6 --- /dev/null +++ b/fast/stages-aw/5-tenants/templates/providers.tf.tpl @@ -0,0 +1,35 @@ +/** + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +terraform { + backend "gcs" { + %{~ if bucket != null && bucket != "" ~} + bucket = "${bucket}" + %{~ endif ~} + impersonate_service_account = "${sa}" + %{~ if backend_extra != null ~} + ${indent(4, backend_extra)} + %{~ endif ~} + } +} +provider "google" { + impersonate_service_account = "${sa}" +} +provider "google-beta" { + impersonate_service_account = "${sa}" +} + +# end provider.tf for ${name} diff --git a/fast/stages-aw/5-tenants/tenant-log-sinks.tf b/fast/stages-aw/5-tenants/tenant-log-sinks.tf new file mode 100644 index 000000000..df8b6e4f8 --- /dev/null +++ b/fast/stages-aw/5-tenants/tenant-log-sinks.tf @@ -0,0 +1,138 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# tfdoc:file:description Tenant logging sinks for organization-level log routing. + +# Data source to get bootstrap stage outputs +# data "terraform_remote_state" "bootstrap" { +# backend = "gcs" +# config = { +# bucket = var.automation.outputs_bucket +# prefix = "terraform/bootstrap/state" +# } +# } + +locals { + tenant_log_buckets = { + for loc in toset(var.locations.logging) : + "${var.prefix}-${var.tenant.name}-audit-logs-${loc}" => { + tenant = var.tenant.name + filter = "" # Empty filter captures all logs for the tenant + location = loc + description = "Centralized audit logs for tenant ${var.tenant.name} - captures all activity including admin, data access, system events, security events, and policy violations" + } + } + + tenant_pubsub_topics = { + for loc in toset(var.locations.pubsub) : + "${var.prefix}-${var.tenant.name}-tier-1-${loc}" => { + tenant = var.tenant.name + filter = "" + location = loc + description = "Centralized audit pubsub topic for tenant ${var.tenant.name} - captures all activity including admin, data access, system events, security events, and policy violations" + } + } + + log_sink_filter = flatten([ + for folder_id in lookup(local.tenant_folder_mapping, var.tenant.name, []) : [ + # Complete folder capture + "(resource.type=\"folder\" AND resource.labels.folder_id=\"${replace(folder_id, "folders/", "")}\")", + "(protoPayload.resourceName:\"${folder_id}\" OR protoPayload.resourceName:\"${folder_id}/*\")", + + # Complete project capture under tenant folders + "(resource.type=\"project\" AND resource.labels.parent_id=\"${replace(folder_id, "folders/", "")}\")", + + # All tenant project activities + "(resource.labels.project_id:\"${var.prefix}-${var.tenant.name}-*\")", + "(protoPayload.resourceName:\"projects/${var.prefix}-${var.tenant.name}-*\")", + "(protoPayload.resourceName:\"projects/${var.prefix}-${var.tenant.name}-*/*\")" + ] + ]) + + pubsub_log_tier_filters = { + tier_1 = join(" OR ", [ + "protoPayload.serviceName=\"cloudaudit.googleapis.com\"", + "resource.type=\"gce_subnetwork\" AND logName:\"logs/compute.googleapis.com%2Fvpc_flows\"" + ]) + } + + # Create mapping of tenant names to their folder IDs + tenant_folder_mapping = { + for k, v in local.tenant_envs : v.tenant => module.tenant-top-folders.id... + } + + tenant_log_bucket_sink = { + for bucket, config in local.tenant_log_buckets : bucket => { + bq_partitioned_table = false + destination = module.tenant-log-buckets[bucket].id + filter = join(" OR ", local.log_sink_filter) + include_children = true + type = "logging" + } + } + + tenant_pubsub_sink = { + for pubsub, config in local.tenant_pubsub_topics : pubsub => { + bq_partitioned_table = false + destination = module.tenant-pubsub-topic[pubsub].id + filter = local.pubsub_log_tier_filters.tier_1 + include_children = true + type = "pubsub" + } + } + + tenant_log_sinks = merge( + local.tenant_log_bucket_sink, + local.tenant_pubsub_sink + ) +} + +module "tenant-log-buckets" { + source = "../../../modules/logging-bucket" + for_each = local.tenant_log_buckets + name = "${each.key}-log-bucket" + parent_type = "project" + parent = var.logging.project_id + location = each.value.location + retention = 30 + description = each.value.description + log_analytics = { enable = true } + kms_key_name = "projects/${var.logging.project_id}/locations/${each.value.location}/keyRings/logging-${each.value.location}/cryptoKeys/log-sink" +} + +module "tenant-pubsub-topic" { + source = "../../../modules/pubsub" + for_each = local.tenant_pubsub_topics + project_id = var.logging.project_id + name = "${each.key}-pubsub-topic" + regions = [each.value.location] + kms_key = "projects/${var.logging.project_id}/locations/${local.primary_location_pubsub}/keyRings/logging-${local.primary_location_pubsub}/cryptoKeys/pubsub" + iam_bindings_additive = { + "roles/pubsub.subscriber" = { + role = "roles/pubsub.subscriber" + member = "serviceAccount:${var.logging.service_accounts.c5isr-pubsub}" + } + } + subscriptions = { + "${each.key}-pull-sub" = { + message_retention_duration = "604800s" + expiration_policy_ttl = "" + ack_deadline_seconds = 60 + } + } + depends_on = [ + module.tenant-project-keys + ] +} diff --git a/fast/stages-aw/5-tenants/terraform.tfvars.sample b/fast/stages-aw/5-tenants/terraform.tfvars.sample new file mode 100644 index 000000000..8a7fd3229 --- /dev/null +++ b/fast/stages-aw/5-tenants/terraform.tfvars.sample @@ -0,0 +1,43 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +tenant = { + name = "ten_name" + admin_principal = "group:gcp-devops@group:gcp-devops@sub.domain.org" + size = "SIZE" + + locations = { + gcs = "us-east4" + kms = "us-east4" + } + + tenant_specific_envs = ["dev", "test", "prod"] + + spoke_subnets = { + dev = "0.0.0.0/32" + test = "0.0.0.0/32" + prod = "0.0.0.0/32" + } + tenant_groups = { + "tenant-admin" = { + "roles" = { + "editor", + "storage.admin", + "compute.instanceAdminv1" + } + } + } +} diff --git a/fast/stages-aw/5-tenants/variables.tf b/fast/stages-aw/5-tenants/variables.tf new file mode 100644 index 000000000..1a366aaea --- /dev/null +++ b/fast/stages-aw/5-tenants/variables.tf @@ -0,0 +1,207 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# defaults for variables marked with global tfdoc annotations, can be set via +# the tfvars file generated in stage 00 and stored in its outputs + +variable "alert_email" { + description = "Email to receive log alerts." + type = string +} + +variable "automation" { + # tfdoc:variable:source 1-assured-workload + description = "Automation resources created by the bootstrap stage." + type = object({ + inputs_bucket = string + outputs_bucket = string + project_id = string + project_number = string + federated_identity_pool = string + federated_identity_providers = map(object({ + audiences = list(string) + issuer = string + issuer_uri = string + name = string + principal_branch = string + principal_repo = string + })) + service_accounts = object({ + resman = string + resman-r = string + tenant = string + }) + tenant_bucket = string + }) +} + +variable "cicd" { + description = "Optional CICD variables to add Workload Identity Federation and a GitLab provider." + type = object({ + gitlab_project_path = string + gitlab_uri = string + jwks_json = optional(string) + }) +} + +variable "edge_group_id" { + description = "ID of the edge group created in stage 3 for the spoke to join." + type = string +} + +variable "hub_id" { + description = "ID of the hub created in stage 3 so we can add spokes to it." + type = string +} + +variable "ilb_ips" { + description = "ILB IP addresses for each environment." + type = object({ + transit = string + }) +} + + +variable "locations" { + # tfdoc:variable:source 1-assured-workload + description = "Optional locations for GCS, BigQuery, and logging buckets created here." + type = object({ + bq = string + gcs = list(string) + logging = list(string) + pubsub = list(string) + kms = list(string) + }) + default = { + bq = "US" + gcs = ["US"] + kms = ["nam9"] + logging = ["us"] + pubsub = [] + } + nullable = false +} + +variable "logging" { + # tfdoc:variables:source 1-assured-workload + description = "Logging resources created by the bootstrap stage." + type = object({ + project_id = string + project_number = string + writer_identities = optional(map(string)) + pubsub_topics = optional(map(string)) + service_accounts = object({ + c5isr-pubsub = string + }) + }) +} + +variable "organization" { + # tfdoc:variable:source 1-assured-workload + description = "Organization details." + type = object({ + domain = string + id = number + customer_id = string + }) +} + +variable "outputs_location" { + description = "Enable writing provider, tfvars and CI/CD workflow files to local filesystem. Leave null to disable." + type = string + default = null +} + +variable "prefix" { + # tfdoc:variable:source 1-assured-workload + description = "Prefix used for resources that need unique names. Use 7 characters or less." + type = string + + validation { + condition = try(length(var.prefix), 0) <= 10 + error_message = "Use a maximum of 7 characters for prefix." + } +} + +variable "regions" { + description = "Region definitions." + type = object({ + primary = string + secondary = list(string) + }) + default = { + primary = "us-east4" + secondary = [""] + } +} + +variable "tenant" { + description = "Lightweight tenant definition for a single environment." + type = object({ + name = string + macom = string + admin_principal = string + size = string + tenant_specific_envs = list(string) + compliance = optional(object({ + regime = string + location = string + })) + locations = optional(object({ + gcs = string + kms = string + })) + organization = optional(object({ + customer_id = string + domain = string + id = number + })) + spoke_subnets = object({ + dev = string + test = string + prod = string + }) + tenant_groups = optional(map(object({ + roles = list(string) + }))) + deploy_network_project = optional(bool) + }) + nullable = false + + validation { + condition = length(var.tenant.name) < 8 + error_message = "Tenant keys must be less than 8 characters." + } + validation { + condition = length(var.tenant.macom) < 8 + error_message = "Macom name must be less than 8 characters." + } +} + +variable "tenant_config" { + description = "Lightweight tenants shared configuration. Roles will be assigned to tenant admin group and service accounts." + type = object({ + core_folder_roles = optional(list(string), []) + tenant_folder_roles = optional(list(string), []) + top_folder_roles = optional(list(string), []) + }) + nullable = false + default = {} +} + +variable "tenants_folder_id" { + description = "The Overarching Tenant Folder inside of Dev." + type = string +} diff --git a/fast/stages-aw/README.md b/fast/stages-aw/README.md index 0f4f58ba0..18f8c89e6 100644 --- a/fast/stages-aw/README.md +++ b/fast/stages-aw/README.md @@ -1,3 +1,19 @@ + + # FAST Stages Each of the git folders contained here is a separate "stage", or Terraform root module. @@ -9,7 +25,7 @@ When combined together, each stage is designed to leverage the previous stage's This has two important consequences - any stage can be swapped out and replaced by different code as long as it respects the contract by providing a predefined set of outputs and optionally accepting a predefined set of variables -- data flow between stages can be partially automated (see [stage 00 documentation on output files](./0-bootstrap/README.md#output-files-and-cross-stage-variables)), reducing the effort and pain required to compile variables by hand +- data flow between stages can be partially automated (see [stage 00 documentation on output files](./1-assured-workload/README.md#output-files-and-cross-stage-variables)), reducing the effort and pain required to compile variables by hand One important assumption is that the flow of data is always forward looking, so no stage needs to depend on outputs generated further down the chain. This greatly simplifies both the logic and the implementation, and allows stages to be effectively independent. @@ -17,28 +33,43 @@ To achieve this, we rely on specific GCP functionality like [delegated role gran Refer to each stage's documentation for a detailed description of its purpose, the architectural choices made in its design, and how it can be configured and wired together to terraform a whole GCP organization. The following is a brief overview of each stage. -To destroy a previous FAST deployment follow the instructions detailed in [cleanup](CLEANUP.md). +To destroy a previous FAST deployment follow the instructions detailed in [Google Cloud Deletion Guide](https://docs.google.com/document/d/18Bs1XgBOi-XSFASZfOlU6F_VBmDq6mUau47mJ0hYesk/edit?tab=t.vut5ezfgtd6j) ## Fast Stages Diagram -![Stellar Engine Fast Stages](../stages.png) +![Stellar Engine Landing Zone Fast Stages](../stages.png) -## Organization (0 and 1) +## Organization (0, 1 and 2) -- [Bootstrap](0-bootstrap/README.md) - Enables critical Google Cloud Organization level functionality, including the provisioning of a top-level Assured Workloads Google Cloud Folder, that depends on broad permissions. It has two primary purposes. The first is to bootstrap the resources needed for automation of this and the following stages (service accounts, GCS buckets). Secondly, it applies the minimum amount of configuration needed at the Google Cloud Organization level to avoid the need of broad permissions later on, and to implement from the start critical auditing or security features like organization policies, sinks and exports.\ +- [Organization Bootstrap](0-organization-bootstrap/README.md) + Enables critical Google Cloud Organization level functionality. It has two primary purposes. The first is to bootstrap the resources needed for automation of this and the following stages (service accounts, GCS buckets). Secondly, it applies the minimum amount of configuration needed at the Google Cloud Organization level to avoid the need of broad permissions later on, and to implement from the start critical auditing or security features like organization policies, sinks and exports.\ Exports: automation variables, organization-level custom roles -- [Resource Management](1-resman/README.md) +- [Assured Workload](1-assured-workload/README.md) + Enables the provisioning of a top-level Assured Workloads Google Cloud Folder, that depends on broad permissions. Stages the necessary resources for each Assured Workload that will be deployed into the Google Cloud Organization. +- [Resource Management](2-resman/README.md) Creates the base resource hierarchy (Google Cloud Folders) and the automation resources that will be required later to delegate deployment of each part of the hierarchy to separate stages. This stage also configures resource management tags used in scoping specific IAM roles on the resource hierarchy. Note that the project factory takes place in this stage to ensure consistency with the architecture established by Cloud One. To add, modify, or delete users, please modify the tfvars file in this stage and rerun the terraform. -## Networking (2) +## Networking (3) -- [IL5 Compliant](2-networking-b-il5-ngfw/README.md) -- [FedRAMP High Compliant](2-networking-a-fedramp-high/README.md) +- [IL5 Compliant](3-networking/README.md) Manages centralized network resources in a separate stage, and is typically owned by the networking team. This stage implements a hub-and-spoke design, and includes connectivity via VPN to on-premises, and YAML-based factories for firewall rules (hierarchical and VPC-level) and subnets. Currently, two networking options (IL5 and FedRAMP High Compliant) are available, with a third lightweight networking option currently being developed, with recommended usage in IL2 and FedRAMP Moderate environments. -## Security (3) +## Security (4) -- [Security](3-security/README.md) +- [Security](4-security/README.md) This stage provides an added layer of security to deployment. To further secure your environment, please see the [Security Best Practices Guide](https://docs.google.com/document/d/1uv62Fqg73r9oJNP-NPZebpzoBom8rOgLoHkiMZPutbo/edit?tab=t.0#heading=h.gjdgxs). You will need to request access if you do not already have it. + + +### Optional Shared Services + +In addition to the core 6-stage lifecycle (Stages 0–5), `fast/stages-aw/shared-services` contains **optional, standalone enterprise services** that can be selectively deployed based on organizational requirements: + +- **`acas` (Optional)**: Assured Compliance Assessment Solution (Tenable vulnerability scanners for defense/federal compliance). +- **`bcap` (Optional)**: Boundary Cloud Access Point for connecting to NIPRNet or dedicated enterprise boundary networks. +- **`ad` (Optional)**: Windows Active Directory Domain Controllers. +- **`dns` (Optional)**: Centralized enterprise DNS forwarding. +- **`ntp` (Optional)**: Internal Network Time Protocol servers. +- **`smtp` (Optional)**: Internal SMTP mail relays. + +*These services are completely optional and decoupled from the baseline landing zone deployment.* diff --git a/fast/stages-aw/shared-services/README.md b/fast/stages-aw/shared-services/README.md new file mode 100644 index 000000000..d12affe97 --- /dev/null +++ b/fast/stages-aw/shared-services/README.md @@ -0,0 +1,44 @@ + + +# Optional Shared Services Stages + +The stages contained in this directory (`shared-services/`) provide **optional, modular enterprise services** that can be selectively deployed based on an organization's specific compliance, security, and networking requirements. + +> [!NOTE] +> **None of these stages are required** to deploy or operate the baseline `stellar-engine` landing zone. Stages 0 through 5 form the core landing zone infrastructure. The shared services stages below can be deployed independently as needed. + +--- + +## Available Optional Services + +| Service Stage | Purpose & Description | Typical Use Case | +| :--- | :--- | :--- | +| **`acas`** | **Assured Compliance Assessment Solution**
Provisions Tenable SecurityCenter and Nessus vulnerability scanners on GCP. | Mandated for DoD/defense compliance regimes requiring centralized vulnerability and compliance scanning. | +| **`bcap`** | **Boundary Cloud Access Point**
Provisions high-availability boundary routing and inspection infrastructure. | Used for connecting the landing zone to dedicated external boundary networks (such as NIPRNet, DISA BCAP, or private enterprise boundary access points). | +| **`ad`** | **Active Directory Domain Controllers**
Deploys high-availability Windows Server Active Directory DCs in dedicated shared VPC subnets. | Organizations requiring native on-cloud Active Directory domain services and Kerberos/LDAP authentication. | +| **`dns`** | **Enterprise DNS Forwarding**
Configures centralized DNS forwarding rules and inbound/outbound server policies. | Environments integrating GCP Cloud DNS with on-premises or external enterprise DNS resolvers. | +| **`ntp`** | **Network Time Protocol (NTP) Servers**
Deploys dedicated internal Chrony/NTP servers for time synchronization. | Air-gapped or restricted networks requiring authenticated, centralized internal time synchronization. | +| **`smtp`** | **Internal SMTP Relay**
Deploys postfix mail relay instances for internal alert and notification delivery. | Internal workloads and appliances requiring local mail relay without direct public internet egress. | + +--- + +## Deployment Model + +All shared services stages are decoupled from the core landing zone stages (Stages 0–5). To deploy any shared service: +1. Ensure Stages 0 through 3 (Networking & Security) are deployed. +2. Navigate to the desired service directory (e.g. `fast/stages-aw/shared-services/bcap`). +3. Populate `terraform.tfvars` and run `terraform apply`. diff --git a/fast/stages-aw/shared-services/acas/README.md b/fast/stages-aw/shared-services/acas/README.md new file mode 100644 index 000000000..db8433e33 --- /dev/null +++ b/fast/stages-aw/shared-services/acas/README.md @@ -0,0 +1,131 @@ + + +# ACAS Shared Service (Nessus Scanner & Tenable SecurityCenter) + +This blueprint provisions an ACAS solution (Tenable SecurityCenter and Nessus Scanners) on Google Cloud Platform (GCP), designed for IL5 compliance under DoD Assured Workloads requirements. + +--- + +## 1. Directory Structure & Workspace Layout + +All configuration and code is located under `fast/stages-aw/shared-services/acas/`: + +``` +acas/ +├── README.md # Deployment Guide +├── data/ +│ └── config.yml # Centralized Configuration +├── image-factory/ # Provisions Private YUM Repo & Cloud Build Triggers +├── scanner/ # Nessus Scanner VM Module +└── securitycenter/ # Tenable SecurityCenter VM Module +``` + +--- + +## 2. End-to-End Operational Lifecycle + +The following diagram illustrates the end-to-end operational flow: + +```text + [1. INGESTION] + ├── Download CAC-protected RHEL8 RPMs from DISA Patch Repo + └── Stage packages in gs://-il5-prod-iac-core-outputs/acas-staging/ + + [2. ACAS IMAGE FACTORY] + ├── Synchronize staged RPMs into private YUM repository + └── Trigger Cloud Build to bake CMEK-encrypted Golden Images + + [3. VM DEPLOYMENTS] + ├── Query latest Golden Image families (acas-scanner-golden / acas-sc-golden) + └── Terraform provisions private VMs on vdms-default subnet + + [4. CONNECTIVITY] + └── Tunnel administrative SSH & Web Console traffic securely via Cloud IAP +``` + +--- + +## 3. Core Architectural Principles + +All VMs are deployed with strict IL5 security controls: +* **Immutable Infrastructure:** Cloud Build uses private YUM repos to bake CMEK-encrypted Golden Images from a CIS STIG-hardened base RHEL image. +* **Dynamic Image Families:** VM deployments resolve and mount target boot disks dynamically using GCP Image Families (`acas-scanner-golden` and `acas-sc-golden`). +* **Custom VPC Integration:** Deploys directly into custom host VPC subnetworks, parsing details dynamically from resource self-links. +* **Secure, Zero-Trust Ingress:** All VMs have no public IP addresses; administrative SSH and web access is proxied exclusively via Cloud Identity-Aware Proxy (IAP). +* **Self-Contained KMS Keys:** Disks are encrypted with Customer-Managed Encryption Keys (CMEK) managed natively directly inside the project. + +--- + +## 4. Configuration & Package Ingestion + +* **Package Ingestion:** Because ACAS RPMs are CAC-protected, download them manually from the [DoD Patch Repository](https://patches.csd.disa.mil) and copy them to your secure staging GCS bucket: + ```bash + gcloud storage cp *.rpm "gs://-il5-prod-iac-core-outputs/acas-staging/" + ``` + The deployment automation automatically pulls, stages, and hosts these packages inside a private Artifact Registry YUM repository. + +--- + +## 5. Deployment Options + +### Option A: Interactive Local Execution +Execute the automated Shared Services interactive shell script: +```bash +./automation/shared-services-deploy.sh +``` +Follow the prompts to run the **Image Factory**, **Nessus Scanner**, or **SecurityCenter** phases. The script automatically handles local variables, states, and RPM staging. + +### Option B: GitLab CI/CD Pipelines +Trigger jobs via tag pushes matching `dev/v*` or `prod/v*`, or specify the variables `DEPLOY_STAGES` as `SERVICES` or `ACAS`. + +The pipeline implements the following execution workflow: +1. **`plan/apply-acas-factory`:** Stages RPMs, sets up the private YUM repo, and bakes the CMEK-encrypted Golden Images. +2. **`plan-acas-scanner` & `plan-acas-sc`:** Run downstream of the factory. By utilizing GitLab `needs` with `optional: true`, these planning jobs automatically pause until the Golden Images have been compiled. If you are deploying changes *only* to the VMs (skipping the factory), they run immediately. +3. **`apply-acas-scanner` & `apply-acas-sc`:** Trigger manually to provision the Nessus Scanner or SecurityCenter instances once their respective downstream plans pass. + +--- + +## 6. Verification & Connection Guide + +### A. Accessing the Nessus Scanner Console +1. Establish a local-to-remote secure IAP tunnel: + ```bash + gcloud compute start-iap-tunnel 8834 \ + --local-host-port=localhost:8834 \ + --project= \ + --zone= + ``` +2. Open your browser and navigate to **https://localhost:8834**. + +### B. Accessing the SecurityCenter Console +1. Establish a local-to-remote secure IAP tunnel: + ```bash + gcloud compute start-iap-tunnel 443 \ + --local-host-port=localhost:8443 \ + --project= \ + --zone= + ``` +2. Open your browser and navigate to **https://localhost:8443**. + +### C. SSH Access +To securely open a command terminal to your private instances, simply run: +```bash +gcloud compute ssh \ + --project= \ + --zone= \ + --tunnel-through-iap +``` \ No newline at end of file diff --git a/fast/stages-aw/shared-services/acas/data/config.yml b/fast/stages-aw/shared-services/acas/data/config.yml new file mode 100644 index 000000000..f82c01dd0 --- /dev/null +++ b/fast/stages-aw/shared-services/acas/data/config.yml @@ -0,0 +1,53 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +image_factory: + artifact_registry_repo_id: "acas-rpms" + base_image: "projects/cis-public/global/images/family/cis-rhel8-stig" + scanner_rpm_filename: "nessus-scanner-10.12.0-el8.x86_64.rpm" + sc_rpm_filename: "SecurityCenter-x.x.x-el8.x86_64.rpm" + build_scanner_image: true + build_sc_image: false + # KMS key deletion policy. + # - Use "ABANDON" for Dev/Test (prevents key destruction on teardown). + # - Use "PREVENT_DESTROY" for Production to lock key versions from accidental destruction. + kms_deletion_policy: "PREVENT_DESTROY" + network: "https://www.googleapis.com/compute/v1/projects/prod-il5-vdss-host/global/networks/vdss-landing-0" + subnetwork: "https://www.googleapis.com/compute/v1/projects/prod-il5-vdss-host/regions/us-east4/subnetworks/vdms-default" + +scanner_deployment: + enable: true + enable_confidential_compute: false + network: "https://www.googleapis.com/compute/v1/projects/prod-il5-vdss-host/global/networks/vdss-landing-0" + subnetwork: "https://www.googleapis.com/compute/v1/projects/prod-il5-vdss-host/regions/us-east4/subnetworks/vdms-default" + scanner_configs: + scanner-1: + instance_name: "acas-nessus-scanner-01" + machine_type: "n2d-standard-4" + boot_disk_size: 100 + iap_source_ranges: ["35.235.240.0/20"] + securitycenter_source_ranges: ["128.63.27.103/32"] + scan_target_destination_ranges: ["10.0.0.0/8"] + admin_ssh_source_ranges: ["128.63.27.98/32, 128.63.27.80/32"] + +securitycenter_deployment: + enable: false + enable_confidential_compute: false + network: "https://www.googleapis.com/compute/v1/projects/prod-il5-vdss-host/global/networks/vdss-landing-0" + subnetwork: "https://www.googleapis.com/compute/v1/projects/prod-il5-vdss-host/regions/us-east4/subnetworks/vdms-default" + boot_disk_size: 100 + data_disk_size: 500 + iap_source_ranges: ["35.235.240.0/20"] + sc_mgmt_source_ranges: ["10.0.0.0/8"] + admin_ssh_source_ranges: ["10.0.0.0/8"] diff --git a/fast/stages-aw/shared-services/acas/image-factory/cloudbuild-sc.yaml b/fast/stages-aw/shared-services/acas/image-factory/cloudbuild-sc.yaml new file mode 100644 index 000000000..e6d456bd2 --- /dev/null +++ b/fast/stages-aw/shared-services/acas/image-factory/cloudbuild-sc.yaml @@ -0,0 +1,184 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# cloudbuild-sc.yaml +# Dummy placeholders for required substitutions: ${_REGION} ${_NETWORK_PROJECT} +# Builds the ACAS SecurityCenter Golden Image. +# +# Workflow: +# 1. Writes install.sh to the shared /workspace volume. +# 2. Creates a temporary RHEL 8 builder VM. +# 3. Waits for SSH readiness over IAP. +# 4. Copies the install script via SCP and executes it. +# 5. Stops the builder VM. +# 6. Captures the Golden Image from the stopped VM. +# 7. Cleans up the temporary builder VM. + +steps: + # Step 1: Write the install script to the shared /workspace volume. + - name: "gcr.io/google.com/cloudsdktool/cloud-sdk" + id: "write-install-script" + entrypoint: "bash" + args: + - "-c" + - | + cat > /workspace/install.sh << 'EOF' + #!/bin/bash + set -euo pipefail + echo "=== ACAS install-script begin ===" + + # Force Artifact Registry to resolve to the Private Google Access VIP + # This bypasses the VPC's default ILB firewall route. + echo "199.36.153.8 us-east4-yum.pkg.dev" >> /etc/hosts + + # Fetch an OAuth2 token for Artifact Registry YUM authentication + token_json=$(curl -sf -H "Metadata-Flavor: Google" \ + "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token") + access_token=$(echo "$token_json" | sed -n 's/.*"access_token"[ ]*:[ ]*"\([^"]*\)".*/\1/p') + + printf '[acas-rpms]\nname=ACAS RPMs\nbaseurl=https://PLACEHOLDER_ARTIFACT_REGISTRY\nenabled=1\ngpgcheck=0\nusername=oauth2accesstoken\npassword=%s\n' "$access_token" \ + > /etc/yum.repos.d/acas.repo + + echo "Installing SecurityCenter..." + dnf install -y --disablerepo="*" --enablerepo="acas-rpms" SecurityCenter + systemctl enable SecurityCenter || true + dnf clean all + + echo "Configuring firewalld for internal access..." + # Ensure the SecurityCenter port is explicitly open + firewall-cmd --permanent --add-port=443/tcp + firewall-cmd --reload + echo "firewalld rules applied." + + echo "=== Installation complete ===" + EOF + + sed -i "s|PLACEHOLDER_ARTIFACT_REGISTRY|${_ARTIFACT_REGISTRY}|g" /workspace/install.sh + chmod +x /workspace/install.sh + echo "--- install.sh written ---" + cat /workspace/install.sh + + # Step 2: Create the temporary builder VM. + - name: "gcr.io/google.com/cloudsdktool/cloud-sdk" + id: "create-builder-vm" + entrypoint: "gcloud" + args: + - "compute" + - "instances" + - "create" + - "acas-sc-builder-${BUILD_ID}" + - "--project=${_PROJECT_ID}" + - "--zone=${_ZONE}" + - "--machine-type=n2-standard-8" + - "--image=${_BASE_IMAGE}" + - "--boot-disk-size=100GB" + - "--boot-disk-type=pd-ssd" + - "--boot-disk-kms-key=${_KMS_KEY}" + - "--subnet=${_SUBNETWORK}" + - "--no-address" + - "--scopes=cloud-platform" + - "--shielded-secure-boot" + - "--shielded-vtpm" + - "--shielded-integrity-monitoring" + - "--maintenance-policy=TERMINATE" + - "--tags=image-builder" + waitFor: ["write-install-script"] + + # Step 3: Wait for SSH readiness. + - name: "gcr.io/google.com/cloudsdktool/cloud-sdk" + id: "wait-for-ssh" + entrypoint: "bash" + args: + - "-c" + - | + echo "Waiting for VM to boot and SSH to become ready..." + for i in $(seq 1 30); do + if gcloud compute ssh acas-sc-builder-${BUILD_ID} \ + --project=${_PROJECT_ID} --zone=${_ZONE} \ + --tunnel-through-iap --command="echo 'SSH Ready!'"; then + echo "SSH connection established." + exit 0 + fi + echo "Poll $i/30: Retrying SSH..." + sleep 10 + done + echo "ERROR: Timed out waiting for SSH." + exit 1 + waitFor: ["create-builder-vm"] + + # Step 4: Execute installation via IAP. + - name: "gcr.io/google.com/cloudsdktool/cloud-sdk" + id: "execute-installation" + entrypoint: "bash" + args: + - "-c" + - | + echo "Transferring install script..." + gcloud compute scp /workspace/install.sh acas-sc-builder-${BUILD_ID}:/tmp/install.sh \ + --project=${_PROJECT_ID} --zone=${_ZONE} --tunnel-through-iap + + echo "Executing install script synchronously..." + gcloud compute ssh acas-sc-builder-${BUILD_ID} \ + --project=${_PROJECT_ID} --zone=${_ZONE} --tunnel-through-iap \ + --command="sudo bash /tmp/install.sh" -- -t + waitFor: ["wait-for-ssh"] + + # Step 5: Stop the builder VM before disk image capture. + - name: "gcr.io/google.com/cloudsdktool/cloud-sdk" + id: "stop-builder-vm" + entrypoint: "gcloud" + args: + - "compute" + - "instances" + - "stop" + - "acas-sc-builder-${BUILD_ID}" + - "--project=${_PROJECT_ID}" + - "--zone=${_ZONE}" + waitFor: ["execute-installation"] + + # Step 6: Capture the Golden Image from the stopped VM's boot disk. + - name: "gcr.io/google.com/cloudsdktool/cloud-sdk" + id: "capture-golden-image" + entrypoint: "gcloud" + args: + - "compute" + - "images" + - "create" + - "acas-sc-golden-${BUILD_ID}" + - "--project=${_PROJECT_ID}" + - "--source-disk=acas-sc-builder-${BUILD_ID}" + - "--source-disk-zone=${_ZONE}" + - "--family=${_IMAGE_FAMILY}" + - "--kms-key=${_KMS_KEY}" + - "--guest-os-features=UEFI_COMPATIBLE,GVNIC,VIRTIO_SCSI_MULTIQUEUE,SEV_CAPABLE" + - "--description=ACAS SecurityCenter Golden Image. Built by Cloud Build ${BUILD_ID} on official RHEL 8 base." + waitFor: ["stop-builder-vm"] + + # Step 7: Delete the temporary builder VM. + - name: "gcr.io/google.com/cloudsdktool/cloud-sdk" + id: "cleanup-builder-vm" + entrypoint: "gcloud" + args: + - "compute" + - "instances" + - "delete" + - "acas-sc-builder-${BUILD_ID}" + - "--project=${_PROJECT_ID}" + - "--zone=${_ZONE}" + - "--quiet" + waitFor: ["capture-golden-image"] + +timeout: "3600s" +options: + logging: CLOUD_LOGGING_ONLY diff --git a/fast/stages-aw/shared-services/acas/image-factory/cloudbuild-scanner.yaml b/fast/stages-aw/shared-services/acas/image-factory/cloudbuild-scanner.yaml new file mode 100644 index 000000000..86e3a108c --- /dev/null +++ b/fast/stages-aw/shared-services/acas/image-factory/cloudbuild-scanner.yaml @@ -0,0 +1,184 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# cloudbuild-scanner.yaml +# Dummy placeholders for required substitutions: ${_REGION} ${_NETWORK_PROJECT} +# Builds the ACAS Nessus Scanner Golden Image. +# +# Workflow: +# 1. Writes install.sh to the shared /workspace volume. +# 2. Creates a temporary RHEL 8 builder VM. +# 3. Waits for SSH readiness over IAP. +# 4. Copies the install script via SCP and executes it. +# 5. Stops the builder VM. +# 6. Captures the Golden Image from the stopped VM. +# 7. Cleans up the temporary builder VM. + +steps: + # Step 1: Write the install script to the shared /workspace volume. + - name: "gcr.io/google.com/cloudsdktool/cloud-sdk" + id: "write-install-script" + entrypoint: "bash" + args: + - "-c" + - | + cat > /workspace/install.sh << 'EOF' + #!/bin/bash + set -euo pipefail + echo "=== ACAS install-script begin ===" + + # Force Artifact Registry to resolve to the Private Google Access VIP + # This bypasses the VPC's default ILB firewall route. + echo "199.36.153.8 us-east4-yum.pkg.dev" >> /etc/hosts + + # Fetch an OAuth2 token for Artifact Registry YUM authentication + token_json=$(curl -sf -H "Metadata-Flavor: Google" \ + "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token") + access_token=$(echo "$token_json" | sed -n 's/.*"access_token"[ ]*:[ ]*"\([^"]*\)".*/\1/p') + + printf '[acas-rpms]\nname=ACAS RPMs\nbaseurl=https://PLACEHOLDER_ARTIFACT_REGISTRY\nenabled=1\ngpgcheck=0\nusername=oauth2accesstoken\npassword=%s\n' "$access_token" \ + > /etc/yum.repos.d/acas.repo + + echo "Installing Nessus..." + dnf install -y --disablerepo="*" --enablerepo="acas-rpms" Nessus + systemctl enable nessusd || true + dnf clean all + + echo "Configuring firewalld for internal access..." + # Ensure the Nessus port is explicitly open + firewall-cmd --permanent --add-port=8834/tcp + firewall-cmd --reload + echo "firewalld rules applied." + + echo "=== Installation complete ===" + EOF + + sed -i "s|PLACEHOLDER_ARTIFACT_REGISTRY|${_ARTIFACT_REGISTRY}|g" /workspace/install.sh + chmod +x /workspace/install.sh + echo "--- install.sh written ---" + cat /workspace/install.sh + + # Step 2: Create the temporary builder VM. + - name: "gcr.io/google.com/cloudsdktool/cloud-sdk" + id: "create-builder-vm" + entrypoint: "gcloud" + args: + - "compute" + - "instances" + - "create" + - "acas-scanner-builder-${BUILD_ID}" + - "--project=${_PROJECT_ID}" + - "--zone=${_ZONE}" + - "--machine-type=n2-standard-2" + - "--image=${_BASE_IMAGE}" + - "--boot-disk-size=100GB" + - "--boot-disk-type=pd-ssd" + - "--boot-disk-kms-key=${_KMS_KEY}" + - "--subnet=${_SUBNETWORK}" + - "--no-address" + - "--scopes=cloud-platform" + - "--shielded-secure-boot" + - "--shielded-vtpm" + - "--shielded-integrity-monitoring" + - "--maintenance-policy=TERMINATE" + - "--tags=image-builder" + waitFor: ["write-install-script"] + + # Step 3: Wait for SSH readiness. + - name: "gcr.io/google.com/cloudsdktool/cloud-sdk" + id: "wait-for-ssh" + entrypoint: "bash" + args: + - "-c" + - | + echo "Waiting for VM to boot and SSH to become ready..." + for i in $(seq 1 30); do + if gcloud compute ssh acas-scanner-builder-${BUILD_ID} \ + --project=${_PROJECT_ID} --zone=${_ZONE} \ + --tunnel-through-iap --command="echo 'SSH Ready!'"; then + echo "SSH connection established." + exit 0 + fi + echo "Poll $i/30: Retrying SSH..." + sleep 10 + done + echo "ERROR: Timed out waiting for SSH." + exit 1 + waitFor: ["create-builder-vm"] + + # Step 4: Execute installation via IAP. + - name: "gcr.io/google.com/cloudsdktool/cloud-sdk" + id: "execute-installation" + entrypoint: "bash" + args: + - "-c" + - | + echo "Transferring install script..." + gcloud compute scp /workspace/install.sh acas-scanner-builder-${BUILD_ID}:/tmp/install.sh \ + --project=${_PROJECT_ID} --zone=${_ZONE} --tunnel-through-iap + + echo "Executing install script synchronously..." + gcloud compute ssh acas-scanner-builder-${BUILD_ID} \ + --project=${_PROJECT_ID} --zone=${_ZONE} --tunnel-through-iap \ + --command="sudo bash /tmp/install.sh" -- -t + waitFor: ["wait-for-ssh"] + + # Step 5: Stop the builder VM before disk image capture. + - name: "gcr.io/google.com/cloudsdktool/cloud-sdk" + id: "stop-builder-vm" + entrypoint: "gcloud" + args: + - "compute" + - "instances" + - "stop" + - "acas-scanner-builder-${BUILD_ID}" + - "--project=${_PROJECT_ID}" + - "--zone=${_ZONE}" + waitFor: ["execute-installation"] + + # Step 6: Capture the Golden Image from the stopped VM's boot disk. + - name: "gcr.io/google.com/cloudsdktool/cloud-sdk" + id: "capture-golden-image" + entrypoint: "gcloud" + args: + - "compute" + - "images" + - "create" + - "acas-scanner-golden-${BUILD_ID}" + - "--project=${_PROJECT_ID}" + - "--source-disk=acas-scanner-builder-${BUILD_ID}" + - "--source-disk-zone=${_ZONE}" + - "--family=${_IMAGE_FAMILY}" + - "--kms-key=${_KMS_KEY}" + - "--guest-os-features=UEFI_COMPATIBLE,GVNIC,VIRTIO_SCSI_MULTIQUEUE,SEV_CAPABLE" + - "--description=ACAS Nessus Scanner Golden Image. Built by Cloud Build ${BUILD_ID} on official RHEL 8 base." + waitFor: ["stop-builder-vm"] + + # Step 7: Delete the temporary builder VM. + - name: "gcr.io/google.com/cloudsdktool/cloud-sdk" + id: "cleanup-builder-vm" + entrypoint: "gcloud" + args: + - "compute" + - "instances" + - "delete" + - "acas-scanner-builder-${BUILD_ID}" + - "--project=${_PROJECT_ID}" + - "--zone=${_ZONE}" + - "--quiet" + waitFor: ["capture-golden-image"] + +timeout: "3600s" +options: + logging: CLOUD_LOGGING_ONLY diff --git a/fast/stages-aw/shared-services/acas/image-factory/main.tf b/fast/stages-aw/shared-services/acas/image-factory/main.tf new file mode 100644 index 000000000..7aa63a83a --- /dev/null +++ b/fast/stages-aw/shared-services/acas/image-factory/main.tf @@ -0,0 +1,283 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +data "google_project" "current" { + project_id = var.shared_services_project_id +} + +locals { + prefix = var.prefix == null ? "" : "${var.prefix}-" +} + +# --- Project Services --- + +resource "google_project_service" "factory_services" { + for_each = toset([ + "compute.googleapis.com", + "cloudbuild.googleapis.com", + "artifactregistry.googleapis.com", + "cloudkms.googleapis.com", + "iam.googleapis.com", + "osconfig.googleapis.com" + ]) + project = var.shared_services_project_id + service = each.value + disable_on_destroy = false +} + +resource "google_project_service_identity" "ar_identity" { + provider = google-beta + project = google_project_service.factory_services["artifactregistry.googleapis.com"].project + service = "artifactregistry.googleapis.com" +} + +# --- Cloud KMS: Native CMEK Keyring & Key --- + +resource "google_kms_key_ring" "default" { + name = "${local.prefix}acas-keyring-${var.region}" + location = var.region + project = var.shared_services_project_id + + depends_on = [ + google_project_service.factory_services + ] +} + +resource "google_kms_crypto_key" "acas" { + name = "acas" + key_ring = google_kms_key_ring.default.id + rotation_period = "7776000s" + purpose = "ENCRYPT_DECRYPT" + deletion_policy = var.kms_deletion_policy + + labels = { + service = "acas-shared-service" + } + + version_template { + algorithm = "GOOGLE_SYMMETRIC_ENCRYPTION" + protection_level = "HSM" + } +} + +# --- Cloud KMS IAM: Non-authoritative permissions for CMEK Encryption --- + +resource "google_kms_crypto_key_iam_member" "compute_system_kms" { + crypto_key_id = google_kms_crypto_key.acas.id + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + member = "serviceAccount:service-${data.google_project.current.number}@compute-system.iam.gserviceaccount.com" +} + +resource "google_kms_crypto_key_iam_member" "artifact_registry_kms" { + crypto_key_id = google_kms_crypto_key.acas.id + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + member = "serviceAccount:${google_project_service_identity.ar_identity.email}" + + depends_on = [ + google_project_service_identity.ar_identity + ] +} + +# --- Service Account for Custom Image Builder --- + +resource "google_service_account" "image_builder" { + account_id = "acas-image-builder" + display_name = "ACAS Custom Image Builder Service Account" + project = var.shared_services_project_id +} + +resource "google_kms_crypto_key_iam_member" "cloudbuild_kms" { + crypto_key_id = google_kms_crypto_key.acas.id + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + member = google_service_account.image_builder.member +} + +# --- Artifact Registry: YUM Repository for ACAS RPMs --- + +resource "google_artifact_registry_repository" "acas_rpms" { + project = var.shared_services_project_id + location = var.region + repository_id = var.artifact_registry_repo_id + description = "YUM repository hosting ACAS RPMs (SecurityCenter and Nessus Scanner) sourced from the DoD Patch Repository." + format = "YUM" + + # CMEK encryption for IL5 compliance + kms_key_name = google_kms_crypto_key.acas.id + + depends_on = [ + google_project_service.factory_services, + google_kms_crypto_key.acas, + google_kms_crypto_key_iam_member.artifact_registry_kms + ] +} + +# --- IAM: Grant Artifact Registry Reader to Cloud Build SA --- + +resource "google_artifact_registry_repository_iam_member" "cloudbuild_reader" { + project = google_artifact_registry_repository.acas_rpms.project + location = google_artifact_registry_repository.acas_rpms.location + repository = google_artifact_registry_repository.acas_rpms.name + role = "roles/artifactregistry.reader" + member = google_service_account.image_builder.member +} + +resource "google_artifact_registry_repository_iam_member" "compute_default_reader" { + project = google_artifact_registry_repository.acas_rpms.project + location = google_artifact_registry_repository.acas_rpms.location + repository = google_artifact_registry_repository.acas_rpms.name + role = "roles/artifactregistry.reader" + member = "serviceAccount:${data.google_project.current.number}-compute@developer.gserviceaccount.com" +} + +# --- IAM: Allow Cloud Build/Compute Default SA to build images --- + +resource "google_project_iam_member" "cloudbuild_image_builder" { + project = var.shared_services_project_id + role = "roles/compute.imageUser" + member = google_service_account.image_builder.member +} + +resource "google_project_iam_member" "cloudbuild_compute_admin" { + project = var.shared_services_project_id + role = "roles/compute.instanceAdmin.v1" + member = google_service_account.image_builder.member +} + +resource "google_project_iam_member" "cloudbuild_iap_tunnel" { + project = var.shared_services_project_id + role = "roles/iap.tunnelResourceAccessor" + member = google_service_account.image_builder.member +} + +resource "google_service_account_iam_member" "cloudbuild_service_account_user" { + service_account_id = "projects/${var.shared_services_project_id}/serviceAccounts/${data.google_project.current.number}-compute@developer.gserviceaccount.com" + role = "roles/iam.serviceAccountUser" + member = google_service_account.image_builder.member +} + +resource "google_project_iam_member" "cloudbuild_logger" { + project = var.shared_services_project_id + role = "roles/logging.logWriter" + member = google_service_account.image_builder.member +} + +# Allow Cloud Build to act as/impersonate the custom image builder service account +resource "google_service_account_iam_member" "cloudbuild_agent_impersonate" { + service_account_id = google_service_account.image_builder.name + role = "roles/iam.serviceAccountUser" + member = "serviceAccount:service-${data.google_project.current.number}@gcp-sa-cloudbuild.iam.gserviceaccount.com" +} + +resource "google_service_account_iam_member" "cloudbuild_legacy_impersonate" { + service_account_id = google_service_account.image_builder.name + role = "roles/iam.serviceAccountUser" + member = "serviceAccount:${data.google_project.current.number}@cloudbuild.gserviceaccount.com" +} + +# --- Auto-Upload and Trigger: SecurityCenter --- + +resource "null_resource" "upload_and_build_sc" { + count = var.build_sc_image && var.sc_rpm_filename != null ? 1 : 0 + + triggers = { + # Re-runs if the RPM file changes + rpm_hash = filemd5("${path.module}/rpms/${var.sc_rpm_filename}") + } + + provisioner "local-exec" { + command = <<-EOT + gcloud artifacts yum upload ${google_artifact_registry_repository.acas_rpms.repository_id} \ + --location=${var.region} --project=${var.shared_services_project_id} \ + --source="${path.module}/rpms/${var.sc_rpm_filename}" + + gcloud builds submit --no-source \ + --config="${path.module}/cloudbuild-sc.yaml" \ + --project=${var.shared_services_project_id} \ + --region=${var.region} \ + --service-account="projects/${var.shared_services_project_id}/serviceAccounts/${google_service_account.image_builder.email}" \ + --substitutions="_PROJECT_ID=${var.shared_services_project_id},_ZONE=${var.zone},_BASE_IMAGE=${var.base_image},_IMAGE_FAMILY=${var.sc_image_family},_ARTIFACT_REGISTRY=${var.region}-yum.pkg.dev/projects/${var.shared_services_project_id}/${var.artifact_registry_repo_id},_KMS_KEY=${google_kms_crypto_key.acas.id},_SUBNETWORK=${var.subnetwork}" + EOT + } +} + +# --- Auto-Upload and Trigger: Nessus Scanner --- + +resource "null_resource" "upload_and_build_scanner" { + count = var.build_scanner_image && var.scanner_rpm_filename != null ? 1 : 0 + + triggers = { + # Re-runs if the RPM file changes + rpm_hash = filemd5("${path.module}/rpms/${var.scanner_rpm_filename}") + } + + provisioner "local-exec" { + command = <<-EOT + gcloud artifacts yum upload ${google_artifact_registry_repository.acas_rpms.repository_id} \ + --location=${var.region} --project=${var.shared_services_project_id} \ + --source="${path.module}/rpms/${var.scanner_rpm_filename}" + + gcloud builds submit --no-source \ + --config="${path.module}/cloudbuild-scanner.yaml" \ + --project=${var.shared_services_project_id} \ + --region=${var.region} \ + --service-account="projects/${var.shared_services_project_id}/serviceAccounts/${google_service_account.image_builder.email}" \ + --substitutions="_PROJECT_ID=${var.shared_services_project_id},_ZONE=${var.zone},_BASE_IMAGE=${var.base_image},_IMAGE_FAMILY=${var.scanner_image_family},_ARTIFACT_REGISTRY=${var.region}-yum.pkg.dev/projects/${var.shared_services_project_id}/${var.artifact_registry_repo_id},_KMS_KEY=${google_kms_crypto_key.acas.id},_SUBNETWORK=${var.subnetwork}" + EOT + } +} + +# --- Firewall: Allow IAP to SSH into the ephemeral builder VM --- +resource "google_compute_firewall" "allow_iap_ssh_builder" { + name = "allow-iap-ssh-image-builder" + network = var.network + project = var.hub_project_id != null ? var.hub_project_id : var.shared_services_project_id + description = "Allow IAP TCP forwarding to SSH port on image-builder VMs." + direction = "INGRESS" + priority = 1000 + + allow { + protocol = "tcp" + ports = ["22"] + } + + source_ranges = ["35.235.240.0/20"] + target_tags = ["image-builder"] +} + +# --- Private Google Access Route --- +# The VPC's 0.0.0.0/0 route points to an ILB firewall which drops traffic to Google APIs. +# This route ensures traffic to the Private Google Access VIP goes through the default internet gateway, +# allowing the builder VMs to reach Artifact Registry natively. + +resource "google_compute_route" "pga_route" { + name = "allow-pga-for-image-builder" + project = var.hub_project_id + network = var.network + dest_range = "199.36.153.8/30" + next_hop_gateway = "default-internet-gateway" + priority = 0 + tags = ["image-builder"] +} + +# --- IAM: Grant networkUser role on Host Project's subnet to Custom Builder SA --- + +resource "google_compute_subnetwork_iam_member" "cloudbuild_network_user" { + count = var.hub_project_id != null && var.hub_project_id != var.shared_services_project_id ? 1 : 0 + project = var.hub_project_id + region = var.region + subnetwork = var.subnetwork + role = "roles/compute.networkUser" + member = google_service_account.image_builder.member +} diff --git a/fast/stages-aw/shared-services/acas/image-factory/outputs-gcs.tf b/fast/stages-aw/shared-services/acas/image-factory/outputs-gcs.tf new file mode 100644 index 000000000..7724dcaff --- /dev/null +++ b/fast/stages-aw/shared-services/acas/image-factory/outputs-gcs.tf @@ -0,0 +1,26 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# tfdoc:file:description Output files persistence to automation GCS bucket. + +resource "google_storage_bucket_object" "tfvars" { + bucket = var.automation.outputs_bucket + name = "tfvars/shared-services-acas-factory.auto.tfvars.json" + content = jsonencode({ + acas_scanner_image_family = var.scanner_image_family + acas_sc_image_family = var.sc_image_family + acas_artifact_registry_id = google_artifact_registry_repository.acas_rpms.id + }) +} diff --git a/fast/stages-aw/shared-services/acas/image-factory/outputs.tf b/fast/stages-aw/shared-services/acas/image-factory/outputs.tf new file mode 100644 index 000000000..736d109b8 --- /dev/null +++ b/fast/stages-aw/shared-services/acas/image-factory/outputs.tf @@ -0,0 +1,89 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +output "artifact_registry_id" { + description = "Artifact Registry repository resource ID." + value = google_artifact_registry_repository.acas_rpms.id +} + +output "artifact_registry_repo_id" { + description = "Name/ID for the Artifact Registry YUM repository." + value = var.artifact_registry_repo_id +} + +output "artifact_registry_repository" { + description = "The full Artifact Registry repository URI." + value = "${var.region}-yum.pkg.dev/${var.shared_services_project_id}/${var.artifact_registry_repo_id}" +} + +output "base_image" { + description = "The base image to use as the foundation for Golden Images." + value = var.base_image +} + +output "hub_project_id" { + description = "Project ID that hosts the Shared VPC network." + value = var.hub_project_id +} + +output "kms_key_id" { + description = "ID for the dynamically created KMS key." + value = google_kms_crypto_key.acas.id +} + +output "shared_services_project_id" { + description = "GCP project ID where the image factory resources will be created." + value = var.shared_services_project_id +} + +output "region" { + description = "GCP region for regional resources (e.g., Artifact Registry repository)." + value = var.region +} + +output "repository_id" { + description = "ID for the created Artifact Registry repository." + value = google_artifact_registry_repository.acas_rpms.repository_id +} + +output "sc_golden_image_family" { + description = "Compute Image family for the SecurityCenter Golden Image." + value = "projects/${var.shared_services_project_id}/global/images/family/${var.sc_image_family}" +} + +output "sc_image_family" { + description = "Compute Image family for the SecurityCenter Golden Image." + value = var.sc_image_family +} + +output "scanner_golden_image_family" { + description = "Compute Image family for the Nessus Scanner Golden Image." + value = "projects/${var.shared_services_project_id}/global/images/family/${var.scanner_image_family}" +} + +output "scanner_image_family" { + description = "Compute Image family for the Nessus Scanner Golden Image." + value = var.scanner_image_family +} + +output "subnetwork" { + description = "VPC subnetwork to use for the image builder VM." + value = var.subnetwork +} + +output "zone" { + description = "GCP zone where the image builder VM will run." + value = var.zone +} \ No newline at end of file diff --git a/fast/stages-aw/shared-services/acas/image-factory/provider.tf b/fast/stages-aw/shared-services/acas/image-factory/provider.tf new file mode 100644 index 000000000..16475d224 --- /dev/null +++ b/fast/stages-aw/shared-services/acas/image-factory/provider.tf @@ -0,0 +1,32 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +terraform { + required_version = ">= 1.5" + required_providers { + google = { + source = "hashicorp/google" + version = ">= 5.0" + } + google-beta = { + source = "hashicorp/google-beta" + version = ">= 5.0" + } + null = { + source = "hashicorp/null" + version = ">= 3.0" + } + } +} \ No newline at end of file diff --git a/fast/stages-aw/shared-services/acas/image-factory/variables.tf b/fast/stages-aw/shared-services/acas/image-factory/variables.tf new file mode 100644 index 000000000..c9e6e7740 --- /dev/null +++ b/fast/stages-aw/shared-services/acas/image-factory/variables.tf @@ -0,0 +1,117 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +variable "artifact_registry_repo_id" { + description = "Name/ID for the Artifact Registry YUM repository." + type = string + default = "acas-rpms" +} + +variable "automation" { + description = "Automation resources created by the bootstrap stage. Used to write ACAS outputs to the GCS outputs bucket for downstream consumption." + type = object({ + outputs_bucket = string + }) +} + +variable "base_image" { + description = "The base image to use as the foundation for Golden Images. Specify as 'projects/PROJECT/global/images/IMAGE' or 'projects/PROJECT/global/images/family/FAMILY'." + type = string + default = "projects/rhel-cloud/global/images/family/rhel-8" +} + +variable "build_sc_image" { + description = "Whether to trigger the Cloud Build job for the SecurityCenter Golden Image." + type = bool + default = false +} + +variable "build_scanner_image" { + description = "Whether to trigger the Cloud Build job for the Nessus Scanner Golden Image." + type = bool + default = true +} + +variable "hub_project_id" { + description = "The GCP project ID that hosts the Shared VPC network." + type = string +} + +variable "kms_deletion_policy" { + description = "Deletion policy for the ACAS KMS key. Can be ABANDON, PREVENT_DESTROY, or DEFAULT." + type = string + default = "ABANDON" +} + +variable "network" { + description = "Self-link of the VPC network to use for the image builder VM." + type = string +} + +variable "prefix" { + description = "Prefix applied to resource names for org-level naming consistency. Set to null to disable prefixing." + type = string + default = null + validation { + condition = var.prefix != "" + error_message = "Prefix cannot be empty, use null instead." + } +} + +variable "region" { + description = "GCP region for regional resources (e.g., Artifact Registry repository)." + type = string + default = "us-east4" +} + +variable "shared_services_project_id" { + description = "The GCP project ID where the image factory resources will be created." + type = string +} + +variable "sc_image_family" { + description = "Image family name for the SecurityCenter Golden Image." + type = string + default = "acas-sc-golden" +} + +variable "sc_rpm_filename" { + description = "Filename of the SecurityCenter RPM as uploaded to Artifact Registry (e.g., SecurityCenter-6.8.0-el8.x86_64.rpm)." + type = string + default = null +} + +variable "scanner_image_family" { + description = "Image family name for the Nessus Scanner Golden Image." + type = string + default = "acas-scanner-golden" +} + +variable "scanner_rpm_filename" { + description = "Filename of the Nessus Scanner RPM as uploaded to Artifact Registry (e.g., Nessus-10.12.0-el8.x86_64.rpm)." + type = string + default = null +} + +variable "subnetwork" { + description = "Self-link of the subnetwork to use for the image builder VM." + type = string +} + +variable "zone" { + description = "GCP zone where the image builder VM will run." + type = string + default = "us-east4-a" +} diff --git a/fast/stages-aw/shared-services/acas/scanner/firewall.tf b/fast/stages-aw/shared-services/acas/scanner/firewall.tf new file mode 100644 index 000000000..8c2ba1160 --- /dev/null +++ b/fast/stages-aw/shared-services/acas/scanner/firewall.tf @@ -0,0 +1,89 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# Scanner Management (SSH via IAP) +resource "google_compute_firewall" "acas_scanner_ssh" { + name = "acas-scanner-ssh" + network = data.google_compute_network.network.self_link + project = var.hub_project_id + + allow { + protocol = "tcp" + ports = ["22"] + } + + target_tags = ["acas-scanner"] + source_ranges = distinct(concat(var.iap_source_ranges, var.admin_ssh_source_ranges)) +} + +# Scanner Management (SecurityCenter communication + Nessus Web UI) +resource "google_compute_firewall" "acas_scanner_sc_mgmt" { + name = "acas-scanner-sc-mgmt" + network = data.google_compute_network.network.self_link + project = var.hub_project_id + + allow { + protocol = "tcp" + ports = ["8834"] + } + + target_tags = ["acas-scanner"] + source_ranges = distinct(concat(var.securitycenter_source_ranges, var.iap_source_ranges)) +} + +# Scanner to Targets: Outbound scanning traffic +resource "google_compute_firewall" "acas_scanner_to_targets_egress" { + name = "acas-scanner-to-targets-egress" + network = data.google_compute_network.network.self_link + project = var.hub_project_id + direction = "EGRESS" + + allow { + protocol = "tcp" + ports = ["0-65535"] + } + allow { + protocol = "udp" + ports = ["0-65535"] + } + allow { + protocol = "icmp" + } + + target_tags = ["acas-scanner"] + destination_ranges = var.scan_target_destination_ranges +} + +# Target Ingress: Inbound scanning traffic from Scanner to scanned hosts +resource "google_compute_firewall" "acas_targets_ingress_from_scanner" { + name = "acas-targets-ingress-from-scanner" + network = data.google_compute_network.network.self_link + project = var.hub_project_id + direction = "INGRESS" + + allow { + protocol = "tcp" + ports = ["0-65535"] + } + allow { + protocol = "udp" + ports = ["0-65535"] + } + allow { + protocol = "icmp" + } + + source_tags = ["acas-scanner"] +} diff --git a/fast/stages-aw/shared-services/acas/scanner/main.tf b/fast/stages-aw/shared-services/acas/scanner/main.tf new file mode 100644 index 000000000..03eabd71b --- /dev/null +++ b/fast/stages-aw/shared-services/acas/scanner/main.tf @@ -0,0 +1,134 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +data "google_project" "current" { + project_id = var.shared_services_project_id +} + +data "google_compute_network" "network" { + name = split("/", var.network)[length(split("/", var.network)) - 1] + project = var.hub_project_id +} + +data "google_compute_image" "scanner_golden" { + family = "acas-scanner-golden" + project = var.shared_services_project_id +} + +locals { + prefix = var.prefix == null ? "" : "${var.prefix}-" + compute_agent_sa = "serviceAccount:service-${data.google_project.current.number}@compute-system.iam.gserviceaccount.com" + compute_default_sa = "${data.google_project.current.number}-compute@developer.gserviceaccount.com" +} + +# --- KMS Key Lookup --- + +data "google_kms_key_ring" "default" { + name = "${local.prefix}acas-keyring-${var.region}" + location = var.region + project = var.shared_services_project_id +} + +data "google_kms_crypto_key" "default" { + name = "acas" + key_ring = data.google_kms_key_ring.default.id +} + +# --- Project Services --- + +resource "google_project_service" "services" { + for_each = toset([ + "compute.googleapis.com", + "cloudkms.googleapis.com", + "iam.googleapis.com", + "storage.googleapis.com" + ]) + project = var.shared_services_project_id + service = each.value + disable_on_destroy = false +} + +# --- Service Account --- + +resource "google_service_account" "scanner" { + account_id = var.service_account_id + display_name = "ACAS Nessus Scanner Service Account" + project = var.shared_services_project_id +} + +# --- KMS IAM --- + +resource "google_kms_crypto_key_iam_member" "kms_access" { + for_each = toset([ + local.compute_agent_sa, + "serviceAccount:${local.compute_default_sa}", + google_service_account.scanner.member + ]) + crypto_key_id = data.google_kms_crypto_key.default.id + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + member = each.value +} + +# --- ACAS Nessus Scanners --- + +module "scanner-vms" { + for_each = var.scanner_configs + source = "../../../../../modules/compute-vm" + project_id = var.shared_services_project_id + zone = coalesce(each.value.zone, var.zone) + name = coalesce(each.value.instance_name, each.key) + + instance_type = each.value.machine_type + confidential_compute = coalesce(each.value.enable_confidential_compute, var.enable_confidential_compute) + + network_interfaces = [{ + network = var.network + subnetwork = var.subnetwork + }] + + metadata = { + enable-oslogin = true + block-project-ssh-keys = true + } + + shielded_config = { + enable_secure_boot = true + enable_vtpm = true + enable_integrity_monitoring = true + } + + encryption = { + kms_key_self_link = data.google_kms_crypto_key.default.id + } + + service_account = { + email = google_service_account.scanner.email + } + + boot_disk = { + initialize_params = { + image = coalesce(each.value.image, data.google_compute_image.scanner_golden.self_link) + size = each.value.boot_disk_size + type = "pd-ssd" + } + } + + tags = ["acas-scanner"] + + depends_on = [ + google_project_service.services, + google_kms_crypto_key_iam_member.kms_access + ] +} diff --git a/fast/stages-aw/shared-services/acas/scanner/outputs.tf b/fast/stages-aw/shared-services/acas/scanner/outputs.tf new file mode 100644 index 000000000..a7a99cee1 --- /dev/null +++ b/fast/stages-aw/shared-services/acas/scanner/outputs.tf @@ -0,0 +1,33 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +output "scanner_internal_ips" { + description = "Map of Nessus Scanner instance names to internal IP addresses." + value = { for k, v in module.scanner-vms : k => v.internal_ip } +} + +output "service_account_email" { + description = "Service account email attached to the Nessus Scanner VMs." + value = google_service_account.scanner.email +} + +resource "google_storage_bucket_object" "tfvars" { + bucket = var.automation.outputs_bucket + name = "tfvars/shared-services-acas-scanner.auto.tfvars.json" + content = jsonencode({ + acas_scanner_ips = [for k, v in module.scanner-vms : v.internal_ip] + }) +} + diff --git a/fast/stages-aw/shared-services/acas/scanner/provider.tf b/fast/stages-aw/shared-services/acas/scanner/provider.tf new file mode 100644 index 000000000..361a9a6cc --- /dev/null +++ b/fast/stages-aw/shared-services/acas/scanner/provider.tf @@ -0,0 +1,32 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +terraform { + required_version = ">= 1.11.4" + required_providers { + google = { + source = "hashicorp/google" + version = ">= 7.1.0, < 8.0.0" + } + google-beta = { + source = "hashicorp/google-beta" + version = ">= 7.1.0, < 8.0.0" + } + null = { + source = "hashicorp/null" + version = ">= 3.0.0" + } + } +} diff --git a/fast/stages-aw/shared-services/acas/scanner/variables.tf b/fast/stages-aw/shared-services/acas/scanner/variables.tf new file mode 100644 index 000000000..00175f916 --- /dev/null +++ b/fast/stages-aw/shared-services/acas/scanner/variables.tf @@ -0,0 +1,111 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +variable "admin_ssh_source_ranges" { + description = "List of IP ranges allowed to SSH directly into the instance (e.g., from other clouds via VPN/Interconnect)." + type = list(string) + default = [] +} + +variable "enable_confidential_compute" { + description = "Enable Confidential Compute for the Nessus Scanner VMs." + type = bool + default = true +} + +variable "iap_source_ranges" { + description = "List of IP ranges allowed to connect via Identity-Aware Proxy (IAP)." + type = list(string) + default = ["35.235.240.0/20"] +} + +variable "network" { + description = "Self-link of the VPC network to attach Domain Controller VMs to." + type = string +} + +variable "hub_project_id" { + description = "Project ID that hosts the Shared VPC network." + type = string +} + +variable "prefix" { + description = "Prefix applied to resource names for org-level naming consistency. Set to null to disable prefixing." + type = string + default = null + validation { + condition = var.prefix != "" + error_message = "Prefix cannot be empty, use null instead." + } +} + +variable "shared_services_project_id" { + description = "GCP project ID where scanner resources will be created." + type = string +} + +variable "region" { + description = "GCP region for deployment." + type = string + default = "us-east4" +} + +variable "scan_target_destination_ranges" { + description = "List of IP ranges that the Nessus Scanner is allowed to scan." + type = list(string) + default = ["10.0.0.0/8"] +} + +variable "scanner_configs" { + description = "Map of ACAS Nessus Scanner instances to create. Keys are logical scanner names." + type = map(object({ + instance_name = optional(string) + machine_type = optional(string, "n2d-standard-2") + boot_disk_size = optional(number, 100) + image = optional(string) + zone = optional(string) + enable_confidential_compute = optional(bool) + })) +} + +variable "securitycenter_source_ranges" { + description = "List of SecurityCenter IP ranges allowed to connect to the Scanner (port 8834)." + type = list(string) + default = ["10.0.0.0/8"] +} + +variable "service_account_id" { + description = "Service account ID for Nessus Scanner VMs." + type = string + default = "acas-scanner-sa" +} + +variable "subnetwork" { + description = "Self-link of the subnetwork to attach Domain Controller VMs to." + type = string +} + +variable "zone" { + description = "Default GCP zone for scanner VMs. Can be overridden per scanner in scanner_configs." + type = string + default = "us-east4-a" +} + +variable "automation" { + description = "Automation resources created by the bootstrap stage. Used to write ACAS outputs to the GCS outputs bucket for downstream consumption." + type = object({ + outputs_bucket = string + }) +} diff --git a/fast/stages-aw/shared-services/acas/securitycenter/firewall.tf b/fast/stages-aw/shared-services/acas/securitycenter/firewall.tf new file mode 100644 index 000000000..e443415dc --- /dev/null +++ b/fast/stages-aw/shared-services/acas/securitycenter/firewall.tf @@ -0,0 +1,44 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# SecurityCenter Management (SSH via IAP) +resource "google_compute_firewall" "acas_sc_ssh" { + name = "acas-sc-ssh" + network = data.google_compute_network.network.self_link + project = var.hub_project_id + + allow { + protocol = "tcp" + ports = ["22"] + } + + target_tags = ["acas-sc"] + source_ranges = distinct(concat(var.iap_source_ranges, var.admin_ssh_source_ranges)) +} + +# SecurityCenter Management (HTTPS Web UI) +resource "google_compute_firewall" "acas_sc_https" { + name = "acas-sc-https" + network = data.google_compute_network.network.self_link + project = var.hub_project_id + + allow { + protocol = "tcp" + ports = ["443"] + } + + target_tags = ["acas-sc"] + source_ranges = distinct(concat(var.sc_mgmt_source_ranges, var.iap_source_ranges)) +} diff --git a/fast/stages-aw/shared-services/acas/securitycenter/main.tf b/fast/stages-aw/shared-services/acas/securitycenter/main.tf new file mode 100644 index 000000000..b394a6881 --- /dev/null +++ b/fast/stages-aw/shared-services/acas/securitycenter/main.tf @@ -0,0 +1,148 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +data "google_project" "current" { + project_id = var.shared_services_project_id +} + +data "google_compute_network" "network" { + name = split("/", var.network)[length(split("/", var.network)) - 1] + project = var.hub_project_id +} + +data "google_compute_image" "sc_golden" { + family = "acas-sc-golden" + project = var.shared_services_project_id +} + + +locals { + prefix = var.prefix == null ? "" : "${var.prefix}-" + compute_agent_sa = "serviceAccount:service-${data.google_project.current.number}@compute-system.iam.gserviceaccount.com" + compute_default_sa = "${data.google_project.current.number}-compute@developer.gserviceaccount.com" +} + +# --- KMS Key Lookup --- + +data "google_kms_key_ring" "default" { + name = "${local.prefix}acas-keyring-${var.region}" + location = var.region + project = var.shared_services_project_id +} + +data "google_kms_crypto_key" "default" { + name = "acas" + key_ring = data.google_kms_key_ring.default.id +} + +# --- Project Services --- + +resource "google_project_service" "services" { + for_each = toset([ + "compute.googleapis.com", + "cloudkms.googleapis.com", + "iam.googleapis.com", + "storage.googleapis.com" + ]) + project = var.shared_services_project_id + service = each.value + disable_on_destroy = false +} + +# --- Service Account --- + +resource "google_service_account" "sc" { + account_id = var.service_account_id + display_name = "ACAS SecurityCenter Service Account" + project = var.shared_services_project_id +} + +# --- KMS IAM --- + +resource "google_kms_crypto_key_iam_member" "kms_access" { + for_each = toset([ + local.compute_agent_sa, + "serviceAccount:${local.compute_default_sa}", + google_service_account.sc.member + ]) + crypto_key_id = data.google_kms_crypto_key.default.id + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + member = each.value +} + +# --- ACAS SecurityCenter --- + +module "sc-vm" { + source = "../../../../../modules/compute-vm" + project_id = var.shared_services_project_id + zone = var.zone + name = var.instance_name + + instance_type = var.machine_type + confidential_compute = var.enable_confidential_compute + + network_interfaces = [{ + network = var.network + subnetwork = var.subnetwork + }] + + metadata = { + enable-oslogin = true + block-project-ssh-keys = true + } + + shielded_config = { + enable_secure_boot = true + enable_vtpm = true + enable_integrity_monitoring = true + } + + encryption = { + kms_key_self_link = data.google_kms_crypto_key.default.id + } + + service_account = { + email = google_service_account.sc.email + } + + boot_disk = { + initialize_params = { + image = coalesce(var.image, data.google_compute_image.sc_golden.self_link) + size = var.boot_disk_size + type = "pd-ssd" + } + } + + attached_disks = [ + { + auto_delete = false + size = var.data_disk_size + name = "${var.instance_name}-data" + kms_key_self_link = data.google_kms_crypto_key.default.id + options = { + type = "pd-ssd" + } + } + ] + + tags = ["acas-sc"] + + depends_on = [ + google_project_service.services, + google_kms_crypto_key_iam_member.kms_access + ] +} + + diff --git a/fast/stages-aw/shared-services/acas/securitycenter/outputs.tf b/fast/stages-aw/shared-services/acas/securitycenter/outputs.tf new file mode 100644 index 000000000..a6e115817 --- /dev/null +++ b/fast/stages-aw/shared-services/acas/securitycenter/outputs.tf @@ -0,0 +1,33 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +output "internal_ip" { + description = "Internal IP of the ACAS SecurityCenter instance." + value = module.sc-vm.internal_ip +} + +output "service_account_email" { + description = "Service account email attached to SecurityCenter." + value = google_service_account.sc.email +} + +resource "google_storage_bucket_object" "tfvars" { + bucket = var.automation.outputs_bucket + name = "tfvars/shared-services-acas-sc.auto.tfvars.json" + content = jsonencode({ + acas_securitycenter_ip = module.sc-vm.internal_ip + }) +} + diff --git a/fast/stages-aw/shared-services/acas/securitycenter/provider.tf b/fast/stages-aw/shared-services/acas/securitycenter/provider.tf new file mode 100644 index 000000000..361a9a6cc --- /dev/null +++ b/fast/stages-aw/shared-services/acas/securitycenter/provider.tf @@ -0,0 +1,32 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +terraform { + required_version = ">= 1.11.4" + required_providers { + google = { + source = "hashicorp/google" + version = ">= 7.1.0, < 8.0.0" + } + google-beta = { + source = "hashicorp/google-beta" + version = ">= 7.1.0, < 8.0.0" + } + null = { + source = "hashicorp/null" + version = ">= 3.0.0" + } + } +} diff --git a/fast/stages-aw/shared-services/acas/securitycenter/variables.tf b/fast/stages-aw/shared-services/acas/securitycenter/variables.tf new file mode 100644 index 000000000..196b1cb9c --- /dev/null +++ b/fast/stages-aw/shared-services/acas/securitycenter/variables.tf @@ -0,0 +1,123 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +variable "admin_ssh_source_ranges" { + description = "List of IP ranges allowed to SSH directly into the instance (e.g., from other clouds via VPN/Interconnect)." + type = list(string) + default = [] +} + +variable "boot_disk_size" { + description = "Boot disk size in GB." + type = number + default = 100 +} + +variable "data_disk_size" { + description = "Additional data disk size in GB." + type = number + default = 500 +} + +variable "enable_confidential_compute" { + description = "Enable Confidential Compute for the SecurityCenter VM." + type = bool + default = true +} + +variable "iap_source_ranges" { + description = "List of IP ranges allowed to connect via Identity-Aware Proxy (IAP)." + type = list(string) + default = ["35.235.240.0/20"] +} + +variable "image" { + description = "The Golden Image to use for SecurityCenter." + type = string + default = null +} + +variable "instance_name" { + description = "Name of the SecurityCenter instance." + type = string + default = "acas-securitycenter" +} + +variable "network" { + description = "Self-link of the VPC network to attach Domain Controller VMs to." + type = string +} + +variable "hub_project_id" { + description = "Project ID that hosts the Shared VPC network." + type = string +} + +variable "prefix" { + description = "Prefix applied to resource names for org-level naming consistency. Set to null to disable prefixing." + type = string + default = null + validation { + condition = var.prefix != "" + error_message = "Prefix cannot be empty, use null instead." + } +} + +variable "shared_services_project_id" { + description = "GCP project ID where SC resources will be created." + type = string +} + +variable "region" { + description = "GCP region for deployment." + type = string + default = "us-east4" +} + +variable "sc_mgmt_source_ranges" { + description = "List of IP ranges allowed to access the SecurityCenter Web UI (port 443)." + type = list(string) + default = ["10.0.0.0/8"] +} + +variable "service_account_id" { + description = "Service account ID for SC VM." + type = string + default = "acas-sc-sa" +} + +variable "subnetwork" { + description = "Self-link of the subnetwork to attach Domain Controller VMs to." + type = string +} + +variable "zone" { + description = "GCP zone for the SC VM." + type = string + default = "us-east4-a" +} + +variable "machine_type" { + description = "Machine type for the SecurityCenter instance." + type = string + default = "n2d-standard-8" +} + +variable "automation" { + description = "Automation resources created by the bootstrap stage. Used to write ACAS outputs to the GCS outputs bucket for downstream consumption." + type = object({ + outputs_bucket = string + }) +} diff --git a/fast/stages-aw/shared-services/ad/README.md b/fast/stages-aw/shared-services/ad/README.md new file mode 100644 index 000000000..65586e6df --- /dev/null +++ b/fast/stages-aw/shared-services/ad/README.md @@ -0,0 +1,111 @@ + + +# Shared Services - Active Directory Domain Controller +This module deploys two high-availability Windows Server Domain Controllers (DCs) on Google Cloud Platform (GCP) . This infrastructure extends an existing identity perimeter into GCP, acting as a replication partner to a primary Active Directory environment hosted in the Azure example Cloud. + +## Architecture Overview +The configuration is designed to satisfy strict DoD Impact Level 5 (IL5) and DISA STIG compliance requirements while ensuring high availability for authentication services. + +**High Availability**: +Two Windows Server Compute Engine instances are deployed across separate availability zones (-a and -b) within your chosen region. + +**Static Internal Networking**: +Fixed internal IP addresses are reserved before VM creation using the net-address core module. These IPs must be provided to your Azure AD administration team to pre-stage AD Sites and Services. + +**Data Disks Segmentation**: +The Active Directory database (NTDS.dit) and SYSVOL logs are mapped to a secondary persistent SSD (pd-ssd). The auto_delete = false flag protects this directory from an accidental teardown. + +**DoD Hardening and CMEK**: +Computes utilize Shielded VM configurations (Secure Boot, vTPM, Integrity Monitoring) and Customer-Managed Encryption Keys (CMEK) via Cloud KMS to comply with IL5 organizational constraints. + +**Network Isolation**: +Internet egress paths like Cloud NAT are bypassed entirely. Internal APIs securely process logs or monitor platforms using Private Google Access. + +## Deployment Instructions +1. Preparing the terraform.tfvars fileCopy the provided sample file to your active local sheet: +``` +cp terraform.tfvars.sample terraform.tfvars +``` +Fill out your required project IDs, VPC network strings, and the Azure DC IPs. To fetch your active ad service CMEK encryption key reference from your previous networking stage, run: +``` +gcloud storage cat gs:///tfvars/3-networking.auto.tfvars.json | jq -r '.kms_keys["us-east4"].ad' +``` +2. Execution PipelineInitialize your backend space and execute a dry-run plan to verify structural dependencies hold: +``` +terraform init +terraform plan +``` +If your deployment matches compliance validations, execute the apply +``` +terraform apply +``` + +## Post-Deployment Verification +Once `terraform apply` completes successfully, the infrastructure engineer must coordinate with the identity team to execute the following validation steps: + +### Step 1: Connecting to DCs +1. Open a terminal and run `gcloud auth login` to authenticate. +2. Run `gcloud compute start-iap-tunnel DC_NAME 3389 --local-host-port=127.0.0.1:PORT --zone=DC_ZONE --project=SHARED_SERVICES_PROJECT`, this will create an IAP tunnel through the bastion host to 1 of the DC servers. NOTE: Select a port from the dynamic/private port range (49152-65535) +3. Open an RDP client and create a new connection. Enter the following info then save the connection: +``` +PC name: 127.0.0.1:PORT +Credentials: .\gcpadmin +``` +4. If the servers just deployed, wait about 5 minutes then try to connect. If it has been longer than 5 minutes, then you can connect immediately. +5. In the Shared Services project, go to Secret Manager and grab the password from `ad-initial-boot-password`. +6. Enter the password at the prompt and sign in. + + +### Step 2: Subnet Staging in AD Sites and Services +1. Open **Active Directory Sites and Services** (`dssite.msc`) from a management workstation. +2. Create a new Site object named `GCP-Region-Shared-Services` (or your local naming baseline). +3. Right-click **Subnets** -> **New Subnet**. +4. Enter your GCP subnetwork CIDR footprint (e.g., matching your deployed `var.subnetwork` range) and link it directly to the new GCP Site object. + +### Step 3: Run Active Directory Replica Promotion +Execute your target domain promotion path on the new GCP Windows VMs (either via an automated Offline Domain Join blob loop file or by utilizing `Install-ADDSDomainController` targeting the Azure cross-cloud IP addresses). + +### Step 4: Verify High-Availability Replication Topology +Log into your new GCP Domain Controllers via an approved secure access path, open an administrative PowerShell terminal, and run: +``` +repadmin /showrepl +``` + +## Variables + +| name | description | type | required | default | +|---|---|:---:|:---:|:---:| +| [domain_controllers](variables.tf#L19) | Detailed topology map of the target domain controllers. | map(object({…})) | ✓ | | +| [gcp_ntp_relay_ip](variables.tf#L28) | The internal IP address of the local GCP NTP Relay server that the DCs will sync time against. | string | ✓ | | +| [hub_project_id](variables.tf#L33) | The GCP project ID where Domain Controller resources will be deployed. Must be the project that owns the VPC (the VDSS host project), since Cloud Router, Cloud NAT, and firewall rules cannot cross-project reference networks. | string | ✓ | | +| [network](variables.tf#L44) | Self-link of the VPC network to attach Domain Controller VMs to. | string | ✓ | | +| [shared_services_project_id](variables.tf#L59) | The GCP project ID where Domain Controller resources will be deployed. | string | ✓ | | +| [boot_disk_image](variables.tf#L1) | Boot disk image for Domain Controller VMs. Must be an approved, hardened Windows Server image (e.g., Windows Server 2022 Datacenter) meeting DISA STIG baselines. | string | | "projects/windows-cloud/global/images/family/windows-2022" | +| [boot_disk_size](variables.tf#L7) | Boot disk size in GB for Domain Controller VMs. Must be at least as large as the boot image (100 GB recommended for Windows Server system files and updates). | number | | 100 | +| [data_disk_size](variables.tf#L13) | Size in GB for the secondary persistent disk dedicated to the Active Directory database (NTDS) and SYSVOL logs. | number | | 50 | +| [machine_type](variables.tf#L38) | Machine type for Domain r VMs. n2-standard-2 is sufficient for basic AD workloads. Change to n2-standard-4 for a larger VM. | string | | "n2-standard-2" | +| [prefix](variables.tf#L49) | Prefix applied to resource names for org-level naming consistency (e.g. 'da1'). Set to null to disable prefixing. | string | | null | + +## Outputs + +| name | description | sensitive | +|---|---|:---:| +| [domain_controller_ips](outputs.tf#L1) | The static internal IP addresses reserved and assigned to the GCP Domain Controllers. Hand these to the Azure AD team for Site-and-Services configuration. | | +| [domain_controller_names](outputs.tf#L9) | The exact names of the provisioned Compute Engine instances. | | +| [security_compliance](outputs.tf#L14) | A snapshot of the active security features verified at deployment time. | | +| [service_account_email](outputs.tf#L23) | The dedicated, least-privilege service account email assigned to the DCs. | | + diff --git a/fast/stages-aw/shared-services/ad/data/config.yml b/fast/stages-aw/shared-services/ad/data/config.yml new file mode 100644 index 000000000..c5840b48d --- /dev/null +++ b/fast/stages-aw/shared-services/ad/data/config.yml @@ -0,0 +1,40 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +domain_controllers: + "0": + region: "us-east4" + zone: "us-east4-a" + subnetwork: "projects/prod-il5-vdss-host/regions/us-east4/subnetworks/shared-services" + "1": + region: "us-east4" + zone: "us-east4-b" + subnetwork: "projects/prod-il5-vdss-host/regions/us-east4/subnetworks/shared-services" + +boot_disk_image: "projects/cis-public/global/images/family/cis-win2022-l2" + +gcp_ntp_relay_ip: 10.96.0.2 +# domain_controllers: +# "0": +# region: "us-east4" +# zone: "us-east4-a" +# subnetwork: "projects/xxxx-vdss-host/regions/us-east4/subnetworks/shared-services-default" +# "1": +# region: "us-east4" +# zone: "us-east4-b" +# subnetwork: "projects/xxxx-vdss-host/regions/us-east4/subnetworks/shared-services-default" +# # boot_disk_image: "projects/windows-cloud/global/images/family/windows-2022" +# # gcp_ntp_relay_ip: 10.0.0.1 + + diff --git a/fast/stages-aw/shared-services/ad/main.tf b/fast/stages-aw/shared-services/ad/main.tf new file mode 100644 index 000000000..ad06375fd --- /dev/null +++ b/fast/stages-aw/shared-services/ad/main.tf @@ -0,0 +1,270 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +locals { + prefix = var.prefix == null ? "" : "${var.prefix}-" + + dc_nodes = { + for k, v in var.domain_controllers : k => { + region = v.region + zone = v.zone + subnetwork = v.subnetwork + vm_name = "${local.prefix}gcp-dc-${k}" + ip_name = "${local.prefix}gcp-dc-ip-${k}" + } + } + + unique_dc_regions = distinct([ + for k, v in var.domain_controllers : v.region + ]) + + dc_ips_config = { + for k, v in local.dc_nodes : v.ip_name => { + region = v.region + subnetwork = v.subnetwork + name = v.ip_name + } + } +} + +data "google_project" "shared_services" { + project_id = var.shared_services_project_id +} + +resource "google_compute_shared_vpc_service_project" "service_attachment" { + host_project = var.hub_project_id + service_project = var.shared_services_project_id +} + +module "domain-controller-sa" { + source = "../../../../modules/iam-service-account" + project_id = var.shared_services_project_id + name = "ad-dc" + display_name = "AD Domain controller service account." + prefix = var.prefix + iam = {} +} + +module "domain-controller-vms" { + source = "../../../../modules/compute-vm" + for_each = local.dc_nodes + name = each.value.vm_name + project_id = var.shared_services_project_id + zone = each.value.zone + instance_type = var.machine_type + tags = ["domain-controller"] + + attached_disks = [{ + name = "${each.value.vm_name}-data" + device_name = "ad-data-disk" + size = var.data_disk_size + source_type = null + options = { + auto_delete = false + mode = "READ_WRITE" + type = "pd-ssd" + } + }] + + boot_disk = { + initialize_params = { + image = var.boot_disk_image + size = var.boot_disk_size + } + } + + shielded_config = { + enable_secure_boot = true + enable_vtpm = true + enable_integrity_monitoring = true + } + + encryption = { + kms_key_self_link = module.kms[each.value.region].keys["ad"].id + } + + network_interfaces = [{ + network = var.network + subnetwork = each.value.subnetwork + addresses = { + internal = module.domain-controller-ips.internal_addresses[each.value.ip_name].address + } + }] + + service_account = { + email = module.domain-controller-sa.email + } + + metadata = { + block-project-ssh-keys = "true" + serial-port-enable = "false" + ntp-server-ip = var.gcp_ntp_relay_ip + + windows-startup-script-bat = <> %windir%\system32\drivers\etc\hosts + +FOR /F "tokens=*" %%g IN ('powershell -NoProfile -ExecutionPolicy Bypass -Command "$headers = @{'Metadata-Flavor'='Google'}; (Invoke-RestMethod -Headers $headers -Uri 'http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token' -TimeoutSec 5).access_token"') DO SET "TOKEN=%%g" +FOR /F "tokens=*" %%g IN ('powershell -NoProfile -ExecutionPolicy Bypass -Command "$headers = @{'Authorization'='Bearer %TOKEN%'}; $resp = Invoke-RestMethod -Headers $headers -Uri 'https://secretmanager.googleapis.com/v1/projects/${data.google_project.shared_services.number}/secrets/ad-initial-boot-password/versions/latest:access' -TimeoutSec 5; [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($resp.payload.data))"') DO SET "SECURE_PASSWORD=%%g" +net user gcpadmin "%SECURE_PASSWORD%" /add /y /comment:"GCP Admin Bypass" /passwordchg:no +net user gcpadmin "%SECURE_PASSWORD%" +net localgroup Administrators gcpadmin /add +net user gcpadmin /active:yes +SET "SECURE_PASSWORD=" +SET "TOKEN=" +EOF + } + depends_on = [ + google_secret_manager_secret.ad_bootstrap_password, + google_secret_manager_secret_iam_member.ad_password_accessor + ] +} + +module "domain-controller-ips" { + source = "../../../../modules/net-address" + project_id = var.shared_services_project_id + internal_addresses = local.dc_ips_config + depends_on = [ + google_compute_shared_vpc_service_project.service_attachment + ] +} + +module "kms" { + source = "../../../../modules/kms" + project_id = var.shared_services_project_id + for_each = toset(local.unique_dc_regions) + keys = { + "ad" = { + rotation_period = "7776000s" + labels = { service = "active-directory" } + purpose = "ENCRYPT_DECRYPT" + version_template = { + algorithm = "GOOGLE_SYMMETRIC_ENCRYPTION" + protection_level = "HSM" + } + } + } + + iam = { + "roles/cloudkms.cryptoKeyEncrypterDecrypter" = [ + "serviceAccount:service-${data.google_project.shared_services.number}@compute-system.iam.gserviceaccount.com", + ] + } + keyring = { + location = each.value + name = "shdsvr-ad-keyring-${each.value}" + } +} + +resource "google_secret_manager_secret" "ad_bootstrap_password" { + project = var.shared_services_project_id + secret_id = "ad-initial-boot-password" + + replication { + user_managed { + dynamic "replicas" { + for_each = toset(local.unique_dc_regions) + content { + location = replicas.value + customer_managed_encryption { + kms_key_name = module.kms[replicas.value].keys["ad"].id + } + } + } + } + } + depends_on = [ + google_project_service.secretmanager_api, + google_kms_crypto_key_iam_member.secretmanager_kms_binding + ] +} + +resource "google_secret_manager_secret_iam_member" "ad_password_accessor" { + project = var.shared_services_project_id + secret_id = google_secret_manager_secret.ad_bootstrap_password.secret_id + role = "roles/secretmanager.secretAccessor" + member = "serviceAccount:${module.domain-controller-sa.email}" +} + +resource "google_secret_manager_secret_version" "ad_password_payload" { + secret = google_secret_manager_secret.ad_bootstrap_password.id + secret_data_wo = ephemeral.random_password.windows_bootstrap_password.result + secret_data_wo_version = 3 + depends_on = [ + google_project_service.secretmanager_api + ] +} + +resource "google_project_service_identity" "secretmanager_identity" { + provider = google-beta + project = var.shared_services_project_id + service = "secretmanager.googleapis.com" +} + +resource "google_kms_crypto_key_iam_member" "secretmanager_kms_binding" { + for_each = toset(local.unique_dc_regions) + crypto_key_id = module.kms[each.value].keys["ad"].id + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + member = "serviceAccount:${google_project_service_identity.secretmanager_identity.email}" +} + +ephemeral "random_password" "windows_bootstrap_password" { + length = 24 + special = true + override_special = "!#$^&*()-_=+[]{}<>?" + min_upper = 2 + min_lower = 2 + min_numeric = 2 + min_special = 2 +} + +resource "google_project_service" "secretmanager_api" { + project = var.shared_services_project_id + service = "secretmanager.googleapis.com" + disable_on_destroy = false +} + +resource "google_compute_firewall" "allow_rdp_from_iap_to_dcs" { + name = "${local.prefix}allow-rdp-from-iap-to-dc" + network = var.network + project = var.hub_project_id + + direction = "INGRESS" + source_ranges = ["35.235.240.0/20"] + + allow { + protocol = "tcp" + ports = ["3389"] + } + + target_tags = ["domain-controller"] +} + +resource "google_compute_firewall" "allow_restricted_egress_to_google_apis" { + name = "${local.prefix}allow-restricted-egress-to-google-apis" + network = var.network + project = var.hub_project_id + + direction = "EGRESS" + destination_ranges = ["199.36.153.4/30"] + + allow { + protocol = "tcp" + ports = ["443"] + } + + target_tags = ["domain-controller"] +} \ No newline at end of file diff --git a/fast/stages-aw/shared-services/ad/outputs.tf b/fast/stages-aw/shared-services/ad/outputs.tf new file mode 100644 index 000000000..c13da6ef3 --- /dev/null +++ b/fast/stages-aw/shared-services/ad/outputs.tf @@ -0,0 +1,42 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +output "domain_controller_ips" { + description = "The static internal IP addresses reserved and assigned to the GCP Domain Controllers. Hand these to the Azure AD team for Site-and-Services configuration." + value = { + for k, v in module.domain-controller-vms : + local.dc_nodes[k].vm_name => module.domain-controller-ips.internal_addresses[local.dc_nodes[k].ip_name].address + } +} + +output "domain_controller_names" { + description = "The exact names of the provisioned Compute Engine instances." + value = [for k, v in module.domain-controller-vms : local.dc_nodes[k].vm_name] +} + +output "security_compliance" { + description = "A snapshot of the active security features verified at deployment time." + value = { + shielded_vm_enabled = true + secure_boot_enabled = true + cmek_by_region = { for r, mod in module.kms : r => mod != null } + } +} + +output "service_account_email" { + description = "The dedicated, least-privilege service account email assigned to the DCs." + value = module.domain-controller-sa.email +} diff --git a/fast/stages-aw/shared-services/ad/terraform.tfvars.sample b/fast/stages-aw/shared-services/ad/terraform.tfvars.sample new file mode 100644 index 000000000..c2b0fe095 --- /dev/null +++ b/fast/stages-aw/shared-services/ad/terraform.tfvars.sample @@ -0,0 +1,49 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +# Must be the VDSS host project (VPC owner) — Cloud Router, NAT, and +# firewall rules cannot cross-project reference networks. +hub_project_id = "xxxx-vdss-host" +prefix = "da1" + +region = "us-east4" +network = "projects/xxxx-vdss-host/global/networks/shared-services" +domain_controllers= { + "0" = { + region = "us-east4" + zone = string + subnetwork = string + }, + "1" = { + region = string + zone = string + subnetwork = string + } +} +subnetwork = "projects/xxxx-vdss-host/regions/us-east4/subnetworks/shared-services" + +gcp_ntp_relay_ip = "10.0.0.2" + +# Required for IL5 — constraints/gcp.restrictNonCmekServices enforced. +# Use the dedicated AD key from stage 3-networking (not the shared "default" key): +# gcloud storage cat gs:///tfvars/3-networking.auto.tfvars.json | jq -r '.kms_keys["us-east4"].ad' +encryption_key = "projects/xxxx-vdss-host/locations/us-east4/keyRings/vdss-keyring-us-east4/cryptoKeys/ad" + +# Uncomment to customize: +# boot_disk_image = "projects/windows-cloud/global/images/family/windows-2022" +# boot_disk_size = 100 +# data_disk_size = 50 +# machine_type = "n2-standard-2" \ No newline at end of file diff --git a/fast/stages-aw/shared-services/ad/variables.tf b/fast/stages-aw/shared-services/ad/variables.tf new file mode 100644 index 000000000..0c22c98fa --- /dev/null +++ b/fast/stages-aw/shared-services/ad/variables.tf @@ -0,0 +1,78 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +variable "boot_disk_image" { + description = "Boot disk image for Domain Controller VMs. Must be an approved, hardened Windows Server image (e.g., Windows Server 2022 Datacenter) meeting DISA STIG baselines." + type = string + default = "projects/windows-cloud/global/images/family/windows-2022" +} + +variable "boot_disk_size" { + description = "Boot disk size in GB for Domain Controller VMs. Must be at least as large as the boot image (100 GB recommended for Windows Server system files and updates)." + type = number + default = 100 +} + +variable "data_disk_size" { + description = "Size in GB for the secondary persistent disk dedicated to the Active Directory database (NTDS) and SYSVOL logs." + type = number + default = 50 +} + +variable "domain_controllers" { + description = "Detailed topology map of the target domain controllers." + type = map(object({ + region = string + zone = string + subnetwork = string + })) +} + +variable "gcp_ntp_relay_ip" { + description = "The internal IP address of the local GCP NTP Relay server that the DCs will sync time against." + type = string +} + +variable "hub_project_id" { + description = "The GCP project ID where Domain Controller resources will be deployed. Must be the project that owns the VPC (the VDSS host project), since Cloud Router, Cloud NAT, and firewall rules cannot cross-project reference networks." + type = string +} + +variable "machine_type" { + description = "Machine type for Domain r VMs. n2-standard-2 is sufficient for basic AD workloads. Change to n2-standard-4 for a larger VM." + type = string + default = "n2-standard-2" +} + +variable "network" { + description = "Self-link of the VPC network to attach Domain Controller VMs to." + type = string +} + +variable "prefix" { + description = "Prefix applied to resource names for org-level naming consistency (e.g. 'da1'). Set to null to disable prefixing." + type = string + default = null + validation { + condition = var.prefix != "" + error_message = "Prefix cannot be empty, use null instead." + } +} + +variable "shared_services_project_id" { + description = "The GCP project ID where Domain Controller resources will be deployed." + type = string +} diff --git a/fast/stages-aw/shared-services/ad/versions.tf b/fast/stages-aw/shared-services/ad/versions.tf new file mode 100644 index 000000000..21d7cdb6b --- /dev/null +++ b/fast/stages-aw/shared-services/ad/versions.tf @@ -0,0 +1,29 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +terraform { + required_version = ">= 1.11.4" + required_providers { + google = { + source = "hashicorp/google" + version = ">= 7.0.1, < 8.0.0" + } + google-beta = { + source = "hashicorp/google-beta" + version = ">= 7.0.1, < 8.0.0" + } + } +} diff --git a/fast/stages-aw/shared-services/bcap/README.md b/fast/stages-aw/shared-services/bcap/README.md new file mode 100644 index 000000000..1a310a546 --- /dev/null +++ b/fast/stages-aw/shared-services/bcap/README.md @@ -0,0 +1,112 @@ + + +# Boundary Cloud Access Point (BCAP) + +This Terraform blueprint provisions the necessary Google Cloud infrastructure to establish a highly available connection to a Boundary Cloud Access Point (BCAP) provider, such as DISA, using Google Cloud Partner Interconnect. + +The BCAP architecture follows the **99.99% Availability for Partner Interconnect** topology as recommended in the [GCP Documentation](https://cloud.google.com/network-connectivity/docs/interconnect/tutorials/partner-creating-9999-availability). +Google BCAP Contact: + + +- [Architecture](#architecture) +- [Prerequisites](#prerequisites) +- [Deployment](#deployment) +- [Disclaimer](#disclaimer) +- [Variables](#variables) +- [Outputs](#outputs) + + +## Architecture + +This blueprint creates the following resources: + +1. **VPC Network** + * A custom-mode VPC (`auto_create_subnetworks = false`), named using `network_name`. +2. **Two VPC Subnets** + * Names are defined via `subnet_configs`. + * Their regions are automatically assigned to `region1` (for `subnet1`) and `region2` (for `subnet2`). + * The IP CIDRs are calculated and split into two /25s from the /24 `dod_base_cidr_block` variable. + * Private Google Access and Flow Logs are enabled by default. +3. **Two Cloud Routers** + * Names are defined via `router_configs` (`router1` is placed in `region1` and `router2` in `region2`). + * Each router is attached to the created VPC, uses the `router_google_asn` (16550 for Partner Interconnect), and by default, advertises **both** calculated DoD /25 subnets. +4. **Four VLAN Attachments** + * Defined via the `attachment_configs` variable and configured as `PARTNER` type. + * The region for each attachment is derived from the region of the router it's linked to via `router_key`. + * MTU is set to 1440 by default as recommended for BCAP. + +## Prerequisites + +* Review the [GCP Documentation](https://cloud.google.com/network-connectivity/docs/interconnect/tutorials/partner-creating-9999-availability). +* The **base /24 CIDR block** assigned by the Department of Defense Network Information Center (DoD NIC) (`dod_base_cidr_block`). +* Completion of BCAP onboarding steps (Phase 1 & 2 from the guide), including obtaining necessary approvals (e.g., Cloud Permission to Connect (CPTC)) and the official IP space from DoD NIC. +* MD5 Authentication Keys (provided by customer/mission owner) to be configured on the Cloud Router BGP sessions *after* the attachments are provisioned and activated by the partner. + +## Deployment + +1. Create a `terraform.tfvars` file based on the example provided (`terraform.tfvars.sample`). +2. Populate the `terraform.tfvars` file with values specific to your environment. +3. Run `terraform init`. +4. Run `terraform plan`. +5. Run `terraform apply`. + +**Post-Apply Steps:** + +1. Retrieve the `pairing_keys` from the Terraform output (`terraform output -json pairing_keys`) or from the Google Cloud web console within each VLAN Attachment's detail screen. +2. Provide these keys to the BCAP provider (DISA/Google BCAP Team) to activate the connections. +3. Once attachments are active, configure BGP peering on the Cloud Routers, including Peer ASN (e.g., 64519 for DISA) and MD5 authentication using the keys provided by the mission owner. + +**Deployment Verification** + +***VPC and Subnetworks*** + +1. Navigate to the [VPC Network](https://console.cloud.google.com/networking/networks/list) within your hub network project. +2. Click on the BCAP VPC name. +3. Click on the Subnets tab. +4. Confirm that the (x1) VPC and (x2) Subnets exist and that the DISA provided /24 `dod_base_cidr_block` is split into two /25 `dod_split_cidr_blocks` for each subnet. + +***Cloud Routers and VLAN Attachments*** + +1. Navigate to the [Cloud Router](https://console.cloud.google.com/hybrid/routers/list) resource within your hub network project. +2. Confirm that (x2) BCAP Cloud Routers exist with their specified VPC, region, and that (x2) VLAN Attachments exist per Cloud router. + +## Disclaimer +- The present GCP Terraform Blueprint in this project is set up and intended to be implemented in an Impact Level 4 (IL4) and Impact Level 5 (IL5) environments using the Assured Workloads within the Google Cloud Platform (GCP) organization. + +## Variables + +| name | description | type | required | default | +|---|---|:---:|:---:|:---:| +| [attachment_configs](variables.tf#L1) | Configuration map for the four Partner VLAN attachments required for 99.99% availability. The region for each attachment is derived from its associated `router_key`. | map(object({…})) | ✓ | | +| [hub_project_id](variables.tf#L29) | The GCP project ID where BCAP resources (VPC, Subnets, Routers, Attachments) will be deployed. | string | ✓ | | +| [network_name](variables.tf#L34) | VPC network name. | string | ✓ | | +| [region1](variables.tf#L39) | The primary GCP region for BCAP deployment (hosts router1 and their associated VLAN attachments). | string | ✓ | | +| [region2](variables.tf#L44) | The secondary GCP region for BCAP deployment (hosts router2 and their associated VLAN attachments). | string | ✓ | | +| [router_configs](variables.tf#L49) | Configuration map for the two Cloud Routers. Names are user-defined; regions are derived from `region1` (for router1) and `region2` (for router2). Keys must be 'router1' and 'router2'. | map(object({…})) | ✓ | | +| [subnetwork_name](variables.tf#L67) | VPC subnetwork name. | string | ✓ | | +| [subnetwork_region](variables.tf#L72) | VPC subnetwork region. | string | ✓ | | +| [router_google_asn](variables.tf#L61) | Autonomous System Number (ASN) for the Google side of the BGP sessions on Cloud Routers (should be 16550 for Partner Interconnect). | number | | 16550 | + +## Outputs + +| name | description | sensitive | +|---|---|:---:| +| [attachment_names](outputs.tf#L1) | Names of the created VLAN attachments. | | +| [cloud_routers](outputs.tf#L8) | Details of the created Cloud Routers (map keyed by 'router1', 'router2'). | | +| [pairing_keys](outputs.tf#L13) | Pairing keys for each VLAN attachment. Provide these to the BCAP/DISA team. | ✓ | +| [vlan_attachments](outputs.tf#L21) | Details of the created VLAN attachments. | | + diff --git a/fast/stages-aw/shared-services/bcap/data/config.yml b/fast/stages-aw/shared-services/bcap/data/config.yml new file mode 100644 index 000000000..fc8efd4e0 --- /dev/null +++ b/fast/stages-aw/shared-services/bcap/data/config.yml @@ -0,0 +1,49 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +attachment_configs: + router1-attachment1: + name: "bcap-router1-attachment1-domain1" + description: "BCAP Attachment 1 to Router 1 (Region 1 / Domain 1)" + router_key: "router1" + edge_availability_domain: "AVAILABILITY_DOMAIN_1" + mtu: 1440 + router1-attachment2: + name: "bcap-router1-attachment2-domain2" + description: "BCAP Attachment 2 to Router 1 (Region 1 / Domain 2)" + router_key: "router1" + edge_availability_domain: "AVAILABILITY_DOMAIN_2" + mtu: 1440 + router2-attachment1: + name: "bcap-router2-attachment1-domain1" + description: "BCAP Attachment 1 to Router 2 (Region 2 / Domain 1)" + router_key: "router2" + edge_availability_domain: "AVAILABILITY_DOMAIN_1" + mtu: 1440 + router2-attachment2: + name: "bcap-router2-attachment2-domain2" + description: "BCAP Attachment 2 to Router 2 (Region 2 / Domain 2)" + router_key: "router2" + edge_availability_domain: "AVAILABILITY_DOMAIN_2" + mtu: 1440 +network_name: "bcap" +region1: "us-east4" +region2: "us-central1" +router_configs: + router1: + name: "bcap-cloud-router-primary" + description: "Primary BCAP router" + router2: + name: "bcap-cloud-router-secondary" + description: "Secondary BCAP router" \ No newline at end of file diff --git a/fast/stages-aw/shared-services/bcap/main.tf b/fast/stages-aw/shared-services/bcap/main.tf new file mode 100644 index 000000000..18abe082d --- /dev/null +++ b/fast/stages-aw/shared-services/bcap/main.tf @@ -0,0 +1,89 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +locals { + dod_advertised_ip_ranges = { + (data.google_compute_subnetwork.subnet.ip_cidr_range) = "DoD-Assigned-Subnet-${var.subnetwork_name}" + } + + router_configs = var.router_configs + + router_names = { + router1 = google_compute_router.routers["router1"].name + router2 = google_compute_router.routers["router2"].name + } + + router_regions = { + router1 = var.region1 + router2 = var.region2 + } +} + +data "google_compute_subnetwork" "subnet" { + name = var.subnetwork_name + project = var.hub_project_id + region = var.subnetwork_region +} + +data "google_compute_network" "vpc" { + name = var.network_name + project = var.hub_project_id +} + +# Cloud Routers (x2) +resource "google_compute_router" "routers" { + for_each = local.router_configs + + project = var.hub_project_id + name = each.value.name + network = data.google_compute_network.vpc.self_link + region = local.router_regions[each.key] + bgp { + asn = var.router_google_asn + advertise_mode = "CUSTOM" + + dynamic "advertised_ip_ranges" { + for_each = local.dod_advertised_ip_ranges + content { + range = advertised_ip_ranges.key + description = advertised_ip_ranges.value + } + } + } + description = each.value.description +} + +# VLAN Attachments (x4) +resource "google_compute_interconnect_attachment" "attachments" { + for_each = var.attachment_configs + + project = var.hub_project_id + name = each.value.name + description = each.value.description + region = local.router_regions[each.value.router_key] + router = local.router_names[each.value.router_key] + + type = "PARTNER" + edge_availability_domain = each.value.edge_availability_domain + mtu = each.value.mtu + vlan_tag8021q = each.value.vlan_id + + admin_enabled = true + + depends_on = [ + google_compute_router.routers + ] +} diff --git a/fast/stages-aw/shared-services/bcap/outputs.tf b/fast/stages-aw/shared-services/bcap/outputs.tf new file mode 100644 index 000000000..d00aca477 --- /dev/null +++ b/fast/stages-aw/shared-services/bcap/outputs.tf @@ -0,0 +1,40 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +output "attachment_names" { + description = "Names of the created VLAN attachments." + value = { + for k, attachment in google_compute_interconnect_attachment.attachments : k => attachment.name + } +} + +output "cloud_routers" { + description = "Details of the created Cloud Routers (map keyed by 'router1', 'router2')." + value = google_compute_router.routers +} + +output "pairing_keys" { + description = "Pairing keys for each VLAN attachment. Provide these to the BCAP/DISA team." + value = { + for k, attachment in google_compute_interconnect_attachment.attachments : k => attachment.pairing_key + } + sensitive = true +} + +output "vlan_attachments" { + description = "Details of the created VLAN attachments." + value = google_compute_interconnect_attachment.attachments +} diff --git a/fast/stages-aw/shared-services/bcap/terraform.tfvars.sample b/fast/stages-aw/shared-services/bcap/terraform.tfvars.sample new file mode 100644 index 000000000..845160e57 --- /dev/null +++ b/fast/stages-aw/shared-services/bcap/terraform.tfvars.sample @@ -0,0 +1,85 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +hub_project_id = "xxxx-shared-services" + +# VPC Configuration +network_name = "vdss-bcap-0" + +# Primary and Secondary Regions for BCAP Deployment +region1 = "us-central1" +region2 = "us-east4" + +# DoD Base CIDR Block (to be split into two /25s) - Replace with your DoD NIC assigned /24 CIDR +dod_base_cidr_block = "x.x.x.0/24" + +# Subnet Configurations +subnet_configs = { + "subnet1" = { + name = "bcap-dod-subnet-primary" + description = "BCAP DoD Subnet 1 (Region 1)" + }, + "subnet2" = { + name = "bcap-dod-subnet-secondary" + description = "BCAP DoD Subnet 2 (Region 2)" + } +} + +# Router Configurations +router_configs = { + "router1" = { + name = "bcap-cloud-router-primary" + description = "Primary BCAP Cloud Router" + }, + "router2" = { + name = "bcap-cloud-router-secondary" + description = "Secondary BCAP Cloud Router" + } +} + +# VLAN Attachment Configurations +attachment_configs = { + "router1-attachment1" = { + name = "bcap-router1-attachment1-domain1" + description = "BCAP Attachment 1 to Router 1 (Region 1 / Domain 1)" + router_key = "router1" + edge_availability_domain = "AVAILABILITY_DOMAIN_1" + mtu = 1440 + }, + "router1-attachment2" = { + name = "bcap-router1-attachment2-domain2" + description = "BCAP Attachment 2 to Router 1 (Region 1 / Domain 2)" + router_key = "router1" + edge_availability_domain = "AVAILABILITY_DOMAIN_2" + mtu = 1440 + }, + "router2-attachment1" = { + name = "bcap-router2-attachment1-domain1" + description = "BCAP Attachment 1 to Router 2 (Region 2 / Domain 1)" + router_key = "router2" + edge_availability_domain = "AVAILABILITY_DOMAIN_1" + mtu = 1440 + }, + "router2-attachment2" = { + name = "bcap-router2-attachment2-domain2" + description = "BCAP Attachment 2 to Router 2 (Region 2 / Domain 2)" + router_key = "router2" + edge_availability_domain = "AVAILABILITY_DOMAIN_2" + mtu = 1440 + } +} + +router_google_asn = 16550 diff --git a/fast/stages-aw/shared-services/bcap/variables.tf b/fast/stages-aw/shared-services/bcap/variables.tf new file mode 100644 index 000000000..10f005c28 --- /dev/null +++ b/fast/stages-aw/shared-services/bcap/variables.tf @@ -0,0 +1,91 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +variable "attachment_configs" { + description = "Configuration map for the four Partner VLAN attachments required for 99.99% availability. The region for each attachment is derived from its associated `router_key`." + type = map(object({ + name = string + description = optional(string, "BCAP VLAN Attachment") + router_key = string + edge_availability_domain = string + mtu = optional(number, 1440) + vlan_id = optional(number, null) + })) + validation { + condition = length(keys(var.attachment_configs)) == 4 + error_message = "Exactly four attachment configurations must be provided for 99.99% availability." + } + validation { + condition = alltrue([ + for k, v in var.attachment_configs : contains(["AVAILABILITY_DOMAIN_1", "AVAILABILITY_DOMAIN_2"], v.edge_availability_domain) + ]) + error_message = "The edge_availability_domain must be either AVAILABILITY_DOMAIN_1 or AVAILABILITY_DOMAIN_2." + } + validation { + condition = alltrue([ + for k, v in var.attachment_configs : contains(["router1", "router2"], v.router_key) + ]) + error_message = "The router_key must be either 'router1' or 'router2'." + } +} + +variable "hub_project_id" { + description = "The GCP project ID where BCAP resources (VPC, Subnets, Routers, Attachments) will be deployed." + type = string +} + +variable "network_name" { + description = "VPC network name." + type = string +} + +variable "region1" { + description = "The primary GCP region for BCAP deployment (hosts router1 and their associated VLAN attachments)." + type = string +} + +variable "region2" { + description = "The secondary GCP region for BCAP deployment (hosts router2 and their associated VLAN attachments)." + type = string +} + +variable "router_configs" { + description = "Configuration map for the two Cloud Routers. Names are user-defined; regions are derived from `region1` (for router1) and `region2` (for router2). Keys must be 'router1' and 'router2'." + type = map(object({ + name = string + description = optional(string, "BCAP Cloud Router") + })) + validation { + condition = length(keys(var.router_configs)) == 2 && contains(keys(var.router_configs), "router1") && contains(keys(var.router_configs), "router2") + error_message = "The router_configs map must contain exactly two entries with keys 'router1' and 'router2'." + } +} + +variable "router_google_asn" { + description = "Autonomous System Number (ASN) for the Google side of the BGP sessions on Cloud Routers (should be 16550 for Partner Interconnect)." + type = number + default = 16550 +} + +variable "subnetwork_name" { + description = "VPC subnetwork name." + type = string +} + +variable "subnetwork_region" { + description = "VPC subnetwork region." + type = string +} diff --git a/fast/stages-aw/shared-services/bcap/versions.tf b/fast/stages-aw/shared-services/bcap/versions.tf new file mode 100644 index 000000000..21d7cdb6b --- /dev/null +++ b/fast/stages-aw/shared-services/bcap/versions.tf @@ -0,0 +1,29 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +terraform { + required_version = ">= 1.11.4" + required_providers { + google = { + source = "hashicorp/google" + version = ">= 7.0.1, < 8.0.0" + } + google-beta = { + source = "hashicorp/google-beta" + version = ">= 7.0.1, < 8.0.0" + } + } +} diff --git a/fast/stages-aw/shared-services/dns/README.md b/fast/stages-aw/shared-services/dns/README.md new file mode 100644 index 000000000..a66932e06 --- /dev/null +++ b/fast/stages-aw/shared-services/dns/README.md @@ -0,0 +1,125 @@ + + +# Shared Services — DNS + +This module deploys IL5-compliant DNS forwarding for cross-cloud name resolution. +Domain-specific forwarding zones send queries to the Enterprise DNS resolver in Azure +via the cross-cloud VPN tunnel. DNS peering zones chain resolution across VPCs +within Cloud DNS's 3-VPC / 1-transitive-hop limit. + +## Architecture + +``` +Spoke VPCs ──DNS peering──▶ Landing VPC ──DNS peering──▶ CSP Landing VPC ──forwarding──▶ Enterprise DNS (Azure) +(shared-services, (VPN tunnel) + tenant-transit) +``` + +### Resolution Order + +1. Response policy catches `*.googleapis.com` → PSC endpoint (stage 3-networking) +2. Private zone catches org domain → internal records (stage 3-networking) +3. Forwarding zones catch configured domains (e.g. `mil.`, `gov.`) → Enterprise DNS +4. Compute Engine internal DNS resolves `*.internal` → VM IPs (preserved) +5. Google public DNS resolves everything else + +### Why Domain-Specific Zones + +A root `"."` forwarding zone would intercept Compute Engine internal DNS names +at step 3 before they reach step 4, breaking `.internal` resolution. A validation +rule prevents this. See [Cloud DNS best practices](https://docs.cloud.google.com/dns/docs/best-practices). + +### DNS Forwarding Constraint + +Cloud DNS forwarding cannot use NCC transitive routing. The forwarding zone must +be authorized for the CSP Landing VPC where VPN tunnels terminate. Other VPCs +reach it via DNS peering zones (a control-plane feature, no data-plane transit). + +## Prerequisites + +1. **Enterprise DNS resolver IP** — get from Brian Cunningham +2. **Azure VPN tunnel** must be UP (`3-vpn/` stage) +3. **BGP advertisement** — Cloud Router must advertise `35.199.192.0/19` to Azure + (`3-vpn/gcp_common.tf`). This is the source IP range Cloud DNS uses for + forwarding queries; without it, responses cannot route back through the VPN. +4. **Azure firewall** must allow UDP/TCP 53 from `35.199.192.0/19` +5. **Shared-services SA** must have `roles/dns.admin` on the VDSS host project + (granted by the IAM bindings in `3-networking/projects.tf`) + +## Deployment + +```bash +cd automation +bash shared-services-deploy.sh +``` + +After apply, forwarding zone info is published to GCS at +`tfvars/shared-services-dns.auto.tfvars.json`. + +## Verification + +```bash +# From a GCP VM in the landing VPC: +dig test.example.internal @35.199.192.0 # forwarded → Enterprise DNS +dig vm-name.us-east4-a.c.project.internal # internal DNS preserved +dig storage.googleapis.com @35.199.192.0 # googleapis → PSC endpoint +``` + +## Usage + +```hcl +module "dns" { + source = "./shared-services/dns" + host_project_id = "my-vdss-host" + prefix = "da1" + automation = { outputs_bucket = "my-prod-iac-core-outputs" } + vpc_self_links = { + csp_landing = module.csp-landing-vpc.self_link + landing = module.vdss-vpc.self_link + shared_services = module.shared-services-vpc.self_link + tenant_transit = module.tenant-transit-vpc.self_link + } + forwarding_zones = { + mil = { + domain = "mil." + forwarders = { "10.200.0.4" = "private" } + } + } + private_zone_domain = "da1-il5-vdss.private.example.internal." + dns_policy_rules_file = "../../3-networking/data/dns-policy-rules.yaml" +} +``` + +## Variables + +| name | description | type | required | default | +|---|---|:---:|:---:|:---:| +| [automation](variables.tf#L1) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | +| [host_project_id](variables.tf#L29) | The GCP project ID where DNS zones will be created (the VDSS host project that owns the VPCs). | string | ✓ | | +| [vpc_self_links](variables.tf#L50) | VPC self-links used for DNS zone authorization and peering. | object({…}) | ✓ | | +| [dns_policy_rules_file](variables.tf#L8) | Path to the YAML file containing DNS response policy rules for Private Google Access (googleapis.com, gcr.io, etc.). If set, a response policy is created for the shared-services VPC. | string | | null | +| [forwarding_zones](variables.tf#L14) | DNS forwarding zones keyed by name. Each zone forwards queries for the specified domain to the given forwarder IPs via the cross-cloud VPN tunnel. Use domain-specific zones (e.g. 'mil.', 'Enterprise.mil.') — root domain '.' breaks Compute Engine internal DNS. | map(object({…})) | | {} | +| [prefix](variables.tf#L34) | Prefix applied to resource names for org-level naming consistency (e.g. 'da1'). Set to null to disable prefixing. | string | | null | +| [private_zone_domain](variables.tf#L44) | Domain of the existing private DNS zone in the landing VPC (e.g. 'da1-il5-vdss.private.example.internal.'). A peering zone is created so shared-services and tenant-transit VPCs can resolve records in it. | string | | null | + +## Outputs + +| name | description | sensitive | +|---|---|:---:| +| [forwarding_zones](outputs.tf#L1) | Map of forwarding zone names to their domains. | | +| [peering_zones](outputs.tf#L11) | Map of peering zone names for the landing VPC. | | + diff --git a/fast/stages-aw/shared-services/dns/data/config.yml b/fast/stages-aw/shared-services/dns/data/config.yml new file mode 100644 index 000000000..f41d36e76 --- /dev/null +++ b/fast/stages-aw/shared-services/dns/data/config.yml @@ -0,0 +1,25 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +forwarding_zones: + mil: + domain: "mil." + forwarders: + "8.8.8.8": "private" + gov: + domain: "gov." + forwarders: + "8.8.8.1": "private" +private_zone_domain: "da1-il5-vdss.private.example.internal." + diff --git a/fast/stages-aw/shared-services/dns/main.tf b/fast/stages-aw/shared-services/dns/main.tf new file mode 100644 index 000000000..ad102d84c --- /dev/null +++ b/fast/stages-aw/shared-services/dns/main.tf @@ -0,0 +1,120 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# Forwarding zones — authorized for CSP Landing VPC (direct VPN connectivity). +# Cloud DNS forwarding cannot use NCC transitive routing, so the forwarding +# zone must be in the VPC where VPN tunnels terminate. +module "dns-forwarding-zones" { + source = "../../../../modules/dns" + for_each = var.forwarding_zones + project_id = var.host_project_id + name = "${var.prefix}-fwd-${each.key}" + zone_config = { + domain = each.value.domain + forwarding = { + forwarders = each.value.forwarders + client_networks = [var.vpc_self_links.csp_landing] + } + } +} + +# DNS peering: Landing VPC → CSP Landing VPC (1st hop). +# Allows the hub VPC to resolve forwarded domains through the CSP +# Landing VPC where the forwarding zone is authoritative. +module "dns-peering-landing" { + source = "../../../../modules/dns" + for_each = var.forwarding_zones + project_id = var.host_project_id + name = "${var.prefix}-peer-landing-${each.key}" + zone_config = { + domain = each.value.domain + peering = { + client_networks = [var.vpc_self_links.landing] + peer_network = var.vpc_self_links.csp_landing + } + } +} + +# DNS peering: spoke VPCs → Landing VPC (transitive hop). +# Shared-services and tenant-transit VPCs peer through Landing to reach +# the CSP Landing forwarding zone. This is within the 3-VPC / 1-transitive-hop +# limit for Cloud DNS peering. +module "dns-peering-spokes" { + source = "../../../../modules/dns" + for_each = var.forwarding_zones + project_id = var.host_project_id + name = "${var.prefix}-peer-spokes-${each.key}" + zone_config = { + domain = each.value.domain + peering = { + client_networks = [ + var.vpc_self_links.shared_services, + var.vpc_self_links.tenant_transit, + ] + peer_network = var.vpc_self_links.landing + } + } +} + +# DNS peering: spoke VPCs → Landing VPC for the org private zone. +# The private zone is defined in stage 3-networking and authorized for the +# landing VPC only. This peering zone lets shared-services and tenant-transit +# VPCs resolve records in it without modifying stage 3. +module "dns-peering-private-zone" { + source = "../../../../modules/dns" + count = var.private_zone_domain != null ? 1 : 0 + project_id = var.host_project_id + name = "${var.prefix}-peer-spokes-private" + zone_config = { + domain = var.private_zone_domain + peering = { + client_networks = [ + var.vpc_self_links.shared_services, + var.vpc_self_links.tenant_transit, + ] + peer_network = var.vpc_self_links.landing + } + } +} + +# DNS response policy for Private Google Access on the shared-services VPC. +# Redirects googleapis.com, gcr.io, etc. to the PSC endpoint so traffic +# stays on the Google network. Mirrors the policy in stage 3-networking +# which covers only the landing VPC. +module "dns-policy-googleapis" { + source = "../../../../modules/dns-response-policy" + count = var.dns_policy_rules_file != null ? 1 : 0 + project_id = var.host_project_id + name = "googleapis-shared-services" + factories_config = { + rules = var.dns_policy_rules_file + } + networks = { + shared-services = var.vpc_self_links.shared_services + } +} + +resource "google_storage_bucket_object" "tfvars" { + bucket = var.automation.outputs_bucket + name = "tfvars/shared-services-dns.auto.tfvars.json" + content = jsonencode({ + dns_forwarding_zones = { + for k, v in module.dns-forwarding-zones : k => { + name = v.name + domain = v.domain + } + } + }) +} diff --git a/fast/stages-aw/shared-services/dns/outputs.tf b/fast/stages-aw/shared-services/dns/outputs.tf new file mode 100644 index 000000000..c122ad0e1 --- /dev/null +++ b/fast/stages-aw/shared-services/dns/outputs.tf @@ -0,0 +1,35 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +output "forwarding_zones" { + description = "Map of forwarding zone names to their domains." + value = { + for k, v in module.dns-forwarding-zones : k => { + name = v.name + domain = v.domain + } + } +} + +output "peering_zones" { + description = "Map of peering zone names for the landing VPC." + value = { + for k, v in module.dns-peering-landing : k => { + name = v.name + domain = v.domain + } + } +} diff --git a/fast/stages-aw/shared-services/dns/terraform.tfvars.sample b/fast/stages-aw/shared-services/dns/terraform.tfvars.sample new file mode 100644 index 000000000..92e0306a5 --- /dev/null +++ b/fast/stages-aw/shared-services/dns/terraform.tfvars.sample @@ -0,0 +1,63 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +host_project_id = "xxxx-vdss-host" +prefix = "da1" + +automation = { + outputs_bucket = "xxxx-prod-iac-core-outputs" +} + +vpc_self_links = { + csp_landing = "projects/xxxx-vdss-host/global/networks/csp-landing" + landing = "projects/xxxx-vdss-host/global/networks/vdss-landing-0" + shared_services = "projects/xxxx-vdss-host/global/networks/shared-services" + tenant_transit = "projects/xxxx-vdss-host/global/networks/tenant-transit" +} + +# Domain-specific forwarding zones — forward to Enterprise DNS resolver in Azure. +# Do NOT use "." (root domain) — it breaks Compute Engine internal DNS. +# Get the Enterprise DNS resolver IP from your network administrator. +# +# Prerequisites: +# - Azure VPN tunnel must be UP (3-vpn stage) +# - Cloud Router must advertise 35.199.192.0/19 to Azure (3-vpn/gcp_common.tf). +# This is the source IP range Cloud DNS uses for forwarding queries — without +# it, Azure cannot route DNS responses back through the VPN tunnel. +# See: https://cloud.google.com/dns/docs/zones/forwarding-zones +# - Azure-side firewall must allow UDP/TCP 53 from 35.199.192.0/19 +# Peer to the org private zone so shared-services and tenant-transit VPCs +# can resolve internal records without modifying stage 3-networking. +private_zone_domain = "da1-il5-vdss.private.example.internal." + +# Response policy rules for Private Google Access (googleapis.com → PSC endpoint). +# Use the same rules file as stage 3-networking. +dns_policy_rules_file = "../../3-networking/data/dns-policy-rules.yaml" + +forwarding_zones = { + mil = { + domain = "mil." + forwarders = { + "" = "private" + } + } + gov = { + domain = "gov." + forwarders = { + "" = "private" + } + } +} diff --git a/fast/stages-aw/shared-services/dns/variables.tf b/fast/stages-aw/shared-services/dns/variables.tf new file mode 100644 index 000000000..8dab5ce7f --- /dev/null +++ b/fast/stages-aw/shared-services/dns/variables.tf @@ -0,0 +1,74 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +variable "automation" { + description = "Automation resources created by the bootstrap stage." + type = object({ + outputs_bucket = string + }) +} + +variable "dns_policy_rules_file" { + description = "Path to the YAML file containing DNS response policy rules for Private Google Access (googleapis.com, gcr.io, etc.). If set, a response policy is created for the shared-services VPC." + type = string + default = null +} + +variable "forwarding_zones" { + description = "DNS forwarding zones keyed by name. Each zone forwards queries for the specified domain to the given forwarder IPs via the cross-cloud VPN tunnel. Use domain-specific zones (e.g. 'mil.', 'Enterprise.mil.') — root domain '.' breaks Compute Engine internal DNS." + type = map(object({ + domain = string + forwarders = map(string) + })) + default = {} + validation { + condition = alltrue([ + for k, v in var.forwarding_zones : v.domain != "." + ]) + error_message = "Root domain '.' forwarding zones break Compute Engine internal DNS. Use domain-specific zones instead (e.g. 'mil.', 'Enterprise.mil.')." + } +} + +variable "host_project_id" { + description = "The GCP project ID where DNS zones will be created (the VDSS host project that owns the VPCs)." + type = string +} + +variable "prefix" { + description = "Prefix applied to resource names for org-level naming consistency (e.g. 'da1'). Set to null to disable prefixing." + type = string + default = null + validation { + condition = var.prefix != "" + error_message = "Prefix cannot be empty, use null instead." + } +} + +variable "private_zone_domain" { + description = "Domain of the existing private DNS zone in the landing VPC (e.g. 'da1-il5-vdss.private.example.internal.'). A peering zone is created so shared-services and tenant-transit VPCs can resolve records in it." + type = string + default = null +} + +variable "vpc_self_links" { + description = "VPC self-links used for DNS zone authorization and peering." + type = object({ + csp_landing = string + landing = string + shared_services = string + tenant_transit = string + }) +} diff --git a/fast/stages-aw/shared-services/dns/versions.tf b/fast/stages-aw/shared-services/dns/versions.tf new file mode 100644 index 000000000..21d7cdb6b --- /dev/null +++ b/fast/stages-aw/shared-services/dns/versions.tf @@ -0,0 +1,29 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +terraform { + required_version = ">= 1.11.4" + required_providers { + google = { + source = "hashicorp/google" + version = ">= 7.0.1, < 8.0.0" + } + google-beta = { + source = "hashicorp/google-beta" + version = ">= 7.0.1, < 8.0.0" + } + } +} diff --git a/fast/stages-aw/shared-services/ntp/README.md b/fast/stages-aw/shared-services/ntp/README.md new file mode 100644 index 000000000..3243b0e4b --- /dev/null +++ b/fast/stages-aw/shared-services/ntp/README.md @@ -0,0 +1,142 @@ + + +# Shared Services — NTP Relay + +This module deploys a DISA STIG-compliant NTP relay in the shared-services VPC. +Relay VMs synchronize against US Naval Observatory (USNO) authoritative sources over the public internet and serve all spoke VMs internally over UDP 123. + +## Architecture + +``` +USNO (192.5.41.40/41/209) ← Stratum 1 + │ UDP 123 outbound (Cloud NAT) + ▼ +NTP Relay VM in shared-services ← Stratum 2 + │ UDP 123 internal only + ▼ +All spoke VMs (dev/prod tenants) ← Stratum 3 +``` + +## Architecture + +### VM Relay + +A dedicated VM in the shared-services VPC runs `chronyd` and relays time to all spoke VMs. + +## STIG Compliance + +This module addresses the following DISA STIG rules: + +| Rule | Requirement | How Met | +| -------------------------- | -------------------------------------------- | ------------------------------------------------------------------------- | +| SV-230484 (RHEL-08-030740) | Sync to USNO/DoD/GPS; `maxpoll ≤ 16` | Relay upstreams to USNO; `maxpoll 6` in chrony.conf (within STIG ceiling) | +| SV-204603 (RHEL-07-040500) | `chronyd` or `ntpd` must be running (CAT II) | Startup script enables and starts `chronyd` | + +## Spoke VM Configuration + +After deployment, configure each spoke VM's `/etc/chrony.conf` to point at the relay IPs output by this module: + +``` +server iburst maxpoll 6 +``` + +Remove any existing `metadata.google.internal` or `pool.ntp.org` lines — mixing GCP's leap-smeared source with a strict UTC relay causes unpredictable time behavior. + +## Verification + +On a relay VM: + +```bash +chronyc tracking # check sync status and offset +chronyc sources # verify USNO servers are reachable +``` + +On a spoke VM: + +```bash +chronyc sources # should show relay IP(s) as source +``` + +## Deployment + +Deploy via the shared-services automation script: + +```bash +cd automation +bash shared-services-deploy.sh +``` + +The script walks you through pulling providers from GCS, creating `terraform.tfvars`, and running init/plan/apply. After apply, relay IPs are automatically published to GCS at `tfvars/shared-services-ntp.auto.tfvars.json` for downstream consumption. + +Retrieve relay IPs: + +```bash +gcloud storage cat gs://--prod-iac-core-outputs/tfvars/shared-services-ntp.auto.tfvars.json +``` + +## Notes +## Known Gaps + +**VPC Service Controls:** VPC-SC restricts Google Cloud API access, not network-level traffic. NTP relay VMs communicate with USNO via Cloud NAT over UDP 123, which is unaffected by VPC-SC perimeters. + +**BCAP routing to USNO:** When BCAP is live and DoD network routes are in place, NTP traffic should route through BCAP instead of the public internet. Set `create_cloud_nat = false` and ensure BCAP advertises routes to USNO IPs (192.5.41.x). + +**Multi-region:** This module deploys to a single region. For multi-region deployments, create a second NTP root with its own `terraform.tfvars` targeting the second region. + +**Monitoring:** No automated alerting if the relay loses sync or goes offline. Operators should periodically verify with `chronyc tracking` on the relay VM. For automated monitoring, consider Cloud Monitoring uptime checks or Ops Agent integration as a future enhancement. + +## Usage + +```hcl +module "ntp" { + source = "./shared-services/ntp" + hub_project_id = "my-vdss-host" + region = "us-east4" + network = module.shared-services-vpc.self_link + subnetwork = module.shared-services-vpc.subnet_self_links["us-east4/shared-services-default"] + encryption_key = module.kms["us-east4"].keys.ntp.id + automation = { outputs_bucket = "my-prod-iac-core-outputs" } +} +``` + +## Variables + +| name | description | type | required | default | +|---|---|:---:|:---:|:---:| +| [automation](variables.tf#L7) | Automation resources created by the bootstrap stage. Used to write NTP relay IPs to the GCS outputs bucket for downstream consumption. | object({…}) | ✓ | | +| [encryption_key](variables.tf#L32) | KMS key self-link for CMEK disk encryption on NTP relay VMs. Required for IL5 deployments where constraints/gcp.restrictNonCmekServices is enforced. | string | ✓ | | +| [hub_project_id](variables.tf#L37) | The GCP project ID where NTP relay resources will be deployed. Must be the project that owns the VPC (the VDSS host project), since Cloud Router, Cloud NAT, and firewall rules cannot cross-project reference networks. | string | ✓ | | +| [network](variables.tf#L54) | Self-link of the VPC network to attach NTP relay VMs to. | string | ✓ | | +| [region](variables.tf#L79) | GCP region for NTP relay VM deployment. | string | ✓ | | +| [subnetwork](variables.tf#L84) | Self-link of the subnetwork to attach NTP relay VMs to. | string | ✓ | | +| [allowed_client_ranges](variables.tf#L1) | Internal CIDR ranges permitted to query the NTP relay over UDP 123. Defaults to all RFC 1918 space. | list(string) | | ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"] | +| [boot_disk_image](variables.tf#L14) | Boot disk image for NTP relay VMs. The image must have chrony pre-installed — the startup script only configures it, it does not install packages. Use a hardened RHEL 8 image for full STIG compliance. | string | | "projects/rhel-cloud/global/images/family/rhel-8" | +| [boot_disk_size](variables.tf#L20) | Boot disk size in GB for NTP relay VMs. Must be at least as large as the boot image (20 GB for RHEL 8). | number | | 20 | +| [create_cloud_nat](variables.tf#L26) | Create a Cloud NAT and router to provide NTP relay VMs with outbound internet access to USNO. Set to false if the shared-services VPC already has a Cloud NAT. | bool | | true | +| [instance_name_prefix](variables.tf#L42) | Name prefix for NTP relay VM instances. | string | | "ntp-relay" | +| [machine_type](variables.tf#L48) | Machine type for NTP relay VMs. e2-micro is sufficient for NTP workloads. | string | | "e2-micro" | +| [ntp_servers](variables.tf#L59) | Upstream NTP server IP addresses to configure on relay VMs. Must be IP addresses (not hostnames) as they are also used in firewall destination_ranges. Defaults to USNO authoritative DoD sources as required by DISA STIG SV-230484. | list(string) | | ["192.5.41.40", "192.5.41.41", "192.5.41.209"] | +| [prefix](variables.tf#L69) | Prefix applied to resource names for org-level naming consistency (e.g. 'da1'). Set to null to disable prefixing. | string | | null | + +## Outputs + +| name | description | sensitive | +|---|---|:---:| +| [relay_ip](outputs.tf#L1) | Internal IP address of the NTP relay VM. | | +| [relay_self_link](outputs.tf#L6) | Self-link of the NTP relay VM instance. | | +| [service_account](outputs.tf#L11) | Service account email used by the NTP relay VM. | | + diff --git a/fast/stages-aw/shared-services/ntp/data/config.yml b/fast/stages-aw/shared-services/ntp/data/config.yml new file mode 100644 index 000000000..6d7cdbd6e --- /dev/null +++ b/fast/stages-aw/shared-services/ntp/data/config.yml @@ -0,0 +1,15 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +region: us-east4 \ No newline at end of file diff --git a/fast/stages-aw/shared-services/ntp/main.tf b/fast/stages-aw/shared-services/ntp/main.tf new file mode 100644 index 000000000..e635f77c0 --- /dev/null +++ b/fast/stages-aw/shared-services/ntp/main.tf @@ -0,0 +1,161 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +locals { + zone = "${var.region}-a" + + ntp_server_cidrs = [for s in var.ntp_servers : "${s}/32"] + + chrony_server_lines = join("\n", [ + for s in var.ntp_servers : "server ${s} iburst maxpoll 6" + ]) + + chrony_allow_lines = join("\n", [ + for c in var.allowed_client_ranges : "allow ${c}" + ]) + + startup_script = templatefile("${path.module}/startup-script.tpl", { + server_lines = local.chrony_server_lines + allow_lines = local.chrony_allow_lines + }) +} + +module "ntp-relay-sa" { + source = "../../../../modules/iam-service-account" + project_id = var.hub_project_id + name = "ntp-relay" + display_name = "NTP relay service account." + prefix = var.prefix + iam = {} +} + +module "ntp-relay" { + source = "../../../../modules/compute-vm" + project_id = var.hub_project_id + zone = local.zone + name = var.instance_name_prefix + instance_type = var.machine_type + tags = ["ntp-relay"] + + boot_disk = { + initialize_params = { + image = var.boot_disk_image + size = var.boot_disk_size + } + } + + shielded_config = { + enable_secure_boot = true + enable_vtpm = true + enable_integrity_monitoring = true + } + + encryption = var.encryption_key == null ? null : { + kms_key_self_link = var.encryption_key + } + + network_interfaces = [{ + network = var.network + subnetwork = var.subnetwork + }] + + service_account = { + email = module.ntp-relay-sa.email + } + + metadata = { + startup-script = local.startup_script + block-project-ssh-keys = "true" + serial-port-enable = "false" + } +} + +resource "google_compute_firewall" "ntp-relay-egress-usno" { + project = var.hub_project_id + name = "ntp-relay-egress-usno" + network = var.network + direction = "EGRESS" + priority = 500 + + target_tags = ["ntp-relay"] + destination_ranges = local.ntp_server_cidrs + + allow { + protocol = "udp" + ports = ["123"] + } + + log_config { + metadata = "INCLUDE_ALL_METADATA" + } +} + +resource "google_compute_firewall" "ntp-relay-egress-deny" { + project = var.hub_project_id + name = "ntp-relay-egress-deny" + network = var.network + direction = "EGRESS" + priority = 65534 + + target_tags = ["ntp-relay"] + destination_ranges = ["0.0.0.0/0"] + + deny { + protocol = "all" + } + + log_config { + metadata = "INCLUDE_ALL_METADATA" + } +} + +resource "google_compute_firewall" "ntp-relay-ingress-clients" { + project = var.hub_project_id + name = "ntp-relay-ingress-clients" + network = var.network + direction = "INGRESS" + priority = 500 + + target_tags = ["ntp-relay"] + source_ranges = var.allowed_client_ranges + + allow { + protocol = "udp" + ports = ["123"] + } + + log_config { + metadata = "INCLUDE_ALL_METADATA" + } +} + +module "ntp-relay-nat" { + count = var.create_cloud_nat ? 1 : 0 + source = "../../../../modules/net-cloudnat" + project_id = var.hub_project_id + region = var.region + name = "ntp-relay-nat" + router_network = var.network + router_create = true + router_name = "ntp-relay-router" + + config_source_subnetworks = { + all = false + subnetworks = [{ + self_link = var.subnetwork + all_ranges = true + }] + } +} diff --git a/fast/stages-aw/shared-services/ntp/outputs-gcs.tf b/fast/stages-aw/shared-services/ntp/outputs-gcs.tf new file mode 100644 index 000000000..fe224ba1c --- /dev/null +++ b/fast/stages-aw/shared-services/ntp/outputs-gcs.tf @@ -0,0 +1,24 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# tfdoc:file:description Output files persistence to automation GCS bucket. + +resource "google_storage_bucket_object" "tfvars" { + bucket = var.automation.outputs_bucket + name = "tfvars/shared-services-ntp.auto.tfvars.json" + content = jsonencode({ + ntp_relay_ip = module.ntp-relay.internal_ip + }) +} diff --git a/fast/stages-aw/shared-services/ntp/outputs.tf b/fast/stages-aw/shared-services/ntp/outputs.tf new file mode 100644 index 000000000..32b300f73 --- /dev/null +++ b/fast/stages-aw/shared-services/ntp/outputs.tf @@ -0,0 +1,30 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +output "relay_ip" { + description = "Internal IP address of the NTP relay VM." + value = module.ntp-relay.internal_ip +} + +output "relay_self_link" { + description = "Self-link of the NTP relay VM instance." + value = module.ntp-relay.self_link +} + +output "service_account" { + description = "Service account email used by the NTP relay VM." + value = module.ntp-relay-sa.email +} diff --git a/fast/stages-aw/shared-services/ntp/startup-script.tpl b/fast/stages-aw/shared-services/ntp/startup-script.tpl new file mode 100644 index 000000000..1b7e72613 --- /dev/null +++ b/fast/stages-aw/shared-services/ntp/startup-script.tpl @@ -0,0 +1,36 @@ +#!/bin/bash +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +set -euo pipefail + +# Image must have chrony pre-installed — egress-deny blocks package managers. +if ! command -v chronyd &>/dev/null; then + echo "ERROR: chronyd not found. Use an image with chrony pre-installed (e.g. RHEL 8)." >&2 + exit 1 +fi + +tee /etc/chrony.conf > /dev/null << 'CHRONY_EOF' +${server_lines} + +${allow_lines} + +driftfile /var/lib/chrony/drift +makestep 1.0 3 +rtcsync +logdir /var/log/chrony +CHRONY_EOF + +# Service unit is 'chronyd' on RHEL, 'chrony' on Debian/Ubuntu. +systemctl enable chronyd 2>/dev/null || systemctl enable chrony +systemctl restart chronyd 2>/dev/null || systemctl restart chrony diff --git a/fast/stages-aw/shared-services/ntp/terraform.tfvars.sample b/fast/stages-aw/shared-services/ntp/terraform.tfvars.sample new file mode 100644 index 000000000..b4080bcda --- /dev/null +++ b/fast/stages-aw/shared-services/ntp/terraform.tfvars.sample @@ -0,0 +1,42 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +# Must be the VDSS host project (VPC owner) — Cloud Router, NAT, and +# firewall rules cannot cross-project reference networks. +hub_project_id = "xxxx-vdss-host" +prefix = "da1" + +automation = { + outputs_bucket = "xxxx-prod-iac-core-outputs" +} + +region = "us-east4" +network = "projects/xxxx-vdss-host/global/networks/shared-services" +subnetwork = "projects/xxxx-vdss-host/regions/us-east4/subnetworks/shared-services-default" + +# IPs only — hostnames break firewall destination_ranges. +# tick.usno.navy.mil, tock.usno.navy.mil, ntp2.usno.navy.mil +ntp_servers = ["192.5.41.40", "192.5.41.41", "192.5.41.209"] + +# Set to false if shared-services VPC already has a Cloud NAT, or when using BCAP routing. +create_cloud_nat = true + +allowed_client_ranges = ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"] + +# Required for IL5 — constraints/gcp.restrictNonCmekServices enforced. +# Use the dedicated NTP key from stage 3-networking (not the shared "default" key): +# gcloud storage cat gs:///tfvars/3-networking.auto.tfvars.json | jq -r '.kms_keys["us-east4"].ntp' +encryption_key = "projects/xxxx-vdss-host/locations/us-east4/keyRings/vdss-keyring-us-east4/cryptoKeys/ntp" diff --git a/fast/stages-aw/shared-services/ntp/variables.tf b/fast/stages-aw/shared-services/ntp/variables.tf new file mode 100644 index 000000000..432d5a218 --- /dev/null +++ b/fast/stages-aw/shared-services/ntp/variables.tf @@ -0,0 +1,103 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +variable "allowed_client_ranges" { + description = "Internal CIDR ranges permitted to query the NTP relay over UDP 123. Defaults to all RFC 1918 space." + type = list(string) + default = ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"] +} + +variable "automation" { + description = "Automation resources created by the bootstrap stage. Used to write NTP relay IPs to the GCS outputs bucket for downstream consumption." + type = object({ + outputs_bucket = string + }) +} + +variable "boot_disk_image" { + description = "Boot disk image for NTP relay VMs. The image must have chrony pre-installed — the startup script only configures it, it does not install packages. Use a hardened RHEL 8 image for full STIG compliance." + type = string + default = "projects/rhel-cloud/global/images/family/rhel-8" +} + +variable "boot_disk_size" { + description = "Boot disk size in GB for NTP relay VMs. Must be at least as large as the boot image (20 GB for RHEL 8)." + type = number + default = 20 +} + +variable "create_cloud_nat" { + description = "Create a Cloud NAT and router to provide NTP relay VMs with outbound internet access to USNO. Set to false if the shared-services VPC already has a Cloud NAT." + type = bool + default = true +} + +variable "encryption_key" { + description = "KMS key self-link for CMEK disk encryption on NTP relay VMs. Required for IL5 deployments where constraints/gcp.restrictNonCmekServices is enforced." + type = string +} + +variable "hub_project_id" { + description = "The GCP project ID where NTP relay resources will be deployed. Must be the project that owns the VPC (the VDSS host project), since Cloud Router, Cloud NAT, and firewall rules cannot cross-project reference networks." + type = string +} + +variable "instance_name_prefix" { + description = "Name prefix for NTP relay VM instances." + type = string + default = "ntp-relay" +} + +variable "machine_type" { + description = "Machine type for NTP relay VMs. e2-micro is sufficient for NTP workloads." + type = string + default = "e2-micro" +} + +variable "network" { + description = "Self-link of the VPC network to attach NTP relay VMs to." + type = string +} + +variable "ntp_servers" { + description = "Upstream NTP server IP addresses to configure on relay VMs. Must be IP addresses (not hostnames) as they are also used in firewall destination_ranges. Defaults to USNO authoritative DoD sources as required by DISA STIG SV-230484." + type = list(string) + default = ["192.5.41.40", "192.5.41.41", "192.5.41.209"] + validation { + condition = length(var.ntp_servers) >= 1 + error_message = "At least one NTP server IP address must be specified." + } +} + +variable "prefix" { + description = "Prefix applied to resource names for org-level naming consistency (e.g. 'da1'). Set to null to disable prefixing." + type = string + default = null + validation { + condition = var.prefix != "" + error_message = "Prefix cannot be empty, use null instead." + } +} + +variable "region" { + description = "GCP region for NTP relay VM deployment." + type = string +} + +variable "subnetwork" { + description = "Self-link of the subnetwork to attach NTP relay VMs to." + type = string +} diff --git a/fast/stages-aw/shared-services/ntp/versions.tf b/fast/stages-aw/shared-services/ntp/versions.tf new file mode 100644 index 000000000..21d7cdb6b --- /dev/null +++ b/fast/stages-aw/shared-services/ntp/versions.tf @@ -0,0 +1,29 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +terraform { + required_version = ">= 1.11.4" + required_providers { + google = { + source = "hashicorp/google" + version = ">= 7.0.1, < 8.0.0" + } + google-beta = { + source = "hashicorp/google-beta" + version = ">= 7.0.1, < 8.0.0" + } + } +} diff --git a/fast/stages-aw/shared-services/smtp/README.md b/fast/stages-aw/shared-services/smtp/README.md new file mode 100644 index 000000000..bb3d0b434 --- /dev/null +++ b/fast/stages-aw/shared-services/smtp/README.md @@ -0,0 +1,167 @@ + + +# Shared Services — SMTP Relay + +This module deploys a DISA STIG-compliant Postfix SMTP relay (smarthost) in the +shared-services VPC. All outbound email from spoke VMs is relayed through the +DISA Enterprise Email Security Gateway (EESG) at `mail.mil` via Cloud +Interconnect / BCAP. GCP blocks outbound port 25 on the public internet, but +traffic routed internally over Cloud Interconnect is permitted on port 25. + +## Architecture + +``` +Spoke VMs (dev/prod tenants) + │ TCP 25 internal only + ▼ +SMTP Relay VM in shared-services ← Postfix smarthost + │ TCP 25 via Cloud Interconnect / BCAP + ▼ +DISA EESG (mail.mil) ← Enterprise Email Security Gateway +``` + +## STIG Compliance + +| Rule | Requirement | How Met | +| -------------------------- | ------------------------------------ | -------------------------------------------------------------- | +| SV-230550 (RHEL-08-040290) | Prevent unrestricted mail relaying | `smtpd_client_restrictions = permit_mynetworks, reject` | +| SV-230489 (RHEL-08-040002) | Sendmail must not be installed | Startup script removes sendmail if present | +| DoD TLS requirement | Mandatory TLS 1.2+ for transit | `smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1` | +| FIPS 140-2 | FIPS-approved cryptographic modules | `smtp_tls_fingerprint_digest = sha256`; FIPS mode is an image-level prerequisite | + +## Prerequisites + +1. **DISA EESG relay IP** — coordinate with DISA POC for IP whitelisting and + mail envelope restrictions. Set `disa_relay_hosts` to the relay IP(s). +2. **BCAP / Cloud Interconnect** must be UP and routing traffic to the DISA + relay IPs. +3. **KMS key** for CMEK disk encryption (IL5 requirement) — reference from the + stage 3-networking keyring. +4. **Shared-services SA** must have appropriate IAM bindings on the VDSS host + project (granted by `3-networking/projects.tf`). +5. **FIPS 140-2** should be enabled at the OS image level for IL5 compliance. + This is an image-level concern, not module-level (same as NTP). + +## Deployment + +```bash +cd automation +bash shared-services-deploy.sh +``` + +After apply, the relay IP is published to GCS at +`tfvars/shared-services-smtp.auto.tfvars.json`. + +Retrieve the relay IP: + +```bash +gcloud storage cat gs://--prod-iac-core-outputs/tfvars/shared-services-smtp.auto.tfvars.json +``` + +## Spoke Application Configuration + +Configure spoke applications to relay mail through the SMTP relay IP on port 25: + +``` +SMTP_HOST= +SMTP_PORT=25 +``` + +Applications should send mail to the relay VM's internal IP. The relay handles +TLS negotiation with the DISA EESG — spoke applications do not need to +configure TLS for the relay hop. + +## Verification + +On the relay VM: + +```bash +systemctl status postfix # verify service is active +postconf relayhost # confirm DISA relay target +postconf smtpd_client_restrictions # confirm relay restrictions +``` + +From a spoke VM: + +```bash +telnet 25 # expect SMTP 220 banner +``` + +Check firewall logs in Cloud Logging for egress traffic to DISA IPs. + +## Known Gaps + +**DNS records (SPF/DKIM/DMARC):** Out of scope for this module. Managed in the +DNS shared-service module or by DISA as part of the EESG configuration. + +**HA / MIG:** Single-VM deployment for initial rollout (matches NTP pattern). +Managed instance group is a future enhancement for high availability. + +**DoD PKI certificates:** If the DISA EESG requires mutual TLS with DoD PKI +certificates, those must be provisioned separately and added to the Postfix +TLS configuration. + +**RHUI access:** The module includes an egress firewall rule for Google's RHEL +Update Infrastructure (`35.190.247.13`) to enable Postfix installation at boot +time and ongoing `dnf-automatic` security updates. This requires Cloud NAT +(`create_cloud_nat = true`, the default). + +## Usage + +```hcl +module "smtp" { + source = "./shared-services/smtp" + hub_project_id = "my-vdss-host" + region = "us-east4" + network = module.shared-services-vpc.self_link + subnetwork = module.shared-services-vpc.subnet_self_links["us-east4/shared-services-default"] + encryption_key = module.kms["us-east4"].keys.smtp.id + automation = { outputs_bucket = "my-prod-iac-core-outputs" } + disa_relay_hosts = [""] +} +``` + +## Variables + +| name | description | type | required | default | +|---|---|:---:|:---:|:---:| +| [automation](variables.tf#L7) | Automation resources created by the bootstrap stage. Used to write SMTP relay IPs to the GCS outputs bucket for downstream consumption. | object({…}) | ✓ | | +| [disa_relay_hosts](variables.tf#L32) | DISA EESG relay IP addresses. Must be IP addresses (not hostnames) as they are also used in firewall destination_ranges. | list(string) | ✓ | | +| [encryption_key](variables.tf#L47) | KMS key self-link for CMEK disk encryption on SMTP relay VMs. Required for IL5 deployments where constraints/gcp.restrictNonCmekServices is enforced. | string | ✓ | | +| [hub_project_id](variables.tf#L52) | The GCP project ID where SMTP relay resources will be deployed. Must be the project that owns the VPC (the VDSS host project), since Cloud Router, Cloud NAT, and firewall rules cannot cross-project reference networks. | string | ✓ | | +| [network](variables.tf#L69) | Self-link of the VPC network to attach SMTP relay VMs to. | string | ✓ | | +| [region](variables.tf#L84) | GCP region for SMTP relay VM deployment. | string | ✓ | | +| [subnetwork](variables.tf#L101) | Self-link of the subnetwork to attach SMTP relay VMs to. | string | ✓ | | +| [allowed_client_ranges](variables.tf#L1) | Internal CIDR ranges permitted to send mail through the SMTP relay over TCP 25. Defaults to all RFC 1918 space. | list(string) | | ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"] | +| [boot_disk_image](variables.tf#L14) | Boot disk image for SMTP relay VMs. The startup script installs Postfix via RHUI if not present. Use a hardened RHEL 8 image for full STIG compliance. | string | | "projects/rhel-cloud/global/images/family/rhel-8" | +| [boot_disk_size](variables.tf#L20) | Boot disk size in GB for SMTP relay VMs. Must be at least as large as the boot image (20 GB for RHEL 8). | number | | 20 | +| [create_cloud_nat](variables.tf#L26) | Create a Cloud NAT and router to provide SMTP relay VMs with outbound access for RHUI package operations. Set to false if the shared-services VPC already has a Cloud NAT. | bool | | true | +| [disa_relay_port](variables.tf#L41) | TCP port for the DISA EESG relay. Standard SMTP is 25. | number | | 25 | +| [instance_name_prefix](variables.tf#L57) | Name prefix for SMTP relay VM instances. | string | | "smtp-relay" | +| [machine_type](variables.tf#L63) | Machine type for SMTP relay VMs. e2-small provides sufficient resources for Postfix workloads. | string | | "e2-small" | +| [prefix](variables.tf#L74) | Prefix applied to resource names for org-level naming consistency (e.g. 'da1'). Set to null to disable prefixing. | string | | null | +| [smtp_domain](variables.tf#L89) | Domain name used in Postfix mydomain directive. | string | | "mil" | +| [smtp_hostname](variables.tf#L95) | Hostname used in Postfix myhostname directive. | string | | "smtp.mil" | + +## Outputs + +| name | description | sensitive | +|---|---|:---:| +| [relay_ip](outputs.tf#L1) | Internal IP address of the SMTP relay VM. | | +| [relay_self_link](outputs.tf#L6) | Self-link of the SMTP relay VM instance. | | +| [service_account](outputs.tf#L11) | Service account email used by the SMTP relay VM. | | + diff --git a/fast/stages-aw/shared-services/smtp/data/config.yml b/fast/stages-aw/shared-services/smtp/data/config.yml new file mode 100644 index 000000000..87d9a4897 --- /dev/null +++ b/fast/stages-aw/shared-services/smtp/data/config.yml @@ -0,0 +1,20 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +region: us-east4 + +disa_relay_hosts: + - "214.24.31.240" + +create_cloud_nat: false diff --git a/fast/stages-aw/shared-services/smtp/main.tf b/fast/stages-aw/shared-services/smtp/main.tf new file mode 100644 index 000000000..20b65ff59 --- /dev/null +++ b/fast/stages-aw/shared-services/smtp/main.tf @@ -0,0 +1,176 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +locals { + zone = "${var.region}-a" + + disa_relay_cidrs = [for s in var.disa_relay_hosts : "${s}/32"] + + startup_script = templatefile("${path.module}/startup-script.tpl", { + smtp_hostname = var.smtp_hostname + smtp_domain = var.smtp_domain + disa_relay_host = var.disa_relay_hosts[0] + disa_relay_port = var.disa_relay_port + allowed_networks = join(" ", var.allowed_client_ranges) + }) +} + +module "smtp-relay-sa" { + source = "../../../../modules/iam-service-account" + project_id = var.hub_project_id + name = "smtp-relay" + display_name = "SMTP relay service account." + prefix = var.prefix + iam = {} +} + +module "smtp-relay" { + source = "../../../../modules/compute-vm" + project_id = var.hub_project_id + zone = local.zone + name = var.instance_name_prefix + instance_type = var.machine_type + tags = ["smtp-relay"] + + boot_disk = { + initialize_params = { + image = var.boot_disk_image + size = var.boot_disk_size + } + } + + shielded_config = { + enable_secure_boot = true + enable_vtpm = true + enable_integrity_monitoring = true + } + + encryption = var.encryption_key == null ? null : { + kms_key_self_link = var.encryption_key + } + + network_interfaces = [{ + network = var.network + subnetwork = var.subnetwork + }] + + service_account = { + email = module.smtp-relay-sa.email + } + + metadata = { + startup-script = local.startup_script + block-project-ssh-keys = "true" + serial-port-enable = "false" + } +} + +resource "google_compute_firewall" "smtp-relay-egress-disa" { + project = var.hub_project_id + name = "smtp-relay-egress-disa" + network = var.network + direction = "EGRESS" + priority = 500 + + target_tags = ["smtp-relay"] + destination_ranges = local.disa_relay_cidrs + + allow { + protocol = "tcp" + ports = [tostring(var.disa_relay_port)] + } + + log_config { + metadata = "INCLUDE_ALL_METADATA" + } +} + +resource "google_compute_firewall" "smtp-relay-egress-rhui" { + project = var.hub_project_id + name = "smtp-relay-egress-rhui" + network = var.network + direction = "EGRESS" + priority = 500 + + target_tags = ["smtp-relay"] + destination_ranges = ["35.190.247.13/32"] + + allow { + protocol = "tcp" + ports = ["443"] + } + + log_config { + metadata = "INCLUDE_ALL_METADATA" + } +} + +resource "google_compute_firewall" "smtp-relay-egress-deny" { + project = var.hub_project_id + name = "smtp-relay-egress-deny" + network = var.network + direction = "EGRESS" + priority = 65534 + + target_tags = ["smtp-relay"] + destination_ranges = ["0.0.0.0/0"] + + deny { + protocol = "all" + } + + log_config { + metadata = "INCLUDE_ALL_METADATA" + } +} + +resource "google_compute_firewall" "smtp-relay-ingress-clients" { + project = var.hub_project_id + name = "smtp-relay-ingress-clients" + network = var.network + direction = "INGRESS" + priority = 500 + + target_tags = ["smtp-relay"] + source_ranges = var.allowed_client_ranges + + allow { + protocol = "tcp" + ports = ["25"] + } + + log_config { + metadata = "INCLUDE_ALL_METADATA" + } +} + +module "smtp-relay-nat" { + count = var.create_cloud_nat ? 1 : 0 + source = "../../../../modules/net-cloudnat" + project_id = var.hub_project_id + region = var.region + name = "smtp-relay-nat" + router_network = var.network + router_create = true + router_name = "smtp-relay-router" + + config_source_subnetworks = { + all = false + subnetworks = [{ + self_link = var.subnetwork + all_ranges = true + }] + } +} diff --git a/fast/stages-aw/shared-services/smtp/outputs-gcs.tf b/fast/stages-aw/shared-services/smtp/outputs-gcs.tf new file mode 100644 index 000000000..ffdffeaab --- /dev/null +++ b/fast/stages-aw/shared-services/smtp/outputs-gcs.tf @@ -0,0 +1,24 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +# tfdoc:file:description Output files persistence to automation GCS bucket. + +resource "google_storage_bucket_object" "tfvars" { + bucket = var.automation.outputs_bucket + name = "tfvars/shared-services-smtp.auto.tfvars.json" + content = jsonencode({ + smtp_relay_ip = module.smtp-relay.internal_ip + }) +} diff --git a/fast/stages-aw/shared-services/smtp/outputs.tf b/fast/stages-aw/shared-services/smtp/outputs.tf new file mode 100644 index 000000000..7c8bab6a0 --- /dev/null +++ b/fast/stages-aw/shared-services/smtp/outputs.tf @@ -0,0 +1,30 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +output "relay_ip" { + description = "Internal IP address of the SMTP relay VM." + value = module.smtp-relay.internal_ip +} + +output "relay_self_link" { + description = "Self-link of the SMTP relay VM instance." + value = module.smtp-relay.self_link +} + +output "service_account" { + description = "Service account email used by the SMTP relay VM." + value = module.smtp-relay-sa.email +} diff --git a/fast/stages-aw/shared-services/smtp/startup-script.tpl b/fast/stages-aw/shared-services/smtp/startup-script.tpl new file mode 100644 index 000000000..1e856a50b --- /dev/null +++ b/fast/stages-aw/shared-services/smtp/startup-script.tpl @@ -0,0 +1,54 @@ +#!/bin/bash +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +set -euo pipefail + +# STIG SV-230489 (RHEL-08-040002) — sendmail must not be installed. +if rpm -q sendmail &>/dev/null; then + dnf remove -y sendmail +fi + +# Install Postfix if not present — RHUI egress rule allows access to +# Google's RHEL Update Infrastructure (35.190.247.13) for package operations. +if ! command -v postfix &>/dev/null; then + dnf install -y postfix +fi + +tee /etc/postfix/main.cf > /dev/null << 'POSTFIX_EOF' +myhostname = ${smtp_hostname} +mydomain = ${smtp_domain} + +relayhost = [${disa_relay_host}]:${disa_relay_port} + +inet_interfaces = all +mynetworks = 127.0.0.0/8 ${allowed_networks} + +smtp_tls_security_level = encrypt +smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 +smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 +smtp_tls_mandatory_ciphers = high +smtp_tls_fingerprint_digest = sha256 +smtp_tls_loglevel = 1 + +# STIG SV-230550 (RHEL-08-040290) — prevent unrestricted mail relaying. +smtpd_client_restrictions = permit_mynetworks, reject +smtpd_relay_restrictions = permit_mynetworks, reject + +disable_vrfy_command = yes + +maillog_file = /var/log/maillog +POSTFIX_EOF + +systemctl enable postfix +systemctl restart postfix diff --git a/fast/stages-aw/shared-services/smtp/terraform.tfvars.sample b/fast/stages-aw/shared-services/smtp/terraform.tfvars.sample new file mode 100644 index 000000000..5f6ee5ac6 --- /dev/null +++ b/fast/stages-aw/shared-services/smtp/terraform.tfvars.sample @@ -0,0 +1,40 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +# SMTP Shared Service — sample tfvars +# Copy to terraform.tfvars and update values for your environment. + +hub_project_id = "my-vdss-host-project" +region = "us-east4" +network = "projects/my-vdss-host-project/global/networks/shared-services" +subnetwork = "projects/my-vdss-host-project/regions/us-east4/subnetworks/shared-services-default" +encryption_key = "projects/my-kms-project/locations/us-east4/keyRings/shared-services/cryptoKeys/smtp" + +automation = { + outputs_bucket = "da1-il5-prod-iac-core-outputs" +} + +# DISA EESG relay IPs — coordinate with DISA POC for IP whitelisting. +disa_relay_hosts = [""] + +# Uncomment to customize: +# disa_relay_port = 25 +# prefix = "da1" +# smtp_hostname = "smtp.mil" +# smtp_domain = "mil" +# machine_type = "e2-small" +# create_cloud_nat = true +# allowed_client_ranges = ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"] diff --git a/fast/stages-aw/shared-services/smtp/variables.tf b/fast/stages-aw/shared-services/smtp/variables.tf new file mode 100644 index 000000000..5be6842b7 --- /dev/null +++ b/fast/stages-aw/shared-services/smtp/variables.tf @@ -0,0 +1,120 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +variable "allowed_client_ranges" { + description = "Internal CIDR ranges permitted to send mail through the SMTP relay over TCP 25. Defaults to all RFC 1918 space." + type = list(string) + default = ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"] +} + +variable "automation" { + description = "Automation resources created by the bootstrap stage. Used to write SMTP relay IPs to the GCS outputs bucket for downstream consumption." + type = object({ + outputs_bucket = string + }) +} + +variable "boot_disk_image" { + description = "Boot disk image for SMTP relay VMs. The startup script installs Postfix via RHUI if not present. Use a hardened RHEL 8 image for full STIG compliance." + type = string + default = "projects/rhel-cloud/global/images/family/rhel-8" +} + +variable "boot_disk_size" { + description = "Boot disk size in GB for SMTP relay VMs. Must be at least as large as the boot image (20 GB for RHEL 8)." + type = number + default = 20 +} + +variable "create_cloud_nat" { + description = "Create a Cloud NAT and router to provide SMTP relay VMs with outbound access for RHUI package operations. Set to false if the shared-services VPC already has a Cloud NAT." + type = bool + default = true +} + +variable "disa_relay_hosts" { + description = "DISA EESG relay IP addresses. Must be IP addresses (not hostnames) as they are also used in firewall destination_ranges." + type = list(string) + validation { + condition = length(var.disa_relay_hosts) >= 1 + error_message = "At least one DISA relay host IP address must be specified." + } +} + +variable "disa_relay_port" { + description = "TCP port for the DISA EESG relay. Standard SMTP is 25." + type = number + default = 25 +} + +variable "encryption_key" { + description = "KMS key self-link for CMEK disk encryption on SMTP relay VMs. Required for IL5 deployments where constraints/gcp.restrictNonCmekServices is enforced." + type = string +} + +variable "hub_project_id" { + description = "The GCP project ID where SMTP relay resources will be deployed. Must be the project that owns the VPC (the VDSS host project), since Cloud Router, Cloud NAT, and firewall rules cannot cross-project reference networks." + type = string +} + +variable "instance_name_prefix" { + description = "Name prefix for SMTP relay VM instances." + type = string + default = "smtp-relay" +} + +variable "machine_type" { + description = "Machine type for SMTP relay VMs. e2-small provides sufficient resources for Postfix workloads." + type = string + default = "e2-small" +} + +variable "network" { + description = "Self-link of the VPC network to attach SMTP relay VMs to." + type = string +} + +variable "prefix" { + description = "Prefix applied to resource names for org-level naming consistency (e.g. 'da1'). Set to null to disable prefixing." + type = string + default = null + validation { + condition = var.prefix != "" + error_message = "Prefix cannot be empty, use null instead." + } +} + +variable "region" { + description = "GCP region for SMTP relay VM deployment." + type = string +} + +variable "smtp_domain" { + description = "Domain name used in Postfix mydomain directive." + type = string + default = "mil" +} + +variable "smtp_hostname" { + description = "Hostname used in Postfix myhostname directive." + type = string + default = "smtp.mil" +} + +variable "subnetwork" { + description = "Self-link of the subnetwork to attach SMTP relay VMs to." + type = string +} diff --git a/fast/stages-aw/shared-services/smtp/versions.tf b/fast/stages-aw/shared-services/smtp/versions.tf new file mode 100644 index 000000000..21d7cdb6b --- /dev/null +++ b/fast/stages-aw/shared-services/smtp/versions.tf @@ -0,0 +1,29 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +terraform { + required_version = ">= 1.11.4" + required_providers { + google = { + source = "hashicorp/google" + version = ">= 7.0.1, < 8.0.0" + } + google-beta = { + source = "hashicorp/google-beta" + version = ">= 7.0.1, < 8.0.0" + } + } +} diff --git a/generate-mocks.sh b/generate-mocks.sh index 9bca5c605..67983d23d 100755 --- a/generate-mocks.sh +++ b/generate-mocks.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,6 +14,7 @@ # limitations under the License. + SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) # Generate mock provider files for all stages in stages-aw diff --git a/modules/README.md b/modules/README.md index 682419f19..cf21e8620 100644 --- a/modules/README.md +++ b/modules/README.md @@ -1,3 +1,19 @@ + + # Terraform modules suite for Google Cloud The modules collected in this folder are designed as a suite: they are meant to be composed together, and are designed to be forked and modified where use of third party code and sources is not allowed. diff --git a/modules/__docs/20230816-iam-refactor.md b/modules/__docs/20230816-iam-refactor.md index e2c51e1f7..c89cfbcfc 100644 --- a/modules/__docs/20230816-iam-refactor.md +++ b/modules/__docs/20230816-iam-refactor.md @@ -1,3 +1,19 @@ + + # Refactor IAM interface **authors:** [Ludo](https://github.com/ludoo), [Julio](https://github.com/juliocc) diff --git a/modules/__docs/20231106-factories.md b/modules/__docs/20231106-factories.md index b9ebf4518..f01c3e95f 100644 --- a/modules/__docs/20231106-factories.md +++ b/modules/__docs/20231106-factories.md @@ -1,3 +1,19 @@ + + # Factories Refactor and Plan Forward **authors:** [Ludo](https://github.com/ludoo) diff --git a/modules/__docs/README.md b/modules/__docs/README.md index da5c91819..b8da88397 100644 --- a/modules/__docs/README.md +++ b/modules/__docs/README.md @@ -1,3 +1,19 @@ + + # Fabric modules architectural documents This folder contains assorted bits of documentation used to log current architectural choices, or past decisions. Format is inspired by [Michael Nygard's decision record template](https://github.com/joelparkerhenderson/architecture-decision-record/blob/main/templates/decision-record-template-by-michael-nygard/index.md). diff --git a/modules/access-context-manager/README.md b/modules/access-context-manager/README.md index 7cf463926..501d6ec98 100644 --- a/modules/access-context-manager/README.md +++ b/modules/access-context-manager/README.md @@ -1,3 +1,19 @@ + + # Access Context Manager This modules manages the creation ofAccess Context Manager (ACM). Access Context Manager (ACM) in Google Cloud Platform (GCP) is a security service that allows you to define and enforce fine-grained access controls for your resources. diff --git a/modules/access-context-manager/main.tf b/modules/access-context-manager/main.tf index 367c6c293..9992a9138 100644 --- a/modules/access-context-manager/main.tf +++ b/modules/access-context-manager/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ data "google_access_context_manager_access_policy" "policy" { parent = "organizations/${var.organization_id}" diff --git a/modules/access-context-manager/outputs.tf b/modules/access-context-manager/outputs.tf index 3c863a0ad..365ac3aeb 100644 --- a/modules/access-context-manager/outputs.tf +++ b/modules/access-context-manager/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "access_levels" { description = "The list of created access levels." diff --git a/modules/access-context-manager/providers.tf b/modules/access-context-manager/providers.tf index c7f24e20a..a273c6ae6 100644 --- a/modules/access-context-manager/providers.tf +++ b/modules/access-context-manager/providers.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ provider "google-beta" { project = var.project_id diff --git a/modules/access-context-manager/variables.tf b/modules/access-context-manager/variables.tf index 42812c643..979d56a39 100644 --- a/modules/access-context-manager/variables.tf +++ b/modules/access-context-manager/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "access_levels" { description = "List of access levels to create. Each access level is a map containing 'name', 'description', and 'conditions'." diff --git a/modules/alloydb/README.md b/modules/alloydb/README.md index ba49b28fd..505c0e02b 100644 --- a/modules/alloydb/README.md +++ b/modules/alloydb/README.md @@ -1,3 +1,19 @@ + + # AlloyDB module This module manages the creation of an AlloyDB cluster. It also supports cross-region replication scenario by setting up a secondary cluster and the addition of read pools to support read offloads in both primary and secondary regions. diff --git a/modules/alloydb/main.tf b/modules/alloydb/main.tf index 14bff4738..0323bfa34 100644 --- a/modules/alloydb/main.tf +++ b/modules/alloydb/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { prefix = var.prefix == null ? "" : "${var.prefix}-" is_regional = var.availability_type == "REGIONAL" diff --git a/modules/alloydb/outputs.tf b/modules/alloydb/outputs.tf index a7066d0a7..b3aedd988 100644 --- a/modules/alloydb/outputs.tf +++ b/modules/alloydb/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _all_instances = { primary = google_alloydb_instance.primary diff --git a/modules/alloydb/tags.tf b/modules/alloydb/tags.tf index cd5648c16..1adeaa7e9 100644 --- a/modules/alloydb/tags.tf +++ b/modules/alloydb/tags.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - data "google_project" "project" { count = var.project_number == null ? 1 : 0 project_id = var.project_id diff --git a/modules/alloydb/variables.tf b/modules/alloydb/variables.tf index 95f4b186b..54b88bb06 100644 --- a/modules/alloydb/variables.tf +++ b/modules/alloydb/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "annotations" { description = "Map FLAG_NAME=>VALUE for annotations which allow client tools to store small amount of arbitrary data." type = map(string) diff --git a/modules/alloydb/versions.tf b/modules/alloydb/versions.tf index f91d09a59..40a0741bb 100644 --- a/modules/alloydb/versions.tf +++ b/modules/alloydb/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/analytics-hub/README.md b/modules/analytics-hub/README.md index 3482d797c..0328ab642 100644 --- a/modules/analytics-hub/README.md +++ b/modules/analytics-hub/README.md @@ -1,3 +1,19 @@ + + # BigQuery Analytics Hub This module allows managing [Analytics Hub](https://cloud.google.com/bigquery/docs/analytics-hub-introduction) Exchange and Listing resources. diff --git a/modules/analytics-hub/iam.tf b/modules/analytics-hub/iam.tf index ed8b98fe1..c19f93d4f 100644 --- a/modules/analytics-hub/iam.tf +++ b/modules/analytics-hub/iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _exchange_iam_principal_roles = distinct(flatten(values(var.iam_by_principals))) _exchange_iam_principals = { diff --git a/modules/analytics-hub/main.tf b/modules/analytics-hub/main.tf index 0480dea63..8e82ef3dd 100644 --- a/modules/analytics-hub/main.tf +++ b/modules/analytics-hub/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { prefix = var.prefix == null || var.prefix == "" ? "" : "${var.prefix}_" _factory_listings = { diff --git a/modules/analytics-hub/outputs.tf b/modules/analytics-hub/outputs.tf index 5cbf45d8a..7657385b4 100644 --- a/modules/analytics-hub/outputs.tf +++ b/modules/analytics-hub/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "data_exchange_id" { description = "Data exchange id." value = google_bigquery_analytics_hub_data_exchange.data_exchange.data_exchange_id diff --git a/modules/analytics-hub/variables-iam.tf b/modules/analytics-hub/variables-iam.tf index 5ad9a377d..d9df492eb 100644 --- a/modules/analytics-hub/variables-iam.tf +++ b/modules/analytics-hub/variables-iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "iam" { description = "Authoritative IAM bindings in {ROLE => [MEMBERS]} format." type = map(list(string)) diff --git a/modules/analytics-hub/variables.tf b/modules/analytics-hub/variables.tf index 6f6136389..54afa9fd0 100644 --- a/modules/analytics-hub/variables.tf +++ b/modules/analytics-hub/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "description" { description = "Resource description for data exchange." default = null diff --git a/modules/analytics-hub/versions.tf b/modules/analytics-hub/versions.tf index 443252fa9..c60a26812 100644 --- a/modules/analytics-hub/versions.tf +++ b/modules/analytics-hub/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/api-gateway/README.md b/modules/api-gateway/README.md index d3c16d38c..0e6c3eb6f 100644 --- a/modules/api-gateway/README.md +++ b/modules/api-gateway/README.md @@ -1,3 +1,19 @@ + + # API Gateway This module allows creating an API with its associated API config and API gateway. It also allows you grant IAM roles on the created resources. diff --git a/modules/api-gateway/main.tf b/modules/api-gateway/main.tf index 5b6ce0781..ae16017b6 100644 --- a/modules/api-gateway/main.tf +++ b/modules/api-gateway/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { service_account_email = ( var.service_account_create diff --git a/modules/api-gateway/outputs.tf b/modules/api-gateway/outputs.tf index 863c3828f..8338ddbb3 100644 --- a/modules/api-gateway/outputs.tf +++ b/modules/api-gateway/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "api" { description = "API." value = google_api_gateway_api.api diff --git a/modules/api-gateway/variables.tf b/modules/api-gateway/variables.tf index ef5bd41d4..b8cab2ca4 100644 --- a/modules/api-gateway/variables.tf +++ b/modules/api-gateway/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "api_id" { description = "API identifier." type = string diff --git a/modules/api-gateway/versions.tf b/modules/api-gateway/versions.tf index bee69cd60..077b9aa69 100644 --- a/modules/api-gateway/versions.tf +++ b/modules/api-gateway/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/apigee/README.md b/modules/apigee/README.md index a4be05599..97978d97d 100644 --- a/modules/apigee/README.md +++ b/modules/apigee/README.md @@ -1,3 +1,19 @@ + + # Apigee This module simplifies the creation of a Apigee resources (organization, environment groups, environment group attachments, environments, instances and instance attachments). diff --git a/modules/apigee/iam.tf b/modules/apigee/iam.tf index c942e6162..ee86dda9f 100644 --- a/modules/apigee/iam.tf +++ b/modules/apigee/iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_apigee_environment_iam_binding" "authoritative" { for_each = merge(concat([for k1, v1 in var.environments : { for k2, v2 in v1.iam : "${k1}-${k2}" => { diff --git a/modules/apigee/main.tf b/modules/apigee/main.tf index 480d19feb..3ad1b93de 100644 --- a/modules/apigee/main.tf +++ b/modules/apigee/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { org_id = try(google_apigee_organization.organization[0].id, "organizations/${var.project_id}") org_name = try(google_apigee_organization.organization[0].name, var.project_id) diff --git a/modules/apigee/outputs.tf b/modules/apigee/outputs.tf index 34c58a25a..851b0ccb0 100644 --- a/modules/apigee/outputs.tf +++ b/modules/apigee/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "endpoint_attachment_hosts" { description = "Endpoint hosts." value = { for k, v in google_apigee_endpoint_attachment.endpoint_attachments : k => v.host } diff --git a/modules/apigee/variables.tf b/modules/apigee/variables.tf index e8d1ffb66..0a42e1d76 100644 --- a/modules/apigee/variables.tf +++ b/modules/apigee/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "addons_config" { description = "Addons configuration." type = object({ diff --git a/modules/apigee/versions.tf b/modules/apigee/versions.tf index eefd7d0ae..bfbd7735a 100644 --- a/modules/apigee/versions.tf +++ b/modules/apigee/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/app-engine/README.md b/modules/app-engine/README.md index 479cab592..58ad1fe7b 100644 --- a/modules/app-engine/README.md +++ b/modules/app-engine/README.md @@ -1,3 +1,19 @@ + + # App Engine This module deploys a Google Cloud App Engine Instance diff --git a/modules/app-engine/main.tf b/modules/app-engine/main.tf index 0089ec58d..462b72ff4 100644 --- a/modules/app-engine/main.tf +++ b/modules/app-engine/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/app_engine_application resource "google_app_engine_application" "app" { diff --git a/modules/app-engine/outputs.tf b/modules/app-engine/outputs.tf index 99ed20a74..dcb66386b 100644 --- a/modules/app-engine/outputs.tf +++ b/modules/app-engine/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "app_id" { value = google_app_engine_application.app.app_id diff --git a/modules/app-engine/variables.tf b/modules/app-engine/variables.tf index 6c5971e4d..7e44cfb42 100644 --- a/modules/app-engine/variables.tf +++ b/modules/app-engine/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "auth_domain" { description = "The domain to authenticate users with when using App Engine's User API." diff --git a/modules/artifact-registry/README.md b/modules/artifact-registry/README.md index f38217a25..1456c24b7 100644 --- a/modules/artifact-registry/README.md +++ b/modules/artifact-registry/README.md @@ -1,3 +1,19 @@ + + # Google Cloud Artifact Registry Module This module simplifies the creation of repositories using Google Cloud Artifact Registry. diff --git a/modules/artifact-registry/iam.tf b/modules/artifact-registry/iam.tf index da0c78df7..87b51fa9e 100644 --- a/modules/artifact-registry/iam.tf +++ b/modules/artifact-registry/iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - moved { from = google_artifact_registry_repository_iam_binding.bindings to = google_artifact_registry_repository_iam_binding.authoritative diff --git a/modules/artifact-registry/main.tf b/modules/artifact-registry/main.tf index a9ac681e3..19ac524ed 100644 --- a/modules/artifact-registry/main.tf +++ b/modules/artifact-registry/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { format_obj = one([for k, v in var.format : v if v != null]) format_string = one([for k, v in var.format : k if v != null]) diff --git a/modules/artifact-registry/outputs.tf b/modules/artifact-registry/outputs.tf index b471e6dbf..dd4be8e5a 100644 --- a/modules/artifact-registry/outputs.tf +++ b/modules/artifact-registry/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "id" { description = "Fully qualified repository id." value = google_artifact_registry_repository.registry.id diff --git a/modules/artifact-registry/variables-iam.tf b/modules/artifact-registry/variables-iam.tf index 1f7530abf..bf56699ed 100644 --- a/modules/artifact-registry/variables-iam.tf +++ b/modules/artifact-registry/variables-iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description IAM bindings locals { diff --git a/modules/artifact-registry/variables.tf b/modules/artifact-registry/variables.tf index 23b194a39..8350bfdb3 100644 --- a/modules/artifact-registry/variables.tf +++ b/modules/artifact-registry/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "cleanup_policies" { description = "Object containing details about the cleanup policies for an Artifact Registry repository." type = map(object({ diff --git a/modules/artifact-registry/versions.tf b/modules/artifact-registry/versions.tf index ad37b3723..e5e1b4f74 100644 --- a/modules/artifact-registry/versions.tf +++ b/modules/artifact-registry/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/beyondcorp/README.md b/modules/beyondcorp/README.md index d820bf184..ec4786e6b 100644 --- a/modules/beyondcorp/README.md +++ b/modules/beyondcorp/README.md @@ -1,3 +1,19 @@ + + # Beyondcorp This module simplifies the deployment and configuration of BeyondCorp. diff --git a/modules/beyondcorp/main.tf b/modules/beyondcorp/main.tf index 4ea4d9ce5..40ded00c8 100644 --- a/modules/beyondcorp/main.tf +++ b/modules/beyondcorp/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ data "google_access_context_manager_access_policy" "existing_policy" { parent = "organizations/${var.organization_id}" diff --git a/modules/beyondcorp/outputs.tf b/modules/beyondcorp/outputs.tf index aa63a3d87..bcc28e228 100644 --- a/modules/beyondcorp/outputs.tf +++ b/modules/beyondcorp/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "endpoint_name" { description = "Name of the endpoint that was created." diff --git a/modules/beyondcorp/provider.tf b/modules/beyondcorp/provider.tf index 1bcf54408..38a2dbc85 100644 --- a/modules/beyondcorp/provider.tf +++ b/modules/beyondcorp/provider.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ provider "google" { project = var.project_id diff --git a/modules/beyondcorp/variables.tf b/modules/beyondcorp/variables.tf index aa9a5276a..8fdc2ac49 100644 --- a/modules/beyondcorp/variables.tf +++ b/modules/beyondcorp/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "endpoint_name" { description = "Name for endpoint." diff --git a/modules/biglake-catalog/README.md b/modules/biglake-catalog/README.md index efb391ead..c96d6c387 100644 --- a/modules/biglake-catalog/README.md +++ b/modules/biglake-catalog/README.md @@ -1,3 +1,19 @@ + + # Biglake Catalog This module allows to create a BigLake Metastore with databases and corresponding tables in each database. diff --git a/modules/biglake-catalog/main.tf b/modules/biglake-catalog/main.tf index 055b71056..f3d4b3eaf 100644 --- a/modules/biglake-catalog/main.tf +++ b/modules/biglake-catalog/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { tables = merge([ for k1, v1 in var.databases : { diff --git a/modules/biglake-catalog/outputs.tf b/modules/biglake-catalog/outputs.tf index 76d73242d..cadcc30ee 100644 --- a/modules/biglake-catalog/outputs.tf +++ b/modules/biglake-catalog/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "catalog" { description = "Catalog." value = google_biglake_catalog.catalog diff --git a/modules/biglake-catalog/variables.tf b/modules/biglake-catalog/variables.tf index 131b0e4d9..ab1504793 100644 --- a/modules/biglake-catalog/variables.tf +++ b/modules/biglake-catalog/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "databases" { description = "Databases." type = map(object({ diff --git a/modules/bigquery-dataset/README.md b/modules/bigquery-dataset/README.md index 6ab90184c..8198e5d0d 100644 --- a/modules/bigquery-dataset/README.md +++ b/modules/bigquery-dataset/README.md @@ -1,3 +1,19 @@ + + # Google Cloud Bigquery Module This module allows managing a single BigQuery dataset, including access configuration, tables and views. diff --git a/modules/bigquery-dataset/main.tf b/modules/bigquery-dataset/main.tf index 85b5ba51e..76a2e3748 100644 --- a/modules/bigquery-dataset/main.tf +++ b/modules/bigquery-dataset/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { access_domain = { for k, v in var.access : k => v if v.type == "domain" } access_group = { for k, v in var.access : k => v if v.type == "group" } diff --git a/modules/bigquery-dataset/outputs.tf b/modules/bigquery-dataset/outputs.tf index 9d056d59c..7d1cb4963 100644 --- a/modules/bigquery-dataset/outputs.tf +++ b/modules/bigquery-dataset/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "dataset" { description = "Dataset resource." value = google_bigquery_dataset.default diff --git a/modules/bigquery-dataset/tags.tf b/modules/bigquery-dataset/tags.tf index 55e9d33fe..f6d91b22d 100644 --- a/modules/bigquery-dataset/tags.tf +++ b/modules/bigquery-dataset/tags.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_tags_location_tag_binding" "binding" { for_each = var.tag_bindings parent = "//bigquery.googleapis.com/${google_bigquery_dataset.default.id}" diff --git a/modules/bigquery-dataset/variables.tf b/modules/bigquery-dataset/variables.tf index 1c3579cea..94c9888da 100644 --- a/modules/bigquery-dataset/variables.tf +++ b/modules/bigquery-dataset/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "access" { description = "Map of access rules with role and identity type. Keys are arbitrary and must match those in the `access_identities` variable, types are `domain`, `group`, `special_group`, `user`, `view`." type = map(object({ diff --git a/modules/bigquery-dataset/versions.tf b/modules/bigquery-dataset/versions.tf index 0d9a1d496..b7315c96b 100644 --- a/modules/bigquery-dataset/versions.tf +++ b/modules/bigquery-dataset/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/bigtable-instance/README.md b/modules/bigtable-instance/README.md index 42ad0975d..78361b393 100644 --- a/modules/bigtable-instance/README.md +++ b/modules/bigtable-instance/README.md @@ -1,3 +1,19 @@ + + # Google Cloud BigTable Module This module allows managing a single BigTable instance, including access configuration and tables. diff --git a/modules/bigtable-instance/main.tf b/modules/bigtable-instance/main.tf index 3aafaf261..849059d6d 100644 --- a/modules/bigtable-instance/main.tf +++ b/modules/bigtable-instance/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { gc_pairs = flatten([ for table, table_obj in var.tables : [ diff --git a/modules/bigtable-instance/outputs.tf b/modules/bigtable-instance/outputs.tf index 5cfabd6a7..e72e4d2e5 100644 --- a/modules/bigtable-instance/outputs.tf +++ b/modules/bigtable-instance/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "id" { description = "Fully qualified instance id." value = google_bigtable_instance.default.id diff --git a/modules/bigtable-instance/variables.tf b/modules/bigtable-instance/variables.tf index ca1fbb0e5..d7ac924e9 100644 --- a/modules/bigtable-instance/variables.tf +++ b/modules/bigtable-instance/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "clusters" { description = "Clusters to be created in the BigTable instance. Set more than one cluster to enable replication. If you set autoscaling, num_nodes will be ignored." nullable = false diff --git a/modules/bigtable-instance/versions.tf b/modules/bigtable-instance/versions.tf index 208040169..354a1f5cd 100644 --- a/modules/bigtable-instance/versions.tf +++ b/modules/bigtable-instance/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/billing-account/README.md b/modules/billing-account/README.md index 2d6a0e1c3..acd9409d0 100644 --- a/modules/billing-account/README.md +++ b/modules/billing-account/README.md @@ -1,3 +1,19 @@ + + # Billing Account Module This module allows managing resources and policies related to a billing account: diff --git a/modules/billing-account/budgets.tf b/modules/billing-account/budgets.tf index 2a66aee2b..af93dfbc2 100644 --- a/modules/billing-account/budgets.tf +++ b/modules/billing-account/budgets.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_monitoring_notification_channel" "default" { for_each = var.budget_notification_channels description = each.value.description diff --git a/modules/billing-account/factory.tf b/modules/billing-account/factory.tf index 097627e43..c3a8c6afb 100644 --- a/modules/billing-account/factory.tf +++ b/modules/billing-account/factory.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # any changes to this factory should be mirrored in the project factory locals { diff --git a/modules/billing-account/iam.tf b/modules/billing-account/iam.tf index 9d6704a86..9c2268478 100644 --- a/modules/billing-account/iam.tf +++ b/modules/billing-account/iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description IAM bindings. locals { diff --git a/modules/billing-account/logging.tf b/modules/billing-account/logging.tf index 9dcf7e69b..cc0fbd456 100644 --- a/modules/billing-account/logging.tf +++ b/modules/billing-account/logging.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Log sinks and supporting resources. locals { diff --git a/modules/billing-account/main.tf b/modules/billing-account/main.tf index f477cbb42..ab389708f 100644 --- a/modules/billing-account/main.tf +++ b/modules/billing-account/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_billing_project_info" "default" { for_each = toset(var.projects) billing_account = var.id diff --git a/modules/billing-account/outputs.tf b/modules/billing-account/outputs.tf index f8359c530..86e7d00d0 100644 --- a/modules/billing-account/outputs.tf +++ b/modules/billing-account/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "billing_budget_ids" { description = "Billing budget ids." value = { diff --git a/modules/billing-account/variables-iam.tf b/modules/billing-account/variables-iam.tf index 4299d4554..ab682e5d1 100644 --- a/modules/billing-account/variables-iam.tf +++ b/modules/billing-account/variables-iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "iam" { description = "IAM bindings in {ROLE => [MEMBERS]} format." type = map(list(string)) diff --git a/modules/billing-account/variables.tf b/modules/billing-account/variables.tf index 2b4d1bfbc..8de9b3d78 100644 --- a/modules/billing-account/variables.tf +++ b/modules/billing-account/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "budget_notification_channels" { description = "Notification channels used by budget alerts." type = map(object({ diff --git a/modules/billing-account/versions.tf b/modules/billing-account/versions.tf index 8d38b2c51..ede28729d 100644 --- a/modules/billing-account/versions.tf +++ b/modules/billing-account/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/binauthz/README.md b/modules/binauthz/README.md index 400ba576c..40e821521 100644 --- a/modules/binauthz/README.md +++ b/modules/binauthz/README.md @@ -1,3 +1,19 @@ + + # Google Cloud Binary Authroization Module This module simplifies the creation of a Binary Authorization policy, attestors and attestor IAM bindings. diff --git a/modules/binauthz/main.tf b/modules/binauthz/main.tf index 2c1af463a..c24ac615c 100644 --- a/modules/binauthz/main.tf +++ b/modules/binauthz/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_binary_authorization_policy" "policy" { project = var.project_id dynamic "admission_whitelist_patterns" { diff --git a/modules/binauthz/outputs.tf b/modules/binauthz/outputs.tf index 874f9ae6f..45e977341 100644 --- a/modules/binauthz/outputs.tf +++ b/modules/binauthz/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "attestors" { description = "Attestors." value = google_binary_authorization_attestor.attestors diff --git a/modules/binauthz/variables.tf b/modules/binauthz/variables.tf index edfafaafb..0a06591e0 100644 --- a/modules/binauthz/variables.tf +++ b/modules/binauthz/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "admission_whitelist_patterns" { description = "An image name pattern to allowlist." type = list(string) diff --git a/modules/binauthz/versions.tf b/modules/binauthz/versions.tf index 07adbdc12..5f440d435 100644 --- a/modules/binauthz/versions.tf +++ b/modules/binauthz/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/certificate-authority-service/README.md b/modules/certificate-authority-service/README.md index b99c87711..d59979389 100644 --- a/modules/certificate-authority-service/README.md +++ b/modules/certificate-authority-service/README.md @@ -1,3 +1,19 @@ + + # Certificate Authority Service (CAS) The module allows you to create one or more CAs and an optional CA pool. diff --git a/modules/certificate-authority-service/iam.tf b/modules/certificate-authority-service/iam.tf index ad2396776..dbdd12606 100644 --- a/modules/certificate-authority-service/iam.tf +++ b/modules/certificate-authority-service/iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description IAM bindings. locals { diff --git a/modules/certificate-authority-service/main.tf b/modules/certificate-authority-service/main.tf index d7f100dd8..59c20c905 100644 --- a/modules/certificate-authority-service/main.tf +++ b/modules/certificate-authority-service/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { pool_id = try( var.ca_pool_config.use_pool.id, diff --git a/modules/certificate-authority-service/outputs.tf b/modules/certificate-authority-service/outputs.tf index 56535c8c5..2b010f816 100644 --- a/modules/certificate-authority-service/outputs.tf +++ b/modules/certificate-authority-service/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "ca_chains" { description = "The CA chains in PEM format." value = { diff --git a/modules/certificate-authority-service/variables-iam.tf b/modules/certificate-authority-service/variables-iam.tf index 4299d4554..ab682e5d1 100644 --- a/modules/certificate-authority-service/variables-iam.tf +++ b/modules/certificate-authority-service/variables-iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "iam" { description = "IAM bindings in {ROLE => [MEMBERS]} format." type = map(list(string)) diff --git a/modules/certificate-authority-service/variables.tf b/modules/certificate-authority-service/variables.tf index e5e1229c7..55a71a951 100644 --- a/modules/certificate-authority-service/variables.tf +++ b/modules/certificate-authority-service/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "ca_configs" { description = "The CA configurations." type = map(object({ diff --git a/modules/certificate-authority-service/versions.tf b/modules/certificate-authority-service/versions.tf index a16ef3da5..8db1dce6d 100644 --- a/modules/certificate-authority-service/versions.tf +++ b/modules/certificate-authority-service/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/certificate-manager/README.md b/modules/certificate-manager/README.md index 1e7c3cf46..d52ebf626 100644 --- a/modules/certificate-manager/README.md +++ b/modules/certificate-manager/README.md @@ -1,3 +1,19 @@ + + # Certificate manager This module allows you to create a certificate manager map and associated entries, certificates, DNS authorizations and issueance configs. Map and associated entries creation is optional. diff --git a/modules/certificate-manager/main.tf b/modules/certificate-manager/main.tf index e82248f9a..fc8045d73 100644 --- a/modules/certificate-manager/main.tf +++ b/modules/certificate-manager/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_certificate_manager_certificate_map" "map" { count = var.map == null ? 0 : 1 project = var.project_id diff --git a/modules/certificate-manager/outputs.tf b/modules/certificate-manager/outputs.tf index 1648593be..c328bc4d2 100644 --- a/modules/certificate-manager/outputs.tf +++ b/modules/certificate-manager/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "certificate_ids" { description = "Certificate ids." value = { for k, v in google_certificate_manager_certificate.certificates : k => v.id } diff --git a/modules/certificate-manager/variables.tf b/modules/certificate-manager/variables.tf index d70169278..5d9fbd8f1 100644 --- a/modules/certificate-manager/variables.tf +++ b/modules/certificate-manager/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "certificates" { description = "Certificates." type = map(object({ diff --git a/modules/certificate-manager/versions.tf b/modules/certificate-manager/versions.tf index f5b095d90..cd375e7b1 100644 --- a/modules/certificate-manager/versions.tf +++ b/modules/certificate-manager/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/cis-log-alerts/README.md b/modules/cis-log-alerts/README.md index 139bf5bfb..2b8056321 100644 --- a/modules/cis-log-alerts/README.md +++ b/modules/cis-log-alerts/README.md @@ -1,3 +1,19 @@ + + # CIS Log Alerts Module This module provisions log-based alerts to satisfy the CIS Google Cloud Computing Foundation Benchmark requirements for monitoring and alerting. diff --git a/modules/cis-log-alerts/main.tf b/modules/cis-log-alerts/main.tf index 340ef8834..0daeebac4 100644 --- a/modules/cis-log-alerts/main.tf +++ b/modules/cis-log-alerts/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ locals { alert_filters = { diff --git a/modules/cis-log-alerts/variables.tf b/modules/cis-log-alerts/variables.tf index 01a310127..61dfd292d 100644 --- a/modules/cis-log-alerts/variables.tf +++ b/modules/cis-log-alerts/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "alert_email" { description = "Alert email." diff --git a/modules/cis-log-metrics/README.md b/modules/cis-log-metrics/README.md index b8dba06ba..a45aec302 100644 --- a/modules/cis-log-metrics/README.md +++ b/modules/cis-log-metrics/README.md @@ -1,3 +1,19 @@ + + # CIS Log Metrics Module This module creates log-based metrics to satisfy the CIS Google Cloud Computing Foundation Benchmark requirements for monitoring and alerting. diff --git a/modules/cis-log-metrics/main.tf b/modules/cis-log-metrics/main.tf index 1b9dd31a8..f2b9adab7 100644 --- a/modules/cis-log-metrics/main.tf +++ b/modules/cis-log-metrics/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ locals { log_filter = { diff --git a/modules/cis-log-metrics/variables.tf b/modules/cis-log-metrics/variables.tf index b4261d6b7..e44fd1527 100644 --- a/modules/cis-log-metrics/variables.tf +++ b/modules/cis-log-metrics/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "project" { description = "Project ID." diff --git a/modules/cloud-config-container/README.md b/modules/cloud-config-container/README.md index b41490040..415b19d9b 100644 --- a/modules/cloud-config-container/README.md +++ b/modules/cloud-config-container/README.md @@ -1,3 +1,19 @@ + + # Instance Configuration via `cloud-config` This set of modules creates specialized [cloud-config](https://cloud.google.com/container-optimized-os/docs/how-to/run-container-instance#starting_a_docker_container_via_cloud-config) configurations, which are designed for use with [Container Optimized OS](https://cloud.google.com/container-optimized-os/docs) (the onprem module is the only exception) but can also be used as a basis for other image types or cloud providers. diff --git a/modules/cloud-config-container/bindplane/README.md b/modules/cloud-config-container/bindplane/README.md index 055b22f22..814423211 100644 --- a/modules/cloud-config-container/bindplane/README.md +++ b/modules/cloud-config-container/bindplane/README.md @@ -1,3 +1,19 @@ + + # Containerized Bindplane on Container Optimized OS This module manages a `cloud-config` configuration that starts a containerized [Bindplane](https://observiq.com/solutions) service on Container Optimized OS, using the official [Bindplane EE image](https://hub.docker.com/r/observiq/bindplane-ee) provided by observIQ and documented in the [official documentation page](https://observiq.com/download) when selecting "Docker" as target platform. diff --git a/modules/cloud-config-container/bindplane/cloud-config.yaml b/modules/cloud-config-container/bindplane/cloud-config.yaml index 885a0af40..706e69db6 100644 --- a/modules/cloud-config-container/bindplane/cloud-config.yaml +++ b/modules/cloud-config-container/bindplane/cloud-config.yaml @@ -1,12 +1,12 @@ #cloud-config -# Copyright 2024 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# https://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + # https://hub.docker.com/r/nginx/nginx/ # https://nginx.io/manual/toc/#installation diff --git a/modules/cloud-config-container/bindplane/main.tf b/modules/cloud-config-container/bindplane/main.tf index ab7ba0660..64d12c0c8 100644 --- a/modules/cloud-config-container/bindplane/main.tf +++ b/modules/cloud-config-container/bindplane/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { cloud_config = templatefile(local.template, merge(var.config_variables, { bindplane_prometheus_image = var.bindplane_config.bindplane_prometheus_image diff --git a/modules/cloud-config-container/bindplane/outputs.tf b/modules/cloud-config-container/bindplane/outputs.tf index 56e082429..713997735 100644 --- a/modules/cloud-config-container/bindplane/outputs.tf +++ b/modules/cloud-config-container/bindplane/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "cloud_config" { description = "Rendered cloud-config file to be passed as user-data instance metadata." value = local.cloud_config diff --git a/modules/cloud-config-container/bindplane/variables.tf b/modules/cloud-config-container/bindplane/variables.tf index 92082aa8d..8bef6ad4f 100644 --- a/modules/cloud-config-container/bindplane/variables.tf +++ b/modules/cloud-config-container/bindplane/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "bindplane_config" { description = "Bindplane configurations." type = object({ diff --git a/modules/cloud-config-container/bindplane/versions.tf b/modules/cloud-config-container/bindplane/versions.tf index f6e661879..a46bd8a43 100644 --- a/modules/cloud-config-container/bindplane/versions.tf +++ b/modules/cloud-config-container/bindplane/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/cloud-config-container/coredns/README.md b/modules/cloud-config-container/coredns/README.md index c4f63a90b..f43bef25a 100644 --- a/modules/cloud-config-container/coredns/README.md +++ b/modules/cloud-config-container/coredns/README.md @@ -1,3 +1,19 @@ + + # Containerized CoreDNS on Container Optimized OS This module manages a `cloud-config` configuration that starts a containerized [CoreDNS](https://coredns.io/) service on Container Optimized OS, using the [official image](https://hub.docker.com/r/coredns/coredns/). diff --git a/modules/cloud-config-container/coredns/cloud-config.yaml b/modules/cloud-config-container/coredns/cloud-config.yaml index 4293c762b..07fbe65a5 100644 --- a/modules/cloud-config-container/coredns/cloud-config.yaml +++ b/modules/cloud-config-container/coredns/cloud-config.yaml @@ -1,12 +1,12 @@ #cloud-config -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# https://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + # https://hub.docker.com/r/coredns/coredns/ # https://coredns.io/manual/toc/#installation diff --git a/modules/cloud-config-container/coredns/main.tf b/modules/cloud-config-container/coredns/main.tf index 789168ca4..a51c29e13 100644 --- a/modules/cloud-config-container/coredns/main.tf +++ b/modules/cloud-config-container/coredns/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { cloud_config = templatefile(local.template, merge(var.config_variables, { corefile = templatefile(local.corefile, var.config_variables) diff --git a/modules/cloud-config-container/coredns/outputs.tf b/modules/cloud-config-container/coredns/outputs.tf index 7d8d41656..713997735 100644 --- a/modules/cloud-config-container/coredns/outputs.tf +++ b/modules/cloud-config-container/coredns/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "cloud_config" { description = "Rendered cloud-config file to be passed as user-data instance metadata." value = local.cloud_config diff --git a/modules/cloud-config-container/coredns/variables.tf b/modules/cloud-config-container/coredns/variables.tf index c323017fc..dc1831792 100644 --- a/modules/cloud-config-container/coredns/variables.tf +++ b/modules/cloud-config-container/coredns/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "cloud_config" { description = "Cloud config template path. If null default will be used." type = string diff --git a/modules/cloud-config-container/coredns/versions.tf b/modules/cloud-config-container/coredns/versions.tf index 982159d8c..dc3bb94fe 100644 --- a/modules/cloud-config-container/coredns/versions.tf +++ b/modules/cloud-config-container/coredns/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/cloud-config-container/cos-generic-metadata/README.md b/modules/cloud-config-container/cos-generic-metadata/README.md index 88073986d..0410127a7 100644 --- a/modules/cloud-config-container/cos-generic-metadata/README.md +++ b/modules/cloud-config-container/cos-generic-metadata/README.md @@ -1,3 +1,19 @@ + + # Generic cloud-init generator for Container Optimized OS This helper module manages a `cloud-config` configuration that can start a container on [Container Optimized OS](https://cloud.google.com/container-optimized-os/docs) (COS). Either a complete `cloud-config` template can be provided via the `cloud_config` variable with optional template variables via the `config_variables`, or a generic `cloud-config` can be generated based on typical parameters needed to start a container. diff --git a/modules/cloud-config-container/cos-generic-metadata/cloud-config.yaml b/modules/cloud-config-container/cos-generic-metadata/cloud-config.yaml index d34833635..32ba581c0 100644 --- a/modules/cloud-config-container/cos-generic-metadata/cloud-config.yaml +++ b/modules/cloud-config-container/cos-generic-metadata/cloud-config.yaml @@ -1,12 +1,12 @@ #cloud-config -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# https://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + %{ if length(users) > 0 ~} users: %{ for user in users ~} diff --git a/modules/cloud-config-container/cos-generic-metadata/main.tf b/modules/cloud-config-container/cos-generic-metadata/main.tf index eb807c5ae..438fa5601 100644 --- a/modules/cloud-config-container/cos-generic-metadata/main.tf +++ b/modules/cloud-config-container/cos-generic-metadata/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { cloud_config = templatefile(local.template, merge(var.config_variables, { boot_commands = var.boot_commands diff --git a/modules/cloud-config-container/cos-generic-metadata/outputs.tf b/modules/cloud-config-container/cos-generic-metadata/outputs.tf index 7d8d41656..713997735 100644 --- a/modules/cloud-config-container/cos-generic-metadata/outputs.tf +++ b/modules/cloud-config-container/cos-generic-metadata/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "cloud_config" { description = "Rendered cloud-config file to be passed as user-data instance metadata." value = local.cloud_config diff --git a/modules/cloud-config-container/cos-generic-metadata/variables.tf b/modules/cloud-config-container/cos-generic-metadata/variables.tf index 022591649..285842524 100644 --- a/modules/cloud-config-container/cos-generic-metadata/variables.tf +++ b/modules/cloud-config-container/cos-generic-metadata/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "authenticate_gcr" { description = "Setup docker to pull images from private GCR. Requires at least one user since the token is stored in the home of the first user defined." type = bool diff --git a/modules/cloud-config-container/cos-generic-metadata/versions.tf b/modules/cloud-config-container/cos-generic-metadata/versions.tf index a8ee08475..8e6807b1e 100644 --- a/modules/cloud-config-container/cos-generic-metadata/versions.tf +++ b/modules/cloud-config-container/cos-generic-metadata/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/cloud-config-container/envoy-sni-dyn-fwd-proxy/README.md b/modules/cloud-config-container/envoy-sni-dyn-fwd-proxy/README.md index 76d1b19d4..389d6813f 100644 --- a/modules/cloud-config-container/envoy-sni-dyn-fwd-proxy/README.md +++ b/modules/cloud-config-container/envoy-sni-dyn-fwd-proxy/README.md @@ -1,3 +1,19 @@ + + # Containerized Envoy as SNI dynamic forward proxy on Container Optimized OS This module manages a `cloud-config` configuration that starts a containerized [Envoy SNI Dynamic forward proxy]https://www.envoyproxy.io/docs/envoy/latest/configuration/listeners/network_filters/sni_dynamic_forward_proxy_filter) service on Container Optimized OS running on port 443. diff --git a/modules/cloud-config-container/envoy-sni-dyn-fwd-proxy/files/envoy.yaml b/modules/cloud-config-container/envoy-sni-dyn-fwd-proxy/files/envoy.yaml index d9ad5643b..92c95c7ba 100644 --- a/modules/cloud-config-container/envoy-sni-dyn-fwd-proxy/files/envoy.yaml +++ b/modules/cloud-config-container/envoy-sni-dyn-fwd-proxy/files/envoy.yaml @@ -1,10 +1,10 @@ -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# https://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + admin: address: socket_address: diff --git a/modules/cloud-config-container/envoy-sni-dyn-fwd-proxy/main.tf b/modules/cloud-config-container/envoy-sni-dyn-fwd-proxy/main.tf index f0b7cdfb2..75190e756 100644 --- a/modules/cloud-config-container/envoy-sni-dyn-fwd-proxy/main.tf +++ b/modules/cloud-config-container/envoy-sni-dyn-fwd-proxy/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - module "cos-envoy" { source = "../cos-generic-metadata" container_image = var.envoy_image diff --git a/modules/cloud-config-container/envoy-sni-dyn-fwd-proxy/outputs.tf b/modules/cloud-config-container/envoy-sni-dyn-fwd-proxy/outputs.tf index 417c73e7d..5753d0d4a 100644 --- a/modules/cloud-config-container/envoy-sni-dyn-fwd-proxy/outputs.tf +++ b/modules/cloud-config-container/envoy-sni-dyn-fwd-proxy/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "cloud_config" { description = "Rendered cloud-config file to be passed as user-data instance metadata." value = module.cos-envoy.cloud_config diff --git a/modules/cloud-config-container/envoy-sni-dyn-fwd-proxy/variables.tf b/modules/cloud-config-container/envoy-sni-dyn-fwd-proxy/variables.tf index 3868a1742..f294cf217 100644 --- a/modules/cloud-config-container/envoy-sni-dyn-fwd-proxy/variables.tf +++ b/modules/cloud-config-container/envoy-sni-dyn-fwd-proxy/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "envoy_image" { description = "Image." type = string diff --git a/modules/cloud-config-container/envoy-sni-dyn-fwd-proxy/versions.tf b/modules/cloud-config-container/envoy-sni-dyn-fwd-proxy/versions.tf index 29afe3375..3bbc09919 100644 --- a/modules/cloud-config-container/envoy-sni-dyn-fwd-proxy/versions.tf +++ b/modules/cloud-config-container/envoy-sni-dyn-fwd-proxy/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/cloud-config-container/envoy-traffic-director/README.md b/modules/cloud-config-container/envoy-traffic-director/README.md index caa0ec5ec..d14739f3a 100644 --- a/modules/cloud-config-container/envoy-traffic-director/README.md +++ b/modules/cloud-config-container/envoy-traffic-director/README.md @@ -1,3 +1,19 @@ + + # Containerized Envoy Proxy with Traffic Director on Container Optimized OS This module manages a `cloud-config` configuration that starts a containerized Envoy Proxy on Container Optimized OS connected to Traffic Director. The default configuration creates a reverse proxy exposed on the node's port 80. Traffic routing policies and management should be managed by other means via Traffic Director. diff --git a/modules/cloud-config-container/envoy-traffic-director/files/customize.sh b/modules/cloud-config-container/envoy-traffic-director/files/customize.sh index afd884c37..932c19238 100644 --- a/modules/cloud-config-container/envoy-traffic-director/files/customize.sh +++ b/modules/cloud-config-container/envoy-traffic-director/files/customize.sh @@ -1,11 +1,11 @@ #!/bin/bash -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + ENVOY_NODE_ID=$(uuidgen) ENVOY_ZONE=$(curl -s -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/zone | cut -f 4 -d '/') CONFIG_PROJECT_NUMBER=$(curl -s -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/network-interfaces/0/network | cut -f 2 -d '/') diff --git a/modules/cloud-config-container/envoy-traffic-director/files/envoy.yaml b/modules/cloud-config-container/envoy-traffic-director/files/envoy.yaml index 981837c5c..4eb49d7bf 100644 --- a/modules/cloud-config-container/envoy-traffic-director/files/envoy.yaml +++ b/modules/cloud-config-container/envoy-traffic-director/files/envoy.yaml @@ -1,10 +1,10 @@ -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + node: # The id must be in the following format: projects//networks//nodes/ id: "projects/CONFIG_PROJECT_NUMBER/networks/VPC_NETWORK_NAME/nodes/ENVOY_NODE_ID" diff --git a/modules/cloud-config-container/envoy-traffic-director/main.tf b/modules/cloud-config-container/envoy-traffic-director/main.tf index a6da7847d..fafc42b0f 100644 --- a/modules/cloud-config-container/envoy-traffic-director/main.tf +++ b/modules/cloud-config-container/envoy-traffic-director/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - module "cos-envoy-td" { source = "../cos-generic-metadata" diff --git a/modules/cloud-config-container/envoy-traffic-director/outputs.tf b/modules/cloud-config-container/envoy-traffic-director/outputs.tf index 4ce8d2473..97121cb70 100644 --- a/modules/cloud-config-container/envoy-traffic-director/outputs.tf +++ b/modules/cloud-config-container/envoy-traffic-director/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "cloud_config" { description = "Rendered cloud-config file to be passed as user-data instance metadata." value = module.cos-envoy-td.cloud_config diff --git a/modules/cloud-config-container/envoy-traffic-director/variables.tf b/modules/cloud-config-container/envoy-traffic-director/variables.tf index 82cdbbd6c..45bbfd3a9 100644 --- a/modules/cloud-config-container/envoy-traffic-director/variables.tf +++ b/modules/cloud-config-container/envoy-traffic-director/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "envoy_image" { description = "Envoy Proxy container image to use." type = string diff --git a/modules/cloud-config-container/envoy-traffic-director/versions.tf b/modules/cloud-config-container/envoy-traffic-director/versions.tf index db3e3463a..22057815d 100644 --- a/modules/cloud-config-container/envoy-traffic-director/versions.tf +++ b/modules/cloud-config-container/envoy-traffic-director/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/cloud-config-container/mysql/README.md b/modules/cloud-config-container/mysql/README.md index 31045804d..542944d23 100644 --- a/modules/cloud-config-container/mysql/README.md +++ b/modules/cloud-config-container/mysql/README.md @@ -1,3 +1,19 @@ + + # Containerized MySQL on Container Optimized OS This module manages a `cloud-config` configuration that starts a containerized [MySQL](https://www.mysql.com/) service on Container Optimized OS, using the [official image](https://hub.docker.com/_/mysql). diff --git a/modules/cloud-config-container/mysql/cloud-config.yaml b/modules/cloud-config-container/mysql/cloud-config.yaml index 7d7cd4d6e..f034e8e0c 100644 --- a/modules/cloud-config-container/mysql/cloud-config.yaml +++ b/modules/cloud-config-container/mysql/cloud-config.yaml @@ -1,12 +1,12 @@ #cloud-config -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# https://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + users: - name: mysql uid: 2000 diff --git a/modules/cloud-config-container/mysql/main.tf b/modules/cloud-config-container/mysql/main.tf index 4e44c4693..00c11ed54 100644 --- a/modules/cloud-config-container/mysql/main.tf +++ b/modules/cloud-config-container/mysql/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { cloud_config = templatefile(local.template, merge(var.config_variables, { image = var.image diff --git a/modules/cloud-config-container/mysql/outputs.tf b/modules/cloud-config-container/mysql/outputs.tf index 7d8d41656..713997735 100644 --- a/modules/cloud-config-container/mysql/outputs.tf +++ b/modules/cloud-config-container/mysql/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "cloud_config" { description = "Rendered cloud-config file to be passed as user-data instance metadata." value = local.cloud_config diff --git a/modules/cloud-config-container/mysql/variables.tf b/modules/cloud-config-container/mysql/variables.tf index 52bb3dbbd..bca209c39 100644 --- a/modules/cloud-config-container/mysql/variables.tf +++ b/modules/cloud-config-container/mysql/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "cloud_config" { description = "Cloud config template path. If null default will be used." type = string diff --git a/modules/cloud-config-container/mysql/versions.tf b/modules/cloud-config-container/mysql/versions.tf index 7bafaf7a9..51a183bb1 100644 --- a/modules/cloud-config-container/mysql/versions.tf +++ b/modules/cloud-config-container/mysql/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/cloud-config-container/nginx-tls/README.md b/modules/cloud-config-container/nginx-tls/README.md index 15f2ffe0c..a37f6e4e0 100644 --- a/modules/cloud-config-container/nginx-tls/README.md +++ b/modules/cloud-config-container/nginx-tls/README.md @@ -1,3 +1,19 @@ + + # Containerized Nginx with self-signed TLS on Container Optimized OS This module manages a `cloud-config` configuration that starts a containerized Nginx with a self-signed TLS cert on Container Optimized OS. This can be useful if you need quickly a VM or instance group answering HTTPS for prototyping. diff --git a/modules/cloud-config-container/nginx-tls/assets/cloud-config.yaml b/modules/cloud-config-container/nginx-tls/assets/cloud-config.yaml index e6282e327..34ed51ca9 100644 --- a/modules/cloud-config-container/nginx-tls/assets/cloud-config.yaml +++ b/modules/cloud-config-container/nginx-tls/assets/cloud-config.yaml @@ -1,12 +1,12 @@ #cloud-config -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# https://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + users: - name: nginx uid: 2000 diff --git a/modules/cloud-config-container/nginx-tls/assets/customize.sh b/modules/cloud-config-container/nginx-tls/assets/customize.sh index 52ddbe779..a7d3c7859 100644 --- a/modules/cloud-config-container/nginx-tls/assets/customize.sh +++ b/modules/cloud-config-container/nginx-tls/assets/customize.sh @@ -1,11 +1,11 @@ #!/bin/bash -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + FQDN=$(\ curl -s -H "Metadata-Flavor: Google" \ http://metadata/computeMetadata/v1/instance/hostname) diff --git a/modules/cloud-config-container/nginx-tls/outputs.tf b/modules/cloud-config-container/nginx-tls/outputs.tf index 2acd83f64..3b8cb5c8a 100644 --- a/modules/cloud-config-container/nginx-tls/outputs.tf +++ b/modules/cloud-config-container/nginx-tls/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "cloud_config" { description = "Rendered cloud-config file to be passed as user-data instance metadata." value = templatefile("${path.module}/assets/cloud-config.yaml", { diff --git a/modules/cloud-config-container/nginx-tls/variables.tf b/modules/cloud-config-container/nginx-tls/variables.tf index f3cab5826..26735e61b 100644 --- a/modules/cloud-config-container/nginx-tls/variables.tf +++ b/modules/cloud-config-container/nginx-tls/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "files" { description = "Map of extra files to create on the instance, path as key. Owner and permissions will use defaults if null." type = map(object({ diff --git a/modules/cloud-config-container/nginx-tls/versions.tf b/modules/cloud-config-container/nginx-tls/versions.tf index f32e1767c..702730599 100644 --- a/modules/cloud-config-container/nginx-tls/versions.tf +++ b/modules/cloud-config-container/nginx-tls/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/cloud-config-container/nginx/README.md b/modules/cloud-config-container/nginx/README.md index dad3d55d9..51172b5d4 100644 --- a/modules/cloud-config-container/nginx/README.md +++ b/modules/cloud-config-container/nginx/README.md @@ -1,3 +1,19 @@ + + # Containerized Nginx on Container Optimized OS This module manages a `cloud-config` configuration that starts a containerized [Nginx](https://nginx.org/en/) service on Container Optimized OS, using the [hello demo image](https://hub.docker.com/r/nginxdemos/hello/). diff --git a/modules/cloud-config-container/nginx/cloud-config.yaml b/modules/cloud-config-container/nginx/cloud-config.yaml index bada8bc67..8db2c6ccd 100644 --- a/modules/cloud-config-container/nginx/cloud-config.yaml +++ b/modules/cloud-config-container/nginx/cloud-config.yaml @@ -1,12 +1,12 @@ #cloud-config -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# https://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + # https://hub.docker.com/r/nginx/nginx/ # https://nginx.io/manual/toc/#installation diff --git a/modules/cloud-config-container/nginx/main.tf b/modules/cloud-config-container/nginx/main.tf index 39c59930f..ec5e06fb9 100644 --- a/modules/cloud-config-container/nginx/main.tf +++ b/modules/cloud-config-container/nginx/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { cloud_config = templatefile(local.template, merge(var.config_variables, { etc_mount = ( diff --git a/modules/cloud-config-container/nginx/outputs.tf b/modules/cloud-config-container/nginx/outputs.tf index 7d8d41656..713997735 100644 --- a/modules/cloud-config-container/nginx/outputs.tf +++ b/modules/cloud-config-container/nginx/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "cloud_config" { description = "Rendered cloud-config file to be passed as user-data instance metadata." value = local.cloud_config diff --git a/modules/cloud-config-container/nginx/variables.tf b/modules/cloud-config-container/nginx/variables.tf index 973baff28..91eeb2526 100644 --- a/modules/cloud-config-container/nginx/variables.tf +++ b/modules/cloud-config-container/nginx/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "cloud_config" { description = "Cloud config template path. If null default will be used." type = string diff --git a/modules/cloud-config-container/nginx/versions.tf b/modules/cloud-config-container/nginx/versions.tf index 0fa7367cf..00ed0b132 100644 --- a/modules/cloud-config-container/nginx/versions.tf +++ b/modules/cloud-config-container/nginx/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/cloud-config-container/simple-nva/README.md b/modules/cloud-config-container/simple-nva/README.md index 0f3741fac..93794d421 100644 --- a/modules/cloud-config-container/simple-nva/README.md +++ b/modules/cloud-config-container/simple-nva/README.md @@ -1,3 +1,19 @@ + + # Google Simple NVA Module The module allows you to create Network Virtual Appliances (NVAs) as a stub for future appliances deployments. diff --git a/modules/cloud-config-container/simple-nva/cloud-config.yaml b/modules/cloud-config-container/simple-nva/cloud-config.yaml index b5553793c..80ec9cc41 100644 --- a/modules/cloud-config-container/simple-nva/cloud-config.yaml +++ b/modules/cloud-config-container/simple-nva/cloud-config.yaml @@ -1,12 +1,12 @@ #cloud-config -# Copyright 2024 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# https://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + write_files: %{ for path, data in files } - path: ${path} diff --git a/modules/cloud-config-container/simple-nva/files/ipprefix_by_netmask.sh b/modules/cloud-config-container/simple-nva/files/ipprefix_by_netmask.sh index 169438253..b17f72645 100644 --- a/modules/cloud-config-container/simple-nva/files/ipprefix_by_netmask.sh +++ b/modules/cloud-config-container/simple-nva/files/ipprefix_by_netmask.sh @@ -1,12 +1,12 @@ #!/bin/bash -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + # https://stackoverflow.com/questions/50413579/bash-convert-netmask-in-cidr-notation c=0 x=0$(printf '%o' ${1//./ }) while [ $x -gt 0 ]; do diff --git a/modules/cloud-config-container/simple-nva/files/policy_based_routing.sh b/modules/cloud-config-container/simple-nva/files/policy_based_routing.sh index 008aa0b83..b6cd5ec59 100644 --- a/modules/cloud-config-container/simple-nva/files/policy_based_routing.sh +++ b/modules/cloud-config-container/simple-nva/files/policy_based_routing.sh @@ -1,12 +1,12 @@ #!/bin/bash -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + IF_NAME=$1 IF_NUMBER=$(echo $IF_NAME | sed -e s/eth//) IF_GW=$(curl http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/$IF_NUMBER/gateway -H "Metadata-Flavor: Google") diff --git a/modules/cloud-config-container/simple-nva/main.tf b/modules/cloud-config-container/simple-nva/main.tf index 7fb0f163f..5e17455c8 100644 --- a/modules/cloud-config-container/simple-nva/main.tf +++ b/modules/cloud-config-container/simple-nva/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _files = merge( { diff --git a/modules/cloud-config-container/simple-nva/outputs.tf b/modules/cloud-config-container/simple-nva/outputs.tf index 54942c1ad..713997735 100644 --- a/modules/cloud-config-container/simple-nva/outputs.tf +++ b/modules/cloud-config-container/simple-nva/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "cloud_config" { description = "Rendered cloud-config file to be passed as user-data instance metadata." value = local.cloud_config diff --git a/modules/cloud-config-container/simple-nva/variables.tf b/modules/cloud-config-container/simple-nva/variables.tf index 20eecd0ab..bf301d14c 100644 --- a/modules/cloud-config-container/simple-nva/variables.tf +++ b/modules/cloud-config-container/simple-nva/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "cloud_config" { description = "Cloud config template path. If null default will be used." type = string diff --git a/modules/cloud-config-container/simple-nva/versions.tf b/modules/cloud-config-container/simple-nva/versions.tf index 254029325..d9c2d9b0c 100644 --- a/modules/cloud-config-container/simple-nva/versions.tf +++ b/modules/cloud-config-container/simple-nva/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/cloud-function-v1/README.md b/modules/cloud-function-v1/README.md index 6b427e654..2b8415f7e 100644 --- a/modules/cloud-function-v1/README.md +++ b/modules/cloud-function-v1/README.md @@ -1,3 +1,19 @@ + + # Cloud Function Module (V1) Cloud Function management, with support for IAM roles, optional bucket creation and bundle via GCS URI, local zip, or local source folder. diff --git a/modules/cloud-function-v1/bundle.tf b/modules/cloud-function-v1/bundle.tf index 661ece842..044ffcbf3 100644 --- a/modules/cloud-function-v1/bundle.tf +++ b/modules/cloud-function-v1/bundle.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { bundle_type = ( startswith(var.bundle_config.path, "gs://") diff --git a/modules/cloud-function-v1/main.tf b/modules/cloud-function-v1/main.tf index e51ded541..8e3575ce2 100644 --- a/modules/cloud-function-v1/main.tf +++ b/modules/cloud-function-v1/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { bucket = ( var.bucket_config == null diff --git a/modules/cloud-function-v1/outputs.tf b/modules/cloud-function-v1/outputs.tf index 16fddf15e..413360ab6 100644 --- a/modules/cloud-function-v1/outputs.tf +++ b/modules/cloud-function-v1/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "bucket" { description = "Bucket resource (only if auto-created)." value = try( diff --git a/modules/cloud-function-v1/variables.tf b/modules/cloud-function-v1/variables.tf index 98f1f10af..5be337f93 100644 --- a/modules/cloud-function-v1/variables.tf +++ b/modules/cloud-function-v1/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "bucket_config" { description = "Enable and configure auto-created bucket. Set fields to null to use defaults." type = object({ diff --git a/modules/cloud-function-v1/versions.tf b/modules/cloud-function-v1/versions.tf index f92cb3d4c..a2f14515c 100644 --- a/modules/cloud-function-v1/versions.tf +++ b/modules/cloud-function-v1/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/cloud-function-v2/README.md b/modules/cloud-function-v2/README.md index 366eac29d..aac66a1d6 100644 --- a/modules/cloud-function-v2/README.md +++ b/modules/cloud-function-v2/README.md @@ -1,3 +1,19 @@ + + # Cloud Function Module (v2) Cloud Function management, with support for IAM roles, optional bucket creation and bundle via GCS URI, local zip, or local source folder. diff --git a/modules/cloud-function-v2/bundle.tf b/modules/cloud-function-v2/bundle.tf index 661ece842..044ffcbf3 100644 --- a/modules/cloud-function-v2/bundle.tf +++ b/modules/cloud-function-v2/bundle.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { bundle_type = ( startswith(var.bundle_config.path, "gs://") diff --git a/modules/cloud-function-v2/main.tf b/modules/cloud-function-v2/main.tf index 691720106..39e9d6030 100644 --- a/modules/cloud-function-v2/main.tf +++ b/modules/cloud-function-v2/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { bucket = ( var.bucket_config == null diff --git a/modules/cloud-function-v2/outputs.tf b/modules/cloud-function-v2/outputs.tf index d2256d256..1b344380d 100644 --- a/modules/cloud-function-v2/outputs.tf +++ b/modules/cloud-function-v2/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "bucket" { description = "Bucket resource (only if auto-created)." value = try( diff --git a/modules/cloud-function-v2/variables.tf b/modules/cloud-function-v2/variables.tf index f51ba347d..4e7d980e5 100644 --- a/modules/cloud-function-v2/variables.tf +++ b/modules/cloud-function-v2/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "bucket_config" { description = "Enable and configure auto-created bucket. Set fields to null to use defaults." type = object({ diff --git a/modules/cloud-function-v2/versions.tf b/modules/cloud-function-v2/versions.tf index 49734d86e..679f236b3 100644 --- a/modules/cloud-function-v2/versions.tf +++ b/modules/cloud-function-v2/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/cloud-identity-group/README.md b/modules/cloud-identity-group/README.md index eee01c407..d030f38e7 100644 --- a/modules/cloud-identity-group/README.md +++ b/modules/cloud-identity-group/README.md @@ -1,3 +1,19 @@ + + # Cloud Identity Group Module This module allows creating a Cloud Identity group and assigning members. diff --git a/modules/cloud-identity-group/main.tf b/modules/cloud-identity-group/main.tf index 7e0455ef0..386df4a39 100644 --- a/modules/cloud-identity-group/main.tf +++ b/modules/cloud-identity-group/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_cloud_identity_group" "group" { display_name = var.display_name parent = var.customer_id diff --git a/modules/cloud-identity-group/outputs.tf b/modules/cloud-identity-group/outputs.tf index 95c31de20..ff85fc408 100644 --- a/modules/cloud-identity-group/outputs.tf +++ b/modules/cloud-identity-group/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "id" { description = "Fully qualified group id." value = google_cloud_identity_group.group.id diff --git a/modules/cloud-identity-group/variables.tf b/modules/cloud-identity-group/variables.tf index 221bcb849..2f1af65d7 100644 --- a/modules/cloud-identity-group/variables.tf +++ b/modules/cloud-identity-group/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "customer_id" { description = "Directory customer ID in the form customers/C0xxxxxxx." type = string diff --git a/modules/cloud-identity-group/versions.tf b/modules/cloud-identity-group/versions.tf index 4e8153ec5..4ef48401a 100644 --- a/modules/cloud-identity-group/versions.tf +++ b/modules/cloud-identity-group/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/cloud-run-v2-se/README.md b/modules/cloud-run-v2-se/README.md index 0a651c41a..8a57f9d70 100644 --- a/modules/cloud-run-v2-se/README.md +++ b/modules/cloud-run-v2-se/README.md @@ -1,3 +1,19 @@ + + # Cloud Run Module Cloud Run Services and Jobs, with support for IAM roles and Eventarc trigger creation. This module uses provider default value for `deletion_protection`, which means service is by default protected from removal (or reprovisioning). diff --git a/modules/cloud-run-v2-se/job.tf b/modules/cloud-run-v2-se/job.tf index bd2584f15..7f0390106 100644 --- a/modules/cloud-run-v2-se/job.tf +++ b/modules/cloud-run-v2-se/job.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_cloud_run_v2_job" "job" { count = var.create_job ? 1 : 0 provider = google-beta diff --git a/modules/cloud-run-v2-se/main.tf b/modules/cloud-run-v2-se/main.tf index 5e506de7c..d277db971 100644 --- a/modules/cloud-run-v2-se/main.tf +++ b/modules/cloud-run-v2-se/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { connector = ( var.vpc_connector_create != null diff --git a/modules/cloud-run-v2-se/outputs.tf b/modules/cloud-run-v2-se/outputs.tf index 0abcebd09..7ba38f4b5 100644 --- a/modules/cloud-run-v2-se/outputs.tf +++ b/modules/cloud-run-v2-se/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "id" { description = "Fully qualified job or service id." value = var.create_job ? google_cloud_run_v2_job.job[0].id : google_cloud_run_v2_service.service[0].id diff --git a/modules/cloud-run-v2-se/service.tf b/modules/cloud-run-v2-se/service.tf index 3ede9ce2a..f99583608 100644 --- a/modules/cloud-run-v2-se/service.tf +++ b/modules/cloud-run-v2-se/service.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_cloud_run_v2_service" "service" { count = var.create_job ? 0 : 1 provider = google-beta diff --git a/modules/cloud-run-v2-se/tags.tf b/modules/cloud-run-v2-se/tags.tf index 001911d03..60bacbbe9 100644 --- a/modules/cloud-run-v2-se/tags.tf +++ b/modules/cloud-run-v2-se/tags.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_tags_location_tag_binding" "binding" { for_each = var.create_job ? {} : var.tag_bindings parent = ( diff --git a/modules/cloud-run-v2-se/variables-vpcconnector.tf b/modules/cloud-run-v2-se/variables-vpcconnector.tf index 199f2d5bc..34edafbe7 100644 --- a/modules/cloud-run-v2-se/variables-vpcconnector.tf +++ b/modules/cloud-run-v2-se/variables-vpcconnector.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "vpc_connector_create" { description = "Populate this to create a Serverless VPC Access connector." type = object({ diff --git a/modules/cloud-run-v2-se/variables.tf b/modules/cloud-run-v2-se/variables.tf index 38da2c70a..9ac22642e 100644 --- a/modules/cloud-run-v2-se/variables.tf +++ b/modules/cloud-run-v2-se/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "binary_authorization_mode" { description = "Mode for Binary Authorization. Can be 'default', 'policy', or 'disabled'" type = string diff --git a/modules/cloud-run-v2-se/versions.tf b/modules/cloud-run-v2-se/versions.tf index ee12f597a..151ad734d 100644 --- a/modules/cloud-run-v2-se/versions.tf +++ b/modules/cloud-run-v2-se/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/cloud-run-v2-se/vpcconnector.tf b/modules/cloud-run-v2-se/vpcconnector.tf index 50a7904c9..2900abaa6 100644 --- a/modules/cloud-run-v2-se/vpcconnector.tf +++ b/modules/cloud-run-v2-se/vpcconnector.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_vpc_access_connector" "connector" { count = var.vpc_connector_create != null ? 1 : 0 project = var.project_id diff --git a/modules/cloud-run-v2/README.md b/modules/cloud-run-v2/README.md index 0a651c41a..8a57f9d70 100644 --- a/modules/cloud-run-v2/README.md +++ b/modules/cloud-run-v2/README.md @@ -1,3 +1,19 @@ + + # Cloud Run Module Cloud Run Services and Jobs, with support for IAM roles and Eventarc trigger creation. This module uses provider default value for `deletion_protection`, which means service is by default protected from removal (or reprovisioning). diff --git a/modules/cloud-run-v2/job.tf b/modules/cloud-run-v2/job.tf index bd2584f15..7f0390106 100644 --- a/modules/cloud-run-v2/job.tf +++ b/modules/cloud-run-v2/job.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_cloud_run_v2_job" "job" { count = var.create_job ? 1 : 0 provider = google-beta diff --git a/modules/cloud-run-v2/main.tf b/modules/cloud-run-v2/main.tf index 5e506de7c..d277db971 100644 --- a/modules/cloud-run-v2/main.tf +++ b/modules/cloud-run-v2/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { connector = ( var.vpc_connector_create != null diff --git a/modules/cloud-run-v2/outputs.tf b/modules/cloud-run-v2/outputs.tf index 0abcebd09..7ba38f4b5 100644 --- a/modules/cloud-run-v2/outputs.tf +++ b/modules/cloud-run-v2/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "id" { description = "Fully qualified job or service id." value = var.create_job ? google_cloud_run_v2_job.job[0].id : google_cloud_run_v2_service.service[0].id diff --git a/modules/cloud-run-v2/service.tf b/modules/cloud-run-v2/service.tf index 8df793740..f6330eb8f 100644 --- a/modules/cloud-run-v2/service.tf +++ b/modules/cloud-run-v2/service.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_cloud_run_v2_service" "service" { count = var.create_job ? 0 : 1 provider = google-beta diff --git a/modules/cloud-run-v2/tags.tf b/modules/cloud-run-v2/tags.tf index 001911d03..60bacbbe9 100644 --- a/modules/cloud-run-v2/tags.tf +++ b/modules/cloud-run-v2/tags.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_tags_location_tag_binding" "binding" { for_each = var.create_job ? {} : var.tag_bindings parent = ( diff --git a/modules/cloud-run-v2/variables-vpcconnector.tf b/modules/cloud-run-v2/variables-vpcconnector.tf index 199f2d5bc..34edafbe7 100644 --- a/modules/cloud-run-v2/variables-vpcconnector.tf +++ b/modules/cloud-run-v2/variables-vpcconnector.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "vpc_connector_create" { description = "Populate this to create a Serverless VPC Access connector." type = object({ diff --git a/modules/cloud-run-v2/variables.tf b/modules/cloud-run-v2/variables.tf index 951ad84c1..2e25ee845 100644 --- a/modules/cloud-run-v2/variables.tf +++ b/modules/cloud-run-v2/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "containers" { description = "Containers in name => attributes format." type = map(object({ diff --git a/modules/cloud-run-v2/versions.tf b/modules/cloud-run-v2/versions.tf index ee12f597a..151ad734d 100644 --- a/modules/cloud-run-v2/versions.tf +++ b/modules/cloud-run-v2/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/cloud-run-v2/vpcconnector.tf b/modules/cloud-run-v2/vpcconnector.tf index 50a7904c9..2900abaa6 100644 --- a/modules/cloud-run-v2/vpcconnector.tf +++ b/modules/cloud-run-v2/vpcconnector.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_vpc_access_connector" "connector" { count = var.vpc_connector_create != null ? 1 : 0 project = var.project_id diff --git a/modules/cloud-run/README.md b/modules/cloud-run/README.md index 9dbf641af..c48150c7e 100644 --- a/modules/cloud-run/README.md +++ b/modules/cloud-run/README.md @@ -1,3 +1,19 @@ + + # Cloud Run Module Cloud Run management, with support for IAM roles, revision annotations and optional Eventarc trigger creation. diff --git a/modules/cloud-run/main.tf b/modules/cloud-run/main.tf index f9c859a48..c626df95f 100644 --- a/modules/cloud-run/main.tf +++ b/modules/cloud-run/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _vpcaccess_annotation = ( local.vpc_connector_create diff --git a/modules/cloud-run/outputs.tf b/modules/cloud-run/outputs.tf index dcca33374..2b39a23e4 100644 --- a/modules/cloud-run/outputs.tf +++ b/modules/cloud-run/outputs.tf @@ -1,6 +1,6 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "id" { description = "Fully qualified service id." value = google_cloud_run_service.service.id diff --git a/modules/cloud-run/tags.tf b/modules/cloud-run/tags.tf index c988ed650..0934f0e77 100644 --- a/modules/cloud-run/tags.tf +++ b/modules/cloud-run/tags.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_tags_location_tag_binding" "binding" { for_each = var.tag_bindings parent = ( diff --git a/modules/cloud-run/variables.tf b/modules/cloud-run/variables.tf index 197864505..85fbcd7b0 100644 --- a/modules/cloud-run/variables.tf +++ b/modules/cloud-run/variables.tf @@ -1,6 +1,6 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "container_concurrency" { description = "Maximum allowed in-flight (concurrent) requests per container of the revision." type = string diff --git a/modules/cloud-run/versions.tf b/modules/cloud-run/versions.tf index c4901ba9c..343388893 100644 --- a/modules/cloud-run/versions.tf +++ b/modules/cloud-run/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/cloud-scheduler/README.md b/modules/cloud-scheduler/README.md index b52cd972f..b5d42cbda 100644 --- a/modules/cloud-scheduler/README.md +++ b/modules/cloud-scheduler/README.md @@ -1,3 +1,19 @@ + + # Cloud Schedulder Module This module manages the creation of a Cloud Scheduler Job diff --git a/modules/cloud-scheduler/main.tf b/modules/cloud-scheduler/main.tf index 569d6e760..4f4e55c33 100644 --- a/modules/cloud-scheduler/main.tf +++ b/modules/cloud-scheduler/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ resource "google_cloud_scheduler_job" "job" { project = var.project_id diff --git a/modules/cloud-scheduler/outputs.tf b/modules/cloud-scheduler/outputs.tf index 19456522a..e992d2296 100644 --- a/modules/cloud-scheduler/outputs.tf +++ b/modules/cloud-scheduler/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "id" { description = "Job ID." diff --git a/modules/cloud-scheduler/variables.tf b/modules/cloud-scheduler/variables.tf index 5d4b69d2c..d0bdc206d 100644 --- a/modules/cloud-scheduler/variables.tf +++ b/modules/cloud-scheduler/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "description" { description = "Job description." diff --git a/modules/cloud-scheduler/versions.tf b/modules/cloud-scheduler/versions.tf index 2cea29229..fc10e46b3 100644 --- a/modules/cloud-scheduler/versions.tf +++ b/modules/cloud-scheduler/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2024 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v35.0.0 diff --git a/modules/cloudsql-instance/README.md b/modules/cloudsql-instance/README.md index 925e0a84a..3c6c1ba11 100644 --- a/modules/cloudsql-instance/README.md +++ b/modules/cloudsql-instance/README.md @@ -1,3 +1,19 @@ + + # Cloud SQL instance module This module manages the creation of Cloud SQL instances with potential read replicas in other regions. It can also create an initial set of users and databases via the `users` and `databases` parameters. diff --git a/modules/cloudsql-instance/main.tf b/modules/cloudsql-instance/main.tf index 5f6287cc8..c85a33356 100644 --- a/modules/cloudsql-instance/main.tf +++ b/modules/cloudsql-instance/main.tf @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + /** TO MOD * Copyright 2024 Google LLC * diff --git a/modules/cloudsql-instance/outputs.tf b/modules/cloudsql-instance/outputs.tf index a9f4b814d..066d3ba43 100644 --- a/modules/cloudsql-instance/outputs.tf +++ b/modules/cloudsql-instance/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _all_instances = merge( { primary = google_sql_database_instance.primary }, diff --git a/modules/cloudsql-instance/variables.tf b/modules/cloudsql-instance/variables.tf index 678d4f531..b78be61cc 100644 --- a/modules/cloudsql-instance/variables.tf +++ b/modules/cloudsql-instance/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/cloudsql-instance/versions.tf b/modules/cloudsql-instance/versions.tf index f3b8efea0..d2a0d0c27 100644 --- a/modules/cloudsql-instance/versions.tf +++ b/modules/cloudsql-instance/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/compute-mig/README.md b/modules/compute-mig/README.md index 01aec0163..3f74bcd1c 100644 --- a/modules/compute-mig/README.md +++ b/modules/compute-mig/README.md @@ -1,3 +1,19 @@ + + # GCE Managed Instance Group module This module allows creating a managed instance group supporting one or more application versions via instance templates. Optionally, a health check and an autoscaler can be created, and the managed instance group can be configured to be stateful. diff --git a/modules/compute-mig/autoscaler.tf b/modules/compute-mig/autoscaler.tf index 9f8f9480c..5d9870253 100644 --- a/modules/compute-mig/autoscaler.tf +++ b/modules/compute-mig/autoscaler.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Autoscaler resource. locals { diff --git a/modules/compute-mig/health-check.tf b/modules/compute-mig/health-check.tf index 88f9f6ea7..e3c7b3b71 100644 --- a/modules/compute-mig/health-check.tf +++ b/modules/compute-mig/health-check.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Health check resource. locals { diff --git a/modules/compute-mig/main.tf b/modules/compute-mig/main.tf index 12a8a9b5e..b2950f744 100644 --- a/modules/compute-mig/main.tf +++ b/modules/compute-mig/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { health_check = ( try(var.auto_healing_policies.health_check, null) == null diff --git a/modules/compute-mig/outputs.tf b/modules/compute-mig/outputs.tf index 389a8d296..f530f1868 100644 --- a/modules/compute-mig/outputs.tf +++ b/modules/compute-mig/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "autoscaler" { description = "Auto-created autoscaler resource." value = var.autoscaler_config == null ? null : try( diff --git a/modules/compute-mig/stateful-config.tf b/modules/compute-mig/stateful-config.tf index 0073fba67..888a6a06b 100644 --- a/modules/compute-mig/stateful-config.tf +++ b/modules/compute-mig/stateful-config.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Instance-level stateful configuration resources. resource "google_compute_per_instance_config" "default" { diff --git a/modules/compute-mig/variables.tf b/modules/compute-mig/variables.tf index 20864d186..774c5375d 100644 --- a/modules/compute-mig/variables.tf +++ b/modules/compute-mig/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "all_instances_config" { description = "Metadata and labels set to all instances in the group." type = object({ diff --git a/modules/compute-mig/versions.tf b/modules/compute-mig/versions.tf index 2cb0c4f60..8c3514e37 100644 --- a/modules/compute-mig/versions.tf +++ b/modules/compute-mig/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/compute-vm/README.md b/modules/compute-vm/README.md index 1928a8dce..74282085b 100644 --- a/modules/compute-vm/README.md +++ b/modules/compute-vm/README.md @@ -1,3 +1,19 @@ + + # Google Compute Engine VM module This module can operate in two distinct modes: diff --git a/modules/compute-vm/main.tf b/modules/compute-vm/main.tf index bf215af06..be0a9266a 100644 --- a/modules/compute-vm/main.tf +++ b/modules/compute-vm/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { advanced_mf = var.options.advanced_machine_features attached_disks = { diff --git a/modules/compute-vm/outputs.tf b/modules/compute-vm/outputs.tf index dc5a80266..ca3889571 100644 --- a/modules/compute-vm/outputs.tf +++ b/modules/compute-vm/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "external_ip" { description = "Instance main interface external IP addresses." value = ( diff --git a/modules/compute-vm/resource-policies.tf b/modules/compute-vm/resource-policies.tf index 743e1e335..15d22b542 100644 --- a/modules/compute-vm/resource-policies.tf +++ b/modules/compute-vm/resource-policies.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Resource policies. locals { diff --git a/modules/compute-vm/tags.tf b/modules/compute-vm/tags.tf index 4f494cb95..7133a9be7 100644 --- a/modules/compute-vm/tags.tf +++ b/modules/compute-vm/tags.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Tag bindings. # TODO: re-implement once the following have been addressed in the provider diff --git a/modules/compute-vm/test.tfvars b/modules/compute-vm/test.tfvars index 5c60eab21..d42475e45 100644 --- a/modules/compute-vm/test.tfvars +++ b/modules/compute-vm/test.tfvars @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + project_id = "tf-playground-svpc-gce" zone = "europe-west8-b" name = "test-sa" diff --git a/modules/compute-vm/variables.tf b/modules/compute-vm/variables.tf index 6e84daa84..e3dc63b32 100644 --- a/modules/compute-vm/variables.tf +++ b/modules/compute-vm/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "attached_disk_defaults" { description = "Defaults for attached disks options." type = object({ diff --git a/modules/compute-vm/versions.tf b/modules/compute-vm/versions.tf index d2da71ccc..d8fa6f89d 100644 --- a/modules/compute-vm/versions.tf +++ b/modules/compute-vm/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/container-registry/README.md b/modules/container-registry/README.md index fd8b1c524..390e03210 100644 --- a/modules/container-registry/README.md +++ b/modules/container-registry/README.md @@ -1,3 +1,19 @@ + + # Google Cloud Container Registry Module This module simplifies the creation of GCS buckets used by Google Container Registry. diff --git a/modules/container-registry/main.tf b/modules/container-registry/main.tf index 740975105..29ff9d8ec 100644 --- a/modules/container-registry/main.tf +++ b/modules/container-registry/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_container_registry" "registry" { project = var.project_id location = var.location diff --git a/modules/container-registry/outputs.tf b/modules/container-registry/outputs.tf index 1c2aeb4e4..8907cf56c 100644 --- a/modules/container-registry/outputs.tf +++ b/modules/container-registry/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "id" { description = "Fully qualified id of the registry bucket." value = google_container_registry.registry.id diff --git a/modules/container-registry/variables.tf b/modules/container-registry/variables.tf index f09274e44..2ddaf482e 100644 --- a/modules/container-registry/variables.tf +++ b/modules/container-registry/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "iam" { description = "IAM bindings for topic in {ROLE => [MEMBERS]} format." type = map(list(string)) diff --git a/modules/container-registry/versions.tf b/modules/container-registry/versions.tf index 37eb4e9a5..241821ece 100644 --- a/modules/container-registry/versions.tf +++ b/modules/container-registry/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/data-catalog-policy-tag/README.md b/modules/data-catalog-policy-tag/README.md index a9906ed63..66fede85e 100644 --- a/modules/data-catalog-policy-tag/README.md +++ b/modules/data-catalog-policy-tag/README.md @@ -1,3 +1,19 @@ + + # Data Catalog Module This module simplifies the creation of [Data Catalog](https://cloud.google.com/data-catalog) Policy Tags. Policy Tags can be used to configure [Bigquery column-level access](https://cloud.google.com/bigquery/docs/best-practices-policy-tags). diff --git a/modules/data-catalog-policy-tag/iam.tf b/modules/data-catalog-policy-tag/iam.tf index 4abd98a92..ee2b09fd1 100644 --- a/modules/data-catalog-policy-tag/iam.tf +++ b/modules/data-catalog-policy-tag/iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Data Catalog Taxonomy IAM definition. locals { diff --git a/modules/data-catalog-policy-tag/main.tf b/modules/data-catalog-policy-tag/main.tf index 0ccd9235f..033bf326f 100644 --- a/modules/data-catalog-policy-tag/main.tf +++ b/modules/data-catalog-policy-tag/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Data Catalog Taxonomy definition locals { diff --git a/modules/data-catalog-policy-tag/outputs.tf b/modules/data-catalog-policy-tag/outputs.tf index 4f579c284..7c4b5a713 100644 --- a/modules/data-catalog-policy-tag/outputs.tf +++ b/modules/data-catalog-policy-tag/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "id" { description = "Fully qualified taxonomy id." value = google_data_catalog_taxonomy.default.id diff --git a/modules/data-catalog-policy-tag/variables-iam.tf b/modules/data-catalog-policy-tag/variables-iam.tf index fbe243d8d..733d2b50a 100644 --- a/modules/data-catalog-policy-tag/variables-iam.tf +++ b/modules/data-catalog-policy-tag/variables-iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "iam_by_principals" { description = "Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid cycle errors. Merged internally with the `iam` variable." type = map(list(string)) diff --git a/modules/data-catalog-policy-tag/variables.tf b/modules/data-catalog-policy-tag/variables.tf index c294b086e..8c4f4c30a 100644 --- a/modules/data-catalog-policy-tag/variables.tf +++ b/modules/data-catalog-policy-tag/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "activated_policy_types" { description = "A list of policy types that are activated for this taxonomy." type = list(string) diff --git a/modules/data-catalog-policy-tag/versions.tf b/modules/data-catalog-policy-tag/versions.tf index e8a256022..5723bb1ae 100644 --- a/modules/data-catalog-policy-tag/versions.tf +++ b/modules/data-catalog-policy-tag/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/data-catalog-tag-template/README.md b/modules/data-catalog-tag-template/README.md index 73246cfc4..a301daeea 100644 --- a/modules/data-catalog-tag-template/README.md +++ b/modules/data-catalog-tag-template/README.md @@ -1,3 +1,19 @@ + + # Google Cloud Data Catalog Tag Template Module This module allows managing [Data Catalog Tag Templates](https://cloud.google.com/data-catalog/docs/tags-and-tag-templates). diff --git a/modules/data-catalog-tag-template/iam.tf b/modules/data-catalog-tag-template/iam.tf index 68ffd30bc..114f3035d 100644 --- a/modules/data-catalog-tag-template/iam.tf +++ b/modules/data-catalog-tag-template/iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description IAM bindings locals { diff --git a/modules/data-catalog-tag-template/main.tf b/modules/data-catalog-tag-template/main.tf index 1498dcb81..8e66a620a 100644 --- a/modules/data-catalog-tag-template/main.tf +++ b/modules/data-catalog-tag-template/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { # read factory data _tt_path = try(pathexpand(var.factories_config.tag_templates), null) diff --git a/modules/data-catalog-tag-template/outputs.tf b/modules/data-catalog-tag-template/outputs.tf index 241db2335..d280534c9 100644 --- a/modules/data-catalog-tag-template/outputs.tf +++ b/modules/data-catalog-tag-template/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "data_catalog_tag_template_ids" { description = "Data catalog tag template ids." value = { diff --git a/modules/data-catalog-tag-template/variables.tf b/modules/data-catalog-tag-template/variables.tf index 3e72cc3e2..453ea67d0 100644 --- a/modules/data-catalog-tag-template/variables.tf +++ b/modules/data-catalog-tag-template/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "factories_config" { description = "Paths to data files and folders that enable factory functionality." type = object({ diff --git a/modules/data-catalog-tag-template/versions.tf b/modules/data-catalog-tag-template/versions.tf index bc785e12d..b58486908 100644 --- a/modules/data-catalog-tag-template/versions.tf +++ b/modules/data-catalog-tag-template/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/data-catalog-tag/README.md b/modules/data-catalog-tag/README.md index fa2f3379e..8c4198dd9 100644 --- a/modules/data-catalog-tag/README.md +++ b/modules/data-catalog-tag/README.md @@ -1,3 +1,19 @@ + + # Google Cloud Data Catalog Tag Module This module allows managing [Data Catalog Tag](https://cloud.google.com/data-catalog/docs/tags-and-tag-templates) on GCP resources such as BigQuery Datasets, Tables or columns. diff --git a/modules/data-catalog-tag/main.tf b/modules/data-catalog-tag/main.tf index ee9d1b7cb..6adf5e7cd 100644 --- a/modules/data-catalog-tag/main.tf +++ b/modules/data-catalog-tag/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _factory_tag_template = { for f in try(fileset(var.factories_config.tags, "*.yaml"), []) : diff --git a/modules/data-catalog-tag/outputs.tf b/modules/data-catalog-tag/outputs.tf index 8ee99a901..fe323e583 100644 --- a/modules/data-catalog-tag/outputs.tf +++ b/modules/data-catalog-tag/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "data_catalog_tag_ids" { description = "Data catalog tag ids." value = { for k, v in google_data_catalog_tag.engine : k => v.id } diff --git a/modules/data-catalog-tag/variables.tf b/modules/data-catalog-tag/variables.tf index 7456ca90f..fbe87f53d 100644 --- a/modules/data-catalog-tag/variables.tf +++ b/modules/data-catalog-tag/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "factories_config" { description = "Paths to data files and folders that enable factory functionality." type = object({ diff --git a/modules/data-catalog-tag/versions.tf b/modules/data-catalog-tag/versions.tf index 83d791b33..a341f5722 100644 --- a/modules/data-catalog-tag/versions.tf +++ b/modules/data-catalog-tag/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/dataform-repository/README.md b/modules/dataform-repository/README.md index 47699dc1b..4116973b3 100644 --- a/modules/dataform-repository/README.md +++ b/modules/dataform-repository/README.md @@ -1,3 +1,19 @@ + + # Google Cloud Dataform Repository module This module allows managing a dataform repository, allows adding IAM permissions. Also enables attaching a remote repository. diff --git a/modules/dataform-repository/iam.tf b/modules/dataform-repository/iam.tf index 5763e3c6c..8e309789b 100644 --- a/modules/dataform-repository/iam.tf +++ b/modules/dataform-repository/iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_dataform_repository_iam_binding" "authoritative" { provider = google-beta for_each = var.iam diff --git a/modules/dataform-repository/main.tf b/modules/dataform-repository/main.tf index d37155876..17e0a6cab 100644 --- a/modules/dataform-repository/main.tf +++ b/modules/dataform-repository/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_dataform_repository" "default" { provider = google-beta project = var.project_id diff --git a/modules/dataform-repository/variables.tf b/modules/dataform-repository/variables.tf index 649507b2f..077702731 100644 --- a/modules/dataform-repository/variables.tf +++ b/modules/dataform-repository/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "iam" { description = "IAM bindings in {ROLE => [MEMBERS]} format. Mutually exclusive with the access_* variables used for basic roles." type = map(list(string)) diff --git a/modules/dataform-repository/versions.tf b/modules/dataform-repository/versions.tf index 0251890a4..dc2f98802 100644 --- a/modules/dataform-repository/versions.tf +++ b/modules/dataform-repository/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/datafusion-se/README.md b/modules/datafusion-se/README.md index 0de6157c7..de931c0f5 100644 --- a/modules/datafusion-se/README.md +++ b/modules/datafusion-se/README.md @@ -1,3 +1,19 @@ + + # Google Cloud Data Fusion Module This module allows simple management of ['Google Data Fusion'](https://cloud.google.com/data-fusion) instances. It supports creating Basic or Enterprise, public or private instances. diff --git a/modules/datafusion-se/main.tf b/modules/datafusion-se/main.tf index 402adf7aa..769264647 100644 --- a/modules/datafusion-se/main.tf +++ b/modules/datafusion-se/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/modules/datafusion-se/outputs.tf b/modules/datafusion-se/outputs.tf index 869e3e570..bb2c0d769 100644 --- a/modules/datafusion-se/outputs.tf +++ b/modules/datafusion-se/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "id" { description = "Fully qualified instance id." value = google_data_fusion_instance.default.id diff --git a/modules/datafusion-se/variables.tf b/modules/datafusion-se/variables.tf index be228cd0f..a79c45c98 100644 --- a/modules/datafusion-se/variables.tf +++ b/modules/datafusion-se/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - ############################################################################### # DtaFusion variables # ############################################################################### diff --git a/modules/datafusion-se/versions.tf b/modules/datafusion-se/versions.tf index 2cea29229..fc10e46b3 100644 --- a/modules/datafusion-se/versions.tf +++ b/modules/datafusion-se/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2024 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v35.0.0 diff --git a/modules/datafusion/README.md b/modules/datafusion/README.md index 03b65b7b2..97b04b1e1 100644 --- a/modules/datafusion/README.md +++ b/modules/datafusion/README.md @@ -1,3 +1,19 @@ + + # Google Cloud Data Fusion Module This module allows simple management of ['Google Data Fusion'](https://cloud.google.com/data-fusion) instances. It supports creating Basic or Enterprise, public or private instances. diff --git a/modules/datafusion/main.tf b/modules/datafusion/main.tf index f6784dd97..901316124 100644 --- a/modules/datafusion/main.tf +++ b/modules/datafusion/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { prefix_length = 22 ip_allocation = ( diff --git a/modules/datafusion/outputs.tf b/modules/datafusion/outputs.tf index a7248c137..8d83b54e3 100644 --- a/modules/datafusion/outputs.tf +++ b/modules/datafusion/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "id" { description = "Fully qualified instance id." value = google_data_fusion_instance.default.id diff --git a/modules/datafusion/variables.tf b/modules/datafusion/variables.tf index 19d61f49c..822ce3587 100644 --- a/modules/datafusion/variables.tf +++ b/modules/datafusion/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - ############################################################################### # DtaFusion variables # ############################################################################### diff --git a/modules/datafusion/versions.tf b/modules/datafusion/versions.tf index f9fd6ae95..472afaa9c 100644 --- a/modules/datafusion/versions.tf +++ b/modules/datafusion/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/dataplex-datascan/README.md b/modules/dataplex-datascan/README.md index e36ded9ac..0e9abe2f7 100644 --- a/modules/dataplex-datascan/README.md +++ b/modules/dataplex-datascan/README.md @@ -1,3 +1,19 @@ + + # Dataplex DataScan This module manages the creation of Dataplex DataScan resources. diff --git a/modules/dataplex-datascan/factory.tf b/modules/dataplex-datascan/factory.tf index e76f9af78..e136828b6 100644 --- a/modules/dataplex-datascan/factory.tf +++ b/modules/dataplex-datascan/factory.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _factory_data = ( var.factories_config.data_quality_spec == null diff --git a/modules/dataplex-datascan/iam.tf b/modules/dataplex-datascan/iam.tf index dea671a95..b6410305b 100644 --- a/modules/dataplex-datascan/iam.tf +++ b/modules/dataplex-datascan/iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _iam_principal_roles = distinct(flatten(values(var.iam_by_principals))) _iam_principals = { diff --git a/modules/dataplex-datascan/main.tf b/modules/dataplex-datascan/main.tf index 752fe7730..109549f5f 100644 --- a/modules/dataplex-datascan/main.tf +++ b/modules/dataplex-datascan/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { data_quality_spec = { post_scan_actions = try( diff --git a/modules/dataplex-datascan/outputs.tf b/modules/dataplex-datascan/outputs.tf index f314c57b9..997ac1d94 100644 --- a/modules/dataplex-datascan/outputs.tf +++ b/modules/dataplex-datascan/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "data_scan_id" { description = "Dataplex DataScan ID." value = google_dataplex_datascan.datascan.data_scan_id diff --git a/modules/dataplex-datascan/variables-iam.tf b/modules/dataplex-datascan/variables-iam.tf index 81a93f9ff..ec90cf574 100644 --- a/modules/dataplex-datascan/variables-iam.tf +++ b/modules/dataplex-datascan/variables-iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "iam_by_principals" { description = "Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid cycle errors. Merged internally with the `iam` variable." type = map(list(string)) diff --git a/modules/dataplex-datascan/variables.tf b/modules/dataplex-datascan/variables.tf index 6c6a6a68e..fb916dde8 100644 --- a/modules/dataplex-datascan/variables.tf +++ b/modules/dataplex-datascan/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "data" { description = "The data source for DataScan. The source can be either a Dataplex `entity` or a BigQuery `resource`." type = object({ diff --git a/modules/dataplex-datascan/versions.tf b/modules/dataplex-datascan/versions.tf index 17ccc0709..c18ec86fa 100644 --- a/modules/dataplex-datascan/versions.tf +++ b/modules/dataplex-datascan/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/dataplex/README.md b/modules/dataplex/README.md index bc16be747..102272093 100644 --- a/modules/dataplex/README.md +++ b/modules/dataplex/README.md @@ -1,3 +1,19 @@ + + # Dataplex instance with lake, zone & assets This module manages the creation of Dataplex instance along with lake, zone & assets in single regions. diff --git a/modules/dataplex/main.tf b/modules/dataplex/main.tf index b78ca5481..efe61ef9a 100644 --- a/modules/dataplex/main.tf +++ b/modules/dataplex/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { prefix = var.prefix == null ? "" : "${var.prefix}-" zone_assets = flatten([ diff --git a/modules/dataplex/outputs.tf b/modules/dataplex/outputs.tf index 0da4fcc24..653e372e3 100644 --- a/modules/dataplex/outputs.tf +++ b/modules/dataplex/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "assets" { description = "Assets attached to the lake of Dataplex Lake." value = local.zone_assets[*] diff --git a/modules/dataplex/variables.tf b/modules/dataplex/variables.tf index fa4e65211..cc9d4fa4b 100644 --- a/modules/dataplex/variables.tf +++ b/modules/dataplex/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "iam" { description = "Dataplex lake IAM bindings in {ROLE => [MEMBERS]} format." type = map(list(string)) diff --git a/modules/dataplex/versions.tf b/modules/dataplex/versions.tf index edc25cb23..3b3497c12 100644 --- a/modules/dataplex/versions.tf +++ b/modules/dataplex/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/dataproc/README.md b/modules/dataproc/README.md index 6f7356a24..1a8d73e6a 100644 --- a/modules/dataproc/README.md +++ b/modules/dataproc/README.md @@ -1,3 +1,19 @@ + + # Google Cloud Dataproc This module Manages a Google Cloud [Dataproc](https://cloud.google.com/dataproc) cluster resource, including IAM. diff --git a/modules/dataproc/iam.tf b/modules/dataproc/iam.tf index b3fc6aa47..ea08c52b3 100644 --- a/modules/dataproc/iam.tf +++ b/modules/dataproc/iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description IAM bindings. locals { diff --git a/modules/dataproc/main.tf b/modules/dataproc/main.tf index 02d9f21e4..74066640d 100644 --- a/modules/dataproc/main.tf +++ b/modules/dataproc/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Cloud Dataproc resource definition. resource "google_dataproc_cluster" "cluster" { diff --git a/modules/dataproc/outputs.tf b/modules/dataproc/outputs.tf index 27f47236d..42bcb915a 100644 --- a/modules/dataproc/outputs.tf +++ b/modules/dataproc/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Cloud Dataproc module output. # FIXME: 2024-03-08: broken in provider diff --git a/modules/dataproc/variables-iam.tf b/modules/dataproc/variables-iam.tf index 16f24608a..ffc563689 100644 --- a/modules/dataproc/variables-iam.tf +++ b/modules/dataproc/variables-iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "iam_by_principals" { description = "Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid cycle errors. Merged internally with the `iam` variable." type = map(list(string)) diff --git a/modules/dataproc/variables.tf b/modules/dataproc/variables.tf index 3d39da00a..9d21812c5 100644 --- a/modules/dataproc/variables.tf +++ b/modules/dataproc/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "dataproc_config" { description = "Dataproc cluster config." type = object({ diff --git a/modules/dataproc/versions.tf b/modules/dataproc/versions.tf index 287772fa5..0c0c10d8c 100644 --- a/modules/dataproc/versions.tf +++ b/modules/dataproc/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/dns-response-policy/README.md b/modules/dns-response-policy/README.md index 010c09c5a..df7332a52 100644 --- a/modules/dns-response-policy/README.md +++ b/modules/dns-response-policy/README.md @@ -1,3 +1,19 @@ + + # Google Cloud DNS Response Policy This module allows management of a [Google Cloud DNS policy and its rules](https://cloud.google.com/dns/docs/zones/manage-response-policies). The policy can already exist and be referenced by name by setting the `policy_create` variable to `false`. diff --git a/modules/dns-response-policy/main.tf b/modules/dns-response-policy/main.tf index 0cee3ca14..996f2c50a 100644 --- a/modules/dns-response-policy/main.tf +++ b/modules/dns-response-policy/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _factory_data = ( var.factories_config.rules != null diff --git a/modules/dns-response-policy/outputs.tf b/modules/dns-response-policy/outputs.tf index cea4a5865..3214a521a 100644 --- a/modules/dns-response-policy/outputs.tf +++ b/modules/dns-response-policy/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "id" { description = "Fully qualified policy id." value = try(google_dns_response_policy.default[0].id, null) diff --git a/modules/dns-response-policy/variables.tf b/modules/dns-response-policy/variables.tf index 1c39260a9..665eeb6dd 100644 --- a/modules/dns-response-policy/variables.tf +++ b/modules/dns-response-policy/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "clusters" { description = "Map of GKE clusters to which this policy is applied in name => id format." type = map(string) diff --git a/modules/dns-response-policy/versions.tf b/modules/dns-response-policy/versions.tf index a198a21f5..9426a4966 100644 --- a/modules/dns-response-policy/versions.tf +++ b/modules/dns-response-policy/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/dns/README.md b/modules/dns/README.md index fe2fdb90c..1c0959316 100644 --- a/modules/dns/README.md +++ b/modules/dns/README.md @@ -1,3 +1,19 @@ + + # Google Cloud DNS Module This module allows simple management of Google Cloud DNS zones and records. It supports creating public, private, forwarding, peering, service directory and reverse-managed based zones. To create inbound/outbound server policies, please have a look at the [net-vpc](../net-vpc/README.md) module. diff --git a/modules/dns/main.tf b/modules/dns/main.tf index a13ea40f1..c1513f6c2 100644 --- a/modules/dns/main.tf +++ b/modules/dns/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { managed_zone = (var.zone_config == null ? data.google_dns_managed_zone.dns_managed_zone[0] diff --git a/modules/dns/outputs.tf b/modules/dns/outputs.tf index e84bf9768..7679edd93 100644 --- a/modules/dns/outputs.tf +++ b/modules/dns/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "dns_keys" { description = "DNSKEY and DS records of DNSSEC-signed managed zones." value = try(data.google_dns_keys.dns_keys[0], null) diff --git a/modules/dns/variables.tf b/modules/dns/variables.tf index 4dc10e2c5..509071782 100644 --- a/modules/dns/variables.tf +++ b/modules/dns/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "description" { description = "Domain description." type = string diff --git a/modules/dns/versions.tf b/modules/dns/versions.tf index da3fba6eb..5d3c9a33c 100644 --- a/modules/dns/versions.tf +++ b/modules/dns/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/endpoints/README.md b/modules/endpoints/README.md index 2b687966e..4efc8c606 100644 --- a/modules/endpoints/README.md +++ b/modules/endpoints/README.md @@ -1,3 +1,19 @@ + + # Google Cloud Endpoints This module allows simple management of ['Google Cloud Endpoints'](https://cloud.google.com/endpoints/) services. It supports creating ['OpenAPI'](https://cloud.google.com/endpoints/docs/openapi) or ['gRPC'](https://cloud.google.com/endpoints/docs/grpc/about-grpc) endpoints. diff --git a/modules/endpoints/main.tf b/modules/endpoints/main.tf index dc8c61ba0..4b69d7420 100644 --- a/modules/endpoints/main.tf +++ b/modules/endpoints/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_endpoints_service" "default" { project = var.project_id service_name = var.service_name diff --git a/modules/endpoints/outputs.tf b/modules/endpoints/outputs.tf index 27fe3f60c..d068f3dfc 100644 --- a/modules/endpoints/outputs.tf +++ b/modules/endpoints/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "endpoints" { description = "A list of Endpoint objects." value = google_endpoints_service.default.endpoints diff --git a/modules/endpoints/variables.tf b/modules/endpoints/variables.tf index ffd621ec6..f596002fa 100644 --- a/modules/endpoints/variables.tf +++ b/modules/endpoints/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "grpc_config" { description = "The configuration for a gRPC endpoint. Either this or openapi_config must be specified." type = object({ diff --git a/modules/endpoints/versions.tf b/modules/endpoints/versions.tf index 9f4707a68..eb282a5f9 100644 --- a/modules/endpoints/versions.tf +++ b/modules/endpoints/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/firestore/README.md b/modules/firestore/README.md index 474bc3428..7119bbd70 100644 --- a/modules/firestore/README.md +++ b/modules/firestore/README.md @@ -1,3 +1,19 @@ + + # Firestore This module allows to crete a firestore datatabase, fields, indexes and documents. diff --git a/modules/firestore/main.tf b/modules/firestore/main.tf index 547d0171f..49427fe17 100644 --- a/modules/firestore/main.tf +++ b/modules/firestore/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { firestore_database_name = var.database_create ? google_firestore_database.firestore_database[0].name : var.database.name } diff --git a/modules/firestore/outputs.tf b/modules/firestore/outputs.tf index f72ba2c9c..528d581d3 100644 --- a/modules/firestore/outputs.tf +++ b/modules/firestore/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "firestore_database" { description = "Firestore database." value = var.database_create ? google_firestore_database.firestore_database[0] : null diff --git a/modules/firestore/variables.tf b/modules/firestore/variables.tf index 8a95d5336..f7f61fe44 100644 --- a/modules/firestore/variables.tf +++ b/modules/firestore/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "backup_schedule" { description = "Backup schedule." type = object({ diff --git a/modules/firestore/versions.tf b/modules/firestore/versions.tf index 23ea6bf29..e6e8cf1fa 100644 --- a/modules/firestore/versions.tf +++ b/modules/firestore/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/folder/README.md b/modules/folder/README.md index a1466e3d6..233ce728a 100644 --- a/modules/folder/README.md +++ b/modules/folder/README.md @@ -1,3 +1,19 @@ + + # Google Cloud Folder Module This module allows the creation and management of folders, including support for IAM bindings, organization policies, and hierarchical firewall rules. diff --git a/modules/folder/iam.tf b/modules/folder/iam.tf index af80f2d5b..80e96308e 100644 --- a/modules/folder/iam.tf +++ b/modules/folder/iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description IAM bindings. locals { diff --git a/modules/folder/logging.tf b/modules/folder/logging.tf index 6941a4e7b..1d7d195ed 100644 --- a/modules/folder/logging.tf +++ b/modules/folder/logging.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Log sinks and supporting resources. locals { diff --git a/modules/folder/main.tf b/modules/folder/main.tf index ccb17616e..9e9451f66 100644 --- a/modules/folder/main.tf +++ b/modules/folder/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { folder_id = ( var.assured_workload_config == null diff --git a/modules/folder/organization-policies.tf b/modules/folder/organization-policies.tf index 45c4c8dbe..602deac96 100644 --- a/modules/folder/organization-policies.tf +++ b/modules/folder/organization-policies.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Folder-level organization policies. locals { diff --git a/modules/folder/outputs.tf b/modules/folder/outputs.tf index f9acdad40..a43bd7be2 100644 --- a/modules/folder/outputs.tf +++ b/modules/folder/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "assured_workload" { description = "Assured Workloads workload resource." value = try(google_assured_workloads_workload.folder[0], null) diff --git a/modules/folder/tags.tf b/modules/folder/tags.tf index 323886ef5..305129fe2 100644 --- a/modules/folder/tags.tf +++ b/modules/folder/tags.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_tags_tag_binding" "binding" { for_each = coalesce(var.tag_bindings, {}) parent = "//cloudresourcemanager.googleapis.com/${local.folder_id}" diff --git a/modules/folder/variables-iam.tf b/modules/folder/variables-iam.tf index ba2768b29..9081f5cfd 100644 --- a/modules/folder/variables-iam.tf +++ b/modules/folder/variables-iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "iam" { description = "IAM bindings in {ROLE => [MEMBERS]} format." type = map(list(string)) diff --git a/modules/folder/variables-logging.tf b/modules/folder/variables-logging.tf index 79a47c9d5..b93cae40c 100644 --- a/modules/folder/variables-logging.tf +++ b/modules/folder/variables-logging.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "logging_data_access" { description = "Control activation of data access logs. The special 'allServices' key denotes configuration for all services." type = map(object({ diff --git a/modules/folder/variables.tf b/modules/folder/variables.tf index 7ff29ca55..1f01b78c0 100644 --- a/modules/folder/variables.tf +++ b/modules/folder/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "assured_workload_config" { description = "Create AssuredWorkloads folder instead of regular folder when value is provided. Incompatible with folder_create=false." type = object({ diff --git a/modules/folder/versions.tf b/modules/folder/versions.tf index 47ca67c06..87953bc13 100644 --- a/modules/folder/versions.tf +++ b/modules/folder/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/gcs/README.md b/modules/gcs/README.md index e4e55beff..73c73b7de 100644 --- a/modules/gcs/README.md +++ b/modules/gcs/README.md @@ -1,3 +1,19 @@ + + # Google Cloud Storage Module diff --git a/modules/gcs/iam.tf b/modules/gcs/iam.tf index 69a4f62ac..0a0fa8145 100644 --- a/modules/gcs/iam.tf +++ b/modules/gcs/iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description IAM bindings locals { diff --git a/modules/gcs/main.tf b/modules/gcs/main.tf index f67d5f791..a72d6a4b5 100644 --- a/modules/gcs/main.tf +++ b/modules/gcs/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _name = "${local.prefix}${lower(var.name)}" prefix = var.prefix == null ? "" : "${var.prefix}-" diff --git a/modules/gcs/managed-folders.tf b/modules/gcs/managed-folders.tf index b042c66ac..f8e54accf 100644 --- a/modules/gcs/managed-folders.tf +++ b/modules/gcs/managed-folders.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { # ensure all keys end with / as required by # google_storage_managed_folder diff --git a/modules/gcs/outputs.tf b/modules/gcs/outputs.tf index 8ee19644a..81eaec06d 100644 --- a/modules/gcs/outputs.tf +++ b/modules/gcs/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "bucket" { description = "Bucket resource." value = one(google_storage_bucket.bucket) diff --git a/modules/gcs/tags.tf b/modules/gcs/tags.tf index 9432411ca..f44927a37 100644 --- a/modules/gcs/tags.tf +++ b/modules/gcs/tags.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_tags_location_tag_binding" "binding" { for_each = var.tag_bindings parent = "//storage.googleapis.com/projects/_/buckets/${local._name}" diff --git a/modules/gcs/variables.tf b/modules/gcs/variables.tf index da26b163a..aafdf9332 100644 --- a/modules/gcs/variables.tf +++ b/modules/gcs/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "autoclass" { description = "Enable autoclass to automatically transition objects to appropriate storage classes based on their access pattern. If set to true, storage_class must be set to STANDARD. Defaults to false." type = bool diff --git a/modules/gcs/versions.tf b/modules/gcs/versions.tf index 857a6b0ae..e0d6874eb 100644 --- a/modules/gcs/versions.tf +++ b/modules/gcs/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/gcve-private-cloud/README.md b/modules/gcve-private-cloud/README.md index 0461dc852..e0d9bf6fc 100644 --- a/modules/gcve-private-cloud/README.md +++ b/modules/gcve-private-cloud/README.md @@ -1,3 +1,19 @@ + + # Google Cloud VMWare Engine Private Cloud module The module manages one or more Google Cloud VMWare Engine Private Clouds. diff --git a/modules/gcve-private-cloud/main.tf b/modules/gcve-private-cloud/main.tf index 08e4eca7b..f82fa0638 100644 --- a/modules/gcve-private-cloud/main.tf +++ b/modules/gcve-private-cloud/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { # aggregate clusters into a single map and add their parent private cloud additional_cluster_configs = merge([ diff --git a/modules/gcve-private-cloud/outputs.tf b/modules/gcve-private-cloud/outputs.tf index e42d98ce1..0119186ce 100644 --- a/modules/gcve-private-cloud/outputs.tf +++ b/modules/gcve-private-cloud/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "network" { description = "VMware engine network." value = local.vmw_network diff --git a/modules/gcve-private-cloud/variables.tf b/modules/gcve-private-cloud/variables.tf index cc184a82b..78856fc96 100644 --- a/modules/gcve-private-cloud/variables.tf +++ b/modules/gcve-private-cloud/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "prefix" { description = "Prefix used in resource names." type = string diff --git a/modules/gcve-private-cloud/versions.tf b/modules/gcve-private-cloud/versions.tf index a35ac750f..6b42c1072 100644 --- a/modules/gcve-private-cloud/versions.tf +++ b/modules/gcve-private-cloud/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/gke-cluster-autopilot/README.md b/modules/gke-cluster-autopilot/README.md index 5fb61ee9b..ab4c80fed 100644 --- a/modules/gke-cluster-autopilot/README.md +++ b/modules/gke-cluster-autopilot/README.md @@ -1,3 +1,19 @@ + + # GKE Autopilot cluster module This module offers a way to create and manage Google Kubernetes Engine (GKE) [Autopilot clusters](https://cloud.google.com/kubernetes-engine/docs/concepts/autopilot-overview). With its sensible default settings based on best practices and authors' experience as Google Cloud practitioners, the module accommodates for many common use cases out-of-the-box, without having to rely on verbose configuration. diff --git a/modules/gke-cluster-autopilot/main.tf b/modules/gke-cluster-autopilot/main.tf index 8a60908f5..9834b96da 100644 --- a/modules/gke-cluster-autopilot/main.tf +++ b/modules/gke-cluster-autopilot/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_container_cluster" "cluster" { provider = google-beta project = var.project_id diff --git a/modules/gke-cluster-autopilot/outputs.tf b/modules/gke-cluster-autopilot/outputs.tf index 81bdc2a0c..2fcf49d4b 100644 --- a/modules/gke-cluster-autopilot/outputs.tf +++ b/modules/gke-cluster-autopilot/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "ca_certificate" { description = "Public certificate of the cluster (base64-encoded)." value = google_container_cluster.cluster.master_auth[0].cluster_ca_certificate diff --git a/modules/gke-cluster-autopilot/variables.tf b/modules/gke-cluster-autopilot/variables.tf index 000496e8a..2119c5e94 100644 --- a/modules/gke-cluster-autopilot/variables.tf +++ b/modules/gke-cluster-autopilot/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "access_config" { description = "Control plane endpoint and nodes access configurations." type = object({ diff --git a/modules/gke-cluster-autopilot/versions.tf b/modules/gke-cluster-autopilot/versions.tf index c09096729..1a9762c68 100644 --- a/modules/gke-cluster-autopilot/versions.tf +++ b/modules/gke-cluster-autopilot/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/gke-cluster-standard-se/README.md b/modules/gke-cluster-standard-se/README.md index beebe43c7..4c7f720c0 100644 --- a/modules/gke-cluster-standard-se/README.md +++ b/modules/gke-cluster-standard-se/README.md @@ -1,3 +1,19 @@ + + # GKE Standard cluster module This module offers a way to create and manage Google Kubernetes Engine (GKE) [Standard clusters](https://cloud.google.com/kubernetes-engine/docs/concepts/choose-cluster-mode#why-standard). With its sensible default settings based on best practices and authors' experience as Google Cloud practitioners, the module accommodates for many common use cases out-of-the-box, without having to rely on verbose configuration. diff --git a/modules/gke-cluster-standard-se/main.tf b/modules/gke-cluster-standard-se/main.tf index 76e5024e1..d219589d8 100644 --- a/modules/gke-cluster-standard-se/main.tf +++ b/modules/gke-cluster-standard-se/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { cas = var.cluster_autoscaling cas_apd = try(local.cas.auto_provisioning_defaults, null) diff --git a/modules/gke-cluster-standard-se/outputs.tf b/modules/gke-cluster-standard-se/outputs.tf index 0d7e86064..95f9d8442 100644 --- a/modules/gke-cluster-standard-se/outputs.tf +++ b/modules/gke-cluster-standard-se/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "ca_certificate" { description = "Public certificate of the cluster (base64-encoded)." value = google_container_cluster.cluster.master_auth[0].cluster_ca_certificate diff --git a/modules/gke-cluster-standard-se/variables.tf b/modules/gke-cluster-standard-se/variables.tf index 33452039f..52bb5313f 100644 --- a/modules/gke-cluster-standard-se/variables.tf +++ b/modules/gke-cluster-standard-se/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,8 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - - variable "backup_configs" { description = "Configuration for Backup for GKE." type = object({ diff --git a/modules/gke-cluster-standard-se/versions.tf b/modules/gke-cluster-standard-se/versions.tf index f569ce5af..c019728ee 100644 --- a/modules/gke-cluster-standard-se/versions.tf +++ b/modules/gke-cluster-standard-se/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2024 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v35.0.0 diff --git a/modules/gke-cluster-standard/README.md b/modules/gke-cluster-standard/README.md index e6dbd08b3..383fa8217 100644 --- a/modules/gke-cluster-standard/README.md +++ b/modules/gke-cluster-standard/README.md @@ -1,3 +1,19 @@ + + # GKE Standard cluster module This module offers a way to create and manage Google Kubernetes Engine (GKE) [Standard clusters](https://cloud.google.com/kubernetes-engine/docs/concepts/choose-cluster-mode#why-standard). With its sensible default settings based on best practices and authors' experience as Google Cloud practitioners, the module accommodates for many common use cases out-of-the-box, without having to rely on verbose configuration. diff --git a/modules/gke-cluster-standard/main.tf b/modules/gke-cluster-standard/main.tf index eaa50464e..e0a5b948a 100644 --- a/modules/gke-cluster-standard/main.tf +++ b/modules/gke-cluster-standard/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { cas = var.cluster_autoscaling cas_apd = try(local.cas.auto_provisioning_defaults, null) diff --git a/modules/gke-cluster-standard/outputs.tf b/modules/gke-cluster-standard/outputs.tf index bc6c8e9a4..fe93753da 100644 --- a/modules/gke-cluster-standard/outputs.tf +++ b/modules/gke-cluster-standard/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "ca_certificate" { description = "Public certificate of the cluster (base64-encoded)." value = ( diff --git a/modules/gke-cluster-standard/variables.tf b/modules/gke-cluster-standard/variables.tf index ee2f7d8e7..3c0c57a25 100644 --- a/modules/gke-cluster-standard/variables.tf +++ b/modules/gke-cluster-standard/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "access_config" { description = "Control plane endpoint and nodes access configurations." type = object({ diff --git a/modules/gke-cluster-standard/versions.tf b/modules/gke-cluster-standard/versions.tf index e65879bb2..2abbb7475 100644 --- a/modules/gke-cluster-standard/versions.tf +++ b/modules/gke-cluster-standard/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/gke-hub/README.md b/modules/gke-hub/README.md index c5c7205f4..6f93392b9 100644 --- a/modules/gke-hub/README.md +++ b/modules/gke-hub/README.md @@ -1,3 +1,19 @@ + + # GKE hub module This module allows simplified creation and management of a GKE Hub object and its features for a given set of clusters. The given list of clusters will be registered inside the Hub and all the configured features will be activated. diff --git a/modules/gke-hub/main.tf b/modules/gke-hub/main.tf index 740890d6b..37e7ee59e 100644 --- a/modules/gke-hub/main.tf +++ b/modules/gke-hub/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _cluster_cm_config = flatten([ for template, clusters in var.configmanagement_clusters : [ diff --git a/modules/gke-hub/outputs.tf b/modules/gke-hub/outputs.tf index 2e74cdaf0..280eec4cd 100644 --- a/modules/gke-hub/outputs.tf +++ b/modules/gke-hub/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "cluster_ids" { description = "Fully qualified ids of all clusters." value = { diff --git a/modules/gke-hub/variables.tf b/modules/gke-hub/variables.tf index a981f7de0..edb1bcc94 100644 --- a/modules/gke-hub/variables.tf +++ b/modules/gke-hub/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "clusters" { description = "Clusters members of this GKE Hub in name => id format." type = map(string) diff --git a/modules/gke-hub/versions.tf b/modules/gke-hub/versions.tf index 9244915f2..bbecdfd92 100644 --- a/modules/gke-hub/versions.tf +++ b/modules/gke-hub/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/gke-nodepool/README.md b/modules/gke-nodepool/README.md index 7a3f60251..43e635b7e 100644 --- a/modules/gke-nodepool/README.md +++ b/modules/gke-nodepool/README.md @@ -1,3 +1,19 @@ + + # GKE nodepool module This module allows simplified creation and management of individual GKE nodepools, setting sensible defaults (eg a service account is created for nodes if none is set) and allowing for less verbose usage in most use cases. diff --git a/modules/gke-nodepool/main.tf b/modules/gke-nodepool/main.tf index 4e2b00ca1..4c5873da5 100644 --- a/modules/gke-nodepool/main.tf +++ b/modules/gke-nodepool/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _image = coalesce(var.node_config.image_type, "-") image = { diff --git a/modules/gke-nodepool/outputs.tf b/modules/gke-nodepool/outputs.tf index 4102d9e11..f14d07868 100644 --- a/modules/gke-nodepool/outputs.tf +++ b/modules/gke-nodepool/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "id" { description = "Fully qualified nodepool id." value = google_container_node_pool.nodepool.id diff --git a/modules/gke-nodepool/variables.tf b/modules/gke-nodepool/variables.tf index bf0f69c21..0ce4d4abe 100644 --- a/modules/gke-nodepool/variables.tf +++ b/modules/gke-nodepool/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "cluster_id" { description = "Cluster id. Optional, but providing cluster_id is recommended to prevent cluster misconfiguration in some of the edge cases." type = string diff --git a/modules/gke-nodepool/versions.tf b/modules/gke-nodepool/versions.tf index 6ac171cbe..e8ba6ffd6 100644 --- a/modules/gke-nodepool/versions.tf +++ b/modules/gke-nodepool/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/iam-service-account/README.md b/modules/iam-service-account/README.md index e039fc87f..cc6ec1359 100644 --- a/modules/iam-service-account/README.md +++ b/modules/iam-service-account/README.md @@ -1,3 +1,19 @@ + + # Google Service Account Module This module allows simplified creation and management of one a service account and its IAM bindings. diff --git a/modules/iam-service-account/iam.tf b/modules/iam-service-account/iam.tf index 15ae1acca..e53fd6528 100644 --- a/modules/iam-service-account/iam.tf +++ b/modules/iam-service-account/iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description IAM bindings. locals { diff --git a/modules/iam-service-account/main.tf b/modules/iam-service-account/main.tf index 48eae52b5..400a1989b 100644 --- a/modules/iam-service-account/main.tf +++ b/modules/iam-service-account/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { name = split("@", var.name)[0] prefix = var.prefix == null ? "" : "${var.prefix}-" diff --git a/modules/iam-service-account/outputs.tf b/modules/iam-service-account/outputs.tf index 1ec73afb5..0dce2428f 100644 --- a/modules/iam-service-account/outputs.tf +++ b/modules/iam-service-account/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "email" { description = "Service account email." value = local.resource_email_static diff --git a/modules/iam-service-account/variables.tf b/modules/iam-service-account/variables.tf index c9d944536..83176b253 100644 --- a/modules/iam-service-account/variables.tf +++ b/modules/iam-service-account/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "description" { description = "Optional description." type = string diff --git a/modules/iam-service-account/versions.tf b/modules/iam-service-account/versions.tf index cdbbae8be..bbae9b635 100644 --- a/modules/iam-service-account/versions.tf +++ b/modules/iam-service-account/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/intrusion-detection-system/README.md b/modules/intrusion-detection-system/README.md index dced0cf96..fee0a1f15 100644 --- a/modules/intrusion-detection-system/README.md +++ b/modules/intrusion-detection-system/README.md @@ -1,3 +1,19 @@ + + # Intrusion Detection System Module This module implements Cloud Intrusion Detection System (Cloud IDS) resources, including IDS endpoints and endpoint attachments, for network threat detection. diff --git a/modules/intrusion-detection-system/main.tf b/modules/intrusion-detection-system/main.tf index 65a6008c5..029ade32d 100644 --- a/modules/intrusion-detection-system/main.tf +++ b/modules/intrusion-detection-system/main.tf @@ -1,17 +1,18 @@ -## Copyright 2023 Google LLC -## -## Licensed under the Apache License, Version 2.0 (the "License"); -## you may not use this file except in compliance with the License. -## You may obtain a copy of the License at -## -## https://www.apache.org/licenses/LICENSE-2.0 -## -## Unless required by applicable law or agreed to in writing, software -## distributed under the License is distributed on an "AS IS" BASIS, -## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -## See the License for the specific language governing permissions and -## limitations under the License. - +#/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ data "google_compute_network" "vpc_network" { name = var.landing_network project = var.project diff --git a/modules/intrusion-detection-system/outputs.tf b/modules/intrusion-detection-system/outputs.tf index 1190cfb2e..b0b68dd4f 100644 --- a/modules/intrusion-detection-system/outputs.tf +++ b/modules/intrusion-detection-system/outputs.tf @@ -1,19 +1,18 @@ -## Copyright 2023 Google LLC -## -## Licensed under the Apache License, Version 2.0 (the "License"); -## you may not use this file except in compliance with the License. -## You may obtain a copy of the License at -## -## https://www.apache.org/licenses/LICENSE-2.0 -## -## Unless required by applicable law or agreed to in writing, software -## distributed under the License is distributed on an "AS IS" BASIS, -## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -## See the License for the specific language governing permissions and -## limitations under the License. - - - +#/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "ids_endpoint_severity" { description = "IDS Endpoint severity" value = google_cloud_ids_endpoint.ids_endpoint.severity diff --git a/modules/intrusion-detection-system/variables.tf b/modules/intrusion-detection-system/variables.tf index 1deef7b38..0240869bd 100644 --- a/modules/intrusion-detection-system/variables.tf +++ b/modules/intrusion-detection-system/variables.tf @@ -1,17 +1,18 @@ -## Copyright 2023 Google LLC -## -## Licensed under the Apache License, Version 2.0 (the "License"); -## you may not use this file except in compliance with the License. -## You may obtain a copy of the License at -## -## https://www.apache.org/licenses/LICENSE-2.0 -## -## Unless required by applicable law or agreed to in writing, software -## distributed under the License is distributed on an "AS IS" BASIS, -## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -## See the License for the specific language governing permissions and -## limitations under the License. - +#/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "project_id" { description = "Id of the project you will like to use." type = string diff --git a/modules/intrusion-detection-system/versions.tf b/modules/intrusion-detection-system/versions.tf index 663146342..b1cf03e70 100644 --- a/modules/intrusion-detection-system/versions.tf +++ b/modules/intrusion-detection-system/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2024 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ terraform { required_version = ">= 1.7.4" diff --git a/modules/kms/README.md b/modules/kms/README.md index 59979af95..4bd335752 100644 --- a/modules/kms/README.md +++ b/modules/kms/README.md @@ -1,3 +1,19 @@ + + # Google KMS Module This module allows creating and managing KMS crypto keys and IAM bindings at both the keyring and crypto key level. An existing keyring can be used, or a new one can be created and managed by the module if needed. diff --git a/modules/kms/iam.tf b/modules/kms/iam.tf index 8ac17a567..e12d83820 100644 --- a/modules/kms/iam.tf +++ b/modules/kms/iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { key_iam = flatten([ for k, v in var.keys : [ diff --git a/modules/kms/main.tf b/modules/kms/main.tf index d8b6819a6..620f2abef 100644 --- a/modules/kms/main.tf +++ b/modules/kms/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { keyring = ( var.keyring_create diff --git a/modules/kms/outputs.tf b/modules/kms/outputs.tf index 9346ce6b8..fe3411ef8 100644 --- a/modules/kms/outputs.tf +++ b/modules/kms/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "id" { description = "Fully qualified keyring id." value = local.keyring.id diff --git a/modules/kms/tags.tf b/modules/kms/tags.tf index eaee171de..3b2ab383e 100644 --- a/modules/kms/tags.tf +++ b/modules/kms/tags.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_tags_location_tag_binding" "binding" { for_each = var.tag_bindings parent = "//cloudkms.googleapis.com/${local.keyring.id}" diff --git a/modules/kms/variables.tf b/modules/kms/variables.tf index fabaf0322..e8a1152a5 100644 --- a/modules/kms/variables.tf +++ b/modules/kms/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "iam" { description = "Keyring IAM bindings in {ROLE => [MEMBERS]} format." type = map(list(string)) diff --git a/modules/kms/versions.tf b/modules/kms/versions.tf index 2652f967b..9fa47d8a7 100644 --- a/modules/kms/versions.tf +++ b/modules/kms/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/logging-bucket/README.md b/modules/logging-bucket/README.md index 3f776e3bf..885d5870a 100644 --- a/modules/logging-bucket/README.md +++ b/modules/logging-bucket/README.md @@ -1,3 +1,19 @@ + + # Google Cloud Logging Buckets Module This module manages [logging buckets](https://cloud.google.com/logging/docs/routing/overview#buckets) for a project, folder, organization or billing account. diff --git a/modules/logging-bucket/iam.tf b/modules/logging-bucket/iam.tf index 2f671b209..d149efc22 100644 --- a/modules/logging-bucket/iam.tf +++ b/modules/logging-bucket/iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { view_iam = flatten([ for k, v in var.views : [ diff --git a/modules/logging-bucket/main.tf b/modules/logging-bucket/main.tf index 6fe84adf1..5c4a0c33c 100644 --- a/modules/logging-bucket/main.tf +++ b/modules/logging-bucket/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { bucket = try( google_logging_project_bucket_config.bucket[0], diff --git a/modules/logging-bucket/outputs.tf b/modules/logging-bucket/outputs.tf index 276673a95..474c0886c 100644 --- a/modules/logging-bucket/outputs.tf +++ b/modules/logging-bucket/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "id" { description = "Fully qualified logging bucket id." value = local.bucket.id diff --git a/modules/logging-bucket/variables.tf b/modules/logging-bucket/variables.tf index 39b50bc24..f00bedace 100644 --- a/modules/logging-bucket/variables.tf +++ b/modules/logging-bucket/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "description" { description = "Human-readable description for the logging bucket." type = string diff --git a/modules/logging-bucket/versions.tf b/modules/logging-bucket/versions.tf index 9215f3860..09ba11282 100644 --- a/modules/logging-bucket/versions.tf +++ b/modules/logging-bucket/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/looker-core/README.md b/modules/looker-core/README.md index 330ee9b58..a5347dac2 100644 --- a/modules/looker-core/README.md +++ b/modules/looker-core/README.md @@ -1,3 +1,19 @@ + + # Looker Core module This module manages the creation of a [Looker Core instance](https://cloud.google.com/looker/docs/looker-core). diff --git a/modules/looker-core/main.tf b/modules/looker-core/main.tf index 8278fec6b..b59f6e8d1 100644 --- a/modules/looker-core/main.tf +++ b/modules/looker-core/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { bootstrap_oauth_client = var.oauth_config.client_secret == null || var.oauth_config.client_id == null looker_instance_name = "${local.prefix}${var.name}" diff --git a/modules/looker-core/outputs.tf b/modules/looker-core/outputs.tf index 9c2af964f..25dde05d6 100644 --- a/modules/looker-core/outputs.tf +++ b/modules/looker-core/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "egress_public_ip" { description = "Public IP address of Looker instance for egress." value = google_looker_instance.looker.egress_public_ip diff --git a/modules/looker-core/variables.tf b/modules/looker-core/variables.tf index bc28c71d1..5bdbb9b90 100644 --- a/modules/looker-core/variables.tf +++ b/modules/looker-core/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "admin_settings" { description = "Looker Core admins settings." type = object({ diff --git a/modules/looker-core/versions.tf b/modules/looker-core/versions.tf index d83d9129a..1f00fd05c 100644 --- a/modules/looker-core/versions.tf +++ b/modules/looker-core/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/ncc-spoke-ra/README.md b/modules/ncc-spoke-ra/README.md index f20585242..11976c50f 100644 --- a/modules/ncc-spoke-ra/README.md +++ b/modules/ncc-spoke-ra/README.md @@ -1,3 +1,19 @@ + + # NCC Spoke RA Module This module allows management of NCC Spokes backed by Router Appliances. Network virtual appliances used as router appliances allow to connect an external network to Google Cloud by using a SD-WAN router or another appliance with BGP capabilities (_site-to-cloud_ connectivity). It is also possible to enable site-to-site data transfer, although this feature is not available in all regions, particularly not in EMEA. diff --git a/modules/ncc-spoke-ra/main.tf b/modules/ncc-spoke-ra/main.tf index 2ecaae6b9..a4d30adde 100644 --- a/modules/ncc-spoke-ra/main.tf +++ b/modules/ncc-spoke-ra/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { spoke_vms = [ for ras in var.router_appliances : { diff --git a/modules/ncc-spoke-ra/outputs.tf b/modules/ncc-spoke-ra/outputs.tf index 59ebc213d..6e34fb5ec 100644 --- a/modules/ncc-spoke-ra/outputs.tf +++ b/modules/ncc-spoke-ra/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "hub" { description = "NCC hub resource (only if auto-created)." value = try(google_network_connectivity_hub.hub[0], null) diff --git a/modules/ncc-spoke-ra/variables.tf b/modules/ncc-spoke-ra/variables.tf index 4b01ea168..41766a1c4 100644 --- a/modules/ncc-spoke-ra/variables.tf +++ b/modules/ncc-spoke-ra/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "data_transfer" { description = "Site-to-site data transfer feature, available only in some regions." type = bool diff --git a/modules/ncc-spoke-ra/versions.tf b/modules/ncc-spoke-ra/versions.tf index c2ed365e2..a2b8397bb 100644 --- a/modules/ncc-spoke-ra/versions.tf +++ b/modules/ncc-spoke-ra/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/net-address/README.md b/modules/net-address/README.md index 535b222ac..2a196b4fc 100644 --- a/modules/net-address/README.md +++ b/modules/net-address/README.md @@ -1,3 +1,19 @@ + + # Net Address Reservation Module This module allows reserving Compute Engine external, global, and internal addresses. The module also supports managing VPC network attachments from service projects. diff --git a/modules/net-address/main.tf b/modules/net-address/main.tf index e7c69413c..0eb9cb3c7 100644 --- a/modules/net-address/main.tf +++ b/modules/net-address/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_compute_global_address" "global" { for_each = var.global_addresses project = var.project_id diff --git a/modules/net-address/outputs.tf b/modules/net-address/outputs.tf index 95ab38b11..88566de12 100644 --- a/modules/net-address/outputs.tf +++ b/modules/net-address/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "external_addresses" { description = "Allocated external addresses." value = { diff --git a/modules/net-address/psc.tf b/modules/net-address/psc.tf index 2047a935a..723923393 100644 --- a/modules/net-address/psc.tf +++ b/modules/net-address/psc.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { network_attachments = { for k, v in var.network_attachments : k => merge(v, { diff --git a/modules/net-address/variables.tf b/modules/net-address/variables.tf index fb3760b35..4bf0f962b 100644 --- a/modules/net-address/variables.tf +++ b/modules/net-address/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "external_addresses" { description = "Map of external addresses, keyed by name." type = map(object({ diff --git a/modules/net-address/versions.tf b/modules/net-address/versions.tf index 13c240817..a5bc39bfa 100644 --- a/modules/net-address/versions.tf +++ b/modules/net-address/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/net-cloudnat/README.md b/modules/net-cloudnat/README.md index 1a2b143a1..244070152 100644 --- a/modules/net-cloudnat/README.md +++ b/modules/net-cloudnat/README.md @@ -1,3 +1,19 @@ + + # Cloud NAT Module Simple Cloud NAT management, with optional router creation. diff --git a/modules/net-cloudnat/main.tf b/modules/net-cloudnat/main.tf index 2c6d8eb67..1608cf20c 100644 --- a/modules/net-cloudnat/main.tf +++ b/modules/net-cloudnat/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { router_name = ( var.router_create diff --git a/modules/net-cloudnat/outputs.tf b/modules/net-cloudnat/outputs.tf index 62f6afa88..d5de09873 100644 --- a/modules/net-cloudnat/outputs.tf +++ b/modules/net-cloudnat/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "id" { description = "Fully qualified NAT (router) id." value = google_compute_router_nat.nat.id diff --git a/modules/net-cloudnat/variables.tf b/modules/net-cloudnat/variables.tf index 88fe1cb83..223230421 100644 --- a/modules/net-cloudnat/variables.tf +++ b/modules/net-cloudnat/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "addresses" { description = "Optional list of external address self links." type = list(string) diff --git a/modules/net-cloudnat/versions.tf b/modules/net-cloudnat/versions.tf index 6b2dbfabb..61c7d27d4 100644 --- a/modules/net-cloudnat/versions.tf +++ b/modules/net-cloudnat/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/net-firewall-policy/README.md b/modules/net-firewall-policy/README.md index bffad88a8..fe89b7ad7 100644 --- a/modules/net-firewall-policy/README.md +++ b/modules/net-firewall-policy/README.md @@ -1,3 +1,19 @@ + + # Firewall Policies This module allows creation and management of two different firewall policy types: diff --git a/modules/net-firewall-policy/factory.tf b/modules/net-firewall-policy/factory.tf index 6cc15a5d1..eba7d023f 100644 --- a/modules/net-firewall-policy/factory.tf +++ b/modules/net-firewall-policy/factory.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _factory_egress_rules = coalesce( try( diff --git a/modules/net-firewall-policy/hierarchical.tf b/modules/net-firewall-policy/hierarchical.tf index 7969a559d..bab911041 100644 --- a/modules/net-firewall-policy/hierarchical.tf +++ b/modules/net-firewall-policy/hierarchical.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_compute_firewall_policy" "hierarchical" { count = local.use_hierarchical ? 1 : 0 parent = var.parent_id diff --git a/modules/net-firewall-policy/main.tf b/modules/net-firewall-policy/main.tf index 093c8bf23..565fb3444 100644 --- a/modules/net-firewall-policy/main.tf +++ b/modules/net-firewall-policy/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _rules_egress = { for name, rule in merge(var.egress_rules) : diff --git a/modules/net-firewall-policy/net-global.tf b/modules/net-firewall-policy/net-global.tf index cf837c861..c85062620 100644 --- a/modules/net-firewall-policy/net-global.tf +++ b/modules/net-firewall-policy/net-global.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_compute_network_firewall_policy" "net-global" { count = !local.use_hierarchical && !local.use_regional ? 1 : 0 project = var.parent_id diff --git a/modules/net-firewall-policy/net-regional.tf b/modules/net-firewall-policy/net-regional.tf index 281cbc4f9..b1618224d 100644 --- a/modules/net-firewall-policy/net-regional.tf +++ b/modules/net-firewall-policy/net-regional.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_compute_region_network_firewall_policy" "net-regional" { count = !local.use_hierarchical && local.use_regional ? 1 : 0 project = var.parent_id diff --git a/modules/net-firewall-policy/outputs.tf b/modules/net-firewall-policy/outputs.tf index 589a06768..17e521814 100644 --- a/modules/net-firewall-policy/outputs.tf +++ b/modules/net-firewall-policy/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "id" { description = "Fully qualified firewall policy id." value = ( diff --git a/modules/net-firewall-policy/variables.tf b/modules/net-firewall-policy/variables.tf index bab3ee853..7b40cbfbb 100644 --- a/modules/net-firewall-policy/variables.tf +++ b/modules/net-firewall-policy/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "attachments" { description = "Ids of the resources to which this policy will be attached, in descriptive name => self link format. Specify folders or organization for hierarchical policy, VPCs for network policy." type = map(string) diff --git a/modules/net-firewall-policy/versions.tf b/modules/net-firewall-policy/versions.tf index f9a11f53d..4d9fae4de 100644 --- a/modules/net-firewall-policy/versions.tf +++ b/modules/net-firewall-policy/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/net-ipsec-over-interconnect/README.md b/modules/net-ipsec-over-interconnect/README.md index 8dd0a6471..7bdf8d6ec 100644 --- a/modules/net-ipsec-over-interconnect/README.md +++ b/modules/net-ipsec-over-interconnect/README.md @@ -1,3 +1,19 @@ + + # VLAN Attachment module This module allows for the provisioning of [HA VPN over Interconnect](https://cloud.google.com/network-connectivity/docs/interconnect/concepts/ha-vpn-interconnect?hl=it). Specifically, this module creates a VPN gateway, a configurable number of tunnels, and all the resources required to established IPSec and BGP with the peer routers. diff --git a/modules/net-ipsec-over-interconnect/main.tf b/modules/net-ipsec-over-interconnect/main.tf index 9fe30d15d..e974958c9 100644 --- a/modules/net-ipsec-over-interconnect/main.tf +++ b/modules/net-ipsec-over-interconnect/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { peer_gateway_id = ( var.peer_gateway_config.create diff --git a/modules/net-ipsec-over-interconnect/outputs.tf b/modules/net-ipsec-over-interconnect/outputs.tf index e0ba83fd2..a34c7b2bb 100644 --- a/modules/net-ipsec-over-interconnect/outputs.tf +++ b/modules/net-ipsec-over-interconnect/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,8 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - - output "bgp_peers" { description = "BGP peer resources." value = { diff --git a/modules/net-ipsec-over-interconnect/variables.tf b/modules/net-ipsec-over-interconnect/variables.tf index 780d40b96..92340ab1c 100644 --- a/modules/net-ipsec-over-interconnect/variables.tf +++ b/modules/net-ipsec-over-interconnect/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "interconnect_attachments" { description = "VLAN attachments used by the VPN Gateway." type = object({ diff --git a/modules/net-ipsec-over-interconnect/versions.tf b/modules/net-ipsec-over-interconnect/versions.tf index 271c76d38..ba5767769 100644 --- a/modules/net-ipsec-over-interconnect/versions.tf +++ b/modules/net-ipsec-over-interconnect/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/net-lb-app-ext-regional/README.md b/modules/net-lb-app-ext-regional/README.md index 68d54d322..fe4c21cb5 100644 --- a/modules/net-lb-app-ext-regional/README.md +++ b/modules/net-lb-app-ext-regional/README.md @@ -1,3 +1,19 @@ + + # External Regional Application Load Balancer Module This module allows managing External Regional HTTP/HTTPS Application Load Balancers. It's designed to expose the full configuration of the underlying resources, and to facilitate common usage patterns by providing sensible defaults, and optionally managing prerequisite resources like health checks, instance groups, etc. diff --git a/modules/net-lb-app-ext-regional/backend-service.tf b/modules/net-lb-app-ext-regional/backend-service.tf index 75dc946f6..7c57e4a55 100644 --- a/modules/net-lb-app-ext-regional/backend-service.tf +++ b/modules/net-lb-app-ext-regional/backend-service.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Backend service resources. locals { diff --git a/modules/net-lb-app-ext-regional/groups.tf b/modules/net-lb-app-ext-regional/groups.tf index 285ca79a3..4955996c2 100644 --- a/modules/net-lb-app-ext-regional/groups.tf +++ b/modules/net-lb-app-ext-regional/groups.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_compute_instance_group" "default" { for_each = var.group_configs project = ( diff --git a/modules/net-lb-app-ext-regional/health-check.tf b/modules/net-lb-app-ext-regional/health-check.tf index f7dc9c178..747cb4b7a 100644 --- a/modules/net-lb-app-ext-regional/health-check.tf +++ b/modules/net-lb-app-ext-regional/health-check.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Health check resource. resource "google_compute_region_health_check" "default" { diff --git a/modules/net-lb-app-ext-regional/main.tf b/modules/net-lb-app-ext-regional/main.tf index c009c4c2c..d898404ce 100644 --- a/modules/net-lb-app-ext-regional/main.tf +++ b/modules/net-lb-app-ext-regional/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { fwd_rule_ports = ( var.protocol == "HTTPS" ? [443] : coalesce(var.ports, [80]) diff --git a/modules/net-lb-app-ext-regional/negs.tf b/modules/net-lb-app-ext-regional/negs.tf index d712813d9..d5b1ea4e8 100644 --- a/modules/net-lb-app-ext-regional/negs.tf +++ b/modules/net-lb-app-ext-regional/negs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description NEG resources. locals { diff --git a/modules/net-lb-app-ext-regional/outputs.tf b/modules/net-lb-app-ext-regional/outputs.tf index 9c6773b02..3964c2e79 100644 --- a/modules/net-lb-app-ext-regional/outputs.tf +++ b/modules/net-lb-app-ext-regional/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "address" { description = "Forwarding rule address." value = google_compute_forwarding_rule.default.ip_address diff --git a/modules/net-lb-app-ext-regional/urlmap.tf b/modules/net-lb-app-ext-regional/urlmap.tf index f88cc0a38..9809da781 100644 --- a/modules/net-lb-app-ext-regional/urlmap.tf +++ b/modules/net-lb-app-ext-regional/urlmap.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description URL map resources. locals { diff --git a/modules/net-lb-app-ext-regional/variables-backend-service.tf b/modules/net-lb-app-ext-regional/variables-backend-service.tf index c6b4d6586..c2e52ff9c 100644 --- a/modules/net-lb-app-ext-regional/variables-backend-service.tf +++ b/modules/net-lb-app-ext-regional/variables-backend-service.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Backend services variables. variable "backend_service_configs" { diff --git a/modules/net-lb-app-ext-regional/variables-health-check.tf b/modules/net-lb-app-ext-regional/variables-health-check.tf index be34d779d..b366db1f9 100644 --- a/modules/net-lb-app-ext-regional/variables-health-check.tf +++ b/modules/net-lb-app-ext-regional/variables-health-check.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Health check variable. variable "health_check_configs" { diff --git a/modules/net-lb-app-ext-regional/variables-urlmap.tf b/modules/net-lb-app-ext-regional/variables-urlmap.tf index 385cf687e..4e66a7b2c 100644 --- a/modules/net-lb-app-ext-regional/variables-urlmap.tf +++ b/modules/net-lb-app-ext-regional/variables-urlmap.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description URLmap variable. variable "urlmap_config" { diff --git a/modules/net-lb-app-ext-regional/variables.tf b/modules/net-lb-app-ext-regional/variables.tf index dbd701168..3b51b170d 100644 --- a/modules/net-lb-app-ext-regional/variables.tf +++ b/modules/net-lb-app-ext-regional/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "address" { description = "Optional IP address used for the forwarding rule." type = string diff --git a/modules/net-lb-app-ext-regional/versions.tf b/modules/net-lb-app-ext-regional/versions.tf index 11ef73e02..c18cdd655 100644 --- a/modules/net-lb-app-ext-regional/versions.tf +++ b/modules/net-lb-app-ext-regional/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/net-lb-app-ext/README.md b/modules/net-lb-app-ext/README.md index be91c2d0f..2d32d1198 100644 --- a/modules/net-lb-app-ext/README.md +++ b/modules/net-lb-app-ext/README.md @@ -1,3 +1,19 @@ + + # External Application Load Balancer Module This module allows managing Global HTTP/HTTPS Classic Load Balancers (GLBs). It's designed to expose the full configuration of the underlying resources, and to facilitate common usage patterns by providing sensible defaults, and optionally managing prerequisite resources like health checks, instance groups, etc. diff --git a/modules/net-lb-app-ext/backend-service.tf b/modules/net-lb-app-ext/backend-service.tf index 5093b2853..34f4f3856 100644 --- a/modules/net-lb-app-ext/backend-service.tf +++ b/modules/net-lb-app-ext/backend-service.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Backend service resources. locals { diff --git a/modules/net-lb-app-ext/backends.tf b/modules/net-lb-app-ext/backends.tf index 107e2be65..14f9cd931 100644 --- a/modules/net-lb-app-ext/backends.tf +++ b/modules/net-lb-app-ext/backends.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Backend groups and backend buckets resources. resource "google_compute_backend_bucket" "default" { diff --git a/modules/net-lb-app-ext/groups.tf b/modules/net-lb-app-ext/groups.tf index 285ca79a3..4955996c2 100644 --- a/modules/net-lb-app-ext/groups.tf +++ b/modules/net-lb-app-ext/groups.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_compute_instance_group" "default" { for_each = var.group_configs project = ( diff --git a/modules/net-lb-app-ext/health-check.tf b/modules/net-lb-app-ext/health-check.tf index 66ba58c56..8c0d844ec 100644 --- a/modules/net-lb-app-ext/health-check.tf +++ b/modules/net-lb-app-ext/health-check.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Health check resource. resource "google_compute_health_check" "default" { diff --git a/modules/net-lb-app-ext/main.tf b/modules/net-lb-app-ext/main.tf index c440b3738..c4bf0b254 100644 --- a/modules/net-lb-app-ext/main.tf +++ b/modules/net-lb-app-ext/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { fwd_rule_names = { for k, v in var.forwarding_rules_config : diff --git a/modules/net-lb-app-ext/negs.tf b/modules/net-lb-app-ext/negs.tf index 290866c6f..a0969ab5b 100644 --- a/modules/net-lb-app-ext/negs.tf +++ b/modules/net-lb-app-ext/negs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description NEG resources. locals { diff --git a/modules/net-lb-app-ext/outputs.tf b/modules/net-lb-app-ext/outputs.tf index 0f1f31020..decb88186 100644 --- a/modules/net-lb-app-ext/outputs.tf +++ b/modules/net-lb-app-ext/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "address" { description = "Forwarding rule addresses." value = { diff --git a/modules/net-lb-app-ext/urlmap.tf b/modules/net-lb-app-ext/urlmap.tf index 3a6e8888b..de08413c5 100644 --- a/modules/net-lb-app-ext/urlmap.tf +++ b/modules/net-lb-app-ext/urlmap.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description URL map resources. locals { diff --git a/modules/net-lb-app-ext/variables-backend-service.tf b/modules/net-lb-app-ext/variables-backend-service.tf index 88317c57f..b9073484a 100644 --- a/modules/net-lb-app-ext/variables-backend-service.tf +++ b/modules/net-lb-app-ext/variables-backend-service.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Backend services variables. variable "backend_service_configs" { diff --git a/modules/net-lb-app-ext/variables-health-check.tf b/modules/net-lb-app-ext/variables-health-check.tf index be34d779d..b366db1f9 100644 --- a/modules/net-lb-app-ext/variables-health-check.tf +++ b/modules/net-lb-app-ext/variables-health-check.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Health check variable. variable "health_check_configs" { diff --git a/modules/net-lb-app-ext/variables-urlmap.tf b/modules/net-lb-app-ext/variables-urlmap.tf index e6ffe5551..c889461e1 100644 --- a/modules/net-lb-app-ext/variables-urlmap.tf +++ b/modules/net-lb-app-ext/variables-urlmap.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description URLmap variable. variable "urlmap_config" { diff --git a/modules/net-lb-app-ext/variables.tf b/modules/net-lb-app-ext/variables.tf index f4717fd00..ee2d7a9f5 100644 --- a/modules/net-lb-app-ext/variables.tf +++ b/modules/net-lb-app-ext/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "backend_buckets_config" { description = "Backend buckets configuration." type = map(object({ diff --git a/modules/net-lb-app-ext/versions.tf b/modules/net-lb-app-ext/versions.tf index ea03a78cc..34cdd09f4 100644 --- a/modules/net-lb-app-ext/versions.tf +++ b/modules/net-lb-app-ext/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/net-lb-app-int-cross-region/README.md b/modules/net-lb-app-int-cross-region/README.md index 3e9fa5486..6a8f40126 100644 --- a/modules/net-lb-app-int-cross-region/README.md +++ b/modules/net-lb-app-int-cross-region/README.md @@ -1,3 +1,19 @@ + + # Cross-region Internal Application Load Balancer Module This module allows managing Cross-regional Internal HTTP/HTTPS Load Balancers (L7 ILBs). It's designed to expose the full configuration of the underlying resources, and to facilitate common usage patterns by providing sensible defaults, and optionally managing prerequisite resources like health checks, instance groups, etc. diff --git a/modules/net-lb-app-int-cross-region/backend-service.tf b/modules/net-lb-app-int-cross-region/backend-service.tf index 7b62f0a48..5334d8dc3 100644 --- a/modules/net-lb-app-int-cross-region/backend-service.tf +++ b/modules/net-lb-app-int-cross-region/backend-service.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Backend service resources. locals { diff --git a/modules/net-lb-app-int-cross-region/groups.tf b/modules/net-lb-app-int-cross-region/groups.tf index 53ba6b27f..519fd719c 100644 --- a/modules/net-lb-app-int-cross-region/groups.tf +++ b/modules/net-lb-app-int-cross-region/groups.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_compute_instance_group" "default" { for_each = var.group_configs project = ( diff --git a/modules/net-lb-app-int-cross-region/health-check.tf b/modules/net-lb-app-int-cross-region/health-check.tf index 66ba58c56..8c0d844ec 100644 --- a/modules/net-lb-app-int-cross-region/health-check.tf +++ b/modules/net-lb-app-int-cross-region/health-check.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Health check resource. resource "google_compute_health_check" "default" { diff --git a/modules/net-lb-app-int-cross-region/main.tf b/modules/net-lb-app-int-cross-region/main.tf index a46e01829..5088ed2ad 100644 --- a/modules/net-lb-app-int-cross-region/main.tf +++ b/modules/net-lb-app-int-cross-region/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { # we need keys in the endpoint type to address issue #1055 _neg_endpoints = flatten([ diff --git a/modules/net-lb-app-int-cross-region/outputs.tf b/modules/net-lb-app-int-cross-region/outputs.tf index 0d2b136f4..1a3c1fc6e 100644 --- a/modules/net-lb-app-int-cross-region/outputs.tf +++ b/modules/net-lb-app-int-cross-region/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "addresses" { description = "Forwarding rule address." value = { for k, v in google_compute_global_forwarding_rule.forwarding_rules : k => v.ip_address } diff --git a/modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/README.md b/modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/README.md index 1bdd5a9a6..fe2ce263a 100644 --- a/modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/README.md +++ b/modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/README.md @@ -1,3 +1,19 @@ + + # Cross-region internal Application Load Balancer with VM instance group backends This recipe shows an actual usage scenario for the [cross-region internal application load balancer](../README.md) by implementing the [example provided in the GCP documentation](https://cloud.google.com/load-balancing/docs/l7-internal/setting-up-l7-cross-reg-internal). diff --git a/modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/instances.tf b/modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/instances.tf index 32bf10095..ec8381965 100644 --- a/modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/instances.tf +++ b/modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/instances.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Instance-related locals and resources. locals { diff --git a/modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/main.tf b/modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/main.tf index 237eb606b..432a0b530 100644 --- a/modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/main.tf +++ b/modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Load balancer and VPC resources. locals { diff --git a/modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/nginx-cloud-config.yaml b/modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/nginx-cloud-config.yaml index 7817eb606..232e655dd 100644 --- a/modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/nginx-cloud-config.yaml +++ b/modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/nginx-cloud-config.yaml @@ -1,12 +1,12 @@ #cloud-config -# Copyright 2022 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# https://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + # https://hub.docker.com/r/nginx/nginx/ # https://nginx.io/manual/toc/#installation diff --git a/modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/outputs.tf b/modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/outputs.tf index f0f70880a..1583b509b 100644 --- a/modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/outputs.tf +++ b/modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "instances" { description = "Instances details." value = { diff --git a/modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/region_shortnames.tf b/modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/region_shortnames.tf index 291cfce56..9f2958f19 100644 --- a/modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/region_shortnames.tf +++ b/modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/region_shortnames.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Region shortnames via locals. # adapted from FAST networking stages diff --git a/modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/variables.tf b/modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/variables.tf index e9cef8d68..6e0cdebe5 100644 --- a/modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/variables.tf +++ b/modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "dns_config" { description = "DNS configuration." type = object({ diff --git a/modules/net-lb-app-int-cross-region/urlmap.tf b/modules/net-lb-app-int-cross-region/urlmap.tf index 62ccd9a92..169dc7d3a 100644 --- a/modules/net-lb-app-int-cross-region/urlmap.tf +++ b/modules/net-lb-app-int-cross-region/urlmap.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description URL map resources. locals { diff --git a/modules/net-lb-app-int-cross-region/variables-backend-service.tf b/modules/net-lb-app-int-cross-region/variables-backend-service.tf index 0b92c7849..fb28eb1eb 100644 --- a/modules/net-lb-app-int-cross-region/variables-backend-service.tf +++ b/modules/net-lb-app-int-cross-region/variables-backend-service.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Backend services variables. variable "backend_service_configs" { diff --git a/modules/net-lb-app-int-cross-region/variables-health-check.tf b/modules/net-lb-app-int-cross-region/variables-health-check.tf index a51994ecf..b04ca6e30 100644 --- a/modules/net-lb-app-int-cross-region/variables-health-check.tf +++ b/modules/net-lb-app-int-cross-region/variables-health-check.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Health check variable. variable "health_check_configs" { diff --git a/modules/net-lb-app-int-cross-region/variables-urlmap.tf b/modules/net-lb-app-int-cross-region/variables-urlmap.tf index ee48b7df0..961908e57 100644 --- a/modules/net-lb-app-int-cross-region/variables-urlmap.tf +++ b/modules/net-lb-app-int-cross-region/variables-urlmap.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description URLmap variable. variable "urlmap_config" { diff --git a/modules/net-lb-app-int-cross-region/variables.tf b/modules/net-lb-app-int-cross-region/variables.tf index b707057a0..8cd416a62 100644 --- a/modules/net-lb-app-int-cross-region/variables.tf +++ b/modules/net-lb-app-int-cross-region/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "addresses" { description = "Optional IP address used for the forwarding rule." type = map(string) diff --git a/modules/net-lb-app-int-cross-region/versions.tf b/modules/net-lb-app-int-cross-region/versions.tf index 6af7a3288..2d9fdbb4a 100644 --- a/modules/net-lb-app-int-cross-region/versions.tf +++ b/modules/net-lb-app-int-cross-region/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/net-lb-app-int/README.md b/modules/net-lb-app-int/README.md index 87eaeab54..d3eb9cbea 100644 --- a/modules/net-lb-app-int/README.md +++ b/modules/net-lb-app-int/README.md @@ -1,3 +1,19 @@ + + # Internal Application Load Balancer Module This module allows managing Internal HTTP/HTTPS Load Balancers (L7 ILBs). It's designed to expose the full configuration of the underlying resources, and to facilitate common usage patterns by providing sensible defaults, and optionally managing prerequisite resources like health checks, instance groups, etc. diff --git a/modules/net-lb-app-int/backend-service.tf b/modules/net-lb-app-int/backend-service.tf index d4f5a8dee..0ca0f1502 100644 --- a/modules/net-lb-app-int/backend-service.tf +++ b/modules/net-lb-app-int/backend-service.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Backend service resources. locals { diff --git a/modules/net-lb-app-int/groups.tf b/modules/net-lb-app-int/groups.tf index 53ba6b27f..519fd719c 100644 --- a/modules/net-lb-app-int/groups.tf +++ b/modules/net-lb-app-int/groups.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_compute_instance_group" "default" { for_each = var.group_configs project = ( diff --git a/modules/net-lb-app-int/health-check.tf b/modules/net-lb-app-int/health-check.tf index 66ba58c56..8c0d844ec 100644 --- a/modules/net-lb-app-int/health-check.tf +++ b/modules/net-lb-app-int/health-check.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Health check resource. resource "google_compute_health_check" "default" { diff --git a/modules/net-lb-app-int/main.tf b/modules/net-lb-app-int/main.tf index 6a3e10521..b8ce4b76a 100644 --- a/modules/net-lb-app-int/main.tf +++ b/modules/net-lb-app-int/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { # we need keys in the endpoint type to address issue #1055 _neg_endpoints = flatten([ diff --git a/modules/net-lb-app-int/outputs.tf b/modules/net-lb-app-int/outputs.tf index 103cc0ed1..28319be88 100644 --- a/modules/net-lb-app-int/outputs.tf +++ b/modules/net-lb-app-int/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "address" { description = "Forwarding rule address." value = google_compute_forwarding_rule.default.ip_address diff --git a/modules/net-lb-app-int/urlmap.tf b/modules/net-lb-app-int/urlmap.tf index d680beb03..e8216a744 100644 --- a/modules/net-lb-app-int/urlmap.tf +++ b/modules/net-lb-app-int/urlmap.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description URL map resources. locals { diff --git a/modules/net-lb-app-int/variables-backend-service.tf b/modules/net-lb-app-int/variables-backend-service.tf index 9340becf9..36c0ac134 100644 --- a/modules/net-lb-app-int/variables-backend-service.tf +++ b/modules/net-lb-app-int/variables-backend-service.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Backend services variables. variable "backend_service_configs" { diff --git a/modules/net-lb-app-int/variables-health-check.tf b/modules/net-lb-app-int/variables-health-check.tf index a51994ecf..b04ca6e30 100644 --- a/modules/net-lb-app-int/variables-health-check.tf +++ b/modules/net-lb-app-int/variables-health-check.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Health check variable. variable "health_check_configs" { diff --git a/modules/net-lb-app-int/variables-urlmap.tf b/modules/net-lb-app-int/variables-urlmap.tf index ee48b7df0..961908e57 100644 --- a/modules/net-lb-app-int/variables-urlmap.tf +++ b/modules/net-lb-app-int/variables-urlmap.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description URLmap variable. variable "urlmap_config" { diff --git a/modules/net-lb-app-int/variables.tf b/modules/net-lb-app-int/variables.tf index d3311fbe3..424cfde06 100644 --- a/modules/net-lb-app-int/variables.tf +++ b/modules/net-lb-app-int/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "address" { description = "Optional IP address used for the forwarding rule." type = string diff --git a/modules/net-lb-app-int/versions.tf b/modules/net-lb-app-int/versions.tf index 601ed8bf2..447feb972 100644 --- a/modules/net-lb-app-int/versions.tf +++ b/modules/net-lb-app-int/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/net-lb-ext/README.md b/modules/net-lb-ext/README.md index 1d45eadbe..283949bee 100644 --- a/modules/net-lb-ext/README.md +++ b/modules/net-lb-ext/README.md @@ -1,3 +1,19 @@ + + # External Passthrough Network Load Balancer Module This module allows managing a GCE Network Load Balancer and integrates the forwarding rule, regional backend, and optional health check resources. It's designed to be a simple match for the [`compute-vm`](../compute-vm) module, which can be used to manage instance templates and instance groups. diff --git a/modules/net-lb-ext/groups.tf b/modules/net-lb-ext/groups.tf index 3389fb17d..e704a2232 100644 --- a/modules/net-lb-ext/groups.tf +++ b/modules/net-lb-ext/groups.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Optional instance group resources. resource "google_compute_instance_group" "default" { diff --git a/modules/net-lb-ext/health-check.tf b/modules/net-lb-ext/health-check.tf index 250058056..e0e3b7126 100644 --- a/modules/net-lb-ext/health-check.tf +++ b/modules/net-lb-ext/health-check.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Health check resource. locals { diff --git a/modules/net-lb-ext/main.tf b/modules/net-lb-ext/main.tf index 27dd19675..ba29ea165 100644 --- a/modules/net-lb-ext/main.tf +++ b/modules/net-lb-ext/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { bs_conntrack = var.backend_service_config.connection_tracking bs_failover = var.backend_service_config.failover_config diff --git a/modules/net-lb-ext/outputs.tf b/modules/net-lb-ext/outputs.tf index fd11e67f1..673310530 100644 --- a/modules/net-lb-ext/outputs.tf +++ b/modules/net-lb-ext/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "backend_service" { description = "Backend resource." value = google_compute_region_backend_service.default diff --git a/modules/net-lb-ext/variables.tf b/modules/net-lb-ext/variables.tf index a048cd178..49febe443 100644 --- a/modules/net-lb-ext/variables.tf +++ b/modules/net-lb-ext/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "backend_service_config" { description = "Backend service level configuration." type = object({ diff --git a/modules/net-lb-ext/versions.tf b/modules/net-lb-ext/versions.tf index ff32e2fee..79ccc8788 100644 --- a/modules/net-lb-ext/versions.tf +++ b/modules/net-lb-ext/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/net-lb-int/README.md b/modules/net-lb-int/README.md index 5b6de2fa3..92f69c691 100644 --- a/modules/net-lb-int/README.md +++ b/modules/net-lb-int/README.md @@ -1,3 +1,19 @@ + + # Internal Passthrough Network Load Balancer Module This module allows managing a GCE Internal Load Balancer and integrates the forwarding rule, regional backend, and optional health check resources. It's designed to be a simple match for the [`compute-vm`](../compute-vm) module, which can be used to manage instance templates and instance groups. diff --git a/modules/net-lb-int/groups.tf b/modules/net-lb-int/groups.tf index 736dfc6f5..42fb2dbc5 100644 --- a/modules/net-lb-int/groups.tf +++ b/modules/net-lb-int/groups.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Optional instance group resources. resource "google_compute_instance_group" "default" { diff --git a/modules/net-lb-int/health-check.tf b/modules/net-lb-int/health-check.tf index 1e0bd193b..ff784ae9d 100644 --- a/modules/net-lb-int/health-check.tf +++ b/modules/net-lb-int/health-check.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Health check resource. locals { diff --git a/modules/net-lb-int/main.tf b/modules/net-lb-int/main.tf index 1b1996a57..64e0480a4 100644 --- a/modules/net-lb-int/main.tf +++ b/modules/net-lb-int/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,8 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - - locals { bs_conntrack = var.backend_service_config.connection_tracking bs_failover = var.backend_service_config.failover_config diff --git a/modules/net-lb-int/outputs.tf b/modules/net-lb-int/outputs.tf index 29c925443..9f26e8eab 100644 --- a/modules/net-lb-int/outputs.tf +++ b/modules/net-lb-int/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "backend_service" { description = "Backend resource." sensitive = true diff --git a/modules/net-lb-int/recipe-ilb-next-hop/README.md b/modules/net-lb-int/recipe-ilb-next-hop/README.md index 4234b2579..d874d8841 100644 --- a/modules/net-lb-int/recipe-ilb-next-hop/README.md +++ b/modules/net-lb-int/recipe-ilb-next-hop/README.md @@ -1,3 +1,19 @@ + + # Internal Network Load Balancer as Next Hop This recipe shows how to bootstraps a minimal infrastructure for testing [ILB as next hop](https://cloud.google.com/load-balancing/docs/internal/ilb-next-hop-overview), using simple Linux gateway VMS between two VPCs to emulate virtual appliances. diff --git a/modules/net-lb-int/recipe-ilb-next-hop/assets/gw.yaml b/modules/net-lb-int/recipe-ilb-next-hop/assets/gw.yaml index 73bd18dce..11ca3d6e7 100644 --- a/modules/net-lb-int/recipe-ilb-next-hop/assets/gw.yaml +++ b/modules/net-lb-int/recipe-ilb-next-hop/assets/gw.yaml @@ -1,12 +1,12 @@ #cloud-config -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + write_files: - path: /etc/sysctl.conf permissions: "0644" diff --git a/modules/net-lb-int/recipe-ilb-next-hop/backend.tf.sample b/modules/net-lb-int/recipe-ilb-next-hop/backend.tf.sample index e1bb8eaf5..13f55ed94 100644 --- a/modules/net-lb-int/recipe-ilb-next-hop/backend.tf.sample +++ b/modules/net-lb-int/recipe-ilb-next-hop/backend.tf.sample @@ -1,10 +1,10 @@ -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# https://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -13,6 +13,7 @@ # limitations under the License. + terraform { backend "gcs" { bucket = "" diff --git a/modules/net-lb-int/recipe-ilb-next-hop/gateways.tf b/modules/net-lb-int/recipe-ilb-next-hop/gateways.tf index 2e99956e2..6cbe9c402 100644 --- a/modules/net-lb-int/recipe-ilb-next-hop/gateways.tf +++ b/modules/net-lb-int/recipe-ilb-next-hop/gateways.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - module "gw" { source = "../../../modules/compute-vm" for_each = local.zones diff --git a/modules/net-lb-int/recipe-ilb-next-hop/main.tf b/modules/net-lb-int/recipe-ilb-next-hop/main.tf index efdc0f08b..f42f2aa60 100644 --- a/modules/net-lb-int/recipe-ilb-next-hop/main.tf +++ b/modules/net-lb-int/recipe-ilb-next-hop/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { addresses = { for k, v in module.addresses.internal_addresses : diff --git a/modules/net-lb-int/recipe-ilb-next-hop/outputs.tf b/modules/net-lb-int/recipe-ilb-next-hop/outputs.tf index c69501d92..9384eb0ec 100644 --- a/modules/net-lb-int/recipe-ilb-next-hop/outputs.tf +++ b/modules/net-lb-int/recipe-ilb-next-hop/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "addresses" { description = "IP addresses." value = { diff --git a/modules/net-lb-int/recipe-ilb-next-hop/variables.tf b/modules/net-lb-int/recipe-ilb-next-hop/variables.tf index be59b2177..7eaf79b1b 100644 --- a/modules/net-lb-int/recipe-ilb-next-hop/variables.tf +++ b/modules/net-lb-int/recipe-ilb-next-hop/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "_testing" { description = "Populate this variable to avoid triggering the data source." type = object({ diff --git a/modules/net-lb-int/recipe-ilb-next-hop/vms.tf b/modules/net-lb-int/recipe-ilb-next-hop/vms.tf index 259eacb09..2fe19aa2c 100644 --- a/modules/net-lb-int/recipe-ilb-next-hop/vms.tf +++ b/modules/net-lb-int/recipe-ilb-next-hop/vms.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { vm_startup_script = < + # Internal Proxy Network Load Balancer Module This module allows managing Internal HTTP/HTTPS Load Balancers (L7 ILBs). It's designed to expose the full configuration of the underlying resources, and to facilitate common usage patterns by providing sensible defaults, and optionally managing prerequisite resources like health checks, instance groups, etc. diff --git a/modules/net-lb-proxy-int/backend-service.tf b/modules/net-lb-proxy-int/backend-service.tf index e6aa07a28..664e5d94f 100644 --- a/modules/net-lb-proxy-int/backend-service.tf +++ b/modules/net-lb-proxy-int/backend-service.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Backend service resources. locals { diff --git a/modules/net-lb-proxy-int/groups.tf b/modules/net-lb-proxy-int/groups.tf index 53ba6b27f..519fd719c 100644 --- a/modules/net-lb-proxy-int/groups.tf +++ b/modules/net-lb-proxy-int/groups.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_compute_instance_group" "default" { for_each = var.group_configs project = ( diff --git a/modules/net-lb-proxy-int/health-check.tf b/modules/net-lb-proxy-int/health-check.tf index 5ec01c255..2e0cdf79d 100644 --- a/modules/net-lb-proxy-int/health-check.tf +++ b/modules/net-lb-proxy-int/health-check.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Health check resource. locals { diff --git a/modules/net-lb-proxy-int/main.tf b/modules/net-lb-proxy-int/main.tf index 096ae33ce..192edc4ee 100644 --- a/modules/net-lb-proxy-int/main.tf +++ b/modules/net-lb-proxy-int/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { # we need keys in the endpoint type to address issue #1055 _neg_endpoints = flatten([ diff --git a/modules/net-lb-proxy-int/outputs.tf b/modules/net-lb-proxy-int/outputs.tf index 7f37aa7e6..d713831c0 100644 --- a/modules/net-lb-proxy-int/outputs.tf +++ b/modules/net-lb-proxy-int/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "address" { description = "Forwarding rule address." value = google_compute_forwarding_rule.default.ip_address diff --git a/modules/net-lb-proxy-int/variables.tf b/modules/net-lb-proxy-int/variables.tf index 119265d24..f1f81b037 100644 --- a/modules/net-lb-proxy-int/variables.tf +++ b/modules/net-lb-proxy-int/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "address" { description = "Optional IP address used for the forwarding rule." type = string diff --git a/modules/net-lb-proxy-int/versions.tf b/modules/net-lb-proxy-int/versions.tf index bc98cd235..1e3da28b1 100644 --- a/modules/net-lb-proxy-int/versions.tf +++ b/modules/net-lb-proxy-int/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/net-swp/README.md b/modules/net-swp/README.md index 53758eb81..93fbc7fea 100644 --- a/modules/net-swp/README.md +++ b/modules/net-swp/README.md @@ -1,3 +1,19 @@ + + # Google Cloud Secure Web Proxy This module allows creation and management of [Secure Web Proxy](https://cloud.google.com/secure-web-proxy/docs/overview), and its URL lists and policy rules. diff --git a/modules/net-swp/main.tf b/modules/net-swp/main.tf index 471cf5f35..faeac361b 100644 --- a/modules/net-swp/main.tf +++ b/modules/net-swp/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _url_lists_path = try(pathexpand(var.factories_config.url_lists), null) _url_lists = { diff --git a/modules/net-swp/outputs.tf b/modules/net-swp/outputs.tf index fe271d9a9..d6b82cb2b 100644 --- a/modules/net-swp/outputs.tf +++ b/modules/net-swp/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "gateway" { description = "The gateway resource." value = google_network_services_gateway.default diff --git a/modules/net-swp/policy-rules.tf b/modules/net-swp/policy-rules.tf index f534ad68c..18f2f4581 100644 --- a/modules/net-swp/policy-rules.tf +++ b/modules/net-swp/policy-rules.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _policy_rules_path = try(pathexpand(var.factories_config.policy_rules), null) _policy_rules = { diff --git a/modules/net-swp/variables.tf b/modules/net-swp/variables.tf index cff9e3f49..fb67c3d8a 100644 --- a/modules/net-swp/variables.tf +++ b/modules/net-swp/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "certificates" { description = "List of certificates to be used for Secure Web Proxy." type = list(string) diff --git a/modules/net-swp/versions.tf b/modules/net-swp/versions.tf index 458e04439..22ba189bd 100644 --- a/modules/net-swp/versions.tf +++ b/modules/net-swp/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/net-vlan-attachment/README.md b/modules/net-vlan-attachment/README.md index a72cb9387..6c5d6a701 100644 --- a/modules/net-vlan-attachment/README.md +++ b/modules/net-vlan-attachment/README.md @@ -1,3 +1,19 @@ + + # VLAN Attachment module This module allows for the provisioning of VLAN Attachments for [Dedicated Interconnect](https://cloud.google.com/network-connectivity/docs/interconnect/how-to/dedicated/creating-vlan-attachments) or [Partner Interconnect](https://cloud.google.com/network-connectivity/docs/interconnect/how-to/partner/creating-vlan-attachments). diff --git a/modules/net-vlan-attachment/main.tf b/modules/net-vlan-attachment/main.tf index 40b2c81f6..58360e224 100644 --- a/modules/net-vlan-attachment/main.tf +++ b/modules/net-vlan-attachment/main.tf @@ -1,162 +1,161 @@ -/** - * Copyright 2023 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -locals { - ipsec_enabled = var.vpn_gateways_ip_range == null ? false : true - router = ( - var.router_config.create - ? local.ipsec_enabled ? try(google_compute_router.encrypted[0].name, null) : try(google_compute_router.unencrypted[0].name, null) - : var.router_config.name - ) - secret = random_id.secret.b64_url -} - -resource "google_compute_address" "default" { - count = local.ipsec_enabled ? 1 : 0 - project = var.project_id - network = var.network - region = var.region - name = "pool-${var.name}" - address_type = "INTERNAL" - purpose = "IPSEC_INTERCONNECT" - address = split("/", var.vpn_gateways_ip_range)[0] - prefix_length = split("/", var.vpn_gateways_ip_range)[1] -} - -resource "google_compute_interconnect_attachment" "default" { - project = var.project_id - region = var.region - router = local.router - name = var.name - description = var.description - interconnect = try(var.dedicated_interconnect_config.interconnect, null) - bandwidth = try(var.dedicated_interconnect_config.bandwidth, null) - mtu = local.ipsec_enabled ? null : var.mtu - candidate_subnets = var.dedicated_interconnect_config != null ? [var.dedicated_interconnect_config.bgp_range] : null - vlan_tag8021q = try(var.dedicated_interconnect_config.vlan_tag, null) - admin_enabled = var.admin_enabled - encryption = local.ipsec_enabled ? "IPSEC" : null - type = var.dedicated_interconnect_config == null ? "PARTNER" : "DEDICATED" - edge_availability_domain = try(var.partner_interconnect_config.edge_availability_domain, null) - ipsec_internal_addresses = local.ipsec_enabled ? [google_compute_address.default[0].self_link] : null -} - -resource "google_compute_router" "encrypted" { - count = var.router_config.create && local.ipsec_enabled ? 1 : 0 - name = "${var.name}-underlay" - network = var.network - project = var.project_id - region = var.region - encrypted_interconnect_router = true - bgp { - asn = var.router_config.asn - advertise_mode = var.dedicated_interconnect_config == null ? "DEFAULT" : "CUSTOM" - dynamic "advertised_ip_ranges" { - for_each = var.dedicated_interconnect_config == null ? var.ipsec_gateway_ip_ranges : {} - content { - description = advertised_ip_ranges.key - range = advertised_ip_ranges.value - } - } - } -} - -resource "google_compute_router" "unencrypted" { - count = var.router_config.create && !local.ipsec_enabled ? 1 : 0 - name = coalesce(var.router_config.name, "underlay-${var.name}") - project = var.project_id - region = var.region - network = var.network - bgp { - advertise_mode = ( - var.router_config.custom_advertise != null - ? "CUSTOM" - : "DEFAULT" - ) - advertised_groups = ( - try(var.router_config.custom_advertise.all_subnets, false) - ? ["ALL_SUBNETS"] - : [] - ) - dynamic "advertised_ip_ranges" { - for_each = try(var.router_config.custom_advertise.ip_ranges, {}) - iterator = range - content { - range = range.key - description = range.value - } - } - keepalive_interval = try(var.router_config.keepalive, null) - asn = var.router_config.asn - } -} - -resource "google_compute_router_interface" "default" { - count = var.dedicated_interconnect_config != null ? 1 : 0 - project = var.project_id - region = var.region - name = "${var.name}-intf" - router = local.router - ip_range = google_compute_interconnect_attachment.default.cloud_router_ip_address - interconnect_attachment = google_compute_interconnect_attachment.default.self_link -} - -resource "google_compute_router_peer" "default" { - count = var.dedicated_interconnect_config != null ? 1 : 0 - name = "${var.name}-peer" - project = var.project_id - router = local.router - region = var.region - peer_ip_address = split("/", google_compute_interconnect_attachment.default.customer_router_ip_address)[0] - peer_asn = var.peer_asn - interface = google_compute_router_interface.default[0].name - advertised_route_priority = var.dedicated_interconnect_config.bgp_priority - advertise_mode = "CUSTOM" - - dynamic "advertised_ip_ranges" { - for_each = var.ipsec_gateway_ip_ranges - content { - description = advertised_ip_ranges.key - range = advertised_ip_ranges.value - } - } - - dynamic "bfd" { - for_each = var.router_config.bfd != null ? toset([var.router_config.bfd]) : [] - content { - session_initialization_mode = bfd.value.session_initialization_mode - min_receive_interval = bfd.value.min_receive_interval - min_transmit_interval = bfd.value.min_transmit_interval - multiplier = bfd.value.multiplier - } - } - - dynamic "md5_authentication_key" { - for_each = var.router_config.md5_authentication_key != null ? [var.router_config.md5_authentication_key] : [] - content { - name = md5_authentication_key.value.name - key = coalesce(md5_authentication_key.value.key, local.secret) - } - } - - depends_on = [ - google_compute_router_interface.default - ] -} - -resource "random_id" "secret" { - byte_length = 12 -} +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +locals { + ipsec_enabled = var.vpn_gateways_ip_range == null ? false : true + router = ( + var.router_config.create + ? local.ipsec_enabled ? try(google_compute_router.encrypted[0].name, null) : try(google_compute_router.unencrypted[0].name, null) + : var.router_config.name + ) + secret = random_id.secret.b64_url +} + +resource "google_compute_address" "default" { + count = local.ipsec_enabled ? 1 : 0 + project = var.project_id + network = var.network + region = var.region + name = "pool-${var.name}" + address_type = "INTERNAL" + purpose = "IPSEC_INTERCONNECT" + address = split("/", var.vpn_gateways_ip_range)[0] + prefix_length = split("/", var.vpn_gateways_ip_range)[1] +} + +resource "google_compute_interconnect_attachment" "default" { + project = var.project_id + region = var.region + router = local.router + name = var.name + description = var.description + interconnect = try(var.dedicated_interconnect_config.interconnect, null) + bandwidth = try(var.dedicated_interconnect_config.bandwidth, null) + mtu = local.ipsec_enabled ? null : var.mtu + candidate_subnets = var.dedicated_interconnect_config != null ? [var.dedicated_interconnect_config.bgp_range] : null + vlan_tag8021q = try(var.dedicated_interconnect_config.vlan_tag, null) + admin_enabled = var.admin_enabled + encryption = local.ipsec_enabled ? "IPSEC" : null + type = var.dedicated_interconnect_config == null ? "PARTNER" : "DEDICATED" + edge_availability_domain = try(var.partner_interconnect_config.edge_availability_domain, null) + ipsec_internal_addresses = local.ipsec_enabled ? [google_compute_address.default[0].self_link] : null +} + +resource "google_compute_router" "encrypted" { + count = var.router_config.create && local.ipsec_enabled ? 1 : 0 + name = "${var.name}-underlay" + network = var.network + project = var.project_id + region = var.region + encrypted_interconnect_router = true + bgp { + asn = var.router_config.asn + advertise_mode = var.dedicated_interconnect_config == null ? "DEFAULT" : "CUSTOM" + dynamic "advertised_ip_ranges" { + for_each = var.dedicated_interconnect_config == null ? var.ipsec_gateway_ip_ranges : {} + content { + description = advertised_ip_ranges.key + range = advertised_ip_ranges.value + } + } + } +} + +resource "google_compute_router" "unencrypted" { + count = var.router_config.create && !local.ipsec_enabled ? 1 : 0 + name = coalesce(var.router_config.name, "underlay-${var.name}") + project = var.project_id + region = var.region + network = var.network + bgp { + advertise_mode = ( + var.router_config.custom_advertise != null + ? "CUSTOM" + : "DEFAULT" + ) + advertised_groups = ( + try(var.router_config.custom_advertise.all_subnets, false) + ? ["ALL_SUBNETS"] + : [] + ) + dynamic "advertised_ip_ranges" { + for_each = try(var.router_config.custom_advertise.ip_ranges, {}) + iterator = range + content { + range = range.key + description = range.value + } + } + keepalive_interval = try(var.router_config.keepalive, null) + asn = var.router_config.asn + } +} + +resource "google_compute_router_interface" "default" { + count = var.dedicated_interconnect_config != null ? 1 : 0 + project = var.project_id + region = var.region + name = "${var.name}-intf" + router = local.router + ip_range = google_compute_interconnect_attachment.default.cloud_router_ip_address + interconnect_attachment = google_compute_interconnect_attachment.default.self_link +} + +resource "google_compute_router_peer" "default" { + count = var.dedicated_interconnect_config != null ? 1 : 0 + name = "${var.name}-peer" + project = var.project_id + router = local.router + region = var.region + peer_ip_address = split("/", google_compute_interconnect_attachment.default.customer_router_ip_address)[0] + peer_asn = var.peer_asn + interface = google_compute_router_interface.default[0].name + advertised_route_priority = var.dedicated_interconnect_config.bgp_priority + advertise_mode = "CUSTOM" + + dynamic "advertised_ip_ranges" { + for_each = var.ipsec_gateway_ip_ranges + content { + description = advertised_ip_ranges.key + range = advertised_ip_ranges.value + } + } + + dynamic "bfd" { + for_each = var.router_config.bfd != null ? toset([var.router_config.bfd]) : [] + content { + session_initialization_mode = bfd.value.session_initialization_mode + min_receive_interval = bfd.value.min_receive_interval + min_transmit_interval = bfd.value.min_transmit_interval + multiplier = bfd.value.multiplier + } + } + + dynamic "md5_authentication_key" { + for_each = var.router_config.md5_authentication_key != null ? [var.router_config.md5_authentication_key] : [] + content { + name = md5_authentication_key.value.name + key = coalesce(md5_authentication_key.value.key, local.secret) + } + } + + depends_on = [ + google_compute_router_interface.default + ] +} + +resource "random_id" "secret" { + byte_length = 12 +} diff --git a/modules/net-vlan-attachment/outputs.tf b/modules/net-vlan-attachment/outputs.tf index 6a8533075..0496edc4b 100644 --- a/modules/net-vlan-attachment/outputs.tf +++ b/modules/net-vlan-attachment/outputs.tf @@ -1,61 +1,60 @@ -/** - * Copyright 2023 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -output "attachment" { - description = "VLAN Attachment resource." - value = google_compute_interconnect_attachment.default -} - -output "id" { - description = "Fully qualified VLAN attachment id." - value = google_compute_interconnect_attachment.default.id -} - -output "md5_configuration" { - description = "MD5 configuration." - value = ( - var.router_config.md5_authentication_key != null - ? { - name = var.router_config.md5_authentication_key.name - key = coalesce(var.router_config.md5_authentication_key.key, local.secret) - } : {} - ) -} - -output "name" { - description = "The name of the VLAN attachment created." - value = google_compute_interconnect_attachment.default.name -} - -output "pairing_key" { - description = "Opaque identifier of an PARTNER attachment used to initiate provisioning with a selected partner." - value = google_compute_interconnect_attachment.default.pairing_key -} - -output "router" { - description = "Router resource (only if auto-created)." - value = local.ipsec_enabled ? one(google_compute_router.encrypted[*]) : one(google_compute_router.unencrypted[*]) -} - -output "router_interface" { - description = "Router interface created for the VLAN attachment." - value = google_compute_router_interface.default -} - -output "router_name" { - description = "Router name." - value = local.router -} +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +output "attachment" { + description = "VLAN Attachment resource." + value = google_compute_interconnect_attachment.default +} + +output "id" { + description = "Fully qualified VLAN attachment id." + value = google_compute_interconnect_attachment.default.id +} + +output "md5_configuration" { + description = "MD5 configuration." + value = ( + var.router_config.md5_authentication_key != null + ? { + name = var.router_config.md5_authentication_key.name + key = coalesce(var.router_config.md5_authentication_key.key, local.secret) + } : {} + ) +} + +output "name" { + description = "The name of the VLAN attachment created." + value = google_compute_interconnect_attachment.default.name +} + +output "pairing_key" { + description = "Opaque identifier of an PARTNER attachment used to initiate provisioning with a selected partner." + value = google_compute_interconnect_attachment.default.pairing_key +} + +output "router" { + description = "Router resource (only if auto-created)." + value = local.ipsec_enabled ? one(google_compute_router.encrypted[*]) : one(google_compute_router.unencrypted[*]) +} + +output "router_interface" { + description = "Router interface created for the VLAN attachment." + value = google_compute_router_interface.default +} + +output "router_name" { + description = "Router name." + value = local.router +} diff --git a/modules/net-vlan-attachment/variables.tf b/modules/net-vlan-attachment/variables.tf index cd87b39c9..27d87b5ca 100644 --- a/modules/net-vlan-attachment/variables.tf +++ b/modules/net-vlan-attachment/variables.tf @@ -1,119 +1,118 @@ -/** - * Copyright 2023 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -variable "admin_enabled" { - description = "Whether the VLAN attachment is enabled." - type = bool - default = true -} - -variable "dedicated_interconnect_config" { - description = "Dedicated interconnect configuration." - type = object({ - # Possible values @ https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_interconnect_attachment#bandwidth - bandwidth = optional(string, "BPS_10G") - bgp_range = optional(string) - bgp_priority = optional(number) - interconnect = string - vlan_tag = string - }) - default = null -} - -variable "description" { - description = "VLAN attachment description." - type = string -} - -variable "ipsec_gateway_ip_ranges" { - description = "IPSec Gateway IP Ranges." - type = map(string) - default = {} -} - -variable "mtu" { - description = "The MTU associated to the VLAN attachment (1440 / 1500)." - type = number - default = "1500" -} - -variable "name" { - description = "The common resources name, used after resource type prefix and suffix." - type = string -} - -variable "network" { - description = "The VPC name to which resources are associated to." - type = string -} - -variable "partner_interconnect_config" { - description = "Partner interconnect configuration." - type = object({ - edge_availability_domain = string - }) - validation { - condition = var.partner_interconnect_config == null ? true : contains(["AVAILABILITY_DOMAIN_1", "AVAILABILITY_DOMAIN_2", "AVAILABILITY_DOMAIN_ANY"], var.partner_interconnect_config.edge_availability_domain) - error_message = "The edge_availability_domain must have one of these values: AVAILABILITY_DOMAIN_1, AVAILABILITY_DOMAIN_2, AVAILABILITY_DOMAIN_ANY." - } - default = null -} - -variable "peer_asn" { - description = "The on-premises underlay router ASN." - type = string -} - -variable "project_id" { - description = "The project id where resources are created." - type = string -} - -variable "region" { - description = "The region where resources are created." - type = string -} - -variable "router_config" { - description = "Cloud Router configuration for the VPN. If you want to reuse an existing router, set create to false and use name to specify the desired router." - type = object({ - create = optional(bool, true) - asn = optional(number, 65001) - bfd = optional(object({ - min_receive_interval = optional(number) - min_transmit_interval = optional(number) - multiplier = optional(number) - session_initialization_mode = optional(string, "ACTIVE") - })) - custom_advertise = optional(object({ - all_subnets = bool - ip_ranges = map(string) - })) - md5_authentication_key = optional(object({ - name = string - key = optional(string) - })) - keepalive = optional(number) - name = optional(string, "router") - }) - nullable = false -} - -variable "vpn_gateways_ip_range" { - description = "The IP range (cidr notation) to be used for the GCP VPN gateways. If null IPSec over Interconnect is not enabled." - type = string - default = null -} +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +variable "admin_enabled" { + description = "Whether the VLAN attachment is enabled." + type = bool + default = true +} + +variable "dedicated_interconnect_config" { + description = "Dedicated interconnect configuration." + type = object({ + # Possible values @ https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_interconnect_attachment#bandwidth + bandwidth = optional(string, "BPS_10G") + bgp_range = optional(string) + bgp_priority = optional(number) + interconnect = string + vlan_tag = string + }) + default = null +} + +variable "description" { + description = "VLAN attachment description." + type = string +} + +variable "ipsec_gateway_ip_ranges" { + description = "IPSec Gateway IP Ranges." + type = map(string) + default = {} +} + +variable "mtu" { + description = "The MTU associated to the VLAN attachment (1440 / 1500)." + type = number + default = "1500" +} + +variable "name" { + description = "The common resources name, used after resource type prefix and suffix." + type = string +} + +variable "network" { + description = "The VPC name to which resources are associated to." + type = string +} + +variable "partner_interconnect_config" { + description = "Partner interconnect configuration." + type = object({ + edge_availability_domain = string + }) + validation { + condition = var.partner_interconnect_config == null ? true : contains(["AVAILABILITY_DOMAIN_1", "AVAILABILITY_DOMAIN_2", "AVAILABILITY_DOMAIN_ANY"], var.partner_interconnect_config.edge_availability_domain) + error_message = "The edge_availability_domain must have one of these values: AVAILABILITY_DOMAIN_1, AVAILABILITY_DOMAIN_2, AVAILABILITY_DOMAIN_ANY." + } + default = null +} + +variable "peer_asn" { + description = "The on-premises underlay router ASN." + type = string +} + +variable "project_id" { + description = "The project id where resources are created." + type = string +} + +variable "region" { + description = "The region where resources are created." + type = string +} + +variable "router_config" { + description = "Cloud Router configuration for the VPN. If you want to reuse an existing router, set create to false and use name to specify the desired router." + type = object({ + create = optional(bool, true) + asn = optional(number, 65001) + bfd = optional(object({ + min_receive_interval = optional(number) + min_transmit_interval = optional(number) + multiplier = optional(number) + session_initialization_mode = optional(string, "ACTIVE") + })) + custom_advertise = optional(object({ + all_subnets = bool + ip_ranges = map(string) + })) + md5_authentication_key = optional(object({ + name = string + key = optional(string) + })) + keepalive = optional(number) + name = optional(string, "router") + }) + nullable = false +} + +variable "vpn_gateways_ip_range" { + description = "The IP range (cidr notation) to be used for the GCP VPN gateways. If null IPSec over Interconnect is not enabled." + type = string + default = null +} diff --git a/modules/net-vlan-attachment/versions.tf b/modules/net-vlan-attachment/versions.tf index 89277df1f..58fa6ad6c 100644 --- a/modules/net-vlan-attachment/versions.tf +++ b/modules/net-vlan-attachment/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/net-vpc-firewall/README.md b/modules/net-vpc-firewall/README.md index b23a270c4..140e734ad 100644 --- a/modules/net-vpc-firewall/README.md +++ b/modules/net-vpc-firewall/README.md @@ -1,3 +1,19 @@ + + # Google Cloud VPC Firewall This module allows creation and management of different types of firewall rules for a single VPC network: diff --git a/modules/net-vpc-firewall/default-rules.tf b/modules/net-vpc-firewall/default-rules.tf index 976c45e6b..62d68b989 100644 --- a/modules/net-vpc-firewall/default-rules.tf +++ b/modules/net-vpc-firewall/default-rules.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Optional default rule resources. locals { diff --git a/modules/net-vpc-firewall/main.tf b/modules/net-vpc-firewall/main.tf index 1f9442ef4..49148573e 100644 --- a/modules/net-vpc-firewall/main.tf +++ b/modules/net-vpc-firewall/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _factory_rules_folder = try(pathexpand(var.factories_config.rules_folder), null) # define list of rule files diff --git a/modules/net-vpc-firewall/outputs.tf b/modules/net-vpc-firewall/outputs.tf index 9206ab546..928a37f81 100644 --- a/modules/net-vpc-firewall/outputs.tf +++ b/modules/net-vpc-firewall/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "default_rules" { description = "Default rule resources." value = { diff --git a/modules/net-vpc-firewall/variables.tf b/modules/net-vpc-firewall/variables.tf index 104f87d5b..66f0eccf0 100644 --- a/modules/net-vpc-firewall/variables.tf +++ b/modules/net-vpc-firewall/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "default_rules_config" { description = "Optionally created convenience rules. Set the 'disabled' attribute to true, or individual rule attributes to empty lists to disable." type = object({ diff --git a/modules/net-vpc-firewall/versions.tf b/modules/net-vpc-firewall/versions.tf index 9c5346dec..908e5cf4f 100644 --- a/modules/net-vpc-firewall/versions.tf +++ b/modules/net-vpc-firewall/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/net-vpc-peering/README.md b/modules/net-vpc-peering/README.md index 869ad1563..262fdfc95 100644 --- a/modules/net-vpc-peering/README.md +++ b/modules/net-vpc-peering/README.md @@ -1,3 +1,19 @@ + + # Google Network Peering This module allows creation of a [VPC Network Peering](https://cloud.google.com/vpc/docs/vpc-peering) between two networks. diff --git a/modules/net-vpc-peering/main.tf b/modules/net-vpc-peering/main.tf index 234881e30..3421d4930 100644 --- a/modules/net-vpc-peering/main.tf +++ b/modules/net-vpc-peering/main.tf @@ -1,11 +1,11 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { local_network_name = element(reverse(split("/", var.local_network)), 0) auto_local_name = "${local.prefix}${local.local_network_name}-${local.peer_network_name}" diff --git a/modules/net-vpc-peering/outputs.tf b/modules/net-vpc-peering/outputs.tf index 558c4bac1..218e326d3 100644 --- a/modules/net-vpc-peering/outputs.tf +++ b/modules/net-vpc-peering/outputs.tf @@ -1,11 +1,11 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "local_network_peering" { description = "Network peering resource." value = google_compute_network_peering.local_network_peering diff --git a/modules/net-vpc-peering/variables.tf b/modules/net-vpc-peering/variables.tf index b30446368..bddfdc829 100644 --- a/modules/net-vpc-peering/variables.tf +++ b/modules/net-vpc-peering/variables.tf @@ -1,11 +1,11 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "local_network" { description = "The full resource link (self-link) of the local VPC network for the peering connection." type = string diff --git a/modules/net-vpc-peering/versions.tf b/modules/net-vpc-peering/versions.tf index faa10f69a..e8211b389 100644 --- a/modules/net-vpc-peering/versions.tf +++ b/modules/net-vpc-peering/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/net-vpc/README.md b/modules/net-vpc/README.md index 57570c508..d9128389c 100644 --- a/modules/net-vpc/README.md +++ b/modules/net-vpc/README.md @@ -1,3 +1,19 @@ + + # VPC module This module allows creation and management of VPC networks including subnetworks and subnetwork IAM bindings, and most features and options related to VPCs and subnets. diff --git a/modules/net-vpc/main.tf b/modules/net-vpc/main.tf index dd9a19295..361e870de 100644 --- a/modules/net-vpc/main.tf +++ b/modules/net-vpc/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { network = ( var.vpc_create diff --git a/modules/net-vpc/outputs.tf b/modules/net-vpc/outputs.tf index 8184e96d4..3d4d82d0e 100644 --- a/modules/net-vpc/outputs.tf +++ b/modules/net-vpc/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "id" { description = "Fully qualified network id." value = local.network.id diff --git a/modules/net-vpc/psa.tf b/modules/net-vpc/psa.tf index 959193896..9ae85df67 100644 --- a/modules/net-vpc/psa.tf +++ b/modules/net-vpc/psa.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Private Service Access resources. locals { diff --git a/modules/net-vpc/routes.tf b/modules/net-vpc/routes.tf index be16bb936..963965a69 100644 --- a/modules/net-vpc/routes.tf +++ b/modules/net-vpc/routes.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Route resources. locals { diff --git a/modules/net-vpc/subnets.tf b/modules/net-vpc/subnets.tf index a75f5b7b9..d980b96ab 100644 --- a/modules/net-vpc/subnets.tf +++ b/modules/net-vpc/subnets.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Subnet resources. locals { diff --git a/modules/net-vpc/variables.tf b/modules/net-vpc/variables.tf index fcbc7843f..f7da06b32 100644 --- a/modules/net-vpc/variables.tf +++ b/modules/net-vpc/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "auto_create_subnetworks" { description = "Set to true to create an auto mode subnet, defaults to custom mode." type = bool diff --git a/modules/net-vpc/versions.tf b/modules/net-vpc/versions.tf index 0a9f3e1c8..283fd0561 100644 --- a/modules/net-vpc/versions.tf +++ b/modules/net-vpc/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/net-vpn-dynamic/README.md b/modules/net-vpn-dynamic/README.md index 5f79ffaaa..cef080af9 100644 --- a/modules/net-vpn-dynamic/README.md +++ b/modules/net-vpn-dynamic/README.md @@ -1,3 +1,19 @@ + + # Cloud VPN Dynamic Module ## Example diff --git a/modules/net-vpn-dynamic/main.tf b/modules/net-vpn-dynamic/main.tf index fcf26934b..5cae8d77f 100644 --- a/modules/net-vpn-dynamic/main.tf +++ b/modules/net-vpn-dynamic/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { gateway_address = ( var.gateway_address_create diff --git a/modules/net-vpn-dynamic/outputs.tf b/modules/net-vpn-dynamic/outputs.tf index 2595a8fc4..83b284f90 100644 --- a/modules/net-vpn-dynamic/outputs.tf +++ b/modules/net-vpn-dynamic/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "address" { description = "VPN gateway address." value = local.gateway_address diff --git a/modules/net-vpn-dynamic/variables.tf b/modules/net-vpn-dynamic/variables.tf index 33d23a040..2a9e7730a 100644 --- a/modules/net-vpn-dynamic/variables.tf +++ b/modules/net-vpn-dynamic/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "gateway_address" { description = "Optional address assigned to the VPN gateway. Ignored unless gateway_address_create is set to false." type = string diff --git a/modules/net-vpn-dynamic/versions.tf b/modules/net-vpn-dynamic/versions.tf index 5ee6d91a2..a7d66b883 100644 --- a/modules/net-vpn-dynamic/versions.tf +++ b/modules/net-vpn-dynamic/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/net-vpn-ha/README.md b/modules/net-vpn-ha/README.md index edd623907..d8325344b 100644 --- a/modules/net-vpn-ha/README.md +++ b/modules/net-vpn-ha/README.md @@ -1,3 +1,19 @@ + + # Cloud HA VPN Module This module makes it easy to deploy either GCP-to-GCP or GCP-to-On-prem [Cloud HA VPN](https://cloud.google.com/network-connectivity/docs/vpn/concepts/overview#ha-vpn). diff --git a/modules/net-vpn-ha/main.tf b/modules/net-vpn-ha/main.tf index c53e18e52..011f8a66e 100644 --- a/modules/net-vpn-ha/main.tf +++ b/modules/net-vpn-ha/main.tf @@ -1,6 +1,6 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { md5_keys = { for k, v in random_id.md5_keys diff --git a/modules/net-vpn-ha/outputs.tf b/modules/net-vpn-ha/outputs.tf index 09e96e625..31785dd58 100644 --- a/modules/net-vpn-ha/outputs.tf +++ b/modules/net-vpn-ha/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,8 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - - output "bgp_peers" { description = "BGP peer resources." value = { diff --git a/modules/net-vpn-ha/variables.tf b/modules/net-vpn-ha/variables.tf index d20b48daa..469f573e7 100644 --- a/modules/net-vpn-ha/variables.tf +++ b/modules/net-vpn-ha/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "name" { description = "VPN Gateway name (if an existing VPN Gateway is not used), and prefix used for dependent resources." type = string diff --git a/modules/net-vpn-ha/versions.tf b/modules/net-vpn-ha/versions.tf index dc908a08c..efbb41f7d 100644 --- a/modules/net-vpn-ha/versions.tf +++ b/modules/net-vpn-ha/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/net-vpn-static/README.md b/modules/net-vpn-static/README.md index 902fc1e46..be1b0fbaa 100644 --- a/modules/net-vpn-static/README.md +++ b/modules/net-vpn-static/README.md @@ -1,3 +1,19 @@ + + # Cloud VPN Route-based Module ## Example diff --git a/modules/net-vpn-static/main.tf b/modules/net-vpn-static/main.tf index f05771c16..9a6ac6deb 100644 --- a/modules/net-vpn-static/main.tf +++ b/modules/net-vpn-static/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { gateway_address = ( var.gateway_address_create diff --git a/modules/net-vpn-static/outputs.tf b/modules/net-vpn-static/outputs.tf index 946063f72..95358e93b 100644 --- a/modules/net-vpn-static/outputs.tf +++ b/modules/net-vpn-static/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "address" { description = "VPN gateway address." value = local.gateway_address diff --git a/modules/net-vpn-static/variables.tf b/modules/net-vpn-static/variables.tf index 935c543a4..9446f3b91 100644 --- a/modules/net-vpn-static/variables.tf +++ b/modules/net-vpn-static/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "gateway_address" { description = "Optional address assigned to the VPN gateway. Ignored unless gateway_address_create is set to false." type = string diff --git a/modules/net-vpn-static/versions.tf b/modules/net-vpn-static/versions.tf index bb04113a6..8d26c8ab6 100644 --- a/modules/net-vpn-static/versions.tf +++ b/modules/net-vpn-static/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/organization-se/README.md b/modules/organization-se/README.md index 525ae912a..b075d6143 100644 --- a/modules/organization-se/README.md +++ b/modules/organization-se/README.md @@ -1,3 +1,19 @@ + + # Organization Module This module allows managing several organization properties: diff --git a/modules/organization-se/iam.tf b/modules/organization-se/iam.tf index 607a54f0a..bb0cf6137 100644 --- a/modules/organization-se/iam.tf +++ b/modules/organization-se/iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description IAM bindings. locals { diff --git a/modules/organization-se/logging.tf b/modules/organization-se/logging.tf index 9e0874c05..ac8b5cde8 100644 --- a/modules/organization-se/logging.tf +++ b/modules/organization-se/logging.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Log sinks and data access logs. locals { diff --git a/modules/organization-se/main.tf b/modules/organization-se/main.tf index 45668ceec..aa7148342 100644 --- a/modules/organization-se/main.tf +++ b/modules/organization-se/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { organization_id_numeric = split("/", var.organization_id)[1] } diff --git a/modules/organization-se/org-policy-custom-constraints.tf b/modules/organization-se/org-policy-custom-constraints.tf index 4508acb50..eebb8cd2f 100644 --- a/modules/organization-se/org-policy-custom-constraints.tf +++ b/modules/organization-se/org-policy-custom-constraints.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _custom_constraints_factory_data_raw = merge([ for f in try(fileset(var.factories_config.org_policy_custom_constraints, "*.yaml"), []) : diff --git a/modules/organization-se/organization-policies.tf b/modules/organization-se/organization-policies.tf index 732d052c0..cdbc2a2fd 100644 --- a/modules/organization-se/organization-policies.tf +++ b/modules/organization-se/organization-policies.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Organization-level organization policies. locals { diff --git a/modules/organization-se/outputs.tf b/modules/organization-se/outputs.tf index 51905624f..b0910315e 100644 --- a/modules/organization-se/outputs.tf +++ b/modules/organization-se/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "custom_constraint_ids" { description = "Map of CUSTOM_CONSTRAINTS => ID in the organization." value = { for k, v in google_org_policy_custom_constraint.constraint : k => v.id } diff --git a/modules/organization-se/variables-iam.tf b/modules/organization-se/variables-iam.tf index 95929afb8..aa663c907 100644 --- a/modules/organization-se/variables-iam.tf +++ b/modules/organization-se/variables-iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "iam" { description = "IAM bindings, in {ROLE => [MEMBERS]} format." type = map(list(string)) diff --git a/modules/organization-se/variables-logging.tf b/modules/organization-se/variables-logging.tf index f30fb2080..745738afc 100644 --- a/modules/organization-se/variables-logging.tf +++ b/modules/organization-se/variables-logging.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "logging_data_access" { description = "Control activation of data access logs. The special 'allServices' key denotes configuration for all services." type = map(object({ diff --git a/modules/organization-se/variables.tf b/modules/organization-se/variables.tf index 0ef099644..4d676ce5a 100644 --- a/modules/organization-se/variables.tf +++ b/modules/organization-se/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "contacts" { description = "List of essential contacts for this resource. Must be in the form EMAIL -> [NOTIFICATION_TYPES]. Valid notification types are ALL, SUSPENSION, SECURITY, TECHNICAL, BILLING, LEGAL, PRODUCT_UPDATES." type = map(list(string)) diff --git a/modules/organization-se/versions.tf b/modules/organization-se/versions.tf index f5645b5da..c034a4da7 100644 --- a/modules/organization-se/versions.tf +++ b/modules/organization-se/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/organization/README.md b/modules/organization/README.md index 525ae912a..b075d6143 100644 --- a/modules/organization/README.md +++ b/modules/organization/README.md @@ -1,3 +1,19 @@ + + # Organization Module This module allows managing several organization properties: diff --git a/modules/organization/iam.tf b/modules/organization/iam.tf index 607a54f0a..bb0cf6137 100644 --- a/modules/organization/iam.tf +++ b/modules/organization/iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description IAM bindings. locals { diff --git a/modules/organization/logging.tf b/modules/organization/logging.tf index 9e0874c05..ac8b5cde8 100644 --- a/modules/organization/logging.tf +++ b/modules/organization/logging.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Log sinks and data access logs. locals { diff --git a/modules/organization/main.tf b/modules/organization/main.tf index 45668ceec..aa7148342 100644 --- a/modules/organization/main.tf +++ b/modules/organization/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { organization_id_numeric = split("/", var.organization_id)[1] } diff --git a/modules/organization/org-policy-custom-constraints.tf b/modules/organization/org-policy-custom-constraints.tf index cae888d1c..8ddfc11b3 100644 --- a/modules/organization/org-policy-custom-constraints.tf +++ b/modules/organization/org-policy-custom-constraints.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _custom_constraints_factory_data_raw = merge([ for f in try(fileset(var.factories_config.org_policy_custom_constraints, "*.yaml"), []) : diff --git a/modules/organization/organization-policies.tf b/modules/organization/organization-policies.tf index ff65f0df1..dd2ce41bc 100644 --- a/modules/organization/organization-policies.tf +++ b/modules/organization/organization-policies.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Organization-level organization policies. locals { diff --git a/modules/organization/outputs.tf b/modules/organization/outputs.tf index 9422134a7..d17c0a555 100644 --- a/modules/organization/outputs.tf +++ b/modules/organization/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "custom_constraint_ids" { description = "Map of CUSTOM_CONSTRAINTS => ID in the organization." value = { for k, v in google_org_policy_custom_constraint.constraint : k => v.id } diff --git a/modules/organization/tags.tf b/modules/organization/tags.tf index 0321818a5..ae0cd2b4c 100644 --- a/modules/organization/tags.tf +++ b/modules/organization/tags.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _tag_iam = flatten([ for k, v in local.tags : [ diff --git a/modules/organization/variables-iam.tf b/modules/organization/variables-iam.tf index 95929afb8..aa663c907 100644 --- a/modules/organization/variables-iam.tf +++ b/modules/organization/variables-iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "iam" { description = "IAM bindings, in {ROLE => [MEMBERS]} format." type = map(list(string)) diff --git a/modules/organization/variables-logging.tf b/modules/organization/variables-logging.tf index f30fb2080..745738afc 100644 --- a/modules/organization/variables-logging.tf +++ b/modules/organization/variables-logging.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "logging_data_access" { description = "Control activation of data access logs. The special 'allServices' key denotes configuration for all services." type = map(object({ diff --git a/modules/organization/variables-tags.tf b/modules/organization/variables-tags.tf index 21a0efe6f..542d00c01 100644 --- a/modules/organization/variables-tags.tf +++ b/modules/organization/variables-tags.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "network_tags" { description = "Network tags by key name. If `id` is provided, key creation is skipped. The `iam` attribute behaves like the similarly named one at module level." type = map(object({ diff --git a/modules/organization/variables.tf b/modules/organization/variables.tf index e9b67bb01..5ce8ba33a 100644 --- a/modules/organization/variables.tf +++ b/modules/organization/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "contacts" { description = "List of essential contacts for this resource. Must be in the form EMAIL -> [NOTIFICATION_TYPES]. Valid notification types are ALL, SUSPENSION, SECURITY, TECHNICAL, BILLING, LEGAL, PRODUCT_UPDATES." type = map(list(string)) diff --git a/modules/organization/versions.tf b/modules/organization/versions.tf index f5645b5da..c034a4da7 100644 --- a/modules/organization/versions.tf +++ b/modules/organization/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/private-service-connect/README.md b/modules/private-service-connect/README.md index e6f6d4441..8280c474f 100644 --- a/modules/private-service-connect/README.md +++ b/modules/private-service-connect/README.md @@ -1,3 +1,19 @@ + + # Private Service Connect This module enables the usage of [Private Service Connect](https://cloud.google.com/vpc/docs/private-service-connect) for a specific subnetwork. diff --git a/modules/private-service-connect/dns.tf b/modules/private-service-connect/dns.tf index 5580181ec..e2c7fe106 100644 --- a/modules/private-service-connect/dns.tf +++ b/modules/private-service-connect/dns.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - /****************************************** Private Google APIs DNS Zone & records. *****************************************/ diff --git a/modules/private-service-connect/main.tf b/modules/private-service-connect/main.tf index e5daf633a..c30202101 100644 --- a/modules/private-service-connect/main.tf +++ b/modules/private-service-connect/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { dns_code = var.dns_code != "" ? "${var.dns_code}-" : "" googleapis_url = var.forwarding_rule_target == "vpc-sc" ? "restricted.googleapis.com." : "private.googleapis.com." diff --git a/modules/private-service-connect/metadata.yaml b/modules/private-service-connect/metadata.yaml index 613ae7823..faa4539c8 100644 --- a/modules/private-service-connect/metadata.yaml +++ b/modules/private-service-connect/metadata.yaml @@ -1,10 +1,10 @@ -# Copyright 2024 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + apiVersion: blueprints.cloud.google.com/v1alpha1 kind: BlueprintMetadata metadata: diff --git a/modules/private-service-connect/outputs.tf b/modules/private-service-connect/outputs.tf index 53a892f3b..0a6748e00 100644 --- a/modules/private-service-connect/outputs.tf +++ b/modules/private-service-connect/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "private_service_connect_name" { value = google_compute_global_address.private_service_connect.name description = "Private service connect name" diff --git a/modules/private-service-connect/provider.tf b/modules/private-service-connect/provider.tf index 5e75ee536..e8342dcc0 100644 --- a/modules/private-service-connect/provider.tf +++ b/modules/private-service-connect/provider.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - terraform { required_version = ">= 0.13" required_providers { diff --git a/modules/private-service-connect/variables.tf b/modules/private-service-connect/variables.tf index 5fc7e67fd..f7f34f1ed 100644 --- a/modules/private-service-connect/variables.tf +++ b/modules/private-service-connect/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "project_id" { description = "Project ID for Private Service Connect." type = string diff --git a/modules/project-factory/README.md b/modules/project-factory/README.md index 00f55be66..e1d193191 100644 --- a/modules/project-factory/README.md +++ b/modules/project-factory/README.md @@ -1,3 +1,19 @@ + + # Project and Folder Factory This module implements end-to-end creation processes for a folder hierarchy, projects and billing budgets via YAML data configurations. diff --git a/modules/project-factory/automation.tf b/modules/project-factory/automation.tf index 8ddbe2a07..c70d3052f 100644 --- a/modules/project-factory/automation.tf +++ b/modules/project-factory/automation.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Automation projects locals and resources. locals { diff --git a/modules/project-factory/factory-budgets.tf b/modules/project-factory/factory-budgets.tf index 97c138487..7b1ef12cf 100644 --- a/modules/project-factory/factory-budgets.tf +++ b/modules/project-factory/factory-budgets.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Billing budget factory locals. locals { diff --git a/modules/project-factory/factory-folders.tf b/modules/project-factory/factory-folders.tf index bc9fb812a..9e398c898 100644 --- a/modules/project-factory/factory-folders.tf +++ b/modules/project-factory/factory-folders.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Folder hierarchy factory locals. locals { diff --git a/modules/project-factory/factory-projects.tf b/modules/project-factory/factory-projects.tf index dca889ca6..a6880c493 100644 --- a/modules/project-factory/factory-projects.tf +++ b/modules/project-factory/factory-projects.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Projects factory locals. locals { diff --git a/modules/project-factory/folders.tf b/modules/project-factory/folders.tf index a3e8b4aff..24a4809ee 100644 --- a/modules/project-factory/folders.tf +++ b/modules/project-factory/folders.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Folder hierarchy factory resources. locals { diff --git a/modules/project-factory/main.tf b/modules/project-factory/main.tf index 6787c0cf0..72b7b7224 100644 --- a/modules/project-factory/main.tf +++ b/modules/project-factory/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Projects and billing budgets factory resources. locals { diff --git a/modules/project-factory/outputs.tf b/modules/project-factory/outputs.tf index f33c0eac7..e0d8e6ee7 100644 --- a/modules/project-factory/outputs.tf +++ b/modules/project-factory/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "buckets" { description = "Bucket names." value = { diff --git a/modules/project-factory/variables.tf b/modules/project-factory/variables.tf index b5bb14812..8d9634cba 100644 --- a/modules/project-factory/variables.tf +++ b/modules/project-factory/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "data_defaults" { description = "Optional default values used when corresponding project data from files are missing." type = object({ diff --git a/modules/project/README.md b/modules/project/README.md index 0380ac2ea..43eed4486 100644 --- a/modules/project/README.md +++ b/modules/project/README.md @@ -1,3 +1,19 @@ + + # Project Module This module implements the creation and management of one GCP project including IAM, organization policies, Shared VPC host or service attachment, service API activation, and tag attachment. It also offers a convenient way to refer to managed service identities (aka robot service accounts) for APIs. diff --git a/modules/project/alerts.tf b/modules/project/alerts.tf index 625cb189e..50454586a 100644 --- a/modules/project/alerts.tf +++ b/modules/project/alerts.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _alerts_factory_data_raw = merge([ for k in local.observability_factory_data_raw : diff --git a/modules/project/cmek.tf b/modules/project/cmek.tf index 8bd44a56f..7b2c103c7 100644 --- a/modules/project/cmek.tf +++ b/modules/project/cmek.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Service Agent IAM Bindings for CMEK locals { diff --git a/modules/project/iam.tf b/modules/project/iam.tf index 481edf023..01b157a9a 100644 --- a/modules/project/iam.tf +++ b/modules/project/iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description IAM bindings. # IAM notes: diff --git a/modules/project/logging-metrics.tf b/modules/project/logging-metrics.tf index f46558690..777df958b 100644 --- a/modules/project/logging-metrics.tf +++ b/modules/project/logging-metrics.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _logging_metrics_factory_data_raw = merge([ for k in local.observability_factory_data_raw : diff --git a/modules/project/logging.tf b/modules/project/logging.tf index 6e4303ac9..50905013b 100644 --- a/modules/project/logging.tf +++ b/modules/project/logging.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Log sinks and supporting resources. locals { diff --git a/modules/project/main.tf b/modules/project/main.tf index 9b40ec3d3..5229d9072 100644 --- a/modules/project/main.tf +++ b/modules/project/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { # descriptive_name cannot contain colons, so we omit the universe from the default descriptive_name = ( diff --git a/modules/project/notification-channels.tf b/modules/project/notification-channels.tf index 45d1678c6..e0fc199f3 100644 --- a/modules/project/notification-channels.tf +++ b/modules/project/notification-channels.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _channels_factory_data_raw = merge([ for k in local.observability_factory_data_raw : diff --git a/modules/project/organization-policies.tf b/modules/project/organization-policies.tf index 5861d019c..508b01245 100644 --- a/modules/project/organization-policies.tf +++ b/modules/project/organization-policies.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Project-level organization policies. locals { diff --git a/modules/project/outputs.tf b/modules/project/outputs.tf index ab8cb7304..1144b5400 100644 --- a/modules/project/outputs.tf +++ b/modules/project/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "alert_ids" { description = "Monitoring alert IDs." value = { diff --git a/modules/project/quotas.tf b/modules/project/quotas.tf index 22d7e9d5b..77617d274 100644 --- a/modules/project/quotas.tf +++ b/modules/project/quotas.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _quota_factory_data_raw = merge([ for f in try(fileset(var.factories_config.quotas, "*.yaml"), []) : diff --git a/modules/project/service-agents.tf b/modules/project/service-agents.tf index a1371b955..4e9bf14cb 100644 --- a/modules/project/service-agents.tf +++ b/modules/project/service-agents.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Service agents supporting resources. locals { diff --git a/modules/project/service-agents.yaml b/modules/project/service-agents.yaml index f024a58f5..8f7efc699 100644 --- a/modules/project/service-agents.yaml +++ b/modules/project/service-agents.yaml @@ -1,10 +1,10 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# https://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + - name: aiplatform-cc display_name: AI Platform Custom Code Service Agent api: aiplatform.googleapis.com diff --git a/modules/project/shared-vpc.tf b/modules/project/shared-vpc.tf index 685f9db80..9a6b6205d 100644 --- a/modules/project/shared-vpc.tf +++ b/modules/project/shared-vpc.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Shared VPC project-level configuration. locals { diff --git a/modules/project/sharedvpc-agent-iam.yaml b/modules/project/sharedvpc-agent-iam.yaml index 096c6ff85..30969fa28 100644 --- a/modules/project/sharedvpc-agent-iam.yaml +++ b/modules/project/sharedvpc-agent-iam.yaml @@ -1,10 +1,10 @@ -# Copyright 2024 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + # Cloud Composer # https://cloud.google.com/composer/docs/how-to/managing/configuring-shared-vpc#edit_permissions_for_the_composer_agent_service_account - service: composer.googleapis.com diff --git a/modules/project/tags.tf b/modules/project/tags.tf index 1f9ff378b..b4f38de7f 100644 --- a/modules/project/tags.tf +++ b/modules/project/tags.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _tag_iam = flatten([ for k, v in local.tags : [ diff --git a/modules/project/variables-iam.tf b/modules/project/variables-iam.tf index 21e107624..57462dbf3 100644 --- a/modules/project/variables-iam.tf +++ b/modules/project/variables-iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "iam" { description = "Authoritative IAM bindings in {ROLE => [MEMBERS]} format." type = map(list(string)) diff --git a/modules/project/variables-observability.tf b/modules/project/variables-observability.tf index 5eebaf6f0..294e100b7 100644 --- a/modules/project/variables-observability.tf +++ b/modules/project/variables-observability.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "alerts" { description = "Monitoring alerts." type = map(object({ diff --git a/modules/project/variables-quotas.tf b/modules/project/variables-quotas.tf index d2a7b65ff..71a5aedeb 100644 --- a/modules/project/variables-quotas.tf +++ b/modules/project/variables-quotas.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "quotas" { description = "Service quota configuration." type = map(object({ diff --git a/modules/project/variables-tags.tf b/modules/project/variables-tags.tf index ac73f03fd..25cba7c29 100644 --- a/modules/project/variables-tags.tf +++ b/modules/project/variables-tags.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "network_tags" { description = "Network tags by key name. If `id` is provided, key creation is skipped. The `iam` attribute behaves like the similarly named one at module level." type = map(object({ diff --git a/modules/project/variables.tf b/modules/project/variables.tf index d2b1b0ddb..0ee499e15 100644 --- a/modules/project/variables.tf +++ b/modules/project/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "auto_create_network" { description = "Whether to create the default network for the project." type = bool diff --git a/modules/project/versions.tf b/modules/project/versions.tf index b85bbf300..09f6e87ed 100644 --- a/modules/project/versions.tf +++ b/modules/project/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/project/vpc-sc.tf b/modules/project/vpc-sc.tf index cef1d73bc..a2c4dfc25 100644 --- a/modules/project/vpc-sc.tf +++ b/modules/project/vpc-sc.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description VPC-SC project-level perimeter configuration. locals { diff --git a/modules/projects-data-source/README.md b/modules/projects-data-source/README.md index c5a19d76c..2de75a982 100644 --- a/modules/projects-data-source/README.md +++ b/modules/projects-data-source/README.md @@ -1,3 +1,19 @@ + + # Projects Data Source Module This module extends functionality of [google_projects](https://registry.terraform.io/providers/hashicorp/google/latest/docs/data-sources/projects) data source by retrieving all the projects under a specific `parent` recursively with only one API call against [Cloud Asset Inventory](https://cloud.google.com/asset-inventory) service. diff --git a/modules/projects-data-source/main.tf b/modules/projects-data-source/main.tf index 6bd5631cc..c8ab64e96 100644 --- a/modules/projects-data-source/main.tf +++ b/modules/projects-data-source/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _ignore_folder_numbers = [for folder_id in var.ignore_folders : trimprefix(folder_id, "folders/")] _ignore_folders_query = join(" AND NOT folders:", concat([""], local._ignore_folder_numbers)) diff --git a/modules/projects-data-source/outputs.tf b/modules/projects-data-source/outputs.tf index b1710fa20..54994d5ec 100644 --- a/modules/projects-data-source/outputs.tf +++ b/modules/projects-data-source/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "project_numbers" { description = "List of project numbers." value = [for item in local.projects_after_ignore : trimprefix(item.project, "projects/")] diff --git a/modules/projects-data-source/variables.tf b/modules/projects-data-source/variables.tf index 888cab21a..3f10d5c9a 100644 --- a/modules/projects-data-source/variables.tf +++ b/modules/projects-data-source/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "ignore_folders" { description = "A list of folder IDs or numbers to be excluded from the output, all the subfolders and projects are excluded from the output regardless of the include_projects variable." type = list(string) diff --git a/modules/projects-data-source/versions.tf b/modules/projects-data-source/versions.tf index 3e3b39094..dbfd5ff6c 100644 --- a/modules/projects-data-source/versions.tf +++ b/modules/projects-data-source/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/pubsub/README.md b/modules/pubsub/README.md index 958044906..3ca1e829a 100644 --- a/modules/pubsub/README.md +++ b/modules/pubsub/README.md @@ -1,3 +1,19 @@ + + # Google Cloud Pub/Sub Module This module allows managing a single Pub/Sub topic, including multiple subscriptions and IAM bindings at the topic and subscriptions levels, as well as schemas. diff --git a/modules/pubsub/iam.tf b/modules/pubsub/iam.tf index 4e39b43a1..9edb240b4 100644 --- a/modules/pubsub/iam.tf +++ b/modules/pubsub/iam.tf @@ -1,8 +1,8 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the authoritative. + * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { subscription_iam = flatten([ for k, v in var.subscriptions : [ diff --git a/modules/pubsub/main.tf b/modules/pubsub/main.tf index bf05e8140..b09bf7ea4 100644 --- a/modules/pubsub/main.tf +++ b/modules/pubsub/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { topic_id_static = "projects/${var.project_id}/topics/${var.name}" } diff --git a/modules/pubsub/outputs.tf b/modules/pubsub/outputs.tf index 06a907a79..804c3a727 100644 --- a/modules/pubsub/outputs.tf +++ b/modules/pubsub/outputs.tf @@ -1,11 +1,11 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "name" { description = "The name of the created Pub/Sub topic." value = google_pubsub_topic.default.name diff --git a/modules/pubsub/variables.tf b/modules/pubsub/variables.tf index f2a94fc12..de844fdbc 100644 --- a/modules/pubsub/variables.tf +++ b/modules/pubsub/variables.tf @@ -1,11 +1,11 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "iam" { description = "Topic-level IAM bindings (non-authoritative) in {ROLE => [MEMBERS]} format." type = map(list(string)) diff --git a/modules/pubsub/versions.tf b/modules/pubsub/versions.tf index b8fdf8114..134fbbb25 100644 --- a/modules/pubsub/versions.tf +++ b/modules/pubsub/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/secret-manager/README.md b/modules/secret-manager/README.md index 59806f3d4..91a6bcf32 100644 --- a/modules/secret-manager/README.md +++ b/modules/secret-manager/README.md @@ -1,3 +1,19 @@ + + # Google Secret Manager Module Simple Secret Manager module that allows managing one or more secrets, their versions, and IAM bindings. diff --git a/modules/secret-manager/main.tf b/modules/secret-manager/main.tf index cdf963595..f2db25bc9 100644 --- a/modules/secret-manager/main.tf +++ b/modules/secret-manager/main.tf @@ -1,11 +1,11 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { # distinct is needed to make the expanding function argument work iam = flatten([ diff --git a/modules/secret-manager/outputs.tf b/modules/secret-manager/outputs.tf index 89215567b..4e75f7d96 100644 --- a/modules/secret-manager/outputs.tf +++ b/modules/secret-manager/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "ids" { description = "Fully qualified secret ids." value = { diff --git a/modules/secret-manager/variables.tf b/modules/secret-manager/variables.tf index 7d118c1f0..854a6302a 100644 --- a/modules/secret-manager/variables.tf +++ b/modules/secret-manager/variables.tf @@ -1,11 +1,11 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "iam" { description = "IAM bindings in {SECRET => {ROLE => [MEMBERS]}} format." type = map(map(list(string))) diff --git a/modules/secret-manager/versions.tf b/modules/secret-manager/versions.tf index fd8a048ed..40ff60f08 100644 --- a/modules/secret-manager/versions.tf +++ b/modules/secret-manager/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/secure-source-manager-instance/README.md b/modules/secure-source-manager-instance/README.md index 9e9985167..099153c7a 100644 --- a/modules/secure-source-manager-instance/README.md +++ b/modules/secure-source-manager-instance/README.md @@ -1,3 +1,19 @@ + + # Secure Source Manager This module allows to create a Secure Source Manager instance and repositories in it. Additionally it allows creating instance IAM bindings and repository IAM bindings. diff --git a/modules/secure-source-manager-instance/iam.tf b/modules/secure-source-manager-instance/iam.tf index 15144931c..08de7c977 100644 --- a/modules/secure-source-manager-instance/iam.tf +++ b/modules/secure-source-manager-instance/iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { repository_iam = merge([for k1, v1 in var.repositories : { for k2, v2 in v1.iam : "${k1}.${k2}" => { diff --git a/modules/secure-source-manager-instance/main.tf b/modules/secure-source-manager-instance/main.tf index f22f6a4be..e0d40decf 100644 --- a/modules/secure-source-manager-instance/main.tf +++ b/modules/secure-source-manager-instance/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_secure_source_manager_instance" "instance" { count = var.instance_create ? 1 : 0 instance_id = var.instance_id diff --git a/modules/secure-source-manager-instance/outputs.tf b/modules/secure-source-manager-instance/outputs.tf index 9ea6f5acb..cce6d278c 100644 --- a/modules/secure-source-manager-instance/outputs.tf +++ b/modules/secure-source-manager-instance/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "instance" { description = "Instance." value = try(google_secure_source_manager_instance.instance[0], null) diff --git a/modules/secure-source-manager-instance/variables-iam.tf b/modules/secure-source-manager-instance/variables-iam.tf index 253c797fe..86d91a7d6 100644 --- a/modules/secure-source-manager-instance/variables-iam.tf +++ b/modules/secure-source-manager-instance/variables-iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "iam" { description = "IAM bindings." type = map(list(string)) diff --git a/modules/secure-source-manager-instance/variables.tf b/modules/secure-source-manager-instance/variables.tf index 4f06dd965..15dc489a5 100644 --- a/modules/secure-source-manager-instance/variables.tf +++ b/modules/secure-source-manager-instance/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "ca_pool" { description = "CA pool." type = string diff --git a/modules/secure-source-manager-instance/versions.tf b/modules/secure-source-manager-instance/versions.tf index 8912f2dfc..bd581f939 100644 --- a/modules/secure-source-manager-instance/versions.tf +++ b/modules/secure-source-manager-instance/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/service-directory/README.md b/modules/service-directory/README.md index c89fe1435..2a50a673c 100644 --- a/modules/service-directory/README.md +++ b/modules/service-directory/README.md @@ -1,3 +1,19 @@ + + # Google Cloud Service Directory Module This module allows managing a single [Service Directory](https://cloud.google.com/service-directory) namespace, including multiple services, endpoints and IAM bindings at the namespace and service levels. diff --git a/modules/service-directory/main.tf b/modules/service-directory/main.tf index 25017a286..09aa7eea6 100644 --- a/modules/service-directory/main.tf +++ b/modules/service-directory/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { endpoint_list = flatten([ for name, attrs in var.services : [ diff --git a/modules/service-directory/outputs.tf b/modules/service-directory/outputs.tf index 964a2136a..a564c8ef4 100644 --- a/modules/service-directory/outputs.tf +++ b/modules/service-directory/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "endpoints" { description = "Endpoint resources." value = google_service_directory_endpoint.default diff --git a/modules/service-directory/variables.tf b/modules/service-directory/variables.tf index 8212081e1..fd818c06d 100644 --- a/modules/service-directory/variables.tf +++ b/modules/service-directory/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # we need a separate variable as address will be dynamic in most cases variable "endpoint_config" { description = "Map of endpoint attributes, keys are in service/endpoint format." diff --git a/modules/service-directory/versions.tf b/modules/service-directory/versions.tf index 6cbbc0ff0..96c0a514d 100644 --- a/modules/service-directory/versions.tf +++ b/modules/service-directory/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/source-repository/README.md b/modules/source-repository/README.md index 31c384da2..ff23ddcbc 100644 --- a/modules/source-repository/README.md +++ b/modules/source-repository/README.md @@ -1,3 +1,19 @@ + + # Google Cloud Source Repository Module This module allows managing a single Cloud Source Repository, including IAM bindings and basic Cloud Build triggers. diff --git a/modules/source-repository/iam.tf b/modules/source-repository/iam.tf index 43de49231..7d1e3d524 100644 --- a/modules/source-repository/iam.tf +++ b/modules/source-repository/iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description IAM bindings. locals { diff --git a/modules/source-repository/main.tf b/modules/source-repository/main.tf index d74b7e6c8..a7ae787bb 100644 --- a/modules/source-repository/main.tf +++ b/modules/source-repository/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - resource "google_sourcerepo_repository" "default" { project = var.project_id name = var.name diff --git a/modules/source-repository/outputs.tf b/modules/source-repository/outputs.tf index 3b06d30cd..cb1473181 100644 --- a/modules/source-repository/outputs.tf +++ b/modules/source-repository/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "id" { description = "Fully qualified repository id." value = google_sourcerepo_repository.default.id diff --git a/modules/source-repository/variables-iam.tf b/modules/source-repository/variables-iam.tf index 4299d4554..ab682e5d1 100644 --- a/modules/source-repository/variables-iam.tf +++ b/modules/source-repository/variables-iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "iam" { description = "IAM bindings in {ROLE => [MEMBERS]} format." type = map(list(string)) diff --git a/modules/source-repository/variables.tf b/modules/source-repository/variables.tf index a467f9fe0..165ca6e17 100644 --- a/modules/source-repository/variables.tf +++ b/modules/source-repository/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "name" { description = "Repository name." type = string diff --git a/modules/source-repository/versions.tf b/modules/source-repository/versions.tf index e891a77e1..3e4f95a09 100644 --- a/modules/source-repository/versions.tf +++ b/modules/source-repository/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/spanner-instance-se/README.md b/modules/spanner-instance-se/README.md index 64ab01d76..fe96c47e6 100644 --- a/modules/spanner-instance-se/README.md +++ b/modules/spanner-instance-se/README.md @@ -1,3 +1,19 @@ + + # Spanner instance This module allows to create a spanner instance with associated spanner instance config and databases in the instance. Additionally it allows creating instance IAM bindings and database IAM bindings. diff --git a/modules/spanner-instance-se/iam.tf b/modules/spanner-instance-se/iam.tf index 582d2bb14..38c048707 100644 --- a/modules/spanner-instance-se/iam.tf +++ b/modules/spanner-instance-se/iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { spanner_database_iam = merge([for k1, v1 in var.databases : { for k2, v2 in v1.iam : "${k1}.${k2}" => { diff --git a/modules/spanner-instance-se/main.tf b/modules/spanner-instance-se/main.tf index 0f74b8b8e..48c7c3444 100644 --- a/modules/spanner-instance-se/main.tf +++ b/modules/spanner-instance-se/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { spanner_instance = ( var.instance_create diff --git a/modules/spanner-instance-se/outputs.tf b/modules/spanner-instance-se/outputs.tf index 7de01704f..dcf52a693 100644 --- a/modules/spanner-instance-se/outputs.tf +++ b/modules/spanner-instance-se/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "spanner_database_ids" { description = "Spanner database ids." value = { for k, v in google_spanner_database.spanner_databases : k => v.id } diff --git a/modules/spanner-instance-se/variables.tf b/modules/spanner-instance-se/variables.tf index d2a80a784..15c3a8110 100644 --- a/modules/spanner-instance-se/variables.tf +++ b/modules/spanner-instance-se/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "databases" { description = "Databases." type = map(object({ diff --git a/modules/spanner-instance-se/versions.tf b/modules/spanner-instance-se/versions.tf index f569ce5af..c019728ee 100644 --- a/modules/spanner-instance-se/versions.tf +++ b/modules/spanner-instance-se/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2024 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v35.0.0 diff --git a/modules/spanner-instance/README.md b/modules/spanner-instance/README.md index ea0f0a147..58b976985 100644 --- a/modules/spanner-instance/README.md +++ b/modules/spanner-instance/README.md @@ -1,3 +1,19 @@ + + # Spanner instance This module allows to create a spanner instance with associated spanner instance config and databases in the instance. Additionally it allows creating instance IAM bindings and database IAM bindings. diff --git a/modules/spanner-instance/iam.tf b/modules/spanner-instance/iam.tf index 582d2bb14..38c048707 100644 --- a/modules/spanner-instance/iam.tf +++ b/modules/spanner-instance/iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { spanner_database_iam = merge([for k1, v1 in var.databases : { for k2, v2 in v1.iam : "${k1}.${k2}" => { diff --git a/modules/spanner-instance/main.tf b/modules/spanner-instance/main.tf index ca9189b0b..1a24e215d 100644 --- a/modules/spanner-instance/main.tf +++ b/modules/spanner-instance/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { spanner_instance = ( var.instance_create diff --git a/modules/spanner-instance/outputs.tf b/modules/spanner-instance/outputs.tf index 7de01704f..dcf52a693 100644 --- a/modules/spanner-instance/outputs.tf +++ b/modules/spanner-instance/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "spanner_database_ids" { description = "Spanner database ids." value = { for k, v in google_spanner_database.spanner_databases : k => v.id } diff --git a/modules/spanner-instance/variables.tf b/modules/spanner-instance/variables.tf index 5fa865e38..af038a1f7 100644 --- a/modules/spanner-instance/variables.tf +++ b/modules/spanner-instance/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "databases" { description = "Databases." type = map(object({ diff --git a/modules/spanner-instance/versions.tf b/modules/spanner-instance/versions.tf index a1030e147..86d52662b 100644 --- a/modules/spanner-instance/versions.tf +++ b/modules/spanner-instance/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/vpc-sc/README.md b/modules/vpc-sc/README.md index 0d0edf39f..16355bac8 100644 --- a/modules/vpc-sc/README.md +++ b/modules/vpc-sc/README.md @@ -1,3 +1,19 @@ + + # VPC Service Controls This module offers a unified interface to manage VPC Service Controls [Access Policy](https://cloud.google.com/access-context-manager/docs/create-access-policy), [Access Levels](https://cloud.google.com/access-context-manager/docs/manage-access-levels), and [Service Perimeters](https://cloud.google.com/vpc-service-controls/docs/service-perimeters). diff --git a/modules/vpc-sc/access-levels.tf b/modules/vpc-sc/access-levels.tf index b173f0f60..58e507125 100644 --- a/modules/vpc-sc/access-levels.tf +++ b/modules/vpc-sc/access-levels.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Access level resources. # this code implements "additive" access levels, if "authoritative" diff --git a/modules/vpc-sc/factory.tf b/modules/vpc-sc/factory.tf index 128a17a40..59dc88f30 100644 --- a/modules/vpc-sc/factory.tf +++ b/modules/vpc-sc/factory.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { _data = { for k, v in local._data_paths : k => { diff --git a/modules/vpc-sc/iam.tf b/modules/vpc-sc/iam.tf index 9b475b68f..73d1fdf7a 100644 --- a/modules/vpc-sc/iam.tf +++ b/modules/vpc-sc/iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description IAM bindings resource "google_access_context_manager_access_policy_iam_binding" "authoritative" { diff --git a/modules/vpc-sc/main.tf b/modules/vpc-sc/main.tf index 89434d05c..7be9265b9 100644 --- a/modules/vpc-sc/main.tf +++ b/modules/vpc-sc/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { access_policy = try( google_access_context_manager_access_policy.default[0].name, diff --git a/modules/vpc-sc/outputs.tf b/modules/vpc-sc/outputs.tf index 280ba4410..eff853e0c 100644 --- a/modules/vpc-sc/outputs.tf +++ b/modules/vpc-sc/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "access_level_names" { description = "Access level resources." value = { diff --git a/modules/vpc-sc/service-perimeters-bridge.tf b/modules/vpc-sc/service-perimeters-bridge.tf index c3ca5cae6..8c18f79b1 100644 --- a/modules/vpc-sc/service-perimeters-bridge.tf +++ b/modules/vpc-sc/service-perimeters-bridge.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Bridge service perimeter resources. # this code implements "additive" service perimeters, if "authoritative" diff --git a/modules/vpc-sc/service-perimeters-regular.tf b/modules/vpc-sc/service-perimeters-regular.tf index d5801042c..97723dd7f 100644 --- a/modules/vpc-sc/service-perimeters-regular.tf +++ b/modules/vpc-sc/service-perimeters-regular.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description Regular service perimeter resources. # this code implements "additive" service perimeters, if "authoritative" diff --git a/modules/vpc-sc/variables.tf b/modules/vpc-sc/variables.tf index c933a7759..a115c03cf 100644 --- a/modules/vpc-sc/variables.tf +++ b/modules/vpc-sc/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2025 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "access_levels" { description = "Access level definitions." type = map(object({ diff --git a/modules/vpc-sc/versions.tf b/modules/vpc-sc/versions.tf index 17920aff8..e0d2c3fd1 100644 --- a/modules/vpc-sc/versions.tf +++ b/modules/vpc-sc/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/modules/workflows/README.md b/modules/workflows/README.md index 18dda612f..2237892f0 100644 --- a/modules/workflows/README.md +++ b/modules/workflows/README.md @@ -1,3 +1,19 @@ + + # Workflows Module Simple module for creating a workflow encryped by a CMEK. diff --git a/modules/workflows/iam.tf b/modules/workflows/iam.tf index fd891e0cc..46e002edf 100644 --- a/modules/workflows/iam.tf +++ b/modules/workflows/iam.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ resource "google_project_iam_binding" "bindings" { for_each = var.iam diff --git a/modules/workflows/main.tf b/modules/workflows/main.tf index eb48a37b2..4752dbb03 100644 --- a/modules/workflows/main.tf +++ b/modules/workflows/main.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ resource "google_workflows_workflow" "workflow" { depends_on = [ diff --git a/modules/workflows/outputs.tf b/modules/workflows/outputs.tf index 81c096917..cf9a63577 100644 --- a/modules/workflows/outputs.tf +++ b/modules/workflows/outputs.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ output "service_account" { description = "The workflow service account." diff --git a/modules/workflows/variables.tf b/modules/workflows/variables.tf index 34a9dc1d1..77505bddf 100644 --- a/modules/workflows/variables.tf +++ b/modules/workflows/variables.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ variable "deletion_protection" { description = "Deletion proteciton." diff --git a/modules/workstation-cluster/README.md b/modules/workstation-cluster/README.md index e6f690905..7f32dd1e8 100644 --- a/modules/workstation-cluster/README.md +++ b/modules/workstation-cluster/README.md @@ -1,3 +1,19 @@ + + # Workstation cluster This module allows to create a workstation cluster with associated workstation configs and workstations. In addition to this it allows to set up IAM bindings for the workstation configs and the workstations. diff --git a/modules/workstation-cluster/iam.tf b/modules/workstation-cluster/iam.tf index 491c5f212..937aab186 100644 --- a/modules/workstation-cluster/iam.tf +++ b/modules/workstation-cluster/iam.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - # tfdoc:file:description IAM bindings locals { diff --git a/modules/workstation-cluster/main.tf b/modules/workstation-cluster/main.tf index 39da0d1e1..6e26ebacf 100644 --- a/modules/workstation-cluster/main.tf +++ b/modules/workstation-cluster/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - locals { workstations = merge(flatten([for k1, v1 in var.workstation_configs : { for k2, v2 in v1.workstations : diff --git a/modules/workstation-cluster/outputs.tf b/modules/workstation-cluster/outputs.tf index 788d11466..781dfdb92 100644 --- a/modules/workstation-cluster/outputs.tf +++ b/modules/workstation-cluster/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - output "cluster_hostname" { description = "Cluster hostname." value = var.private_cluster_config != null ? google_workstations_workstation_cluster.cluster.private_cluster_config[0].cluster_hostname : null diff --git a/modules/workstation-cluster/variables.tf b/modules/workstation-cluster/variables.tf index 71e0bc303..c277ea654 100644 --- a/modules/workstation-cluster/variables.tf +++ b/modules/workstation-cluster/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - variable "annotations" { description = "Workstation cluster annotations." type = map(string) diff --git a/modules/workstation-cluster/versions.tf b/modules/workstation-cluster/versions.tf index 69d8b9b2f..e942341f3 100644 --- a/modules/workstation-cluster/versions.tf +++ b/modules/workstation-cluster/versions.tf @@ -1,16 +1,18 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # Fabric release: v38.0.0 diff --git a/project-config.yml b/project-config.yml new file mode 100644 index 000000000..98fbec3fb --- /dev/null +++ b/project-config.yml @@ -0,0 +1,42 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +projects: + # Stage 0 + - name: centralized-logging-project + project_name: "lz-audit-" + # Stage 1 + - name: automation-project + project_name: "--iac" + - name: billing-export-project + project_name: "--billing" + - name: log-export-project + project_name: "--logging" + # Stage 3 + - name: dev-net-host + project_name: "--dev-net" + - name: test-net-host + project_name: "--test-net" + - name: prod-net-host + project_name: "--prod-net" + - name: vdss-host-project + project_name: "--vdss-host" + # Stage 4 + - name: dev-sec-project + project_name: "--d-sec" + - name: prod-sec-project + project_name: "--p-sec" + # Stage 5 + - name: tenant-projects + project_name: "-" diff --git a/releases.md b/releases.md index 71e2eec8f..7dacce70d 100644 --- a/releases.md +++ b/releases.md @@ -1,3 +1,19 @@ + + # Release Strategy and Documentation This document outlines the versioning scheme, release classification, and release automation process for the `stellar-engine` repository. diff --git a/scripts/README.md b/scripts/README.md index 60566be17..d24f669ea 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -1,3 +1,19 @@ + + # Stellar Engine Experimental Tools This directory contains a suite of powerful automation scripts designed to streamline the deployment, management, and destruction of Stellar Engine environments. These tools are built to be robust, resumable, and transparent. diff --git a/scripts/allow_bq.sh b/scripts/allow_bq.sh index fc7a39fd8..1e6bfea0f 100755 --- a/scripts/allow_bq.sh +++ b/scripts/allow_bq.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,6 +14,7 @@ # limitations under the License. + #### Use this script at your own risk. The author assumes no responsibility for any damages or losses incurred through its use. SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) diff --git a/scripts/clean.sh b/scripts/clean.sh index 099c0316f..8e92acb3e 100755 --- a/scripts/clean.sh +++ b/scripts/clean.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,6 +14,7 @@ # limitations under the License. + #### This script is an experamental state, and is designed to help clean environemnts #### Use this script at your own risk. The author assumes no responsibility for any damages or losses incurred through its use. diff --git a/scripts/common-functions.sh b/scripts/common-functions.sh index 9121caf43..7c6bfba98 100644 --- a/scripts/common-functions.sh +++ b/scripts/common-functions.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + # Common functions for Stellar Engine deployment scripts # Source this file in other scripts to use these functions diff --git a/scripts/config.env.sample b/scripts/config.env.sample index ffe218e2d..b839963e1 100644 --- a/scripts/config.env.sample +++ b/scripts/config.env.sample @@ -1,3 +1,17 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + BILLING_ACCOUNT=012345-67890-12345 BOOTSTRAP_PROJECT_ID=bootstrap-project COMPLIANCE_REGIME=FEDRAMP_HIGH diff --git a/scripts/deploy.sh b/scripts/deploy.sh index 058c04172..aa08ff4f0 100755 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -1,4 +1,17 @@ #!/bin/bash +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. #### Use this script at your own risk. The author assumes no responsibility for any damages or losses incurred through its use. diff --git a/scripts/destroy.sh b/scripts/destroy.sh index 4c6cf6ecf..8a6658731 100755 --- a/scripts/destroy.sh +++ b/scripts/destroy.sh @@ -1,4 +1,17 @@ #!/bin/bash +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. #### Use this script at your own risk. The author assumes no responsibility for any damages or losses incurred through its use. diff --git a/scripts/restore.sh b/scripts/restore.sh index b5a9bfb7f..3752c9fb7 100644 --- a/scripts/restore.sh +++ b/scripts/restore.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,6 +14,7 @@ # limitations under the License. + #### This script is an experemental state, and is designed to help restore environment where the prefix has not been changed #### It is currently best used via copy-and-paste of commands as needed (after sourcing config.env) #### You may still need to change the name of custom org policies in the yaml files for a succesful deployment diff --git a/tenants/sample-tenant.yml b/tenants/sample-tenant.yml new file mode 100644 index 000000000..69dc36240 --- /dev/null +++ b/tenants/sample-tenant.yml @@ -0,0 +1,27 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +name: "sample-tenant" +environment: "dev" +admin_principal: "group:gcp-devops@example.com" +locations: + gcs: "us-east4" + kms: "us-east4" +size: "M" +tenant_specific_envs: "dev" +spoke_subnets: + dev: "10.88.12.0/22" + test: "10.92.12.0/22" + prod: "10.96.12.0/22" +deploy_network_project: true diff --git a/tools/__init__.py b/tools/__init__.py index 5678014ca..9f71a2dc3 100644 --- a/tools/__init__.py +++ b/tools/__init__.py @@ -1,13 +1,14 @@ -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# https://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + diff --git a/tools/changelog.py b/tools/changelog.py index cbf1f2abf..503210abb 100755 --- a/tools/changelog.py +++ b/tools/changelog.py @@ -1,11 +1,11 @@ #!/usr/bin/env python3 -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + import click import collections diff --git a/tools/check_boilerplate.py b/tools/check_boilerplate.py index a0f3ad873..30abf205f 100755 --- a/tools/check_boilerplate.py +++ b/tools/check_boilerplate.py @@ -1,18 +1,19 @@ #!/usr/bin/env python3 -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# https://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + '''Check that boilerplate is present in relevant files. This tools offers a simple way of ensuring that the required boilerplate header diff --git a/tools/check_documentation.py b/tools/check_documentation.py index fab527da3..c38f01348 100755 --- a/tools/check_documentation.py +++ b/tools/check_documentation.py @@ -1,18 +1,19 @@ #!/usr/bin/env python3 -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# https://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + '''Recursively check freshness of tfdoc's generated tables in README files. This tool recursively checks that the embedded variables and outputs tables in diff --git a/tools/check_links.py b/tools/check_links.py index 202bc6401..e00ee2699 100755 --- a/tools/check_links.py +++ b/tools/check_links.py @@ -1,18 +1,19 @@ #!/usr/bin/env python3 -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# https://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + '''Recursively check link destination validity in Markdown files. This tool recursively checks that local links in Markdown files point to valid diff --git a/tools/check_names.py b/tools/check_names.py index eb9b395df..ad858dbcc 100755 --- a/tools/check_names.py +++ b/tools/check_names.py @@ -1,17 +1,18 @@ #!/usr/bin/env python3 -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + 'Parse names from specific Terraform resources and optionally check length.' import collections diff --git a/tools/create_e2e_sandbox.sh b/tools/create_e2e_sandbox.sh index 206a274a7..0403ea314 100755 --- a/tools/create_e2e_sandbox.sh +++ b/tools/create_e2e_sandbox.sh @@ -1,11 +1,11 @@ #!/bin/bash -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + # # create_e2e_sandbox.sh # diff --git a/tools/lint.sh b/tools/lint.sh index 2b1438341..3f664bb55 100755 --- a/tools/lint.sh +++ b/tools/lint.sh @@ -1,12 +1,12 @@ #!/bin/bash -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + # Currently unused # DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) diff --git a/tools/lockfile/default-versions_override.tf b/tools/lockfile/default-versions_override.tf index 0cf335251..e9f73730c 100644 --- a/tools/lockfile/default-versions_override.tf +++ b/tools/lockfile/default-versions_override.tf @@ -1,16 +1,18 @@ -# Copyright 2023 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ # This file specifies the required version of the github provider used # during testing. This has to be in an override file, otherwise the diff --git a/tools/lockfile/main.tf b/tools/lockfile/main.tf index 7614f5bcd..e723acbc3 100644 --- a/tools/lockfile/main.tf +++ b/tools/lockfile/main.tf @@ -1,16 +1,18 @@ -# Copyright 2023 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ data "archive_file" "bundle" {} resource "azuread_user" "default" {} diff --git a/tools/plan_summary.py b/tools/plan_summary.py index 441c638c6..257977196 100755 --- a/tools/plan_summary.py +++ b/tools/plan_summary.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# https://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + import click import sys import tempfile diff --git a/tools/state_iam.py b/tools/state_iam.py index 5d07b1bac..9132f0dd5 100755 --- a/tools/state_iam.py +++ b/tools/state_iam.py @@ -1,17 +1,18 @@ #!/usr/bin/env python3 -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + 'Parse and output IAM bindings from Terraform state file.' import collections diff --git a/tools/tfdoc.py b/tools/tfdoc.py index c3928a236..87dd27dd4 100755 --- a/tools/tfdoc.py +++ b/tools/tfdoc.py @@ -1,18 +1,19 @@ #!/usr/bin/env python3 -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# https://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + '''Generate tables for Terraform root module files, outputs and variables. This tool generates nicely formatted Markdown tables from Terraform source diff --git a/tools/validate_metadata.py b/tools/validate_metadata.py index 2e5f55cc3..a38bc61fb 100755 --- a/tools/validate_metadata.py +++ b/tools/validate_metadata.py @@ -1,18 +1,19 @@ #!/usr/bin/env python3 -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# https://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + '''Validate a YAML file against the standard blueprint metadata schema[1] [1] https://github.com/GoogleCloudPlatform/cloud-foundation-toolkit/blob/master/cli/bpmetadata/schema/bpmetadataschema.json diff --git a/tools/validate_schema.py b/tools/validate_schema.py index 461b448db..2afc5268b 100755 --- a/tools/validate_schema.py +++ b/tools/validate_schema.py @@ -1,18 +1,19 @@ #!/usr/bin/env python3 -# Copyright 2023 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# https://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + '''Validate YaML document against yamale schemas. Fast includes YaML driven resource factories, along with their schemas which are available at `fast/assets/schemas`. diff --git a/tools/vars_sort.awk b/tools/vars_sort.awk index fd106d6e6..36bbb4947 100755 --- a/tools/vars_sort.awk +++ b/tools/vars_sort.awk @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC +# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + # Modified from https://gist.github.com/yermulnik/7e0cf991962680d406692e1db1b551e6 for use on MacOS to sort variables # https://gist.github.com/yermulnik/7e0cf991962680d406692e1db1b551e6