Skip to content

Commit

Permalink
[Synthetics] Store SHA 256 hash of certificates in state instead of t…
Browse files Browse the repository at this point in the history
…he actual cert (#835)

* [Synthetics] Do not store content of client certificate in state

* [Synthetics] Store hashed content for client certificate

Co-authored-by: Hippolyte HENRY <[email protected]>
  • Loading branch information
romainberger and zippolyte authored Jan 15, 2021
1 parent 0439b6c commit 313be09
Show file tree
Hide file tree
Showing 6 changed files with 276 additions and 228 deletions.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2021-01-06T10:49:33.846702+01:00
2021-01-15T11:28:33.525482+01:00

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1 +1 @@
2021-01-06T10:58:05.577416+01:00
2021-01-15T11:42:09.54007+01:00

Large diffs are not rendered by default.

35 changes: 30 additions & 5 deletions datadog/resource_datadog_synthetics_test_.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package datadog

import (
"crypto/sha256"
"encoding/json"
"fmt"
"log"
Expand Down Expand Up @@ -273,6 +274,9 @@ func syntheticsTestRequestClientCertificateItem() *schema.Schema {
Type: schema.TypeString,
Required: true,
Sensitive: true,
StateFunc: func(val interface{}) string {
return convertToSha256(val.(string))
},
},
"filename": {
Description: "File name for the certificate.",
Expand Down Expand Up @@ -1106,14 +1110,14 @@ func updateSyntheticsTestLocalState(d *schema.ResourceData, syntheticsTest *data
key := clientCertificate.GetKey()
localCertificate["key"][0]["filename"] = key.GetFilename()

// the content of the certificate and the key are write-only
// so we need to get them from the config since they will
// not be in the api response
// the content of client certificate is write-only so it will not be returned by the API.
// To avoid useless diff but also prevent storing the value in clear in the state
// we store a hash of the value.
if configCertificateContent, ok := d.GetOk("request_client_certificate.0.cert.0.content"); ok {
localCertificate["cert"][0]["content"] = configCertificateContent.(string)
localCertificate["cert"][0]["content"] = getCertificateStateValue(configCertificateContent.(string))
}
if configKeyContent, ok := d.GetOk("request_client_certificate.0.key.0.content"); ok {
localCertificate["key"][0]["content"] = configKeyContent.(string)
localCertificate["key"][0]["content"] = getCertificateStateValue(configKeyContent.(string))
}

d.Set("request_client_certificate", []map[string][]map[string]string{localCertificate})
Expand Down Expand Up @@ -1371,3 +1375,24 @@ func validateSyntheticsAssertionOperator(val interface{}, key string) (warns []s
}
return
}

func convertToSha256(content string) string {
data := []byte(content)
hash := sha256.Sum256(data)
return fmt.Sprintf("%x", hash[:])
}

// get the sha256 of a client certificate content
// in some case where Terraform compares the state value
// we already get the hashed value so we don't need to
// hash it again
func getCertificateStateValue(content string) string {
contentBytes := []byte(content)

// hacky way to detect if the value is already a sha256 hash
if len(contentBytes) == 64 {
return content
}

return convertToSha256(content)
}
22 changes: 20 additions & 2 deletions datadog/resource_datadog_synthetics_test_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -551,11 +551,11 @@ func createSyntheticsAPITestStepNewAssertionsOptions(accProvider *schema.Provide
resource.TestCheckResourceAttr(
"datadog_synthetics_test.bar", "request_basicauth.0.password", "secret"),
resource.TestCheckResourceAttr(
"datadog_synthetics_test.bar", "request_client_certificate.0.cert.0.content", "content-certificate"),
"datadog_synthetics_test.bar", "request_client_certificate.0.cert.0.content", convertToSha256("content-certificate")),
resource.TestCheckResourceAttr(
"datadog_synthetics_test.bar", "request_client_certificate.0.cert.0.filename", "Provided in Terraform config"),
resource.TestCheckResourceAttr(
"datadog_synthetics_test.bar", "request_client_certificate.0.key.0.content", "content-key"),
"datadog_synthetics_test.bar", "request_client_certificate.0.key.0.content", convertToSha256("content-key")),
resource.TestCheckResourceAttr(
"datadog_synthetics_test.bar", "request_client_certificate.0.key.0.filename", "key"),
resource.TestCheckResourceAttr(
Expand Down Expand Up @@ -872,6 +872,14 @@ func updateSyntheticsAPITestStepNewAssertionsOptions(accProvider *schema.Provide
"datadog_synthetics_test.bar", "request.url", "https://docs.datadoghq.com"),
resource.TestCheckResourceAttr(
"datadog_synthetics_test.bar", "request.timeout", "60"),
resource.TestCheckResourceAttr(
"datadog_synthetics_test.bar", "request_client_certificate.0.cert.0.content", convertToSha256("content-certificate-updated")),
resource.TestCheckResourceAttr(
"datadog_synthetics_test.bar", "request_client_certificate.0.cert.0.filename", "Provided in Terraform config"),
resource.TestCheckResourceAttr(
"datadog_synthetics_test.bar", "request_client_certificate.0.key.0.content", convertToSha256("content-key-updated")),
resource.TestCheckResourceAttr(
"datadog_synthetics_test.bar", "request_client_certificate.0.key.0.filename", "key-updated"),
resource.TestCheckResourceAttr(
"datadog_synthetics_test.bar", "assertion.#", "1"),
resource.TestCheckResourceAttr(
Expand Down Expand Up @@ -932,6 +940,16 @@ resource "datadog_synthetics_test" "bar" {
timeout = 60
}
request_client_certificate {
cert {
content = "content-certificate-updated"
}
key {
content = "content-key-updated"
filename = "key-updated"
}
}
assertion {
type = "body"
operator = "validatesJSONPath"
Expand Down

0 comments on commit 313be09

Please sign in to comment.