diff --git a/blueprints/third-party-solutions/README.md b/blueprints/third-party-solutions/README.md index 13a441b2..94449181 100644 --- a/blueprints/third-party-solutions/README.md +++ b/blueprints/third-party-solutions/README.md @@ -26,4 +26,10 @@ The blueprints in this folder show how to automate installation of specific thir

These examples show how to deploy F5 BigIP-VE load balancers in GCP.

+
+ +### Gitlab + +

This blueprint shows how to deploy a Gitlab instance in GCP. The architecture is based on the reference described in the [official documentation](https://docs.gitlab.com/ee/administration/reference_architectures/1k_users.html) with managed services such as Cloud SQL, Memorystore and Cloud Storage.

+
\ No newline at end of file diff --git a/blueprints/third-party-solutions/gitlab/README.md b/blueprints/third-party-solutions/gitlab/README.md new file mode 100644 index 00000000..f720b8b0 --- /dev/null +++ b/blueprints/third-party-solutions/gitlab/README.md @@ -0,0 +1,389 @@ +# Gitlab Blueprint + +This blueprint is responsible for provisioning a production ready Gitlab 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. + +The following diagram illustrates the high-level design of created resources, which can be adapted to specific requirements via variables: + +

+ Gitlab +

+ +## Table of contents + + +* [Gitlab Blueprint](#gitlab-blueprint) + * [Table of contents](#table-of-contents) + * [Managed Services for Seamless Operations](#managed-services-for-seamless-operations) + * [Object Storage <-> Google Cloud Storage](#object-storage-----google-cloud-storage) + * [Identity](#identity) + * [SAML Integration](#saml-integration) + * [Google Workspace Setup](#google-workspace-setup) + * [Others Identity Integration](#others-identity-integration) + * [Email](#email) + * [Sendgrid integration](#sendgrid-integration) + * [SSL Certificate Configuration](#ssl-certificate-configuration) + * [Networking and scalability](#networking-and-scalability) + * [HA](#ha) + * [Deployment](#deployment) + * [Step 0: Cloning the repository](#step-0--cloning-the-repository) + * [Step 2: Prepare the variables](#step-2--prepare-the-variables) + * [Step 3: Deploy resources](#step-3--deploy-resources) + * [Step 4: Use the created resources](#step-4--use-the-created-resources) + * [Reference and useful links](#reference-and-useful-links) + * [Files](#files) + * [Variables](#variables) + * [Outputs](#outputs) + + +## Managed Services for Seamless Operations + +This Gitlab installation prioritizes the use of Google Cloud managed services to +streamline infrastructure management and optimization. Here's a breakdown of the +managed services incorporated: + +1. [Google Cloud Storage](https://cloud.google.com/storage): is a highly + scalable and secure object storage service for storing and accessing data in + Google Cloud.

+2. [Cloud SQL PostgreSQL](https://cloud.google.com/sql/docs/postgres): Cloud SQL + for Postgres is a fully managed database service on Google Cloud Platform. It + eliminates database administration tasks, allowing you to focus on your + application, while offering high performance, automatic scaling, and secure + management of your PostgreSQL databases.

+3. [Memorystore](https://cloud.google.com/memorystore?hl=en): GCP Memorystore + offers a fully managed Redis service for in-memory data caching and + high-performance data access. + +Benefits: + +- Reduced Operational Overhead: Google handles infrastructure setup, + maintenance, and updates, freeing up your time and resources. +- Enhanced Security: Managed services often benefit from Google's comprehensive + security measures and expertise. +- Scalability: Easily adjust resource allocation to meet evolving demands. +- Cost Optimization: Pay for the resources you use, benefiting from Google's + infrastructure optimization. + Integration: Managed services seamlessly integrate with other GCP services, + promoting a cohesive cloud environment. + This module embraces managed services to deliver a resilient, scalable, and + cost-effective application architecture on Google Cloud. + +### Object Storage <-> Google Cloud Storage + +GitLab supports using an object storage service for holding numerous types of +data. It’s recommended over NFS and in general it’s better in larger setups as +object storage is typically much more performant, reliable, and scalable. + +A single storage connection to Cloud Storage is configured for all object types, +which leverages default Google Compute Engine credential (the so called " +consolidated form"). A Cloud Storage bucket is bootstrapped for each object +type, the table below summarized such a configuration: + +| Object Type | Description | Cloud Storage Bucket | +|------------------|----------------------------------------|-----------------------------------| +| artifacts | CI artifacts | ${prefix}-gitlab-artifacts | +| external_diffs | Merge request diffs | ${prefix}-mr-diffs | +| uploads | User uploads | ${prefix}-gitlab-uploads | +| lfs | Git Large File Storage objects | ${prefix}-gitlab-lfs | +| packages | Project packages (e.g. PyPI, Maven ..) | ${prefix}-gitlab-packages | +| dependency_proxy | Dependency Proxy | ${prefix}-gitlab-dependency-proxy | +| terraform_state | Terraform state files | ${prefix}-gitlab-terraform-state | +| pages | Pages | ${prefix}-gitlab-pages | + +For more information on Gitlab object storage and Google Cloud Storage +integration please refer to the official Gitlab documentation available at the +following [link](https://docs.gitlab.com/ee/administration/object_storage.html). + +- [PostgreSQL service](https://docs.gitlab.com/ee/administration/postgresql/external.html) + +Updated postgres configuration to match documentation, created required database +in postgres instance. + +- [Redis](https://docs.gitlab.com/ee/administration/redis/replication_and_failover_external.html) + +## Identity + +GitLab integrates with a number of OmniAuth providers as well as external +authentication and authorization providers such as Google Secure LDAP and many +other providers. +At this time this stage can deal with SAML integration for both user +authentication and provisioning, in order to setup SAML integration please +provide the saml block on gitlab_config variable. + +### SAML Integration + +This section details how configure GitLab to act as a SAML service provider ( +SP). This allows GitLab to consume assertions from a SAML identity provider ( +IdP), such as Cloud Identity, to authenticate users. Please find instructions +below for integration with: + +- [Google Workspace](#google-workspace-setup) + +#### Google Workspace Setup + +Setup of Google Workspace is documented in the official Gitlab documentation +available at the +following [link](https://docs.gitlab.com/ee/integration/saml.html#set-up-google-workspace) +which are also reported below for simplicity. + +Create a custom SAML webapp following instructions available at the +following [link](https://support.google.com/a/answer/6087519), providing these +information in the service provider configuration: + +| Configuration | Typical Value | Cloud Storage Bucket | +|-------------------|--------------------------------------------------|---------------------------------------------------------------------------------------------| +| Name of SAML App | Gitlab | Name of the app | +| ACS URL | https:///users/auth/saml/callback | Assertion Consumer Service URL. | +| GITLAB_DOMAIN | gitlab.example.com | Your GitLab instance domain. | +| Entity ID | https://gitlab.example.com | A value unique to your SAML application. Set it to the issuer in your GitLab configuration. | +| Name ID | EMAIL | Required value. Also known as name_identifier_format. | + +Then setup the following SAML attribute mappings: + +| Google Directory attributes | App attributes | +|--------------------------------|----------------| +| Basic information > Email | email | +| Basic Information > First name | first_name | +| Basic Information > Last name | last_name | + +After configuring the Google Workspace SAML application, record the following +information: + +| Value | Description | +|------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------| +| SSO URL | Setup in gitlab_config.saml.sso_target_url variable | +| Certificate (download) | Setup in gitlab_config.saml.idp_cert_fingerprint (obtain value with the following command `openssl x509 -in -noout -fingerprint -sha1`) | + +### Others Identity Integration + +- [OpenID Connect OmniAuth](https://docs.gitlab.com/ee/administration/auth/oidc.html#configure-google) +- [Google Secure LDAP](https://docs.gitlab.com/ee/administration/auth/ldap/google_secure_ldap.html) + +## Email + +### Gmail / Workspace + +- [ ] [documentation](https://docs.gitlab.com/ee/administration/incoming_email.html#gmail) + +### Sendgrid integration + +Use +the [Google Cloud Marketplace](https://console.cloud.google.com/marketplace/details/sendgrid-app/sendgrid-email) +to sign up for the SendGrid email service. Make a note of your SendGrid SMTP +account credentials, which include username, password, and hostname. Your SMTP +username and password are the same as what you used to sign up for the service. +The SendGrid hostname is smtp.sendgrid.net. +Create an API key: +Sign in to SendGrid and go to Settings > API Keys. + +1. Create an API key. +2. Select the permissions for the key. At a minimum, the key must have Mail send + permissions to send email. +3. Click Save to create the key. +4. SendGrid generates a new key. This is the only copy of the key, so make sure + that you copy the key and save it for later. + +Configure the sendgrid API key in the gitlab_config variable, under mail, +sendgrid arguments as per the following example: + +```terraform +gitlab_config = { + hostname = "gitlab.example.com" + mail = { + sendgrid = { + api_key = "test" + } + } +} +``` + +## SSL Certificate Configuration + +This module provides flexibility in configuring SSL certificates for the server. +You have two options: + +1. **Provide Your Own Certificates**: If you have existing SSL certificates, you + can place them in the certs folder within the module's directory. The module + will automatically detect and use them. + File Names: Ensure the files are named ${gitlab_hostname}.crt (for the + certificate) and + gitlab_hostname.key (for the private key). Although it is not required in + this stage it is mandatory to also place inside the certs folder the server + CA certificate which is later use to secure HTTPS access from the Gitlab + runner. Name of the CA certificate should be: ${gitlab_hostname}.ca.crt +2. **Use Automatically Generated Self-Signed Certificates**: If you don't + provide certificates, the module will generate a self-signed certificate for + immediate use. + Updating Later: You can replace the self-signed certificate with your own + certificates at any time by placing them in the certs folder and re-running + Terraform. + +**Important Notes:** + +Certificate Validation: Self-signed certificates are not validated by browsers +and will trigger warnings. Use them only for development or testing +environments. + +For more information on how to configure HTTPS on Gitlab please refer to the +original Gitlab documentation available at the +following [link](https://docs.gitlab.com/omnibus/settings/ssl/#configure-https-manually). + +## Networking and scalability + +- [Load balancer](https://docs.gitlab.com/ee/administration/load_balancer.html) + +## HA + +- [High Availability](http://ubimol.it/12.0/ee/administration/high_availability/README.html) + +### Deployment + +#### Step 0: Cloning the repository + +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) + +Otherwise, in your console of choice: + +```bash +git clone https://github.com/GoogleCloudPlatform/cloud-foundation-fabric +``` + +Before you deploy the architecture, you will need at least the following +information (for more precise configuration see the Variables section): + +* The project ID + +The VPC host project, VPC and subnets should already exist and the following networking requirements are satisfied: +- configured PSA for Cloud SQL on the VPC +- subnets configured with PGA and Cloud NAT for internet access +- Inbound firewall rule for IAP on port 22 +- Inbound firewall rule for TCP ports 80, 443, 2222 from proxy subnet CIDR (gitlab) + +#### Step 2: Prepare the variables + +Once you have the required information, head back to your cloned repository. +Make sure you’re in the directory of this tutorial (where this README is in). + +Configure the Terraform variables in your `terraform.tfvars` file. +See [terraform.tfvars.sample](terraform.tfvars.sample) as starting point - just +copy it to `terraform.tfvars` and edit the latter. See the variables +documentation below. + +#### Step 3: Deploy resources + +Initialize your Terraform environment and deploy the resources: + +```shell +terraform init +terraform apply +``` + +#### Step 4: Use the created resources + +Connect to squid-proxy for accessing gitlab instance using the gcloud command +available in the `ssh_to_bastion` terraform output. + +```bash +terraform output ssh_to_bastion +``` + +A gcloud command like the following should be available + +```bash +gcloud compute ssh squid-vm --project ${project} --zone europe-west8-b -- -L 3128:127.0.0.1:3128 -N -q -f +``` + +Set as system proxy ip 127.0.0.1 and port 3128 and connect to Gitlab hostname https://gitlab.gcp.example.com. +Use default admin password available in /run/gitlab/config/initial_root_password or reset admin password via the following command on the Docker container: + +```bash +gitlab-rake “gitlab:password:reset” +``` + +## Reference and useful links + +- [Reference architecture up to 1k users](https://docs.gitlab.com/ee/administration/reference_architectures/1k_users.html) +- [`/etc/gitlab/gitlab.rb` template](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-config-template/gitlab.rb.template) +- [`/etc/gitlab/gitlab.rb` default options](https://docs.gitlab.com/ee/administration/package_information/defaults.html) + + + +## Files + +| name | description | modules | resources | +|---|---|---|---| +| [gitlab.tf](./gitlab.tf) | None | compute-vm · iam-service-account · net-lb-int | | +| [main.tf](./main.tf) | Module-level locals and resources. | project | | +| [outputs.tf](./outputs.tf) | Module outputs. | | | +| [services.tf](./services.tf) | None | cloudsql-instance · gcs | google_redis_instance | +| [ssl.tf](./ssl.tf) | None | | tls_cert_request · tls_locally_signed_cert · tls_private_key · tls_self_signed_cert | +| [variables.tf](./variables.tf) | Module variables. | | | + +## Variables + +| name | description | type | required | default | producer | +|---|---|:---:|:---:|:---:|:---:| +| [gitlab_instance_config](variables.tf#L69) | Gitlab Compute Engine instance config. | object({…}) | ✓ | | | +| [network_config](variables.tf#L89) | Shared VPC network configurations to use for Gitlab Runner VM. | object({…}) | ✓ | | | +| [prefix](variables.tf#L98) | Prefix used for resource names. | string | ✓ | | | +| [project_id](variables.tf#L117) | Project id, references existing project if `project_create` is null. | string | ✓ | | | +| [region](variables.tf#L136) | GCP Region. | string | ✓ | | | +| [admin_principals](variables.tf#L17) | Users, groups and/or service accounts that are assigned roles, in IAM format (`group:foo@example.com`). | list(string) | | [] | | +| [cloudsql_config](variables.tf#L23) | Cloud SQL Postgres config. | object({…}) | | {} | | +| [gcs_config](variables.tf#L34) | GCS for Object Storage config. | object({…}) | | {} | | +| [gitlab_config](variables.tf#L45) | Gitlab configuration. | object({…}) | | {} | | +| [project_create](variables.tf#L108) | Provide values if project creation is needed, uses existing project if null. Parent is in 'folders/nnn' or 'organizations/nnn' format. | object({…}) | | null | | +| [redis_config](variables.tf#L122) | Redis Config. | object({…}) | | {} | | + +## Outputs + +| name | description | sensitive | consumers | +|---|---|:---:|---| +| [gitlab_ilb_ip](outputs.tf#L26) | Gitlab Internal Load Balancer IP Address. | | | +| [instance](outputs.tf#L31) | Gitlab compute engine instance. | | | +| [postgresql_users](outputs.tf#L36) | Gitlab postgres user password. | ✓ | | +| [project](outputs.tf#L42) | GCP project. | | | +| [ssh_to_gitlab](outputs.tf#L47) | gcloud command to ssh gitlab instance. | | | +| [ssl_certs](outputs.tf#L52) | Gitlab SSL Certificates. | ✓ | | + +## Test + +```hcl +module "test" { + source = "./fabric/blueprints/third-party-solutions/gitlab" + gitlab_config = { + hostname = "gitlab.gcp.example.com" + mail = { + sendgrid = { + api_key = "sample_api_key" + } + } + saml = { + idp_cert_fingerprint = "67:90:96.....REPLACE_ME" + sso_target_url = "https://accounts.google.com/o/saml2/idp?idpid=REPLACE_ME" + } + } + gitlab_instance_config = { + replica_zone = "europe-west8-c" + zone = "europe-west8-b" + data_disk = { + replica_zone = "europe-west8-c" + } + } + network_config = { + host_project = "host-project" + network_self_link = "https://www.googleapis.com/compute/v1/projects/prod-net-landing-0/global/networks/prod-landing-0" + subnet_self_link = "https://www.googleapis.com/compute/v1/projects/prod-net-landing-0/regions/europe-west1/subnetworks/landing-default-ew1" + } + prefix = "prefix" + project_create = { + billing_account_id = "1234-ABCD-1234" + parent = "folders/1234563" + } + project_id = "my-project" + region = "europe-west8" +} +# tftest modules=14 resources=50 +``` diff --git a/blueprints/third-party-solutions/gitlab/TODO.md b/blueprints/third-party-solutions/gitlab/TODO.md new file mode 100644 index 00000000..e6eae43e --- /dev/null +++ b/blueprints/third-party-solutions/gitlab/TODO.md @@ -0,0 +1,20 @@ +# Gitlab TODOs + +- Integrations + - [x] Identity + - [x] SAML + - [ ] Email: + - [ ] Gmail / Workspace + - [x] Sendgrid +- [x] ILB +- [ ] MIG +- [ ] Gitaly +- [x] HTTPS SSL +- [x] Gitlab SSH on port 2222 +- [x] Check object store, use GCS wherever possible +- [x] Cloud SQL HA +- Memorystore + - [ ] HA + - [ ] PSC instead of PSA +- [x] Integration with Cloud Logging for Gitlab running on Docker container +- [ ] Integrate with Certificate Manager for SSH certificates diff --git a/blueprints/third-party-solutions/gitlab/assets/cloud-config.yaml b/blueprints/third-party-solutions/gitlab/assets/cloud-config.yaml new file mode 100644 index 00000000..cfce725e --- /dev/null +++ b/blueprints/third-party-solutions/gitlab/assets/cloud-config.yaml @@ -0,0 +1,118 @@ +#cloud-config + +# 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. + +# https://hub.docker.com/r/nginx/nginx/ +# https://nginx.io/manual/toc/#installation + +write_files: + - path: /var/lib/docker/daemon.json + permissions: '0644' + owner: root + content: | + { + "live-restore": true, + "storage-driver": "overlay2", + "log-driver": "gcplogs", + "log-opts": { + "gcp-meta-name": "gitlab-0", + "max-size": "1024m" + } + } + - path: /tmp/gitlab/config/gitlab.rb + permissions: '0600' + owner: root + content: | + ${gitlab_rb} + - path: /tmp/gitlab/ssl/${gitlab_cert_name}.key + permissions: '0600' + owner: root + content: | + ${gitlab_ssl_key} + - path: /tmp/gitlab/ssl/${gitlab_cert_name}.crt + permissions: '0600' + owner: root + content: | + ${gitlab_ssl_crt} + - path: /tmp/gitlab/sshd_config + permissions: '0644' + owner: root + content: | + ${gitlab_sshd_config} + + - path: /etc/systemd/system/gitlab-data.service + permissions: '0644' + owner: root + content: | + [Unit] + Description=Gitlab data disk + ConditionPathExists=/dev/disk/by-id/google-data + Before=gitlab.service + [Service] + Type=oneshot + ExecStart=/bin/mkdir -p /run/gitlab + ExecStart=/bin/bash -c \ + "/bin/lsblk -fn -o FSTYPE \ + /dev/disk/by-id/google-data |grep ext4 \ + || mkfs.ext4 -m 0 -F -E lazy_itable_init=0,lazy_journal_init=0,discard \ + /dev/disk/by-id/google-data" + ExecStart=/bin/bash -c \ + "mount |grep /run/gitlab \ + || mount -t ext4 /dev/disk/by-id/google-data /run/gitlab" + ExecStart=/sbin/resize2fs /dev/disk/by-id/google-data + ExecStart=/bin/mkdir -p /run/gitlab/config + ExecStart=/bin/mkdir -p /run/gitlab/ssl + ExecStart=/bin/mv /tmp/gitlab/config/gitlab.rb /run/gitlab/config/gitlab.rb + ExecStart=/bin/mv /tmp/gitlab/sshd_config /run/gitlab/sshd_config + ExecStart=/bin/bash -c "base64 -d -i /tmp/gitlab/ssl/${gitlab_cert_name}.key > /run/gitlab/ssl/${gitlab_cert_name}.key" + ExecStart=/bin/bash -c "base64 -d -i /tmp/gitlab/ssl/${gitlab_cert_name}.crt > /run/gitlab/ssl/${gitlab_cert_name}.crt" + RemainAfterExit=true + + # https://docs.gitlab.com/ee/install/docker.html#pre-configure-docker-container + + - path: /etc/systemd/system/gitlab.service + permissions: '0644' + owner: root + content: | + [Unit] + Description=Start gitlab container + After=gitlab-data.service gcr-online.target docker.socket + Wants=gitlab-data.service gcr-online.target docker.socket docker-events-collector.service + [Service] + Environment="HOME=/home/gitlab" + ExecStartPre=/usr/bin/docker-credential-gcr configure-docker + ExecStartPre=mkdir -p /run/gitlab + ExecStart=/usr/bin/docker run --rm --name=gitlab \ + --hostname ${gitlab_config.hostname} \ + --shm-size 256m \ + --env GITLAB_OMNIBUS_CONFIG="" \ + --publish 443:443 \ + --publish 80:80 \ + --publish 2222:2222 \ + -v /run/gitlab/config:/etc/gitlab \ + -v /run/gitlab/ssl:/etc/gitlab/ssl \ + -v /run/gitlab/logs:/var/log/gitlab \ + -v /run/gitlab/data:/var/opt/gitlab \ + -v /run/gitlab/sshd_config:/assets/sshd_config \ + gitlab/gitlab-ce + ExecStop=/usr/bin/docker stop gitlab + +runcmd: + - systemctl start node-problem-detector + - iptables -I INPUT 1 -p tcp -m tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT + - iptables -I INPUT 1 -p tcp -m tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT + - iptables -I INPUT 1 -p tcp -m tcp --dport 2222 -m state --state NEW,ESTABLISHED -j ACCEPT + - systemctl daemon-reload + - systemctl start gitlab diff --git a/blueprints/third-party-solutions/gitlab/assets/config.rb.tpl b/blueprints/third-party-solutions/gitlab/assets/config.rb.tpl new file mode 100644 index 00000000..8aaf0c5e --- /dev/null +++ b/blueprints/third-party-solutions/gitlab/assets/config.rb.tpl @@ -0,0 +1,118 @@ +# 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. + +# /etc/gitlab/gitlab.rb + +external_url "https://${hostname}" +letsencrypt['enable'] = false +nginx['redirect_http_to_https'] = true + +# https://docs.gitlab.com/omnibus/settings/redis.html +gitlab_rails['redis_enable_client'] = false +gitlab_rails['redis_host'] = '${redis.host}' +gitlab_rails['redis_port'] = ${redis.port} +# TODO: use auth +# gitlab_rails['redis_password'] = nil +redis['enable'] = false + +# https://docs.gitlab.com/omnibus/settings/database.html#using-a-non-packaged-postgresql-database-management-server +postgresql['enable'] = false +gitlab_rails['db_adapter'] = 'postgresql' +gitlab_rails['db_encoding'] = 'utf8' +gitlab_rails['db_host'] = '${cloudsql.host}' +gitlab_rails['db_port'] = 5432 +gitlab_rails['db_password'] = '${cloudsql.password}' + +# https://docs.gitlab.com/ee/administration/object_storage.html#google-cloud-storage-gcs +# Consolidated object storage configuration +gitlab_rails['object_store']['enabled'] = true +gitlab_rails['object_store']['proxy_download'] = true +gitlab_rails['object_store']['connection'] = { + 'provider' => 'Google', + 'google_project' => '${project_id}', + 'google_application_default' => true +} +# full example using the consolidated form +# https://docs.gitlab.com/ee/administration/object_storage.html#full-example-using-the-consolidated-form-and-amazon-s3 +gitlab_rails['object_store']['objects']['artifacts']['bucket'] = '${prefix}-gitlab-artifacts' +gitlab_rails['object_store']['objects']['external_diffs']['bucket'] = '${prefix}-gitlab-mr-diffs' +gitlab_rails['object_store']['objects']['lfs']['bucket'] = '${prefix}-gitlab-lfs' +gitlab_rails['object_store']['objects']['uploads']['bucket'] = '${prefix}-gitlab-uploads' +gitlab_rails['object_store']['objects']['packages']['bucket'] = '${prefix}-gitlab-packages' +gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = '${prefix}-gitlab-dependency-proxy' +gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = '${prefix}-gitlab-terraform-state' +gitlab_rails['object_store']['objects']['pages']['bucket'] = '${prefix}-gitlab-pages' + +# SAML configuration +# https://docs.gitlab.com/ee/integration/saml.html +%{ if saml != null } +gitlab_rails['omniauth_enabled'] = true +gitlab_rails['omniauth_external_providers'] = ['saml'] +# create new user in case of sign in with SAML provider +gitlab_rails['omniauth_allow_single_sign_on'] = ['saml'] +# do not force approval from admins for newly created users +gitlab_rails['omniauth_block_auto_created_users'] = false +# automatically link a first-time SAML sign-in with existing GitLab users if their email addresses match +gitlab_rails['omniauth_auto_link_saml_user'] = true +# Force user redirection to SAML +# To bypass the auto sign-in setting, append ?auto_sign_in=false in the sign in URL, for example: https://gitlab.example.com/users/sign_in?auto_sign_in=false. +%{ if saml.forced } +gitlab_rails['omniauth_auto_sign_in_with_provider'] = 'saml' +%{ endif } +# SHA1 Fingerprint +gitlab_rails['omniauth_providers'] = [ + { + name: "saml", + label: "SAML", + args: { + assertion_consumer_service_url: "https://${hostname}/users/auth/saml/callback", + idp_cert_fingerprint: '${saml.idp_cert_fingerprint}', + idp_sso_target_url: '${saml.sso_target_url}', + issuer: "https://${hostname}", + name_identifier_format: "${saml.name_identifier_format}" + } + } +] +%{ endif } + + +# mail configuration +%{ if mail.sendgrid != null } +gitlab_rails['smtp_enable'] = true +gitlab_rails['smtp_address'] = "smtp.sendgrid.net" +gitlab_rails['smtp_port'] = 587 +gitlab_rails['smtp_user_name'] = "apikey" +gitlab_rails['smtp_password'] = "${mail.sendgrid.api_key}" +gitlab_rails['smtp_domain'] = "smtp.sendgrid.net" +gitlab_rails['smtp_authentication'] = "plain" +gitlab_rails['smtp_enable_starttls_auto'] = true +gitlab_rails['smtp_tls'] = false +# If use Single Sender Verification You must configure from. If not fail +# 550 The from address does not match a verified Sender Identity. Mail cannot be sent until this error is resolved. +# Visit https://sendgrid.com/docs/for-developers/sending-email/sender-identity/ to see the Sender Identity requirements +%{ if try(mail.sendgrid.email_from != null, false) } +gitlab_rails['gitlab_email_from'] = '${mail.sendgrid.email_from}' +%{ endif } +%{ if try(mail.sendgrid.email_reply_to != null, false) } +gitlab_rails['email_reply_to'] = '${mail.sendgrid.email_reply_to}' +%{ endif } +%{ endif } + + +gitlab_rails['gitlab_shell_ssh_port'] = 2222 +# gitlab_sshd['enable'] = true +# gitlab_sshd['listen_address'] = '[::]:2222' + +# https://docs.gitlab.com/omnibus/installation/index.html#set-up-the-initial-password +# gitlab_rails['initial_root_password'] = '' \ No newline at end of file diff --git a/blueprints/third-party-solutions/gitlab/assets/sshd_config b/blueprints/third-party-solutions/gitlab/assets/sshd_config new file mode 100644 index 00000000..942dd5f8 --- /dev/null +++ b/blueprints/third-party-solutions/gitlab/assets/sshd_config @@ -0,0 +1,27 @@ +Port 2222 +ChallengeResponseAuthentication no +HostKey /etc/gitlab/ssh_host_rsa_key +HostKey /etc/gitlab/ssh_host_ecdsa_key +HostKey /etc/gitlab/ssh_host_ed25519_key +Protocol 2 +PermitRootLogin no +PasswordAuthentication no +MaxStartups 100:30:200 +AllowUsers git +PrintMotd no +PrintLastLog no +PubkeyAuthentication yes +AuthorizedKeysFile %h/.ssh/authorized_keys /gitlab-data/ssh/authorized_keys +AuthorizedKeysCommand /opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell-authorized-keys-check git %u %k +AuthorizedKeysCommandUser git + +# With "UsePAM yes" the "!" is seen as a password disabled account and not fully locked so ssh public key login works +# Please make sure that the account is created without passwordlogin ("*" in /etc/shadow) or configure pam. +# Issue #5891 https://gitlab.com/gitlab-org/omnibus-gitlab +UsePAM no + +# Disabling use DNS in ssh since it tends to slow connecting +UseDNS no + +# Enable the use of Git protocol v2 +AcceptEnv GIT_PROTOCOL diff --git a/blueprints/third-party-solutions/gitlab/diagram.png b/blueprints/third-party-solutions/gitlab/diagram.png new file mode 100644 index 00000000..d3f43ab0 Binary files /dev/null and b/blueprints/third-party-solutions/gitlab/diagram.png differ diff --git a/blueprints/third-party-solutions/gitlab/gitlab.tf b/blueprints/third-party-solutions/gitlab/gitlab.tf new file mode 100644 index 00000000..29ee4c5d --- /dev/null +++ b/blueprints/third-party-solutions/gitlab/gitlab.tf @@ -0,0 +1,130 @@ +/** + * 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. + */ + +locals { + gitlab_rb = templatefile("${path.module}/assets/config.rb.tpl", { + project_id = module.project.project_id + cloudsql = { + host = module.db.instances.primary.private_ip_address + password = module.db.user_passwords.gitlab + } + mail = var.gitlab_config.mail + redis = { + host = google_redis_instance.cache.host + port = google_redis_instance.cache.port + } + prefix = var.prefix + saml = var.gitlab_config.saml + hostname = var.gitlab_config.hostname + }) + gitlab_ssl_crt = local.self_signed_ssl_certs_required ? tls_locally_signed_cert.gitlab_server_singed_cert.0.cert_pem : file("${path.module}/certs/${var.gitlab_config.hostname}.crt") + gitlab_ssl_key = local.self_signed_ssl_certs_required ? tls_private_key.gitlab_server_key.0.private_key_pem : file("${path.module}/certs/${var.gitlab_config.hostname}.key") + gitlab_ssl_ca_crt = local.self_signed_ssl_certs_required ? tls_self_signed_cert.gitlab_ca_cert.0.cert_pem : file("${path.module}/certs/${var.gitlab_config.hostname}.ca.crt") + gitlab_ssl_ca_key = local.self_signed_ssl_certs_required ? tls_private_key.gitlab_ca_private_key.0.private_key_pem : "" + self_signed_ssl_certs_required = fileexists("${path.module}/certs/${var.gitlab_config.hostname}.crt") && fileexists("${path.module}/certs/${var.gitlab_config.hostname}.key") && fileexists("${path.module}/certs/${var.gitlab_config.hostname}.ca.crt") ? false : true + gitlab_user_data = templatefile("${path.module}/assets/cloud-config.yaml", { + gitlab_config = var.gitlab_config + gitlab_rb = indent(6, local.gitlab_rb) + gitlab_sshd_config = indent(6, file("${path.module}/assets/sshd_config")) + gitlab_cert_name = var.gitlab_config.hostname + gitlab_ssl_key = indent(6, base64encode(local.gitlab_ssl_key)) + gitlab_ssl_crt = indent(6, base64encode(local.gitlab_ssl_crt)) + }) +} + +module "gitlab-sa" { + source = "../../../modules/iam-service-account" + project_id = module.project.project_id + name = var.gitlab_instance_config.name + display_name = "Gitlab instance service account" + iam = { + "roles/iam.serviceAccountTokenCreator" = [module.gitlab-sa.iam_email] + } + iam_project_roles = { + (module.project.project_id) = [ + "roles/logging.logWriter", + "roles/monitoring.metricWriter", + "roles/storage.admin" + ] + } +} + +module "gitlab-instance" { + source = "../../../modules/compute-vm" + project_id = module.project.project_id + zone = var.gitlab_instance_config.zone + name = var.gitlab_instance_config.name + instance_type = var.gitlab_instance_config.instance_type + boot_disk = { + initialize_params = { + image = "projects/cos-cloud/global/images/family/cos-stable" + size = var.gitlab_instance_config.boot_disk.size + type = var.gitlab_instance_config.boot_disk.type + } + } + attached_disks = [ + { + name = "data" + size = var.gitlab_instance_config.data_disk.size + type = var.gitlab_instance_config.data_disk.type + options = { + replica_zone = var.gitlab_instance_config.replica_zone + } + } + ] + network_interfaces = [ + { + network = var.network_config.network_self_link + subnetwork = var.network_config.subnet_self_link + } + ] + tags = var.gitlab_instance_config.network_tags + metadata = { + user-data = local.gitlab_user_data + google-logging-enabled = "true" + } + service_account = { + email = module.gitlab-sa.email + } +} + +module "ilb" { + source = "../../../modules/net-lb-int" + project_id = module.project.project_id + region = var.region + name = "ilb" + service_label = "ilb" + vpc_config = { + network = var.network_config.network_self_link + subnetwork = var.network_config.subnet_self_link + } + group_configs = { + gitlab = { + zone = var.gitlab_instance_config.zone + instances = [ + module.gitlab-instance.self_link + ] + } + } + backends = [ + { group = module.ilb.groups.gitlab.self_link } + ] + health_check_config = { + https = { + port = 443 + } + } +} diff --git a/blueprints/third-party-solutions/gitlab/main.tf b/blueprints/third-party-solutions/gitlab/main.tf new file mode 100644 index 00000000..054ea8fc --- /dev/null +++ b/blueprints/third-party-solutions/gitlab/main.tf @@ -0,0 +1,44 @@ +/** + * 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. + */ + +module "project" { + source = "../../../modules/project" + parent = try(var.project_create.parent, null) + billing_account = try(var.project_create.billing_account_id, null) + prefix = var.project_create == null ? null : var.prefix + name = var.project_id + project_create = var.project_create != null + services = [ + "compute.googleapis.com", + "memcache.googleapis.com", + "redis.googleapis.com", + "sqladmin.googleapis.com", + "sql-component.googleapis.com", + "stackdriver.googleapis.com", + "dns.googleapis.com", + "iam.googleapis.com", + ] + shared_vpc_service_config = { + attach = true + host_project = var.network_config.host_project + service_identity_iam = { + "roles/compute.networkUser" = [ + "cloudservices", "compute" + ] + } + network_users = var.admin_principals + } +} diff --git a/blueprints/third-party-solutions/gitlab/outputs.tf b/blueprints/third-party-solutions/gitlab/outputs.tf new file mode 100644 index 00000000..e578f0fc --- /dev/null +++ b/blueprints/third-party-solutions/gitlab/outputs.tf @@ -0,0 +1,56 @@ +/** + * 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. + */ + +locals { + ssl_certs = { + "${var.gitlab_config.hostname}.crt" = local.gitlab_ssl_crt + "${var.gitlab_config.hostname}.key" = local.gitlab_ssl_key, + "${var.gitlab_config.hostname}.ca.crt" = local.gitlab_ssl_ca_crt, + "${var.gitlab_config.hostname}.ca.key" = local.gitlab_ssl_ca_key + } +} + +output "gitlab_ilb_ip" { + description = "Gitlab Internal Load Balancer IP Address." + value = module.ilb.forwarding_rule_addresses[""] +} + +output "instance" { + description = "Gitlab compute engine instance." + value = module.gitlab-instance.instance +} + +output "postgresql_users" { + description = "Gitlab postgres user password." + sensitive = true + value = module.db.user_passwords +} + +output "project" { + description = "GCP project." + value = module.project +} + +output "ssh_to_gitlab" { + description = "gcloud command to ssh gitlab instance." + value = nonsensitive("gcloud compute ssh ${module.gitlab-instance.instance.name} --project ${module.project.project_id} --zone ${module.gitlab-instance.instance.zone} -- -L 8080:127.0.0.1:80 -L 2222:127.0.0.1:2222 -L 8443:127.0.0.1:443 -N -q -f") +} + +output "ssl_certs" { + description = "Gitlab SSL Certificates." + value = local.ssl_certs + sensitive = true +} diff --git a/blueprints/third-party-solutions/gitlab/services.tf b/blueprints/third-party-solutions/gitlab/services.tf new file mode 100644 index 00000000..b5168be9 --- /dev/null +++ b/blueprints/third-party-solutions/gitlab/services.tf @@ -0,0 +1,92 @@ +/** + * 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. + */ + + +locals { + gitlab_buckets = [ + "gitlab-artifacts", "gitlab-mr-diffs", "gitlab-lfs", "gitlab-uploads", + "gitlab-packages", "gitlab-dependency-proxy", "gitlab-terraform-state", + "gitlab-pages" + ] +} + +####################################################################### +# GITLAB MANAGED SERVICES # +####################################################################### + +# https://docs.gitlab.com/ee/install/requirements.html#database +module "db" { + source = "../../../modules/cloudsql-instance" + project_id = module.project.project_id + region = var.region + name = var.cloudsql_config.name + availability_type = var.gitlab_config.ha_required ? "REGIONAL" : "ZONAL" + network_config = { + authorized_networks = {} + connectivity = { + psa_config = { + private_network = var.network_config.network_self_link + } + } + } + database_version = var.cloudsql_config.database_version + databases = [ + "gitlabhq_production" + ] + tier = var.cloudsql_config.tier + users = { + # generate password for user1 + gitlab = { + password = null + type = "BUILT_IN" + } + } +} + +# https://docs.gitlab.com/ee/install/requirements.html#redis +resource "google_redis_instance" "cache" { + project = module.project.project_id + region = var.region + name = var.redis_config.name + tier = var.redis_config.tier + memory_size_gb = var.redis_config.memory_size_gb + authorized_network = var.network_config.network_self_link + connect_mode = "PRIVATE_SERVICE_ACCESS" + + redis_version = var.redis_config.version + display_name = "Gitlab Redis Instance" + persistence_config { + persistence_mode = var.redis_config.persistence_mode + rdb_snapshot_period = var.redis_config.rdb_snapshot_period + } +} + +# https://docs.gitlab.com/ee/administration/object_storage.html#google-cloud-storage-gcs +module "gitlab_object_storage" { + source = "../../../modules/gcs" + for_each = toset(local.gitlab_buckets) + project_id = module.project.project_id + prefix = var.prefix + name = each.key + storage_class = var.gcs_config.storage_class + location = var.gcs_config.location + versioning = var.gcs_config.enable_versioning + iam = { + "roles/storage.objectUser" = [ + "serviceAccount:${module.gitlab-sa.email}", + ] + } +} diff --git a/blueprints/third-party-solutions/gitlab/ssl.tf b/blueprints/third-party-solutions/gitlab/ssl.tf new file mode 100644 index 00000000..96dd7e3d --- /dev/null +++ b/blueprints/third-party-solutions/gitlab/ssl.tf @@ -0,0 +1,107 @@ +/** + * 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. + */ + +locals { + cert_subjects = [ + { + country = "IT" + province = "Lombardy" + locality = "Milan" + organization = "Example" + organizational_unit = "Example" + } + ] +} + +####################################################################### +# GITLAB CA PRIVATE KEY # +####################################################################### + +resource "tls_private_key" "gitlab_ca_private_key" { + count = local.self_signed_ssl_certs_required ? 1 : 0 + algorithm = "RSA" +} + +####################################################################### +# GITLAB CA CERT # +####################################################################### + +resource "tls_self_signed_cert" "gitlab_ca_cert" { + count = local.self_signed_ssl_certs_required ? 1 : 0 + private_key_pem = tls_private_key.gitlab_ca_private_key.0.private_key_pem + is_ca_certificate = true + dynamic "subject" { + for_each = toset(local.cert_subjects) + content { + country = subject.value.country + province = subject.value.province + locality = subject.value.locality + common_name = "Gitlab CA" + organization = subject.value.organization + organizational_unit = subject.value.organizational_unit + } + } + validity_period_hours = 43800 // 1825 days or 5 years + allowed_uses = [ + "digital_signature", + "cert_signing", + "crl_signing", + ] +} + +####################################################################### +# SERVER CERT SIGNED BY CA # +####################################################################### + +resource "tls_private_key" "gitlab_server_key" { + count = local.self_signed_ssl_certs_required ? 1 : 0 + algorithm = "RSA" +} + +# Create CSR for Gitlab Server certificate +resource "tls_cert_request" "gitlab_server_csr" { + count = local.self_signed_ssl_certs_required ? 1 : 0 + private_key_pem = tls_private_key.gitlab_server_key.0.private_key_pem + dns_names = [var.gitlab_config.hostname] + + dynamic "subject" { + for_each = toset(local.cert_subjects) + content { + country = subject.value.country + province = subject.value.province + locality = subject.value.locality + common_name = "Gitlab" + organization = subject.value.organization + organizational_unit = subject.value.organizational_unit + } + } +} + +resource "tls_locally_signed_cert" "gitlab_server_singed_cert" { + count = local.self_signed_ssl_certs_required ? 1 : 0 + cert_request_pem = tls_cert_request.gitlab_server_csr.0.cert_request_pem + ca_private_key_pem = tls_private_key.gitlab_ca_private_key.0.private_key_pem + ca_cert_pem = tls_self_signed_cert.gitlab_ca_cert.0.cert_pem + + validity_period_hours = 43800 + + allowed_uses = [ + "digital_signature", + "key_encipherment", + "server_auth", + "client_auth", + ] +} diff --git a/blueprints/third-party-solutions/gitlab/terraform.tfvars.sample b/blueprints/third-party-solutions/gitlab/terraform.tfvars.sample new file mode 100644 index 00000000..e76642af --- /dev/null +++ b/blueprints/third-party-solutions/gitlab/terraform.tfvars.sample @@ -0,0 +1,19 @@ +gitlab_config = { + hostname = "gitlab.gcp.example.com" + mail = { + sendgrid = { + api_key = "sample_api_key" + } + } + saml = { + idp_cert_fingerprint = "67:90:96.....REPLACE_ME" + sso_target_url = "https://accounts.google.com/o/saml2/idp?idpid=REPLACE_ME" + } +} +network_config = { + host_project = "host-project" + network_self_link = "network_self_link" + subnet_self_link = "subnetwork_self_link" +} +prefix = "prefix" +project_id = "prod-gitlab-0" \ No newline at end of file diff --git a/blueprints/third-party-solutions/gitlab/variables.tf b/blueprints/third-party-solutions/gitlab/variables.tf new file mode 100644 index 00000000..7d6d2445 --- /dev/null +++ b/blueprints/third-party-solutions/gitlab/variables.tf @@ -0,0 +1,139 @@ +/** + * 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 "admin_principals" { + description = "Users, groups and/or service accounts that are assigned roles, in IAM format (`group:foo@example.com`)." + type = list(string) + default = [] +} + +variable "cloudsql_config" { + description = "Cloud SQL Postgres config." + type = object({ + name = optional(string, "gitlab-0") + database_version = optional(string, "POSTGRES_13") + tier = optional(string, "db-custom-2-8192") + }) + default = {} + nullable = false +} + +variable "gcs_config" { + description = "GCS for Object Storage config." + type = object({ + enable_versioning = optional(bool, false) + location = optional(string, "EU") + storage_class = optional(string, "STANDARD") + }) + default = {} + nullable = false +} + +variable "gitlab_config" { + description = "Gitlab configuration." + type = object({ + hostname = optional(string, "gitlab.gcp.example.com") + mail = optional(object({ + enabled = optional(bool, false) + sendgrid = optional(object({ + api_key = optional(string) + email_from = optional(string, null) + email_reply_to = optional(string, null) + }), null) + }), {}) + saml = optional(object({ + forced = optional(bool, false) + idp_cert_fingerprint = string + sso_target_url = string + name_identifier_format = optional(string, "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress") + }), null) + ha_required = optional(bool, false) + }) + default = {} + nullable = false +} + +variable "gitlab_instance_config" { + description = "Gitlab Compute Engine instance config." + type = object({ + instance_type = optional(string, "n1-highcpu-8") + name = optional(string, "gitlab-0") + network_tags = optional(list(string), []) + replica_zone = optional(string) + zone = optional(string) + boot_disk = optional(object({ + size = optional(number, 20) + type = optional(string, "pd-standard") + }), {}) + data_disk = optional(object({ + size = optional(number, 100) + type = optional(string, "pd-ssd") + replica_zone = optional(string) + }), {}) + }) +} + +variable "network_config" { + description = "Shared VPC network configurations to use for Gitlab Runner VM." + type = object({ + host_project = optional(string) + network_self_link = string + subnet_self_link = string + }) +} + +variable "prefix" { + description = "Prefix used for resource names." + type = string + nullable = false + validation { + condition = var.prefix != "" + error_message = "Prefix cannot be empty." + } +} + +variable "project_create" { + description = "Provide values if project creation is needed, uses existing project if null. Parent is in 'folders/nnn' or 'organizations/nnn' format." + type = object({ + billing_account_id = string + parent = string + }) + default = null +} + +variable "project_id" { + description = "Project id, references existing project if `project_create` is null." + type = string +} + +variable "redis_config" { + description = "Redis Config." + type = object({ + memory_size_gb = optional(number, 1) + name = optional(string, "gitlab-0") + persistence_mode = optional(string, "RDB") + rdb_snapshot_period = optional(string, "TWELVE_HOURS") + tier = optional(string, "BASIC") + version = optional(string, "REDIS_6_X") + }) + default = {} + nullable = false +} + +variable "region" { + description = "GCP Region." + type = string +}