Skip to content

Commit 2c0d7d1

Browse files
committed
chore: init repo
0 parents  commit 2c0d7d1

17 files changed

+323
-0
lines changed

.vscode/extensions.json

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"recommendations": [
3+
"hashicorp.terraform",
4+
"nefrob.vscode-just-syntax",
5+
]
6+
}

LICENSE

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Copyright 2025 Yassir Incorporated
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Yassir Terraform modules
2+
3+
A set of standalone, agnostic terraform modules abstracting away common infra provisioning.

modules/aws/.gitkeep

Whitespace-only changes.

modules/gcp/gcs-lb-domain/README.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
2+
3+
It would have been nice if we could offer the possibility to enable IAP for GCS backend services
4+
but it's not currently possible:
5+
https://issuetracker.google.com/issues/114133245?pli=1

modules/gcp/gcs-lb-domain/data.tf

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
data "google_client_config" "current" {}

modules/gcp/gcs-lb-domain/locals.tf

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
locals {
2+
project = data.google_client_config.current.project
3+
4+
labels = merge({
5+
namespace = var.namespace,
6+
domains = join(", ", var.domains),
7+
terraform = "true"
8+
tf_module = "gcp/gcs-lb-domain"
9+
project = local.project
10+
}, var.labels)
11+
12+
services = var.enable_services ? [
13+
"compute.googleapis.com",
14+
"servicenetworking.googleapis.com",
15+
] : []
16+
}

modules/gcp/gcs-lb-domain/main.tf

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Setup custom domains and external load balancer for a given bucket
2+
3+
# Enable the services needed for this module
4+
resource "google_project_service" "services" {
5+
for_each = local.services
6+
project = data.google_client_config.current.project
7+
service = each.value
8+
disable_on_destroy = false
9+
}
10+
11+
# Reserve an external IP
12+
resource "google_compute_global_address" "static_ip" {
13+
name = "${var.namespace}-ip"
14+
labels = local.labels
15+
16+
depends_on = [google_project_service.services]
17+
}
18+
19+
# Create a backend service for the given bucket
20+
resource "google_compute_backend_bucket" "backend_bucket" {
21+
name = "${var.namespace}-backend"
22+
description = "Contains files needed by ${var.bucket_name}"
23+
bucket_name = var.bucket_name
24+
enable_cdn = var.enable_cdn
25+
}
26+
27+
# Create HTTPS certificate
28+
resource "google_compute_managed_ssl_certificate" "ssl_cert" {
29+
name = "${var.namespace}-cert"
30+
managed {
31+
domains = var.domains
32+
}
33+
}
34+
35+
# GCP URL MAP
36+
resource "google_compute_url_map" "url_map" {
37+
name = "${var.namespace}-lb"
38+
default_service = google_compute_backend_bucket.backend_bucket.self_link
39+
}
40+
41+
# GCP target proxy
42+
resource "google_compute_target_https_proxy" "target_proxy" {
43+
name = "${var.namespace}-target-proxy"
44+
url_map = google_compute_url_map.url_map.self_link
45+
ssl_certificates = [google_compute_managed_ssl_certificate.ssl_cert.self_link]
46+
}
47+
48+
# GCP forwarding rule
49+
resource "google_compute_global_forwarding_rule" "forwarding_rule" {
50+
name = "${var.namespace}-fwd-rule"
51+
load_balancing_scheme = "EXTERNAL"
52+
ip_address = google_compute_global_address.static_ip.address
53+
ip_protocol = "TCP"
54+
port_range = "443"
55+
target = google_compute_target_https_proxy.target_proxy.self_link
56+
labels = local.labels
57+
}

modules/gcp/gcs-lb-domain/outputs.tf

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Export the objects created by this module
2+
3+
output "ip" {
4+
description = "The IP address object"
5+
value = google_compute_global_address.static_ip
6+
}
7+
8+
output "ssl_certificate" {
9+
description = "The SSL certificate object"
10+
value = google_compute_managed_ssl_certificate.ssl_cert
11+
sensitive = true
12+
}
13+
14+
output "url_map" {
15+
description = "The URL map object"
16+
value = google_compute_url_map.url_map
17+
}
18+
19+
output "target_proxy" {
20+
description = "The target proxy object"
21+
value = google_compute_target_https_proxy.target_proxy
22+
}
23+
24+
output "forwarding_rule" {
25+
description = "The forwarding rule object"
26+
value = google_compute_global_forwarding_rule.forwarding_rule
27+
}
28+
29+
# Construct the https URLs
30+
output "urls" {
31+
description = "The URLs of the GCS LB domain"
32+
value = {
33+
for domain in var.domains : domain => "https://${domain}"
34+
}
35+
}
36+
37+
# Export the labels used by this module
38+
output "labels" {
39+
description = "The labels used by this module"
40+
value = {
41+
for key, value in local.labels : key => value
42+
}
43+
}
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
variable "namespace" {
2+
description = "The namespace to prefix the GCP resources IDs with"
3+
type = string
4+
}
5+
6+
variable "bucket_name" {
7+
description = "The name of the bucket to serve"
8+
type = string
9+
}
10+
11+
variable "enable_cdn" {
12+
description = "Whether to enable CDN for the bucket backend"
13+
type = bool
14+
default = false
15+
}
16+
17+
variable "domains" {
18+
description = "The domain name to serve the bucket on"
19+
type = list(string)
20+
}
21+
22+
variable "labels" {
23+
description = "Resource labels."
24+
type = map(string)
25+
default = {}
26+
}
27+
28+
variable "enable_services" {
29+
description = "Whether to enable the services needed for this module"
30+
type = bool
31+
default = true
32+
}

modules/gcp/gcs-lb-domain/versions.tf

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
terraform {
2+
required_version = ">= 1.10.2, < 2.0.0"
3+
required_providers {
4+
google = {
5+
source = "hashicorp/google"
6+
version = ">= 6.15.0"
7+
}
8+
google-beta = {
9+
source = "hashicorp/google-beta"
10+
version = ">= 6.15.0"
11+
}
12+
}
13+
}

modules/gcp/wif-github/TFDOC.md

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# workload_identity
2+
3+
<!-- BEGIN_TF_DOCS -->
4+
## Requirements
5+
6+
No requirements.
7+
8+
## Providers
9+
10+
| Name | Version |
11+
|------|---------|
12+
| <a name="provider_google"></a> [google](#provider\_google) | n/a |
13+
14+
## Modules
15+
16+
No modules.
17+
18+
## Resources
19+
20+
| Name | Type |
21+
|------|------|
22+
| [google_iam_workload_identity_pool.wip_pool](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/iam_workload_identity_pool) | resource |
23+
| [google_iam_workload_identity_pool_provider.wip_provider](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/iam_workload_identity_pool_provider) | resource |
24+
| [google_project_iam_member.sa_roles](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/project_iam_member) | resource |
25+
| [google_service_account_iam_member.yassir-dns-sa-iam-member](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/service_account_iam_member) | resource |
26+
27+
## Inputs
28+
29+
| Name | Description | Type | Default | Required |
30+
|------|-------------|------|---------|:--------:|
31+
| <a name="input_access_type"></a> [access\_type](#input\_access\_type) | The type of access to be granted | `string` | n/a | yes |
32+
| <a name="input_github_organization"></a> [github\_organization](#input\_github\_organization) | Github Organization name to restrict service accounts deploying from Yassir owned repos, not public ones | `string` | `"YAtechnologies"` | no |
33+
| <a name="input_members"></a> [members](#input\_members) | A list of principals | `list(string)` | n/a | yes |
34+
| <a name="input_project_id"></a> [project\_id](#input\_project\_id) | The project ID (not number). Could be the same as project.name | `string` | n/a | yes |
35+
| <a name="input_repositories"></a> [repositories](#input\_repositories) | A list of repositories in the form of 'owner/repo' | `list(string)` | `[]` | no |
36+
| <a name="input_roles"></a> [roles](#input\_roles) | Project roles | `list(string)` | `[]` | no |
37+
38+
## Outputs
39+
40+
| Name | Description |
41+
|------|-------------|
42+
| <a name="output_project_id"></a> [project\_id](#output\_project\_id) | The GCP project name |
43+
| <a name="output_service_account"></a> [service\_account](#output\_service\_account) | The service account to use for CI/CD |
44+
| <a name="output_wip_provider"></a> [wip\_provider](#output\_wip\_provider) | The Worload Identity Provider to use for Github Actions |
45+
<!-- END_TF_DOCS -->

modules/gcp/wif-github/data.tf

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
data "google_client_config" "current" {}

modules/gcp/wif-github/locals.tf

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
locals {
2+
project = data.google_client_config.current.project
3+
service_account_id = "projects/${project}/serviceAccounts/${var.service_account_email}"
4+
}

modules/gcp/wif-github/main.tf

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Setup Workload Identity Federation for the given project
2+
3+
resource "google_iam_workload_identity_pool" "wip" {
4+
workload_identity_pool_id = "${var.namespace}-wip"
5+
display_name = "Workload identity pool for ${var.namespace}"
6+
description = "Workload identity pool to be used in Github Actions"
7+
disabled = false
8+
}
9+
10+
resource "google_iam_workload_identity_pool_provider" "wip_provider" {
11+
workload_identity_pool_id = google_iam_workload_identity_pool.wip.workload_identity_pool_id
12+
workload_identity_pool_provider_id = "${var.namespace}-wip-provider"
13+
display_name = "Github WIP provider for ${var.namespace}"
14+
description = "The Workload Identity Pool Provider to be used for CI/CD with Github actions"
15+
16+
attribute_mapping = {
17+
"google.subject" = "assertion.sub"
18+
"attribute.actor" = "assertion.actor"
19+
"attribute.aud" = "assertion.aud"
20+
"attribute.repository" = "assertion.repository"
21+
}
22+
23+
oidc {
24+
issuer_uri = "https://token.actions.githubusercontent.com"
25+
}
26+
27+
attribute_condition = "assertion.repository_owner=='${var.github_organization}'"
28+
}
29+
30+
resource "google_service_account_iam_member" "repositories_iam" {
31+
for_each = toset(var.repositories)
32+
service_account_id = local.service_account_id
33+
role = "roles/iam.workloadIdentityUser"
34+
member = "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.wip.name}/attribute.repository/${each.value}"
35+
depends_on = [google_iam_workload_identity_pool_provider.wip_provider]
36+
}

modules/gcp/wif-github/outputs.tf

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
output "service_account" {
2+
value = var.service_account_email
3+
description = "The service account to use for CI/CD"
4+
}
5+
6+
output "wip_provider" {
7+
value = google_iam_workload_identity_pool_provider.wip_provider.workload_identity_pool_provider_id
8+
description = "The Workload Identity Provider to use for Github Actions"
9+
}
10+
11+
output "connection_info" {
12+
value = {
13+
project = local.project
14+
service_account = var.service_account_email
15+
wip_provider = google_iam_workload_identity_pool_provider.wip_provider.workload_identity_pool_provider_id
16+
repositories = var.repositories
17+
}
18+
}

modules/gcp/wif-github/variables.tf

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
variable "namespace" {
2+
type = string
3+
description = "The namespace to use as a prefix for the resources created by this module"
4+
}
5+
6+
variable "repositories" {
7+
type = list(string)
8+
description = "A list of repositories in the form of 'owner/repo'"
9+
10+
validation {
11+
condition = length(var.repositories) > 0
12+
error_message = "The repositories variable must contain at least one repository"
13+
}
14+
15+
validation {
16+
condition = alltrue(flatten([for repo in var.repositories : can(regex("^[a-zA-Z0-9_-]+/[a-zA-Z0-9_-]+$", repo))]))
17+
error_message = "Each repository must be in the format 'owner/repo'"
18+
}
19+
}
20+
21+
variable "github_organization" {
22+
default = "YAtechnologies"
23+
type = string
24+
description = "A Github Organization name to use as a constraint for the workload identity federation"
25+
}
26+
27+
variable "service_account_email" {
28+
type = string
29+
description = "The service account email to use for the workload identity federation"
30+
}

0 commit comments

Comments
 (0)