Skip to content

Commit

Permalink
Merge pull request #79 from grokify/add/CloudWAFCertificate
Browse files Browse the repository at this point in the history
add Cloud WAF Certificate support
  • Loading branch information
jhanrahan-sigsci authored Sep 24, 2022
2 parents df65a32 + 142dc4b commit 29ae0f3
Show file tree
Hide file tree
Showing 9 changed files with 523 additions and 15 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ provider "sigsci" {

[Cloud WAF Instance](https://github.com/signalsciences/terraform-provider-sigsci/blob/main/docs/resources/corp_cloudwaf_instance.md)

[Cloud WAF Certificate](https://github.com/signalsciences/terraform-provider-sigsci/blob/main/docs/resources/corp_cloudwaf_certificate.md)

## Site resources

[Lists](https://github.com/signalsciences/terraform-provider-sigsci/blob/main/docs/resources/site_list.md)
Expand Down
45 changes: 45 additions & 0 deletions docs/resources/corp_cloudwaf_certificate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
### Example Usage

```hcl-terraform
resource "sigsci_corp_cloudwaf_certificate" "test_corp_cloudwaf_certificate" {
name = "Test Cloud WAF Certificate"
certificate_body = <<CERT
-----BEGIN CERTIFICATE-----
[encoded certificate]
-----END CERTIFICATE-----
CERT
certificate_chain = <<CHAIN
-----BEGIN CERTIFICATE-----
[encoded certificate chain]
-----END CERTIFICATE-----
CHAIN
private_key = <<PRIVATEKEY
-----BEGIN PRIVATE KEY-----
[encoded privatekey]]
----END PRIVATE KEY-----
PRIVATEKEY
}
```

### Argument Reference
- `name` - (Required) Friendly name to identify a CloudWAF certificate.
- `certificate_body` - (Required) Body of the certificate in PEM format.
- `certificate_chain` - (Optional) Certificate chain in PEM format.
- `private_key` - (Required) Private key of the certificate in PEM format - must be unencrypted.

### Attributes Reference
In addition to all arguments, the following fields are also available
- `id` - CloudWAF certificate unique identifier.
- `common_name` - Common name of the uploaded certificate.
- `expires_at` - TimeStamp for when certificate expires in RFC3339 date time format.
- `fingerprint` - SHA1 fingerprint of the certififcate.
- `status` - Current status of the certificate - could be one of "unknown", "active", "pendingverification", "expired", "error".
- `subject_alternative_names` - Subject alternative names from the uploaded certificate.

### Import
You can import corp lists with the generic site import formula

Example:
```shell script
$ terraform import sigsci_corp_cloudwaf_certificate.test id
```
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.17
require (
github.com/davecgh/go-spew v1.1.1
github.com/hashicorp/terraform-plugin-sdk v1.14.0
github.com/signalsciences/go-sigsci v0.1.5
github.com/signalsciences/go-sigsci v0.1.6
)

require (
Expand Down Expand Up @@ -70,4 +70,4 @@ require (
google.golang.org/grpc v1.27.1 // indirect
)

//replace github.com/signalsciences/go-sigsci v0.1.5 => ../go-sigsci
//replace github.com/signalsciences/go-sigsci v0.1.6 => ../go-sigsci
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,8 @@ github.com/posener/complete v1.2.1/go.mod h1:6gapUrK/U1TAN7ciCoNRIdVC5sbdBTUh1DK
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/signalsciences/go-sigsci v0.1.5 h1:sKAFGo70Bv/F1QYL5W9mmo4BAWX0B9xmVk0rWQwmKRA=
github.com/signalsciences/go-sigsci v0.1.5/go.mod h1:9eUL/FIXlslxnqtsf0yk67CSBiYdL4ToYjYybzWQ77A=
github.com/signalsciences/go-sigsci v0.1.6 h1:O3v1kQOA00d+HO4pD8ykymouojBe02bYy0gj15ow8jA=
github.com/signalsciences/go-sigsci v0.1.6/go.mod h1:9eUL/FIXlslxnqtsf0yk67CSBiYdL4ToYjYybzWQ77A=
github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
Expand Down
67 changes: 63 additions & 4 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@ terraform {
required_providers {
sigsci = {
source = "signalsciences/sigsci"
version = "0.4.2"
version = "1.1.0"
}
}
}

// To build locally:
// make && cp terraform-provider-sigsci ~/.terraform.d/plugins/signalsciences/local/sigsci/0.4.2/darwin_amd64/terraform-provider-sigsci && rm .terraform.lock.hcl && tf init
// make && cp terraform-provider-sigsci ~/.terraform.d/plugins/signalsciences/local/sigsci/1.1.0/darwin_amd64/terraform-provider-sigsci && rm .terraform.lock.hcl && tf init
//terraform {
// required_providers {
// sigsci = {
// source = "signalsciences/local/sigsci"
// version = "0.4.2"
// version = "1.1.0"
// }
// }
//}
Expand Down Expand Up @@ -334,4 +334,63 @@ resource "sigsci_site_integration" "test_integration" {
type = "slack"
url = "https://wat.slack.com"
events = ["listCreated"]
}
}

resource "sigsci_corp_cloudwaf_certificate" "test_cloudwaf_certificate"{
name = "Certificate Name"
certificate_body = <<CERT
-----BEGIN CERTIFICATE-----
MIIDzjCCArYCCQD6uBPuCbaDuDANBgkqhkiG9w0BAQsFADCBqDELMAkGA1UEBhMC
VVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28x
HTAbBgNVBAoMFEV4YW1wbGUgT3JnYW5pemF0aW9uMRMwEQYDVQQLDApFeGFtcGxl
IE9VMRQwEgYDVQQDDAtleGFtcGxlLmNvbTEiMCAGCSqGSIb3DQEJARYTZXhhbXBs
ZUBleGFtcGxlLmNvbTAeFw0yMjA5MjQwMDE4MjRaFw0zMjA5MjEwMDE4MjRaMIGo
MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2Fu
IEZyYW5jaXNjbzEdMBsGA1UECgwURXhhbXBsZSBPcmdhbml6YXRpb24xEzARBgNV
BAsMCkV4YW1wbGUgT1UxFDASBgNVBAMMC2V4YW1wbGUuY29tMSIwIAYJKoZIhvcN
AQkBFhNleGFtcGxlQGV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAscvDb2j2s9bdiAIHbqRoM2qZBxdM4atSwAJQrXVe3pbne2KLZw53
kHpVtjaugfMKBnXueR1iilYu5eXtgNfrNHgq0X0+NToL/xtSgYthp89lxBYArUVy
kiM5gy8BqpApfAwQ5MMDgGflIV/mTCcCyNK3DwuOgO7oVp0V2zdtJhgvZ8e3qkuT
3dOxC27aUFYf/P88UILoc9YWRCkw2Gww/Zr908a/mgVBJ9v+/sKP3/yk8jzrRhL5
JsGWC5Gbv1gpkyzSjKyboYePvJJo5D6Fue9XZmzry3wepG1oUcLO6QpH+lTBfTjd
xHKA4sIza1J/RDBLgUBney1nMxLN8RzU5QIDAQABMA0GCSqGSIb3DQEBCwUAA4IB
AQAPRvwDkKTKCDQj5F4ZUTE9AIEs0w99KuXiWBGz3RmYl5zwZCrVWeOI+lPfCG0v
prMgh5ydUgUOqrs8S7MAkt8GaU5lb0MSKmz1jPgEEbLBp6VYv2UbrWlBz9JIxTLw
riPHNUzKb6SXk5wuoO8w7+GsBNI8fWPDSQqSWLlNsi0r4ReLxlM5WBNC10d3q2ia
jV6r8iMpiArwbJn4WSTlFuJ6crrjgbBVCFxxwoF1sHhwGg+5idxm2AHSzvENyFW4
UVhVTn9w3UPLMkEl7nAVzydpdMb/M/GLCV787BrQL35EtiCr9MSL9Gc8vR/9PzPP
QodC+xWXbig7xKLqZgQ/PbPt
-----END CERTIFICATE-----
CERT
private_key = <<PRIVATEKEY
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCxy8NvaPaz1t2I
AgdupGgzapkHF0zhq1LAAlCtdV7elud7YotnDneQelW2Nq6B8woGde55HWKKVi7l
5e2A1+s0eCrRfT41Ogv/G1KBi2Gnz2XEFgCtRXKSIzmDLwGqkCl8DBDkwwOAZ+Uh
X+ZMJwLI0rcPC46A7uhWnRXbN20mGC9nx7eqS5Pd07ELbtpQVh/8/zxQguhz1hZE
KTDYbDD9mv3Txr+aBUEn2/7+wo/f/KTyPOtGEvkmwZYLkZu/WCmTLNKMrJuhh4+8
kmjkPoW571dmbOvLfB6kbWhRws7pCkf6VMF9ON3EcoDiwjNrUn9EMEuBQGd7LWcz
Es3xHNTlAgMBAAECggEAV0K/f52Pf0JUZd1BEo+ESL/nrTBFXni8W1qHiCqTzkFY
CRmbe5ABJJq2GIEL8uF6qSMWUMEYTPbxe4n2oAbY/F6B/WEvt+XuX11kiAoFetvy
gWOfH2t3SLwbDQR0F+c7RROS8wO3Yz0amt+7YuK+nhu1FqBAZ41Z4LCmOnogitIA
cCErKpHqCJbYT99eaXTt2QpXJNI8fItXaO4p8zfKxzBKybhsyu3tEerKWnhqz+25
Xr7OieYkZM3ryrIsVWZ299wH2D+gA9O+PbY2RJ0Vf3YVf8VdyYRJ5oCAaioNUfZw
HeGGlfClZzrpX1MjiNNfli05cLqX0iE2bIO+jvZkIQKBgQDadIMHfGQs8CPxbPqi
fZRuHdPedogM80f4E5RyKhTzEqTG6x0pfjkDr57rdqJEWhM3TjsMIiJRnEIomWar
2tyckmvkxuSioiWb/+HXJN5u6AtsMgQ4WLMm9HOO0ir5uSKQd0iQrCMAaGDNdV52
6eipkWLdhYAhW31bycv9cX04+QKBgQDQWlkTovazzNElJU4h1YQCq99VS1gmYb9U
HAzg3Jmu7WF4Oln+HxZMWqwR38vCuMHiwtCmsqGAEKK2ev6W6iq7iVJLKzTXV++a
612Mr+JohbHNL0bKlgTMt/i2TnmBWOlhL7xuIwduru1pQ4mM7Vh7Hv+CrVTGm4VZ
Khzq+vbCTQKBgEnprgO0ZLiHr8GZ29tqnfP8B5l3hWTMU4duKIXQEzKDFllvZ3iI
ioXiv+RvSUvTJjlKMNRUIER4mDHgZUq0THx1Vigb23PjZNI5a5I9mTzxKhw7eA4Q
hN0jTI4AMiY4K6exlE3O0DDtIAOkOIgHcH8e/9JvvwCKUgniZzCjW3kRAoGAeEId
tgLSyFbIxNrybP7zciNIBdA2MfkrWN3T5RoPLnNfVejANrg0w592P97fmiXP6xWt
Hvpt0yBG+nKlbe/8+D+7mx12I3FjIBUH6wM9+Dxqsta90oKihJMPYBKNeUYbdnf6
F8vqJ02aRK6xvwDjmDT9H6zyCKyNXDi9djeio+UCgYEAm1g/2O42eVBzYG/WTJ2H
7jplYemfbIFVpl3Uo18UJKZl/AIzm9tw/+c884naSubwQ8TukI3bDjwWu99R26bo
HQRmLMnP+t7xp84Rn4jXReWlr9sexXHPg/Lj25MdR1t3Ow53qSh4nw/cUPr42N9o
cX4iWLb38v7KEornZfofXEw=
-----END PRIVATE KEY-----
PRIVATEKEY
}
7 changes: 7 additions & 0 deletions provider/lib.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ import (
"github.com/signalsciences/go-sigsci"
)

func suppressEquivalentTrimSpaceDiffs(k, old, new string, d *schema.ResourceData) bool {
if strings.TrimSpace(old) == strings.TrimSpace(new) {
return true
}
return false
}

type providerMetadata struct {
Corp string
Client sigsci.Client
Expand Down
15 changes: 8 additions & 7 deletions provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,14 @@ func Provider() terraform.ResourceProvider {
"sigsci_site_blocklist": resourceSiteBlocklist(),
"sigsci_site_allowlist": resourceSiteAllowlist(),
//"sigsci_site_monitor": resourceSiteMonitor(),
"sigsci_site_header_link": resourceSiteHeaderLink(),
"sigsci_site_integration": resourceSiteIntegration(),
"sigsci_corp_list": resourceCorpList(),
"sigsci_corp_rule": resourceCorpRule(),
"sigsci_corp_signal_tag": resourceCorpSignalTag(),
"sigsci_corp_integration": resourceCorpIntegration(),
"sigsci_corp_cloudwaf_instance": resourceCorpCloudWAFInstance(),
"sigsci_site_header_link": resourceSiteHeaderLink(),
"sigsci_site_integration": resourceSiteIntegration(),
"sigsci_corp_list": resourceCorpList(),
"sigsci_corp_rule": resourceCorpRule(),
"sigsci_corp_signal_tag": resourceCorpSignalTag(),
"sigsci_corp_integration": resourceCorpIntegration(),
"sigsci_corp_cloudwaf_instance": resourceCorpCloudWAFInstance(),
"sigsci_corp_cloudwaf_certificate": resourceCorpCloudWAFCertificate(),
},
}
provider.ConfigureFunc = providerConfigure()
Expand Down
167 changes: 167 additions & 0 deletions provider/resource_corp_cloudwaf_certificate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
package provider

import (
"strings"

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/signalsciences/go-sigsci"
)

func resourceCorpCloudWAFCertificate() *schema.Resource {
return &schema.Resource{
Create: resourceCorpCloudWAFCertificateCreate,
Read: resourceCorpCloudWAFCertificateRead,
Update: resourceCorpCloudWAFCertificateUpdate,
Delete: resourceCorpCloudWAFCertificateDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Description: "Friendly name to identify a CloudWAF certificate",
Required: true,
},
"certificate_body": {
Type: schema.TypeString,
Description: "Body of the certificate in PEM format",
Required: true,
ForceNew: true,
DiffSuppressFunc: suppressEquivalentTrimSpaceDiffs,
},
"certificate_chain": {
Type: schema.TypeString,
Description: "Certificate chain in PEM format",
Optional: true,
DiffSuppressFunc: suppressEquivalentTrimSpaceDiffs,
},
"private_key": {
Type: schema.TypeString,
Description: "Private key of the certificate in PEM format - must be unencrypted",
Required: true,
ForceNew: true,
Sensitive: true,
},
"common_name": {
Type: schema.TypeString,
Description: "Common name of the uploaded certificate",
Computed: true,
},
"expires_at": {
Type: schema.TypeString,
Description: "TimeStamp for when certificate expires in RFC3339 date time format",
Computed: true,
},
"fingerprint": {
Type: schema.TypeString,
Description: "SHA1 fingerprint of the certififcate",
Computed: true,
},
"status": {
Type: schema.TypeString,
Description: `Current status of the certificate - could be one of "unknown", "active", "pendingverification", "expired", "error"`,
Computed: true,
},
"subject_alternative_names": {
Type: schema.TypeSet,
Description: "Subject alternative names from the uploaded certificate",
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
}
}

func resourceCorpCloudWAFCertificateCreate(d *schema.ResourceData, m interface{}) error {
pm := m.(providerMetadata)
sc := pm.Client

resp, err := sc.UploadCloudWAFCertificate(pm.Corp, sigsci.UploadCloudWAFCertificateBody{
CloudWAFCertificateBase: sigsci.CloudWAFCertificateBase{
Name: d.Get("name").(string),
CertificateBody: strings.TrimSpace(d.Get("certificate_body").(string)),
CertificateChain: strings.TrimSpace(d.Get("certificate_chain").(string)),
},
PrivateKey: strings.TrimSpace(d.Get("private_key").(string)),
})
if err != nil {
return err
}

d.SetId(resp.ID)

return resourceCorpCloudWAFCertificateRead(d, m)
}

func resourceCorpCloudWAFCertificateRead(d *schema.ResourceData, m interface{}) error {
pm := m.(providerMetadata)
sc := pm.Client

cwaf, err := sc.GetCloudWAFCertificate(pm.Corp, d.Id())
if err != nil {
d.SetId("")
return nil
}

d.SetId(d.Id())
err = d.Set("name", cwaf.Name)
if err != nil {
return err
}
err = d.Set("certificate_body", strings.TrimSpace(cwaf.CertificateBody))
if err != nil {
return err
}
err = d.Set("certificate_chain", strings.TrimSpace(cwaf.CertificateChain))
if err != nil {
return err
}
err = d.Set("common_name", cwaf.CommonName)
if err != nil {
return err
}
err = d.Set("expires_at", cwaf.ExpiresAt)
if err != nil {
return err
}
err = d.Set("fingerprint", cwaf.Fingerprint)
if err != nil {
return err
}
err = d.Set("status", cwaf.Status)
if err != nil {
return err
}
err = d.Set("subject_alternative_names", flattenStringArray(cwaf.SubjectAlternativeNames))
if err != nil {
return err
}

return nil
}

func resourceCorpCloudWAFCertificateUpdate(d *schema.ResourceData, m interface{}) error {
pm := m.(providerMetadata)
sc := pm.Client

_, err := sc.UpdateCloudWAFCertificate(pm.Corp, d.Id(), sigsci.UpdateCloudWAFCertificateBody{
Name: d.Get("name").(string),
})
if err != nil {
return nil
}

return resourceCorpCloudWAFCertificateRead(d, m)
}

func resourceCorpCloudWAFCertificateDelete(d *schema.ResourceData, m interface{}) error {
pm := m.(providerMetadata)
sc := pm.Client

err := sc.DeleteCloudWAFCertificate(pm.Corp, d.Id())
if err != nil {
return err
}
d.SetId("")
return nil
}
Loading

0 comments on commit 29ae0f3

Please sign in to comment.