How to rotate Certificate for App Registration to rotate same way as you do for secrets

I have been able to get an App Registration secret to rotate and update the secret value into a keyvault, by following the following example: azuread_application_password

resource "time_rotating" "rotation_secret" {
  rotation_day = 1
  lifecycle {
    create_before_destroy = true
  }
}

resource "azuread_application_password" "client_secret" {
  display_name          = "terraformgenerated"
  application_object_id = module.appreg.object_id
  end_date_relative     = "4320h" #180 days
  rotate_when_changed = {
    "rotation" = time_rotating.rotation_secret.id
  }
  lifecycle {
    create_before_destroy = true
  }
}

resource "azurerm_key_vault_secret" "client_secret" {
  name         = "clientsecret"
  value        = azuread_application_password.client_secret.value
  key_vault_id = module.key_vault.kv_id
}

My code example above, will change the secret and update the Key Vault with the value if I run the Terraform code 1 day after the last time it runs. If I run the Terraform code within that day, then the secret doesn’t change.

However, if the Terraform doesn’t run, the secret within Azure on the App Registration will continue to be valid for 4320 hours (180 days), and the secret will continue to be in the keyvault.


According to the documentation for certificates, the way to rotate them is via the keyvault itself. azurerm_key_vault_certificate

resource "azurerm_key_vault_certificate" "certificate" {
  name = "generated-cert"
  key_vault_id = module.key_vault.id

  certificate_policy {
    issuer_parameters {
      name = "Self"
    }

    key_properties {
      exportable = true
      key_size = 2048
      key_type = "RSA"
      reuse_key = "true"
    }

    lifetime_action {
      action {
        action_type = "AutoRenew"
      }

      trigger {
        days_before_expiry = 27
      }
    }

    secret_properties {
      content_type = "application/x-pkcs12"
    }

    x509_certificate_properties {
      extended_key_usage = ["1.3.6.1.5.5.7.3.1", "1.3.6.1.5.5.7.3.2"]

      key_usage = [
        "dataEncipherment",
        "digitalSignature",
        "keyAgreement",
        "keyCertSign",
        "keyEncipherment",
        "cRLSign"
      ]

      subject = "CN=${module.appreg.application_display_name}"
      validity_in_months = 1
    }
  }
}

resource "azuread_application_certificate" "app_cert" {
  application_object_id = module.appreg.object_id
  type                  = "AsymmetricX509Cert"
  encoding              = "hex"
  value                 = azurerm_key_vault_certificate.certificate.certificate_data
  end_date              = azurerm_key_vault_certificate.certificate.certificate_attribute[0].expires
  start_date            = azurerm_key_vault_certificate.certificate.certificate_attribute[0].not_before
}

My example code above creates a certificate valid for 1 month, with an auto renew 27 days before certificate expires.

However, this code puts the rotation in the hands of the Azure Key Vault. It will automatically rotate the certificate, but unless the Terraform is run again, it will not update App Registration. Meaning from the time the Key Vault rotates the certificate to the Terraform run to update the App Registration, the web applications using that app registration and certificate fail authentication.

Is there a way to get it to work like the secret, where it’s flagged for rotation, but only rotates when the Terraform is run again in a CI/CD pipeline on a cron trigger?

@apparentlymart could you help with this one?

resource “time_rotating” “certificate_rotation” {
rotation_day = 1
lifecycle {
create_before_destroy = true
}
}

resource “azurerm_key_vault_certificate” “certificate” {
name = “generated-cert”
key_vault_id = module.key_vault.id

certificate_policy {
issuer_parameters {
name = “Self”
}

key_properties {
  exportable = true
  key_size = 2048
  key_type = "RSA"
  reuse_key = "true"
}

lifetime_action {
  action {
    action_type = "AutoRenew"
  }

  trigger {
    days_before_expiry = 27
  }
}

secret_properties {
  content_type = "application/x-pkcs12"
}

x509_certificate_properties {
  extended_key_usage = ["1.3.6.1.5.5.7.3.1", "1.3.6.1.5.5.7.3.2"]

  key_usage = [
    "dataEncipherment",
    "digitalSignature",
    "keyAgreement",
    "keyCertSign",
    "keyEncipherment",
    "cRLSign"
  ]

  subject = "CN=${module.appreg.application_display_name}"
  validity_in_months = 1
}

}

rotate_when_changed = {
“rotation” = time_rotating.certificate_rotation.id
}

lifecycle {
create_before_destroy = true
}
}

This will allow Terraform to rotate the certificate once every day, provided that the Terraform code is run. The code will only update the certificate in the Key Vault if the “rotation” value in the “rotate_when_changed” block changes.