okta / terraform-provider-okta

A Terraform provider to manage Okta resources, enabling infrastructure-as-code provisioning and management of users, groups, applications, and other Okta objects.
https://registry.terraform.io/providers/okta/okta
Mozilla Public License 2.0
253 stars 203 forks source link

okta_domain_certificate: certificates in the certificate chain have an invalid format #1426

Closed boekkooi-lengoo closed 1 year ago

boekkooi-lengoo commented 1 year ago

Community Note

Terraform Version

# terraform -v
Terraform v1.3.6
on linux_amd64
+ provider registry.terraform.io/cloudflare/cloudflare v3.32.0
+ provider registry.terraform.io/hashicorp/google v4.48.0
+ provider registry.terraform.io/hashicorp/time v0.9.1
+ provider registry.terraform.io/hashicorp/tls v4.0.4
+ provider registry.terraform.io/okta/okta v3.40.0

Affected Resource(s)

Terraform Configuration Files

locals {
  okta_domain_id   = "<myDomainId>"
  okta_domain_name = "my.example.com"
}

terraform {
  backend "gcs" {
    bucket = "<my-bucket>"
  }
  required_providers {
    # See https://registry.terraform.io/providers/hashicorp/google/latest/docs
    google = {
      source  = "hashicorp/google"
      version = "~> 4.5"
    }
    # See https://registry.terraform.io/providers/okta/okta/latest/docs
    okta = {
      source  = "okta/okta"
      version = "~> 3.20"
    }
    # See https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs
    cloudflare = {
      source                = "cloudflare/cloudflare"
      version               = "~> 3.10"
      configuration_aliases = [cloudflare.api_user_service_key]
    }
    # See https://registry.terraform.io/providers/hashicorp/tls/latest/docs
    tls = {
      source  = "hashicorp/tls"
      version = "~> 4.0"
    }
    # See https://registry.terraform.io/providers/hashicorp/time/latest/docs
    time = {
      source  = "hashicorp/time"
      version = "~> 0.9.1"
    }
  }
}

provider "okta" {
  # Using environment variables
  # see https://registry.terraform.io/providers/okta/okta/latest/docs#environment-variables
  #  scopes = [
  #    "okta.domains.manage",
  #    "okta.domains.read",
  #  ]
}

provider "cloudflare" {
  api_token = "<CloudflareAPIToken>"
}

provider "cloudflare" {
  alias                = "api_user_service_key"
  api_user_service_key = "<CloudflareAPIUserServiceKey>"
}

data "cloudflare_origin_ca_root_certificate" "origin_ca" {
  algorithm = "rsa"
}

data "cloudflare_zone" "tld" {
  name = local.cloudflare_zone
}

# Rotate the certificate automatically very x days
resource "time_rotating" "okta_cert" {
  rotation_days = 200
}

# Create a CSR and generate a CA certificate
resource "tls_private_key" "okta" {
  # Since the rotate ID changes when the rotation changes this will trigger Terraform into recalculating and rotating the certificate
  algorithm = time_rotating.okta_cert.id != "" ? "RSA" : "invalid"
}

resource "tls_cert_request" "okta" {
  private_key_pem = tls_private_key.okta.private_key_pem

  subject {
    common_name  = local.okta_domain_name
    organization = "Lengoo GmbH"
  }
}

# Create a Cloudflare Origin CA certificate used to protect traffic to your origin without involving a third party Certificate Authority.
resource "cloudflare_origin_ca_certificate" "okta" {
  provider           = cloudflare.api_user_service_key
  csr                = tls_cert_request.okta.cert_request_pem
  hostnames          = [local.okta_domain_name]
  request_type       = "origin-rsa"
  requested_validity = 365
}

# Add the certificate to Okta
resource "okta_domain_certificate" "cert" {
  domain_id         = local.okta_domain_id
  type              = "PEM"
  certificate       = chomp(cloudflare_origin_ca_certificate.okta.certificate)
  private_key       = chomp(tls_private_key.okta.private_key_pem)
  certificate_chain = chomp(data.cloudflare_origin_ca_root_certificate.origin_ca.cert_pem)
}

Debug Output

okta_domain_certificate.<company>: Modifying... [id=OcD2s4725ekZeTXsz417]
2023-01-17T19:16:01.257+0100 [INFO]  Starting apply for okta_domain_certificate.cert
2023-01-17T19:16:01.257+0100 [DEBUG] okta_domain_certificate.<company>: applying the planned Update change
2023-01-17T19:16:01.257+0100 [DEBUG] provider.terraform-provider-okta_v3.40.0: 2023/01/17 07:16:01 [DEBUG] performing request: method=PUT url=https://<company>.okta.com/api/v1/domains/OcD2s4725ekZeTXsz417/certificate
2023-01-17T19:16:01.257+0100 [INFO]  provider.terraform-provider-okta_v3.40.0: 2023/01/17 19:16:01 [DEBUG] Okta API Request Details:
---[ REQUEST ]---------------------------------------
PUT /api/v1/domains/OcD2s4725ekZeTXsz417/certificate HTTP/1.1
Host: <company>.okta.com
User-Agent: okta-sdk-golang/2.15.0 golang/go1.17.13 linux/amd64 okta-terraform/3.40.0
Content-Length: 3534
Accept: application/json
Authorization: Bearer <secret>
Content-Type: application/json
Accept-Encoding: gzip

{
 "certificate": "-----BEGIN CERTIFICATE-----<secret>\n-----END CERTIFICATE-----",
 "certificateChain": "bjtTwC3Qf25xWYbibJRxKIuJzX24Qaou3N3GAPGF77EMms2m1kjypHwPVWDb3ghhfxLt_Migw21iCtV3xtUTyQ==",
 "privateKey": "-----BEGIN RSA PRIVATE KEY-----<secret>-----END RSA PRIVATE KEY-----",
 "type": "PEM"
}

-----------------------------------------------------: timestamp=2023-01-17T19:16:01.257+0100
2023-01-17T19:16:01.571+0100 [INFO]  provider.terraform-provider-okta_v3.40.0: 2023/01/17 19:16:01 [DEBUG] Okta API Response Details:
---[ RESPONSE ]--------------------------------------
HTTP/2.0 400 Bad Request
Connection: close
Cache-Control: no-cache, no-store
Content-Security-Policy: default-src 'self' <company>.okta.com *.oktacdn.com; connect-src 'self' <company>.okta.com <company>-admin.okta.com *.oktacdn.com *.mixpanel.com *.mapbox.com app.pendo.io data.pendo.io pendo-static-5634101834153984.storage.googleapis.com pendo-static-5391521872216064.storage.googleapis.com *.mtls.okta.com <company>.kerberos.okta.com *.authenticatorlocalprod.com:8769 http://localhost:8769 http://127.0.0.1:8769 *.authenticatorlocalprod.com:65111 http://localhost:65111 http://127.0.0.1:65111 *.authenticatorlocalprod.com:65121 http://localhost:65121 http://127.0.0.1:65121 *.authenticatorlocalprod.com:65131 http://localhost:65131 http://127.0.0.1:65131 *.authenticatorlocalprod.com:65141 http://localhost:65141 http://127.0.0.1:65141 *.authenticatorlocalprod.com:65151 http://localhost:65151 http://127.0.0.1:65151 https://oinmanager.okta.com data:; script-src 'unsafe-inline' 'unsafe-eval' 'self' <company>.okta.com *.oktacdn.com; style-src 'unsafe-inline' 'self' <company>.okta.com *.oktacdn.com app.pendo.io cdn.pendo.io pendo-static-5634101834153984.storage.googleapis.com pendo-static-5391521872216064.storage.googleapis.com; frame-src 'self' <company>.okta.com <company>-admin.okta.com login.okta.com com-okta-authenticator:; img-src 'self' <company>.okta.com *.oktacdn.com *.tiles.mapbox.com *.mapbox.com app.pendo.io data.pendo.io cdn.pendo.io pendo-static-5634101834153984.storage.googleapis.com pendo-static-5391521872216064.storage.googleapis.com data: blob:; font-src 'self' <company>.okta.com data: *.oktacdn.com fonts.gstatic.com; frame-ancestors 'self'
Content-Type: application/json
Date: Tue, 17 Jan 2023 18:16:01 GMT
Expect-Ct: report-uri="https://oktaexpectct.report-uri.com/r/t/ct/reportOnly", max-age=0
Expires: 0
P3p: CP="HONK"
Pragma: no-cache
Public-Key-Pins-Report-Only: pin-sha256="r5EfzZxQVvQpKo3AgYRaT7X2bDO/kj3ACwmxfdT2zt8="; pin-sha256="MaqlcUgk2mvY/RFSGeSwBRkI+rZ6/dxe/DuQfBT/vnQ="; pin-sha256="72G5IEvDEWn+EThf3qjR7/bQSWaS2ZSLqolhnO6iyJI="; pin-sha256="rrV6CLCCvqnk89gWibYT0JO6fNQ8cCit7GGoiVTjCOg="; max-age=60; report-uri="https://okta.report-uri.com/r/default/hpkp/reportOnly"
Server: nginx
Set-Cookie: sid=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/
Set-Cookie: autolaunch_triggered=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/
Set-Cookie: JSESSIONID=A573179A7BE81B564D8A1EBDFB6B8274; Path=/; Secure; HttpOnly
Strict-Transport-Security: max-age=315360000; includeSubDomains
X-Content-Type-Options: nosniff
X-Okta-Request-Id: Y8bl4fsLiU7HLOQ0T-UmzwAABEw
X-Rate-Limit-Limit: 50
X-Rate-Limit-Remaining: 49
X-Rate-Limit-Reset: 1673979421
X-Xss-Protection: 0

{
 "errorCode": "E0000001",
 "errorSummary": "Api validation failed: certificateChain",
 "errorLink": "E0000001",
 "errorId": "oaeynBtLeccQkibkDoaFNo8bQ",
 "errorCauses": [
  {
   "errorSummary": "certificateChain: One or more certificates in the certificate chain have an invalid format. All certificates in the certificate chain must be valid PEM encoded RSA certificates"
  }
 ]
}
-----------------------------------------------------: timestamp=2023-01-17T19:16:01.571+0100
2023-01-17T19:16:01.571+0100 [ERROR] provider.terraform-provider-okta_v3.40.0: Response contains error diagnostic: @module=sdk.proto diagnostic_summary="failed to update domain's certificate: the API returned an error: Api validation failed: certificateChain. Causes: errorSummary: certificateChain: One or more certificates in the certificate chain have an invalid format. All certificates in the certificate chain must be valid PEM encoded RSA certificates" tf_req_id=af622dce-2b61-2e11-a1b1-d533145df136 tf_resource_type=okta_domain_certificate @caller=github.com/hashicorp/terraform-plugin-go@v0.12.0/tfprotov5/internal/diag/diagnostics.go:56 diagnostic_detail= diagnostic_severity=ERROR tf_proto_version=5.3 tf_provider_addr=provider tf_rpc=ApplyResourceChange timestamp=2023-01-17T19:16:01.571+0100
2023-01-17T19:16:01.572+0100 [ERROR] vertex "okta_domain_certificate.<company>" error: failed to update domain's certificate: the API returned an error: Api validation failed: certificateChain. Causes: errorSummary: certificateChain: One or more certificates in the certificate chain have an invalid format. All certificates in the certificate chain must be valid PEM encoded RSA certificates
╷
│ Error: failed to update domain's certificate: the API returned an error: Api validation failed: certificateChain. Causes: errorSummary: certificateChain: One or more certificates in the certificate chain have an invalid format. All certificates in the certificate chain must be valid PEM encoded RSA certificates
│ 
│   with okta_domain_certificate.<company>,
│   on domain.tf line 58, in resource "okta_domain_certificate" "<company>":
│   58: resource "okta_domain_certificate" "<company>" {
│ 
╵
2023-01-17T19:16:01.896+0100 [DEBUG] provider.stdio: received EOF, stopping recv loop: err="rpc error: code = Unavailable desc = error reading from server: EOF"
2023-01-17T19:16:01.897+0100 [DEBUG] provider: plugin process exited: path=.terraform/providers/registry.terraform.io/okta/okta/3.40.0/linux_amd64/terraform-provider-okta_v3.40.0 pid=126952
2023-01-17T19:16:01.897+0100 [DEBUG] provider: plugin exited

Expected Behavior

That the certificateChain is not a hash but the actual value of data.cloudflare_origin_ca_root_certificate.origin_ca.cert_pem

Actual Behavior

certificateChain, certificate and privateKey become strange hash/base64 values after they are applied (state file contains the correct information). This result in when one of them is tainted (try terraform taint "time_rotating.okta_cert") or otherwise changed the request to the Okta API has the hashed value and not the actual certificate which results in strange errors like certificateChain. Causes: errorSummary: certificateChain: One or more certificates in the certificate chain have an invalid format. All certificates in the certificate chain must be valid PEM encoded RSA certificates.

Steps to Reproduce

In the above config setup replace the string start with< and end with >.

  1. terraform apply
  2. terraform taint "time_rotating.okta_cert"
  3. terraform apply

References

monde commented 1 year ago

@boekkooi-lengoo I really appreciate your attention to detail reporting this issue. I've triaged it onto our internal backlog.

Okta internal reference: https://oktainc.atlassian.net/browse/OKTA-567505

monde commented 1 year ago

Released in https://github.com/okta/terraform-provider-okta/releases/tag/v3.42.0