Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ NEW FEATURES:

* data-source/tls_public_key: Added support for [ED25519](https://ed25519.cr.yp.to/) key algorithm ([#160](https://github.com/hashicorp/terraform-provider-tls/pull/160)).

* resource/tls_cert_request: Added support for [ED25519](https://ed25519.cr.yp.to/) key algorithm ([#173](https://github.com/hashicorp/terraform-provider-tls/pull/173)).

* resource/tls_self_signed_cert: Added support for [ED25519](https://ed25519.cr.yp.to/) key algorithm ([#173](https://github.com/hashicorp/terraform-provider-tls/pull/173)).

* resource/tls_locally_signed_cert: Added support for [ED25519](https://ed25519.cr.yp.to/) key algorithm ([#173](https://github.com/hashicorp/terraform-provider-tls/pull/173)).

ENHANCEMENTS:

* resource/tls_private_key: New attributes `private_key_openssh` (OpenSSH PEM format) and `public_key_fingerprint_sha256` ([#151](https://github.com/hashicorp/terraform-provider-tls/pull/151)).
Expand All @@ -17,12 +23,25 @@ ENHANCEMENTS:
* resource/tls_locally_signed_cert: Resource will validate that `allowed_uses` list contains values that are part
of the documented set, throwing an error if they are invalid, instead of silently ignoring it
([#169](https://github.com/hashicorp/terraform-provider-tls/pull/169)).
* resource/tls_locally_signed_cert: The argument `ca_key_algorithm` is now optional and deprecated, as the resource infers the
algorithm from the given key `ca_private_key_pem`. It will be replaced by a read-only attribute,
exposing the inferred algorithm, in the next major release
([#173](https://github.com/hashicorp/terraform-provider-tls/pull/173)).

* resource/tls_self_signed_cert: Resource will validate that `validity_period_hours` and `early_renewal_hours`
are set to a value greater or equal then zero ([#169](https://github.com/hashicorp/terraform-provider-tls/pull/169)).
* resource/tls_self_signed_cert: Resource will validate that `allowed_uses` list contains values that are part
of the documented set, throwing an error if they are invalid, instead of silently ignoring it
([#169](https://github.com/hashicorp/terraform-provider-tls/pull/169)).
* resource/tls_self_signed_cert: The argument `key_algorithm` is now optional and deprecated, as the resource infers the
algorithm from the given key `private_key_pem`. It will be replaced by a read-only attribute,
exposing the inferred algorithm, in the next major release
([#173](https://github.com/hashicorp/terraform-provider-tls/pull/173)).

* resource/tls_cert_request: The argument `key_algorithm` is now optional and deprecated, as the resource infers the
algorithm from the given key `private_key_pem`. It will be replaced by a read-only attribute,
exposing the inferred algorithm, in the next major release
([#173](https://github.com/hashicorp/terraform-provider-tls/pull/173)).

NOTES:

Expand Down
3 changes: 1 addition & 2 deletions docs/resources/cert_request.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ state and does not create any external managed resources.

```terraform
resource "tls_cert_request" "example" {
key_algorithm = "ECDSA"
private_key_pem = file("private_key.pem")

subject {
Expand All @@ -38,14 +37,14 @@ resource "tls_cert_request" "example" {

### Required

- `key_algorithm` (String) Name of the algorithm used when generating the private key provided in `private_key_pem`.
- `private_key_pem` (String, Sensitive) Private key in [PEM (RFC 1421)](https://datatracker.ietf.org/doc/html/rfc1421) format, that the certificate will belong to. This can be read from a separate file using the [`file`](https://www.terraform.io/language/functions/file) interpolation function. Only an irreversible secure hash of the private key will be stored in the Terraform state.
- `subject` (Block List, Min: 1) The subject for which a certificate is being requested. The acceptable arguments are all optional and their naming is based upon [Issuer Distinguished Names (RFC5280)](https://tools.ietf.org/html/rfc5280#section-4.1.2.4) section. (see [below for nested schema](#nestedblock--subject))

### Optional

- `dns_names` (List of String) List of DNS names for which a certificate is being requested (i.e. certificate subjects).
- `ip_addresses` (List of String) List of IP addresses for which a certificate is being requested (i.e. certificate subjects).
- `key_algorithm` (String, Deprecated) Name of the algorithm used when generating the private key provided in `private_key_pem`. **NOTE**: this is deprecated and ignored, as the key algorithm is now inferred from the key.
- `uris` (List of String) List of URIs for which a certificate is being requested (i.e. certificate subjects).

### Read-Only
Expand Down
3 changes: 1 addition & 2 deletions docs/resources/locally_signed_cert.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ or when deployed internally to an organization.
```terraform
resource "tls_locally_signed_cert" "example" {
cert_request_pem = file("cert_request.pem")
ca_key_algorithm = "ECDSA"
ca_private_key_pem = file("ca_private_key.pem")
ca_cert_pem = file("ca_cert.pem")

Expand All @@ -39,13 +38,13 @@ resource "tls_locally_signed_cert" "example" {

- `allowed_uses` (List of String) List of key usages allowed for the issued certificate. Values are defined in [RFC 5280](https://datatracker.ietf.org/doc/html/rfc5280) and combine flags defined by both [Key Usages](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.3) and [Extended Key Usages](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.12). Accepted values: `any_extended`, `cert_signing`, `client_auth`, `code_signing`, `content_commitment`, `crl_signing`, `data_encipherment`, `decipher_only`, `digital_signature`, `email_protection`, `encipher_only`, `ipsec_end_system`, `ipsec_tunnel`, `ipsec_user`, `key_agreement`, `key_encipherment`, `microsoft_commercial_code_signing`, `microsoft_kernel_code_signing`, `microsoft_server_gated_crypto`, `netscape_server_gated_crypto`, `ocsp_signing`, `server_auth`, `timestamping`.
- `ca_cert_pem` (String) Certificate data of the Certificate Authority (CA) in [PEM (RFC 1421)](https://datatracker.ietf.org/doc/html/rfc1421) format.
- `ca_key_algorithm` (String) Name of the algorithm used when generating the private key provided in `ca_private_key_pem`.
- `ca_private_key_pem` (String, Sensitive) Private key of the Certificate Authority (CA) used to sign the certificate, in [PEM (RFC 1421)](https://datatracker.ietf.org/doc/html/rfc1421) format.
- `cert_request_pem` (String) Certificate request data in [PEM (RFC 1421)](https://datatracker.ietf.org/doc/html/rfc1421) format.
- `validity_period_hours` (Number) Number of hours, after initial issuing, that the certificate will remain valid for.

### Optional

- `ca_key_algorithm` (String, Deprecated) Name of the algorithm used when generating the private key provided in `ca_private_key_pem`. **NOTE**: this is deprecated and ignored, as the key algorithm is now inferred from the key.
- `early_renewal_hours` (Number) The resource will consider the certificate to have expired the given number of hours before its actual expiry time. This can be useful to deploy an updated certificate in advance of the expiration of the current certificate. However, the old certificate remains valid until its true expiration time, since this resource does not (and cannot) support certificate revocation. Also, this advance update can only be performed should the Terraform configuration be applied during the early renewal period. (default: `0`)
- `is_ca_certificate` (Boolean) Is the generated certificate representing a Certificate Authority (CA) (default: `false`).
- `set_subject_key_id` (Boolean) Should the generated certificate include a subject key identifier (default: `false`).
Expand Down
3 changes: 1 addition & 2 deletions docs/resources/self_signed_cert.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ connecting to a server that has a self-signed certificate.

```terraform
resource "tls_self_signed_cert" "example" {
key_algorithm = "ECDSA"
private_key_pem = file("private_key.pem")

subject {
Expand All @@ -43,7 +42,6 @@ resource "tls_self_signed_cert" "example" {
### Required

- `allowed_uses` (List of String) List of key usages allowed for the issued certificate. Values are defined in [RFC 5280](https://datatracker.ietf.org/doc/html/rfc5280) and combine flags defined by both [Key Usages](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.3) and [Extended Key Usages](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.12). Accepted values: `any_extended`, `cert_signing`, `client_auth`, `code_signing`, `content_commitment`, `crl_signing`, `data_encipherment`, `decipher_only`, `digital_signature`, `email_protection`, `encipher_only`, `ipsec_end_system`, `ipsec_tunnel`, `ipsec_user`, `key_agreement`, `key_encipherment`, `microsoft_commercial_code_signing`, `microsoft_kernel_code_signing`, `microsoft_server_gated_crypto`, `netscape_server_gated_crypto`, `ocsp_signing`, `server_auth`, `timestamping`.
- `key_algorithm` (String) Name of the algorithm used when generating the private key provided in `private_key_pem`.
- `private_key_pem` (String, Sensitive) Private key in [PEM (RFC 1421)](https://datatracker.ietf.org/doc/html/rfc1421) format, that the certificate will belong to. This can be read from a separate file using the [`file`](https://www.terraform.io/language/functions/file) interpolation function. Only an irreversible secure hash of the private key will be stored in the Terraform state.
- `subject` (Block List, Min: 1) The subject for which a certificate is being requested. The acceptable arguments are all optional and their naming is based upon [Issuer Distinguished Names (RFC5280)](https://tools.ietf.org/html/rfc5280#section-4.1.2.4) section. (see [below for nested schema](#nestedblock--subject))
- `validity_period_hours` (Number) Number of hours, after initial issuing, that the certificate will remain valid for.
Expand All @@ -54,6 +52,7 @@ resource "tls_self_signed_cert" "example" {
- `early_renewal_hours` (Number) The resource will consider the certificate to have expired the given number of hours before its actual expiry time. This can be useful to deploy an updated certificate in advance of the expiration of the current certificate. However, the old certificate remains valid until its true expiration time, since this resource does not (and cannot) support certificate revocation. Also, this advance update can only be performed should the Terraform configuration be applied during the early renewal period. (default: `0`)
- `ip_addresses` (List of String) List of IP addresses for which a certificate is being requested (i.e. certificate subjects).
- `is_ca_certificate` (Boolean) Is the generated certificate representing a Certificate Authority (CA) (default: `false`).
- `key_algorithm` (String, Deprecated) Name of the algorithm used when generating the private key provided in `private_key_pem`. **NOTE**: this is deprecated and ignored, as the key algorithm is now inferred from the key.
- `set_subject_key_id` (Boolean) Should the generated certificate include a subject key identifier (default: `false`).
- `uris` (List of String) List of URIs for which a certificate is being requested (i.e. certificate subjects).

Expand Down
1 change: 0 additions & 1 deletion examples/resources/tls_cert_request/resource.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
resource "tls_cert_request" "example" {
key_algorithm = "ECDSA"
private_key_pem = file("private_key.pem")

subject {
Expand Down
1 change: 0 additions & 1 deletion examples/resources/tls_locally_signed_cert/resource.tf
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
resource "tls_locally_signed_cert" "example" {
cert_request_pem = file("cert_request.pem")
ca_key_algorithm = "ECDSA"
ca_private_key_pem = file("ca_private_key.pem")
ca_cert_pem = file("ca_cert.pem")

Expand Down
1 change: 0 additions & 1 deletion examples/resources/tls_self_signed_cert/resource.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
resource "tls_self_signed_cert" "example" {
key_algorithm = "ECDSA"
private_key_pem = file("private_key.pem")

subject {
Expand Down
62 changes: 57 additions & 5 deletions internal/provider/common_cert.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,13 @@ func setCertificateSubjectSchema(s map[string]*schema.Schema) {
}

s["key_algorithm"] = &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: "Name of the algorithm used when generating the private key provided in `private_key_pem`.",
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
Deprecated: "This is now ignored, as the key algorithm is inferred from the `private_key_pem`.",
Description: "Name of the algorithm used when generating the private key provided in `private_key_pem`. " +
"**NOTE**: this is deprecated and ignored, as the key algorithm is now inferred from the key. ",
}

s["private_key_pem"] = &schema.Schema{
Expand Down Expand Up @@ -347,7 +350,7 @@ func createCertificate(d *schema.ResourceData, template, parent *x509.Certificat
if err != nil {
return fmt.Errorf("error creating certificate: %s", err)
}
certPem := string(pem.EncodeToMemory(&pem.Block{Type: Certificate.String(), Bytes: certBytes}))
certPem := string(pem.EncodeToMemory(&pem.Block{Type: PreambleCertificate.String(), Bytes: certBytes}))

validFromBytes, err := template.NotBefore.MarshalText()
if err != nil {
Expand Down Expand Up @@ -461,3 +464,52 @@ func distinguishedNamesFromSubjectAttributes(nameMap map[string]interface{}) *pk

return result
}

func parseCertificate(d *schema.ResourceData, pemKey string) (*x509.Certificate, error) {
block, err := decodePEM(d, pemKey, "")
if err != nil {
return nil, err
}

certs, err := x509.ParseCertificates(block.Bytes)
if err != nil {
return nil, fmt.Errorf("failed to parse %s: %s", pemKey, err)
}
if len(certs) < 1 {
return nil, fmt.Errorf("no certificates found in %s", pemKey)
}
if len(certs) > 1 {
return nil, fmt.Errorf("multiple certificates found in %s", pemKey)
}

return certs[0], nil
}

func parseCertificateRequest(d *schema.ResourceData, pemKey string) (*x509.CertificateRequest, error) {
block, err := decodePEM(d, pemKey, PreambleCertificateRequest.String())
if err != nil {
return nil, err
}

certReq, err := x509.ParseCertificateRequest(block.Bytes)
if err != nil {
return nil, fmt.Errorf("failed to parse %s: %s", pemKey, err)
}

return certReq, nil
}

func certificateToMap(cert *x509.Certificate) map[string]interface{} {
return map[string]interface{}{
"signature_algorithm": cert.SignatureAlgorithm.String(),
"public_key_algorithm": cert.PublicKeyAlgorithm.String(),
"serial_number": cert.SerialNumber.String(),
"is_ca": cert.IsCA,
"version": cert.Version,
"issuer": cert.Issuer.String(),
"subject": cert.Subject.String(),
"not_before": cert.NotBefore.Format(time.RFC3339),
"not_after": cert.NotAfter.Format(time.RFC3339),
"sha1_fingerprint": fmt.Sprintf("%x", sha1.Sum(cert.Raw)),
}
}
Loading