Skip to content

Commit

Permalink
Added certificate-manager module (#2387)
Browse files Browse the repository at this point in the history
  • Loading branch information
apichick authored Jun 27, 2024
1 parent 85c1b7c commit 00d4673
Show file tree
Hide file tree
Showing 12 changed files with 917 additions and 1 deletion.
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

0 comments on commit 00d4673

Please sign in to comment.