Skip to main content

Enable origin SSL validation

Origin SSL validation makes CDN edge servers verify that the origin presents a valid TLS certificate for the expected hostname. proxy_ssl_ca is the public CA certificate that checks the origin certificate, while proxy_ssl_data is an uploaded certificate and private key that the edge presents when the origin requests a client certificate.

An API token is required, along with a CDN resource configured for HTTPS origin pull, a CA certificate to store as proxy_ssl_ca, and an uploaded SSL certificate to send as proxy_ssl_data.

export GCORE_API_KEY="{YOUR_API_KEY}"

Add a trusted CA certificate

Upload the CA certificate that issued the origin certificate. If the origin certificate is self-signed, upload that certificate itself.

A trusted CA request stores that public certificate and returns the id for proxy_ssl_ca.

from gcore import CDB

client = CDB()  # Reads GCORE_API_KEY from env

ca = client.cdn.trusted_ca_certificates.create(
    name="origin.mywebsite.com",
    ssl_certificate=open("ca.pem", encoding="ascii").read(),
)
print(ca.id)
package main

import (
    "context"
    "fmt"
    "os"

    gcore "github.com/G-Core/gcore-go"
    "github.com/G-Core/gcore-go/cdn"
)

func main() {
    client := gcore.NewClient() // Reads GCORE_API_KEY from env
    ctx := context.Background()

    pem, err := os.ReadFile("ca.pem")
    if err != nil {
        panic(err)
    }
    ca, err := client.CDN.TrustedCaCertificates.New(ctx, cdn.TrustedCaCertificateNewParams{
        Name:           "origin.mywebsite.com",
        SslCertificate: string(pem),
    })
    if err != nil {
        panic(err)
    }
    fmt.Println(ca.ID)
}
curl -X POST "https://api.cdb-staging.cdn.orange.com/cdn/sslCertificates" \
  -H "Authorization: APIKey $GCORE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "origin.mywebsite.com",
    "sslCertificate": "-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----\n"
  }'

The API returns:

{
  "id": 1004,
  "name": "origin.mywebsite.com"
}

Get the SSL certificate ID

Use the id of the uploaded client certificate and private key as proxy_ssl_data. This object is separate from the trusted CA.

A certificate list returns the id of the certificate with that name.

from gcore import CDB

client = CDB()

certificates = client.cdn.certificates.list()
cert_id = next(item.id for item in certificates if item.name == "client.mywebsite.com")
print(cert_id)
package main

import (
    "context"
    "fmt"

    gcore "github.com/G-Core/gcore-go"
    "github.com/G-Core/gcore-go/cdn"
)

func main() {
    client := gcore.NewClient()
    ctx := context.Background()

    page, err := client.CDN.Certificates.List(ctx, cdn.CertificateListParams{})
    if err != nil {
        panic(err)
    }
    var certID int64
    for _, item := range page.Results {
        if item.Name == "client.mywebsite.com" {
            certID = item.ID
            break
        }
    }
    fmt.Println(certID)
}
curl "https://api.cdb-staging.cdn.orange.com/cdn/sslData?limit=1000" \
  -H "Authorization: APIKey $GCORE_API_KEY"

The API returns:

{
  "results": [
    {
      "id": 1003,
      "name": "client.mywebsite.com"
    }
  ]
}

Enable validation on the resource

The first resource update requires both certificate ids even when the origin does not request a client certificate. Omitting either id returns HTTP 400 with the message Can not enable proxy_ssl feature while both proxy CA certificate and proxy ssl data not specified.

from gcore import CDB

client = CDB()

resource = client.cdn.cdn_resources.update(
    1001,
    proxy_ssl_enabled=True,
    proxy_ssl_ca=1004,
    proxy_ssl_data=1003,
)
print(resource.proxy_ssl_enabled, resource.proxy_ssl_ca, resource.proxy_ssl_data)
package main

import (
    "context"
    "fmt"

    gcore "github.com/G-Core/gcore-go"
    "github.com/G-Core/gcore-go/cdn"
)

func main() {
    client := gcore.NewClient()
    ctx := context.Background()

    resource, err := client.CDN.CDNResources.Update(ctx, 1001, cdn.CDNResourceUpdateParams{
        ProxySslEnabled: gcore.Bool(true),
        ProxySslCa:      gcore.Int(1004),
        ProxySslData:    gcore.Int(1003),
    })
    if err != nil {
        panic(err)
    }
    fmt.Println(resource.ProxySslEnabled, resource.ProxySslCa, resource.ProxySslData)
}
curl -X PATCH "https://api.cdb-staging.cdn.orange.com/cdn/resources/1001" \
  -H "Authorization: APIKey $GCORE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "proxy_ssl_enabled": true,
    "proxy_ssl_ca": 1004,
    "proxy_ssl_data": 1003
  }'

The API returns:

{
  "id": 1001,
  "proxy_ssl_enabled": true,
  "proxy_ssl_ca": 1004,
  "proxy_ssl_data": 1003
}

proxy_ssl_ca and proxy_ssl_data refer to different certificate collections. Sending an SSL certificate id as proxy_ssl_ca, or a trusted CA id as proxy_ssl_data, returns HTTP 400 with the message Invalid pk "1003" - object does not exist.

Disable validation on the resource

The same update turns validation off when proxy_ssl_enabled is false and keeps both certificate ids. A later update can set proxy_ssl_enabled to true alone, because those ids are already stored.

from gcore import CDB

client = CDB()

resource = client.cdn.cdn_resources.update(1001, proxy_ssl_enabled=False)
print(resource.proxy_ssl_enabled, resource.proxy_ssl_ca, resource.proxy_ssl_data)
package main

import (
    "context"
    "fmt"

    gcore "github.com/G-Core/gcore-go"
    "github.com/G-Core/gcore-go/cdn"
)

func main() {
    client := gcore.NewClient()
    ctx := context.Background()

    resource, err := client.CDN.CDNResources.Update(ctx, 1001, cdn.CDNResourceUpdateParams{
        ProxySslEnabled: gcore.Bool(false),
    })
    if err != nil {
        panic(err)
    }
    fmt.Println(resource.ProxySslEnabled, resource.ProxySslCa, resource.ProxySslData)
}
curl -X PATCH "https://api.cdb-staging.cdn.orange.com/cdn/resources/1001" \
  -H "Authorization: APIKey $GCORE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"proxy_ssl_enabled": false}'

The API returns:

{
  "id": 1001,
  "proxy_ssl_enabled": false,
  "proxy_ssl_ca": 1004,
  "proxy_ssl_data": 1003
}

Enable origin SSL validation on a CDN resource with the Terraform provider v2, so edge servers check that the origin presents a valid TLS certificate for the expected hostname. proxy_ssl_ca is the public CA certificate that checks the origin certificate, while proxy_ssl_data is an uploaded client certificate and private key that the edge presents when the origin requests a client certificate. The resource uses HTTPS origin pull.

An uploaded certificate is required for proxy_ssl_data, because the data source reads it when Terraform plans.

proxy_ssl_ca and proxy_ssl_data refer to different certificate collections. Sending a client certificate id as proxy_ssl_ca, or a trusted CA id as proxy_ssl_data, returns HTTP 400 with the message Invalid pk "1003" - object does not exist.

Enable validation

Store the public CA certificate and set proxy_ssl_enabled, proxy_ssl_ca, and proxy_ssl_data on the CDN resource, because creating the resource with proxy_ssl_enabled set to true and only one of those ids returns HTTP 400 with the message Can not enable proxy_ssl feature while both proxy CA certificate and proxy ssl data not specified. If the origin certificate is self-signed, use that certificate as the trusted CA.

data "gcore_cdn_certificates" "account" {}

locals {
  client_certificate_id = one([
    for certificate in data.gcore_cdn_certificates.account.items :
    certificate.id if certificate.name == "client.mywebsite.com"
  ])
}

resource "gcore_cdn_origin_group" "example" {
  name = "my-origin-group"

  sources = [
    {
      source  = "example.com"
      enabled = true
    }
  ]
}

resource "gcore_cdn_trusted_ca_certificate" "example" {
  name            = "origin.mywebsite.com"
  ssl_certificate = file("ca.pem")
}

resource "gcore_cdn_resource" "example" {
  cname             = "sslval.mywebsite.com"
  origin_group      = gcore_cdn_origin_group.example.id
  origin_protocol   = "HTTPS"
  proxy_ssl_enabled = true
  proxy_ssl_ca      = gcore_cdn_trusted_ca_certificate.example.id
  proxy_ssl_data    = local.client_certificate_id
}

Disable validation

Set proxy_ssl_enabled to false and keep both certificate ids. The ids stay on the resource, so a later apply can set proxy_ssl_enabled to true without repeating them.

data "gcore_cdn_certificates" "account" {}

locals {
  client_certificate_id = one([
    for certificate in data.gcore_cdn_certificates.account.items :
    certificate.id if certificate.name == "client.mywebsite.com"
  ])
}

resource "gcore_cdn_origin_group" "example" {
  name = "my-origin-group"

  sources = [
    {
      source  = "example.com"
      enabled = true
    }
  ]
}

resource "gcore_cdn_trusted_ca_certificate" "example" {
  name            = "origin.mywebsite.com"
  ssl_certificate = file("ca.pem")
}

resource "gcore_cdn_resource" "example" {
  cname             = "sslval.mywebsite.com"
  origin_group      = gcore_cdn_origin_group.example.id
  origin_protocol   = "HTTPS"
  proxy_ssl_enabled = false
  proxy_ssl_ca      = gcore_cdn_trusted_ca_certificate.example.id
  proxy_ssl_data    = local.client_certificate_id
}