Blog

Deploy an HTTPS Load Balancer using a Google-managed wildcard SSL certificate on Google Cloud Platform

14 Apr, 2023
Xebia Background Header Wave

Recently I was wondering if I could deploy a Google-managed wildcard SSL certificate on my Global External HTTPS Load Balancer. In this blog, I will show you step by step how you can deploy a Global HTTPS Load Balancer using a Google-managed wildcard SSL certificate.

Background Research

Google-managed SSL certificates for Cloud Load Balancing by default do not support wildcard common names when provisioning load balancers according to this documentation. However, doing a quick search through the Google Cloud Platform documentation, I was led to the Certificate Manager service. It appears that the Certificate Manager service does support Wildcard common names. So, how do we attach certificates from the Certificate Manager to a Global External HTTPS Load Balancer?

Compatibility

First I wanted to check if there was native integration between Cloud Load Balancing and the Certificate Manager. I found an interesting comparison between Certificates and Google Cloud load balancers. The comparison shows which load balancers are compatible with the Certificate Manager, and as luck will have it, the Global External HTTPS load balancer is compatible!

Domain authorization

The next step was to identify which domain authorization method supports wildcard common names. The Certificate Manager requires to configure domain authorization for Google-managed SSL certificates, to prove ownership of the domain(s) of the SSL certificate. Google Cloud Platform provides two options to accomplish this:

  1. Load Balancer Authorization
  2. DNS authorization

Load Balancer authorization

Load balancer authorization is a more basic approach, which does not require any additional DNS changes and is therefore faster to configure, but the attached load balancer authorization does however not support wildcard common names.

DNS authorization

DNS authorization requires additional DNS configuration by adding DNS records to proof ownership by using Cloud DNS or a third-party DNS solution. DNS authorization does support wildcard common names. This makes this the only viable path for implementation.

Deploy the Global HTTPS Load Balancer

Important: Make sure you have configured your Cloud Domain and use the Cloud DNS provider when using these examples.

We will be using Terraform in our deployment examples, as it’s considered best practice to strive for Infrastructure as Code (IaC) wherever possible.

To deploy a Global Load Balancer using a Google-managed wildcard SSL certificate, 3 main components are configured:

  1. Cloud DNS
  2. Certificate Manager
  3. Global HTTPS Load Balancer

Create public DNS zone in Cloud DNS

Before creating the load balancer, first create a public DNS zone in Cloud DNS.

## Enable the Cloud DNS API ##
resource "google_project_service" "cloud_dns" {
  service = "dns.googleapis.com"
}

## Public Cloud DNS zone. Make sure to configure your domain under Google Domains to use Cloud DNS ##
resource "google_dns_managed_zone" "public_dns_zone" {
  name        = "public-dns-zone"
  dns_name    = "example.com."
  description = "Public DNS zone for example.com"

  lifecycle {
    prevent_destroy = true
  }
}

Next, configure the Certificate Manager using DNS authorization and wildcard common names.

## Certificate manager resources to provision a wildcard SSL certificate for a Load Balancer. Requires a Public DNS zone ##

## Enable the certificate manager API ##
resource "google_project_service" "certificate_manager" {
  service = "certificatemanager.googleapis.com"
}

## Configure DNS authorization to provide the ACME challenge DNS records ##
resource "google_certificate_manager_dns_authorization" "dns_authorization" {
  name        = "dns-authorization"
  description = "DNS authorization for example.com to support wildcard certificates"
  domain      = "example.com"
}

## Provision a wildcard managed SSL certificate using DNS authorization ##
resource "google_certificate_manager_certificate" "wildcard_ssl_certificate" {
  name        = "wildcard-ssl-certificate"
  description = "Wildcard certificate for ${local.fqdn} and sub-domains"

  managed {
    domains = ["example.com", "*.example.com"]
    dns_authorizations = [
      google_certificate_manager_dns_authorization.dns_authorization.id
    ]
  }
}

## Certificate map resource to reference to from a forwarding rule ##
resource "google_certificate_manager_certificate_map" "certificate_map" {
  name        = "certificate-map"
  description = "${local.fqdn} certificate map containing the domain names and sub-domains names for the SSL certificate"
}

## Certificate map entry for the top-level domain ##
resource "google_certificate_manager_certificate_map_entry" "domain_certificate_entry" {
  name         = "domain-cert-entry"
  description  = "example.com certificate entry"
  map          = google_certificate_manager_certificate_map.certificate_map.name
  certificates = [google_certificate_manager_certificate.wildcard_ssl_certificate.id]
  hostname     = "example.com"
}

## Certificate map entry for the sub domain
resource "google_certificate_manager_certificate_map_entry" "sub_domain_certificate_entry" {
  name         = "sub-domain-entry"
  description  = "*.example.com certificate entry"
  map          = google_certificate_manager_certificate_map.certificate_map.name
  certificates = [google_certificate_manager_certificate.wildcard_ssl_certificate.id]
  hostname     = "*.example.com"
}

The google_certificate_manager_dns_authorization resource outputs the required DNS information to complete the DNS authorization setup which must be added to the earlier created DNS zone. Add the following DNS record:

## DNS authorization record ##
resource "google_dns_record_set" "dns_authorization_wildcard_certificate" {
  name         = google_certificate_manager_dns_authorization.dns_authorization.dns_resource_record[0].name
  managed_zone = google_dns_managed_zone.public_dns_zone.name
  type         = google_certificate_manager_dns_authorization.dns_authorization.dns_resource_record[0].type
  ttl          = 300
  rrdatas      = [google_certificate_manager_dns_authorization.dns_authorization.dns_resource_record[0].data]
}

Configure external IP-address

To allow for a smooth deployment of the load balancer, we will configure an external IP-address for the Global HTTPS Load Balancer

# Load balancer IP
resource "google_compute_global_address" "lb_ip_address" {
  name        = "example-lb-ip"
  description = "Public IP address of the Global HTTPS load balancer"
}

Update DNS zone with appropriate records

Add Domain name and wildcard sub-domain DNS records to the DNS zone

## Global load balancer DNS records ##
resource "google_dns_record_set" "global_load_balancer_sub_domain" {
  managed_zone = google_dns_managed_zone.public_dns_zone.name
  name         = "*.${google_dns_managed_zone.public_dns_zone.dns_name}"
  type         = "A"
  rrdatas      = [google_compute_global_address.lb_ip_address.address]
}

resource "google_dns_record_set" "global_load_balancer_top_level_domain" {
  managed_zone = google_dns_managed_zone.public_dns_zone.name
  name         = google_dns_managed_zone.public_dns_zone.dns_name
  type         = "A"
  rrdatas      = [google_compute_global_address.lb_ip_address.address]
}

Create Load Balancer resources


# HTTPS load balancer
resource "google_compute_global_forwarding_rule" "https_forwarding_rule" {
  name        = "https-forwarding-rule"
  description = "Global external load balancer"
  ip_address  = google_compute_global_address.lb_ip_address.id
  port_range  = "443"
  target      = google_compute_target_https_proxy.https_proxy.self_link
}

# HTTPS proxy
resource "google_compute_target_https_proxy" "https_proxy" {
  name            = "https-webserver-proxy"
  description     = "HTTPS Proxy mapping for the Load balancer including wildcard ssl certificate"
  url_map         = google_compute_url_map.url_map.self_link
  certificate_map = "//${google_project_service.certificate_manager.service}/${google_certificate_manager_certificate_map.certificate_map.id}"
}

# HTTP proxy
resource "google_compute_global_forwarding_rule" "http_forwarding_rule" {
  name        = "http-forwarding-rule"
  description = "Global external load balancer HTTP redirect"
  ip_address  = google_compute_global_address.lb_ip_address.id
  port_range  = "80"
  target      = google_compute_target_http_proxy.http_proxy.self_link
}

## HTTPS redirect proxy
resource "google_compute_target_http_proxy" "http_proxy" {
  name        = "http-webserver-proxy"
  description = "Redirect proxy mapping for the Load balancer"
  url_map     = google_compute_url_map.http_https_redirect.self_link
}

# Default URL map
resource "google_compute_url_map" "url_map" {
  name        = "url-map"
  description = "Url mapping to the backend services"
}

# Redirect URL map
resource "google_compute_url_map" "http_https_redirect" {
  name        = "http-https-redirect"
  description = "HTTP Redirect map"

  default_url_redirect {
    https_redirect         = true
    redirect_response_code = "MOVED_PERMANENTLY_DEFAULT"
    strip_query            = false
  }
}

By using the certificates_map argument we are able to reference the earlier created certificate map and use the wildcard SSL certificate.

Security considerations

Using a wildcard SSL certificate means that your top-level domain and all your sub-domains would use the same SSL certificate. This means that if a Google-managed SSL certificate is compromised, it will affect all the HTTPS applications which are behind the Global External HTTPS Load Balancer using this certificate. You should always consider if a wildcard SSL certificate fits within your risk appetite.

Conclusion

Attaching a Google-managed wildcard SSL certificate to a Global External HTTPS Load Balancer is possible when using the Certificate Manager service and Cloud DNS using DNS authorization. Using this approach will provide a maintainable and cloud-native approach that removes additional configuration of certificates for sub-domains attached to a Global External HTTPS Load Balancer.


Photo from Parsoa Khorsand from Unsplash

Questions?

Get in touch with us to learn more about the subject and related solutions

Explore related posts