vmware / terraform-provider-avi

Terraform AVI Networks provider
https://registry.terraform.io/providers/vmware/avi/latest/docs
Mozilla Public License 2.0
31 stars 32 forks source link

avi_sslkeyandcertificate always has changes #594

Open lopf opened 4 months ago

lopf commented 4 months ago

Describe the bug

When avi_sslkeyandcertificate is used, it always has changes. Even though neither key or certificate has actually changed.

Reproduction steps

  1. Create a self-signed key/certificate pair, e.g. openssl req -new -newkey rsa:2048 -days 365 -nodes -x509 -keyout server.key -out server.crt
  2. Create a resource like this:

    
    resource "avi_sslkeyandcertificate" "certificate" {
    name = "mycert"
    
    type       = "SSL_CERTIFICATE_TYPE_VIRTUALSERVICE"
    tenant_ref = var.tenant_id  # pass as variable
    
    key = file("./server.key")
    
    certificate {
    self_signed = true
    certificate = file("./server.crt")
    }

}

3. `terraform apply`.. this creates the expected certificate.
4. `terraform apply` or `plan`, shows changes:

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: ~ update in-place

Terraform will perform the following actions:

module.certificate-from-file.avi_sslkeyandcertificate.certificate will be updated in-place

~ resource "avi_sslkeyandcertificate" "certificate" { id = "https://192.168.99.13/api/sslkeyandcertificate/sslkeyandcertificate-667eca56-174f-47ae-af9a-659129d80d70" ~ key = (sensitive value) name = "mycert"

(11 unchanged attributes hidden)

  - certificate {
      - certificate                 = <<-EOT
            -----BEGIN CERTIFICATE-----
            MIIFHzCCAwegAwIBAgIUIjZ+zzC2h9ipipsZHZWnN4mLFmswDQYJKoZIhvcNAQEL
            BQAwHzEdMBsGA1UEAwwUYWxiLXNlbGYtc2lnbmVkLWNlcnQwHhcNMjQwNDEwMDgz
            NjE1WhcNMjUwNDEwMDgzNjE1WjAfMR0wGwYDVQQDDBRhbGItc2VsZi1zaWduZWQt
            Y2VydDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALrH5pwW1O2Mh7BB

... cut for readability



### Expected behavior

If the key or certificate has not changed, nothing should be changed.

### Additional context

Possibly related to #510 and/or #522 ? Tested with provider version v22.1.5, NSX ALB version 22.1.5 2p3. The same is true for the Ansible module which is also not idempotent. So I assume this is because the API doesn't reveal information after the certificate is created. If that's the case, IMO, it should be documented and a workaround (implicit ignore?) offered.
jakauppila commented 1 month ago

Having this issue as well. We're leveraging a Certificate Management profile to issue certificates with Let's Encrypt.

I can get it to issue the certificate appropriately, but subsequent executions are detecting changes as the TF state read is pulling back the rest of the details that are now populated behind the certificate.

Example TF:

data "avi_certificatemanagementprofile" "profile" {
  name = "LetsEncrypt-Infoblox"
}

resource "avi_sslkeyandcertificate" "foo" {
  name = "terraform-example-foo"
  type = "SSL_CERTIFICATE_TYPE_VIRTUALSERVICE"
  certificate {
    self_signed = false
    subject {
      common_name = "letsencryptautomationtest.contoso.com"
      organization = "MYORG"
      organization_unit = "OU"
      locality = "TOWN"
      state = "STATE"
      country = "US"
    }
  }
  key_params {
    algorithm = "SSL_KEY_ALGORITHM_RSA"
    rsa_params {
      key_size = "SSL_KEY_2048_BITS"
    }
  }
  certificate_management_profile_ref = data.avi_certificatemanagementprofile.profile.id
}

Terraform Output:

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # avi_sslkeyandcertificate.foo will be updated in-place
  ~ resource "avi_sslkeyandcertificate" "foo" {
        id                                 = "https://AVICONTROLLER/api/sslkeyandcertificate/sslkeyandcertificate-b146c2ae-af07-4384-b654-df69982e8f39"
        name                               = "terraform-example-foo"
        # (13 unchanged attributes hidden)

      - ca_certs {
          - name   = "(STAGING) Counterfeit Cashew R10" -> null
            # (1 unchanged attribute hidden)
        }

      - certificate {
          - certificate                 = <<-EOT
                -----BEGIN CERTIFICATE-----
                CERT
                -----END CERTIFICATE-----
            EOT -> null
          - certificate_signing_request = <<-EOT
                -----BEGIN CERTIFICATE REQUEST-----
                CSR
                -----END CERTIFICATE REQUEST-----
            EOT -> null
          - days_until_expire           = "365" -> null
          - expiry_status               = "SSL_CERTIFICATE_GOOD" -> null
          - fingerprint                 = "SHA1 Fingerprint=00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00" -> null
          - not_after                   = "2024-11-05 03:38:54" -> null
          - not_before                  = "2024-08-07 03:38:55" -> null
          - public_key                  = <<-EOT
                -----BEGIN PUBLIC KEY-----
                CERT
                -----END PUBLIC KEY-----
            EOT -> null
          - self_signed                 = "false" -> null
          - serial_number               = "000000000000000009515270325387274183089671" -> null
          - signature_algorithm         = "sha256WithRSAEncryption" -> null
          - subject_alt_names           = [] -> null
          - text                        = <<-EOT
                Certificate:
                    Data:
                        Version: 3 (0x2)
                        Serial Number:
                            00:00:00:00:00:90:ff:b2:35:47:c1:9d:75:20:00:00:00:00
                        Signature Algorithm: sha256WithRSAEncryption
                        Issuer: C = US, O = (STAGING) Let's Encrypt, CN = (STAGING) Counterfeit Cashew R10
                        Validity
                            Not Before: Aug  7 03:38:55 2024 GMT
                            Not After : Nov  5 03:38:54 2024 GMT
                        Subject: CN = letsencryptautomationtest.contoso.com
                        Subject Public Key Info:
                            Public Key Algorithm: rsaEncryption
                                RSA Public-Key: (2048 bit)
                                Modulus:
                                    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                                    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                                    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                                    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                                    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                                    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                                    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                                    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                                    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                                    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                                    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                                    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                                    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                                    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                                    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                                    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                                    00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                                    00:00
                                Exponent: 65537 (0x10001)
                        X509v3 extensions:
                            X509v3 Key Usage: critical
                                Digital Signature, Key Encipherment
                            X509v3 Extended Key Usage:
                                TLS Web Server Authentication, TLS Web Client Authentication
                            X509v3 Basic Constraints: critical
                                CA:FALSE
                            X509v3 Subject Key Identifier:
                                00:00:00:00:00:90:ff:b2:35:47:c1:9d:75:20:00:00:00:00
                            X509v3 Authority Key Identifier:
                                keyid:00:00:00:00:00:90:ff:b2:35:47:c1:9d:75:20:00:00:00:00

                            Authority Information Access:
                                OCSP - URI:http://stg-r10.o.lencr.org
                                CA Issuers - URI:http://stg-r10.i.lencr.org/

                            X509v3 Subject Alternative Name:
                                DNS:letsencryptautomationtest.contoso.com
                            X509v3 Certificate Policies:
                                Policy: 2.23.140.1.2.1

                            CT Precertificate SCTs:
                                Signed Certificate Timestamp:
                                    Version   : v1 (0x0)
                                    Log ID    : 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                                                00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                                    Timestamp : Aug  7 04:37:25.144 2024 GMT
                                    Extensions: none
                                    Signature : ecdsa-with-SHA256
                                                00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                                                00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                                                00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                                                00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                                                00:00:00:00:00:00:00:00
                                Signed Certificate Timestamp:
                                    Version   : v1 (0x0)
                                    Log ID    : 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                                                00:00:00:00:00:90:ff:b2:35:47:c1:9d:75:20:00:00
                                    Timestamp : Aug  7 04:37:25.177 2024 GMT
                                    Extensions: none
                                    Signature : ecdsa-with-SHA256
                                                00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                                                00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                                                00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                                                00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                                                00:00:00:00:00:00:00
                    Signature Algorithm: sha256WithRSAEncryption
                         00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                         00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                         00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                         00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                         00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                         00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                         00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                         00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                         00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                         00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                         00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                         00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                         00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                         00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:
                         00:00:00:00
            EOT -> null
          - version                     = "3" -> null
            # (2 unchanged attributes hidden)

          - issuer {
              - common_name        = "(STAGING) Counterfeit Cashew R10" -> null
              - country            = "US" -> null
              - distinguished_name = "C=US, O=(STAGING) Let's Encrypt, CN=(STAGING) Counterfeit Cashew R10" -> null
              - organization       = "(STAGING) Let's Encrypt" -> null
                # (4 unchanged attributes hidden)
            }

          - subject {
              - common_name        = "letsencryptautomationtest.contoso.com" -> null
              - country            = "US" -> null
              - distinguished_name = "CN=letsencryptautomationtest.contoso.com" -> null
              - locality           = "TOWN" -> null
              - organization       = "MYORG" -> null
              - organization_unit  = "OU" -> null
              - state              = "STATE" -> null
                # (1 unchanged attribute hidden)
            }
        }
      + certificate {
          + certificate                 = (known after apply)
          + certificate_signing_request = (known after apply)
          + chain_verified              = (known after apply)
          + days_until_expire           = "365"
          + expiry_status               = "SSL_CERTIFICATE_GOOD"
          + fingerprint                 = (known after apply)
          + not_after                   = (known after apply)
          + not_before                  = (known after apply)
          + public_key                  = (known after apply)
          + self_signed                 = "false"
          + serial_number               = (known after apply)
          + signature                   = (known after apply)
          + signature_algorithm         = (known after apply)
          + subject_alt_names           = []
          + text                        = (known after apply)
          + version                     = (known after apply)

          + subject {
              + common_name        = "letsencryptautomationtest.contoso.com"
              + country            = "US"
              + distinguished_name = (known after apply)
              + email_address      = (known after apply)
              + locality           = "TOWN"
              + organization       = "MYORG"
              + organization_unit  = "OU"
              + state              = "STATE"
            }
        }

        # (1 unchanged block hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.

We can't simply ignore changes on the certificates block since if we have any changes to the subject, etc, we would want TF make the necessary changes and issue a new certificate.

lifecycle {
  ignore_changes = [ certificate, ca_certs ]
}