From 804d714ff644cdcd8fd4a42ebf4831aa94826d4d Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Sat, 24 Sep 2016 12:22:07 -0700 Subject: [PATCH] Restore tls_cert_request to being a managed resource In c244e5a6 this resource was converted to a data source, but that was a mistake since data sources are expected to produce stable results on each run, and yet certificate requests contain a random nonce as part of the signature. Additionally, using the data source as a managed resource through the provided compatibility shim was not actually working, since "Read" was trying to parse the private key out of a SHA1 hash of the key, which is what we place in state due to the StateFunc on that attribute. By restoring this we restore Terraform's ability to produce all of the parts of a basic PKI/CA, which is useful for creating dev environments and bootstrapping PKI for production environments. --- builtin/providers/tls/provider.go | 9 +------- ...rt_request.go => resource_cert_request.go} | 22 ++++++++++++++++--- ..._test.go => resource_cert_request_test.go} | 6 ++--- .../tls/{d => r}/cert_request.html.md | 12 +++++++++- website/source/layouts/tls.erb | 12 +++------- 5 files changed, 37 insertions(+), 24 deletions(-) rename builtin/providers/tls/{data_source_cert_request.go => resource_cert_request.go} (86%) rename builtin/providers/tls/{data_source_cert_request_test.go => resource_cert_request_test.go} (96%) rename website/source/docs/providers/tls/{d => r}/cert_request.html.md (76%) diff --git a/builtin/providers/tls/provider.go b/builtin/providers/tls/provider.go index 6f3363a9555a..e6c1d619804b 100644 --- a/builtin/providers/tls/provider.go +++ b/builtin/providers/tls/provider.go @@ -12,18 +12,11 @@ import ( func Provider() terraform.ResourceProvider { return &schema.Provider{ - DataSourcesMap: map[string]*schema.Resource{ - "tls_cert_request": dataSourceCertRequest(), - }, ResourcesMap: map[string]*schema.Resource{ "tls_private_key": resourcePrivateKey(), "tls_locally_signed_cert": resourceLocallySignedCert(), "tls_self_signed_cert": resourceSelfSignedCert(), - - "tls_cert_request": schema.DataSourceResourceShim( - "tls_cert_request", - dataSourceCertRequest(), - ), + "tls_cert_request": resourceCertRequest(), }, } } diff --git a/builtin/providers/tls/data_source_cert_request.go b/builtin/providers/tls/resource_cert_request.go similarity index 86% rename from builtin/providers/tls/data_source_cert_request.go rename to builtin/providers/tls/resource_cert_request.go index 19bcd3129e7f..267f0db39b8c 100644 --- a/builtin/providers/tls/data_source_cert_request.go +++ b/builtin/providers/tls/resource_cert_request.go @@ -12,9 +12,11 @@ import ( const pemCertReqType = "CERTIFICATE REQUEST" -func dataSourceCertRequest() *schema.Resource { +func resourceCertRequest() *schema.Resource { return &schema.Resource{ - Read: ReadCertRequest, + Create: CreateCertRequest, + Delete: DeleteCertRequest, + Read: ReadCertRequest, Schema: map[string]*schema.Schema{ @@ -22,6 +24,7 @@ func dataSourceCertRequest() *schema.Resource { Type: schema.TypeList, Optional: true, Description: "List of DNS names to use as subjects of the certificate", + ForceNew: true, Elem: &schema.Schema{ Type: schema.TypeString, }, @@ -31,6 +34,7 @@ func dataSourceCertRequest() *schema.Resource { Type: schema.TypeList, Optional: true, Description: "List of IP addresses to use as subjects of the certificate", + ForceNew: true, Elem: &schema.Schema{ Type: schema.TypeString, }, @@ -40,12 +44,14 @@ func dataSourceCertRequest() *schema.Resource { Type: schema.TypeString, Required: true, Description: "Name of the algorithm to use to generate the certificate's private key", + ForceNew: true, }, "private_key_pem": &schema.Schema{ Type: schema.TypeString, Required: true, Description: "PEM-encoded private key that the certificate will belong to", + ForceNew: true, StateFunc: func(v interface{}) string { return hashForState(v.(string)) }, @@ -55,6 +61,7 @@ func dataSourceCertRequest() *schema.Resource { Type: schema.TypeList, Required: true, Elem: nameSchema, + ForceNew: true, }, "cert_request_pem": &schema.Schema{ @@ -65,7 +72,7 @@ func dataSourceCertRequest() *schema.Resource { } } -func ReadCertRequest(d *schema.ResourceData, meta interface{}) error { +func CreateCertRequest(d *schema.ResourceData, meta interface{}) error { key, err := parsePrivateKey(d, "private_key_pem", "key_algorithm") if err != nil { return err @@ -109,3 +116,12 @@ func ReadCertRequest(d *schema.ResourceData, meta interface{}) error { return nil } + +func DeleteCertRequest(d *schema.ResourceData, meta interface{}) error { + d.SetId("") + return nil +} + +func ReadCertRequest(d *schema.ResourceData, meta interface{}) error { + return nil +} diff --git a/builtin/providers/tls/data_source_cert_request_test.go b/builtin/providers/tls/resource_cert_request_test.go similarity index 96% rename from builtin/providers/tls/data_source_cert_request_test.go rename to builtin/providers/tls/resource_cert_request_test.go index 16cd29264e6a..c31b8d6a1797 100644 --- a/builtin/providers/tls/data_source_cert_request_test.go +++ b/builtin/providers/tls/resource_cert_request_test.go @@ -12,12 +12,12 @@ import ( ) func TestCertRequest(t *testing.T) { - r.UnitTest(t, r.TestCase{ + r.Test(t, r.TestCase{ Providers: testProviders, Steps: []r.TestStep{ r.TestStep{ Config: fmt.Sprintf(` - data "tls_cert_request" "test" { + resource "tls_cert_request" "test" { subject { common_name = "example.com" organization = "Example, Inc" @@ -46,7 +46,7 @@ func TestCertRequest(t *testing.T) { EOT } output "key_pem" { - value = "${data.tls_cert_request.test.cert_request_pem}" + value = "${tls_cert_request.test.cert_request_pem}" } `, testPrivateKey), Check: func(s *terraform.State) error { diff --git a/website/source/docs/providers/tls/d/cert_request.html.md b/website/source/docs/providers/tls/r/cert_request.html.md similarity index 76% rename from website/source/docs/providers/tls/d/cert_request.html.md rename to website/source/docs/providers/tls/r/cert_request.html.md index c61308f12643..8869aeac622c 100644 --- a/website/source/docs/providers/tls/d/cert_request.html.md +++ b/website/source/docs/providers/tls/r/cert_request.html.md @@ -13,11 +13,21 @@ typical format used to request a certificate from a certificate authority. This resource is intended to be used in conjunction with a Terraform provider for a particular certificate authority in order to provision a new certificate. +This is a *logical resource*, so it contributes only to the current Terraform +state and does not create any external managed resources. + +~> **Compatibility Note** From Terraform 0.7.0 to 0.7.4 this resource was +converted to a data source, and the resource form of it was deprecated. This +turned out to be a design error since a cert request includes a random number +in the form of the signature nonce, and so the data source form of this +resource caused non-convergent configuration. The data source form is no longer +supported as of Terraform 0.7.5 and any users should return to using the +resource form. ## Example Usage ``` -data "tls_cert_request" "example" { +resource "tls_cert_request" "example" { key_algorithm = "ECDSA" private_key_pem = "${file(\"private_key.pem\")}" diff --git a/website/source/layouts/tls.erb b/website/source/layouts/tls.erb index 2cc50eac086c..97be3879c22d 100644 --- a/website/source/layouts/tls.erb +++ b/website/source/layouts/tls.erb @@ -10,15 +10,6 @@ TLS Provider - > - Data Sources - - - > Resources