Skip to content

Commit

Permalink
Restore tls_cert_request to being a managed resource
Browse files Browse the repository at this point in the history
In c244e5a 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.
  • Loading branch information
apparentlymart committed Sep 24, 2016
1 parent 7d2b51e commit 804d714
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 24 deletions.
9 changes: 1 addition & 8 deletions builtin/providers/tls/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
},
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,19 @@ 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{

"dns_names": &schema.Schema{
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,
},
Expand All @@ -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,
},
Expand All @@ -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))
},
Expand All @@ -55,6 +61,7 @@ func dataSourceCertRequest() *schema.Resource {
Type: schema.TypeList,
Required: true,
Elem: nameSchema,
ForceNew: true,
},

"cert_request_pem": &schema.Schema{
Expand All @@ -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
Expand Down Expand Up @@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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\")}"
Expand Down
12 changes: 3 additions & 9 deletions website/source/layouts/tls.erb
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,6 @@
<a href="/docs/providers/tls/index.html">TLS Provider</a>
</li>

<li<%= sidebar_current(/^docs-tls-data-source/) %>>
<a href="#">Data Sources</a>
<ul class="nav nav-visible">
<li<%= sidebar_current("docs-tls-data-source-cert-request") %>>
<a href="/docs/providers/tls/d/cert_request.html">tls_cert_request</a>
</li>
</ul>
</li>

<li<%= sidebar_current(/^docs-tls-resource/) %>>
<a href="#">Resources</a>
<ul class="nav nav-visible">
Expand All @@ -31,6 +22,9 @@
<li<%= sidebar_current("docs-tls-resource-locally-signed-cert") %>>
<a href="/docs/providers/tls/r/locally_signed_cert.html">tls_locally_signed_cert</a>
</li>
<li<%= sidebar_current("docs-tls-resourse-cert-request") %>>
<a href="/docs/providers/tls/r/cert_request.html">tls_cert_request</a>
</li>
</ul>
</li>
</ul>
Expand Down

0 comments on commit 804d714

Please sign in to comment.