Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added certificate-manager module #2387

Merged
merged 2 commits into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Currently available modules:
- **compute** - [VM/VM group](./modules/compute-vm), [MIG](./modules/compute-mig), [COS container](./modules/cloud-config-container/cos-generic-metadata/) (coredns, mysql, onprem, squid), [GKE cluster](./modules/gke-cluster-standard), [GKE hub](./modules/gke-hub), [GKE nodepool](./modules/gke-nodepool), [GCVE private cloud](./modules/gcve-private-cloud)
- **data** - <!-- [AlloyDB instance](./modules/alloydb-instance), --> [Analytics Hub](./modules/analytics-hub), [BigQuery dataset](./modules/bigquery-dataset), [Bigtable instance](./modules/bigtable-instance), [Dataplex](./modules/dataplex), [Dataplex DataScan](./modules/dataplex-datascan), [Cloud SQL instance](./modules/cloudsql-instance), [Spanner instance](./modules/spanner-instance), [Firestore](./modules/firestore), [Data Catalog Policy Tag](./modules/data-catalog-policy-tag), [Data Catalog Tag](./modules/data-catalog-tag), [Data Catalog Tag Template](./modules/data-catalog-tag-template), [Datafusion](./modules/datafusion), [Dataproc](./modules/dataproc), [GCS](./modules/gcs), [Pub/Sub](./modules/pubsub), [Dataform Repository](./modules/dataform-repository/)
- **development** - [API Gateway](./modules/api-gateway), [Apigee](./modules/apigee), [Artifact Registry](./modules/artifact-registry), [Container Registry](./modules/container-registry), [Cloud Source Repository](./modules/source-repository), [Workstation cluster](./modules/workstation-cluster)
- **security** - [Binauthz](./modules/binauthz/), [KMS](./modules/kms), [SecretManager](./modules/secret-manager), [VPC Service Control](./modules/vpc-sc)
- **security** - [Binauthz](./modules/binauthz/), [KMS](./modules/kms), [SecretManager](./modules/secret-manager), [VPC Service Control](./modules/vpc-sc), [Certificate Manager](./modules/certificate-manager/)
- **serverless** - [Cloud Function v1](./modules/cloud-function-v1), [Cloud Function v2](./modules/cloud-function-v2), [Cloud Run](./modules/cloud-run), [Cloud Run v2](./modules/cloud-run-v2)

For more information and usage examples see each module's README file.
Expand Down
1 change: 1 addition & 0 deletions modules/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ These modules are used in the examples included in this repository. If you are u
- [SecretManager](./secret-manager)
- [VPC Service Control](./vpc-sc)
- [Secure Web Proxy](./net-swp)
- [Certificate Manager](./certificate-manager)

## Serverless

Expand Down
263 changes: 263 additions & 0 deletions modules/certificate-manager/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,263 @@
# 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.

## Examples

### Self-managed certificate

```hcl
resource "tls_private_key" "private_key" {
algorithm = "RSA"
rsa_bits = 2048
}

resource "tls_self_signed_cert" "cert" {
private_key_pem = tls_private_key.private_key.private_key_pem
subject {
common_name = "example.com"
organization = "ACME Examples, Inc"
}
validity_period_hours = 720
allowed_uses = [
"key_encipherment",
"digital_signature",
"server_auth",
]
}

module "certificate-manager" {
source = "./fabric/modules/certificate-manager"
project_id = var.project_id
certificates = {
my-certificate-1 = {
self_managed = {
pem_certificate = tls_self_signed_cert.cert.cert_pem
pem_private_key = tls_private_key.private_key.private_key_pem
}
}
}
}
# tftest modules=1 resources=3 inventory=self-managed-cert.yaml
```

### Certificate map with 1 entry with 1 self-managed certificate

```hcl
resource "tls_private_key" "private_key" {
algorithm = "RSA"
rsa_bits = 2048
}

resource "tls_self_signed_cert" "cert" {
private_key_pem = tls_private_key.private_key.private_key_pem
subject {
common_name = "example.com"
organization = "ACME Examples, Inc"
}
validity_period_hours = 720
allowed_uses = [
"key_encipherment",
"digital_signature",
"server_auth",
]
}

module "certificate-manager" {
source = "./fabric/modules/certificate-manager"
project_id = var.project_id
map = {
name = "my-certificate-map"
description = "My certificate map"
entries = {
mydomain-mycompany-org = {
certificates = [
"my-certificate-1"
]
hostname = "mydomain.mycompany.org"
}
}
}
certificates = {
my-certificate-1 = {
self_managed = {
pem_certificate = tls_self_signed_cert.cert.cert_pem
pem_private_key = tls_private_key.private_key.private_key_pem
}
}
}
}
# tftest modules=1 resources=5 inventory=map-with-self-managed-cert.yaml

```

### Certificate map with 1 entry with 1 managed certificate with load balancer authorization

```hcl
module "certificate-manager" {
source = "./fabric/modules/certificate-manager"
project_id = var.project_id
map = {
name = "my-certificate-map"
description = "My certificate map"
entries = {
mydomain-mycompany-org = {
certificates = [
"my-certificate-1"
]
matcher = "PRIMARY"
}
}
}
certificates = {
my-certificate-1 = {
managed = {
domains = ["mydomain.mycompany.org"]
}
}
}
}
# tftest modules=1 resources=3 inventory=map-with-managed-cert-lb-authz.yaml
```

### Certificate map with 1 entry with 1 managed certificate with DNS authorization

```hcl
module "certificate-manager" {
source = "./fabric/modules/certificate-manager"
project_id = var.project_id
map = {
name = "my-certificate-map"
description = "My certificate map"
entries = {
mydomain-mycompany-org = {
certificates = [
"my-certificate-1"
]
matcher = "PRIMARY"
}
}
}
certificates = {
my-certificate-1 = {
managed = {
domains = ["mydomain.mycompany.org"]
dns_authorizations = ["mydomain-mycompany-org"]
}
}
}
dns_authorizations = {
mydomain-mycompany-org = {
type = "PER_PROJECT_RECORD"
domain = "mydomain.mycompany.org"
}
}
}
# tftest modules=1 resources=4 inventory=map-with-managed-cert-dns-authz.yaml
```

### Certificate map with 1 entry with 1 managed certificate with issued by a CA Service instance

```hcl
resource "google_privateca_ca_pool" "pool" {
name = "ca-pool"
project = var.project_id
location = "us-central1"
tier = "ENTERPRISE"
}

resource "google_privateca_certificate_authority" "ca_authority" {
project = var.project_id
location = "us-central1"
pool = google_privateca_ca_pool.pool.name
certificate_authority_id = "ca-authority"
config {
subject_config {
subject {
organization = "My Company"
common_name = "my-company-authority"
}
subject_alt_name {
dns_names = ["mycompany.org"]
}
}
x509_config {
ca_options {
is_ca = true
}
key_usage {
base_key_usage {
cert_sign = true
crl_sign = true
}
extended_key_usage {
server_auth = true
}
}
}
}
key_spec {
algorithm = "RSA_PKCS1_4096_SHA256"
}
deletion_protection = false
skip_grace_period = true
ignore_active_certificates_on_deletion = true
}

module "certificate-manager" {
source = "./fabric/modules/certificate-manager"
project_id = var.project_id
map = {
name = "my-certificate-map"
description = "My certificate map"
entries = {
mydomain-mycompany-org = {
certificates = [
"my-certificate-1"
]
matcher = "PRIMARY"
}
}
}
certificates = {
my-certificate-1 = {
managed = {
domains = ["mydomain.mycompany.org"]
issuance_config = "my-issuance-config"
}
}
}
issuance_configs = {
my-issuance-config = {
ca_pool = google_privateca_ca_pool.pool.id
key_algorithm = "ECDSA_P256"
lifetime = "1814400s"
rotation_window_percentage = 34
}
}
depends_on = [
google_privateca_certificate_authority.ca_authority
]
}
# tftest modules=1 resources=6 inventory=map-with-managed-cert-ca-service.yaml
```
<!-- BEGIN TFDOC -->
## Variables

| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [project_id](variables.tf#L102) | Project id. | <code>string</code> | ✓ | |
| [certificates](variables.tf#L17) | Certificates. | <code title="map&#40;object&#40;&#123;&#10; description &#61; optional&#40;string&#41;&#10; labels &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; location &#61; optional&#40;string&#41;&#10; scope &#61; optional&#40;string&#41;&#10; self_managed &#61; optional&#40;object&#40;&#123;&#10; pem_certificate &#61; string&#10; pem_private_key &#61; string&#10; &#125;&#41;&#41;&#10; managed &#61; optional&#40;object&#40;&#123;&#10; domains &#61; list&#40;string&#41;&#10; dns_authorizations &#61; optional&#40;list&#40;string&#41;&#41;&#10; issuance_config &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [dns_authorizations](variables.tf#L53) | DNS authorizations. | <code title="map&#40;object&#40;&#123;&#10; domain &#61; string&#10; description &#61; optional&#40;string&#41;&#10; location &#61; optional&#40;string&#41;&#10; type &#61; optional&#40;string&#41;&#10; labels &#61; optional&#40;map&#40;string&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [issuance_configs](variables.tf#L66) | Issuance configs. | <code title="map&#40;object&#40;&#123;&#10; ca_pool &#61; string&#10; description &#61; optional&#40;string&#41;&#10; key_algorithm &#61; string&#10; labels &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; lifetime &#61; string&#10; rotation_window_percentage &#61; number&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [map](variables.tf#L80) | Map attributes. | <code title="object&#40;&#123;&#10; name &#61; string&#10; description &#61; optional&#40;string&#41;&#10; labels &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; entries &#61; optional&#40;map&#40;object&#40;&#123;&#10; description &#61; optional&#40;string&#41;&#10; hostname &#61; optional&#40;string&#41;&#10; labels &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; matcher &#61; optional&#40;string&#41;&#10; certificates &#61; list&#40;string&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |

## Outputs

| name | description | sensitive |
|---|---|:---:|
| [certificate_ids](outputs.tf#L17) | Certificate ids. | |
| [certificates](outputs.tf#L22) | Certificates. | |
| [map](outputs.tf#L27) | Map. | |
| [map_id](outputs.tf#L32) | Map id. | |
<!-- END TFDOC -->
85 changes: 85 additions & 0 deletions modules/certificate-manager/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/**
* 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.
*/

resource "google_certificate_manager_certificate_map" "map" {
count = var.map == null ? 0 : 1
project = var.project_id
name = var.map.name
description = var.map.description
labels = var.map.labels
}

resource "google_certificate_manager_certificate_map_entry" "entries" {
for_each = try(var.map.entries, {})
project = google_certificate_manager_certificate_map.map[0].project
name = each.key
description = each.value.description
map = google_certificate_manager_certificate_map.map[0].name
labels = each.value.labels
certificates = [for v in each.value.certificates : google_certificate_manager_certificate.certificates[v].id]
hostname = each.value.hostname
matcher = each.value.matcher
}

resource "google_certificate_manager_certificate" "certificates" {
for_each = var.certificates
project = var.project_id
name = each.key
description = each.value.description
scope = each.value.scope
labels = each.value.labels
dynamic "managed" {
for_each = each.value.managed == null ? [] : [""]
content {
domains = each.value.managed.domains
dns_authorizations = each.value.managed.dns_authorizations
issuance_config = each.value.managed.issuance_config
}
}
dynamic "self_managed" {
for_each = each.value.self_managed == null ? [] : [""]
content {
pem_certificate = each.value.self_managed.pem_certificate
pem_private_key = each.value.self_managed.pem_private_key
}
}
}

resource "google_certificate_manager_dns_authorization" "dns_authorizations" {
for_each = var.dns_authorizations
project = var.project_id
name = each.key
location = each.value.location
description = each.value.description
type = each.value.type
domain = each.value.domain
}

resource "google_certificate_manager_certificate_issuance_config" "default" {
for_each = var.issuance_configs
project = var.project_id
name = each.key
description = each.value.description
certificate_authority_config {
certificate_authority_service_config {
ca_pool = each.value.ca_pool
}
}
lifetime = each.value.lifetime
rotation_window_percentage = each.value.rotation_window_percentage
key_algorithm = each.value.key_algorithm
labels = each.value.labels
}
Loading