Skip to content

Commit db7821b

Browse files
authored
Create a certificate signing request (#389)
* Create a certificate signing request * Incapsula CSR resource documentation * Incapsula CSR resource documentation
1 parent 71b9b33 commit db7821b

File tree

6 files changed

+320
-0
lines changed

6 files changed

+320
-0
lines changed
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package incapsula
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"io/ioutil"
7+
"log"
8+
"net/url"
9+
)
10+
11+
// Endpoints
12+
const endpointCertificateSigningRequestCreate = "sites/customCertificate/csr"
13+
14+
// CertificateSigningRequestCreateResponse contains confirmation of successful csr
15+
type CertificateSigningRequestCreateResponse struct {
16+
Res int `json:"res,string"`
17+
ResMessage string `json:"res_message"`
18+
Status string `json:"status"`
19+
CsrContent string `json:"csr_content"`
20+
}
21+
22+
// CreateCertificateSigningRequest creates a Certificate Signing Request (CSR)
23+
func (c *Client) CreateCertificateSigningRequest(siteID, domain, email, country, state, city, organization, organizationUnit string) (*CertificateSigningRequestCreateResponse, error) {
24+
25+
log.Printf("[INFO] Creating certificate signing request for site_id: %s", siteID)
26+
27+
values := url.Values{
28+
"site_id": {siteID},
29+
"domain": {domain},
30+
"email": {email},
31+
"country": {country},
32+
"state": {state},
33+
"city": {city},
34+
"organization": {organization},
35+
"organization_unit": {organizationUnit},
36+
}
37+
38+
if domain != "" {
39+
values.Set("domain", domain)
40+
}
41+
if email != "" {
42+
values.Set("email", email)
43+
}
44+
if country != "" {
45+
values.Set("country", country)
46+
}
47+
if state != "" {
48+
values.Set("state", state)
49+
}
50+
if city != "" {
51+
values.Set("city", city)
52+
}
53+
if organization != "" {
54+
values.Set("organization", organization)
55+
}
56+
if organizationUnit != "" {
57+
values.Set("organization_unit", organizationUnit)
58+
}
59+
log.Printf("CertificateSigningRequest\n%v", values)
60+
// Post to Incapsula
61+
reqURL := fmt.Sprintf("%s/%s", c.config.BaseURL, endpointCertificateSigningRequestCreate)
62+
resp, err := c.PostFormWithHeaders(reqURL, values, CreateCertificateSigningRequest)
63+
if err != nil {
64+
return nil, fmt.Errorf("Error from Incapsula service when creating certificate signing request for site_id %s: %s", siteID, err)
65+
}
66+
67+
// Read the body
68+
defer resp.Body.Close()
69+
responseBody, err := ioutil.ReadAll(resp.Body)
70+
71+
// Dump JSON
72+
log.Printf("[DEBUG] Incapsula create certificate signing request JSON response: %s\n", string(responseBody))
73+
74+
// Parse the JSON
75+
var certificateSigningRequestCreateResponse CertificateSigningRequestCreateResponse
76+
err = json.Unmarshal([]byte(responseBody), &certificateSigningRequestCreateResponse)
77+
if err != nil {
78+
return nil, fmt.Errorf("Error parsing create certificate signing request JSON response for site_id %s: %s\nresponse: %s", siteID, err, string(responseBody))
79+
}
80+
81+
// Look at the response status code from Incapsula
82+
if certificateSigningRequestCreateResponse.Res != 0 {
83+
return nil, fmt.Errorf("Error from Incapsula service when creating certificate signing request for site_id %s: %s", siteID, string(responseBody))
84+
}
85+
86+
return &certificateSigningRequestCreateResponse, nil
87+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package incapsula
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"net/http"
7+
"net/http/httptest"
8+
"strings"
9+
"testing"
10+
"time"
11+
)
12+
13+
////////////////////////////////////////////////////////////////
14+
// CreateCertificateSigningRequest Tests
15+
////////////////////////////////////////////////////////////////
16+
17+
func TestClientCreateCertificateSigningRequestBadConnection(t *testing.T) {
18+
log.Printf("======================== BEGIN TEST ========================")
19+
log.Printf("[DEBUG] Running test client_certificate_signing_request_test.TestClientCreateCertificateSigningRequestBadConnection")
20+
config := &Config{APIID: "foo", APIKey: "bar", BaseURL: "badness.incapsula.com"}
21+
client := &Client{config: config, httpClient: &http.Client{Timeout: time.Millisecond * 1}}
22+
siteID := "1234"
23+
domain := "sandwich.au"
24+
email := "test@sandwich.au"
25+
country := "AU"
26+
state := "QLD"
27+
city := "BNE"
28+
organization := "Tacos Pty Ltd"
29+
organizationUnit := "Sales"
30+
certificateSigningRequestCreateResponse, err := client.CreateCertificateSigningRequest(siteID, domain, email, country, state, city, organization, organizationUnit)
31+
if err == nil {
32+
t.Errorf("Should have received an error")
33+
}
34+
if !strings.HasPrefix(err.Error(), fmt.Sprintf("Error from Incapsula service when creating certificate signing request for site_id %s", siteID)) {
35+
t.Errorf("Should have received a client error, got: %s", err)
36+
}
37+
if certificateSigningRequestCreateResponse != nil {
38+
t.Errorf("Should have received a nil certificateSigningRequestCreateResponse instance")
39+
}
40+
}
41+
42+
func TestClientCreateCertificateSigningRequestBadJSON(t *testing.T) {
43+
log.Printf("======================== BEGIN TEST ========================")
44+
log.Printf("[DEBUG] Running test Running test client_certificate_signing_request_test.TestClientCreateCertificateSigningRequestBadJSON")
45+
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
46+
if req.URL.String() != fmt.Sprintf("/%s", endpointCertificateSigningRequestCreate) {
47+
t.Errorf("Should have have hit /%s endpoint. Got: %s", endpointCertificateSigningRequestCreate, req.URL.String())
48+
}
49+
rw.Write([]byte(`{`))
50+
}))
51+
defer server.Close()
52+
53+
config := &Config{APIID: "foo", APIKey: "bar", BaseURL: server.URL}
54+
client := &Client{config: config, httpClient: &http.Client{}}
55+
siteID := "1234"
56+
domain := "sandwich.au"
57+
email := "test@sandwich.au"
58+
country := "AU"
59+
state := "QLD"
60+
city := "BNE"
61+
organization := "Tacos Pty Ltd"
62+
organizationUnit := "Sales"
63+
certificateSigningRequestCreateResponse, err := client.CreateCertificateSigningRequest(siteID, domain, email, country, state, city, organization, organizationUnit)
64+
if err == nil {
65+
t.Errorf("Should have received an error")
66+
}
67+
if !strings.HasPrefix(err.Error(), fmt.Sprintf("Error parsing create certificate signing request JSON response for site_id %s", siteID)) {
68+
t.Errorf("Should have received a JSON parse error, got: %s", err)
69+
}
70+
if certificateSigningRequestCreateResponse != nil {
71+
t.Errorf("Should have received a nil certificateSigningRequestCreateResponse instance")
72+
}
73+
}

incapsula/operation_constants.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ const ReadSecurityRuleException = "read_security_rule_exception"
7474
const UpdateSecurityRuleException = "update_security_rule_exception"
7575
const DeleteSecurityRuleException = "delete_security_rule_exception"
7676

77+
const CreateCertificateSigningRequest = "create_certificate_signing_request"
78+
7779
const CreateCustomCertificate = "create_custom_certificate"
7880
const ReadCustomCertificate = "read_custom_certificate"
7981
const UpdateCustomCertificate = "update_custom_certificate"

incapsula/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ func Provider() *schema.Provider {
101101

102102
ResourcesMap: map[string]*schema.Resource{
103103
"incapsula_cache_rule": resourceCacheRule(),
104+
"incapsula_certificate_signing_request": resourceCertificateSigningRequest(),
104105
"incapsula_custom_certificate": resourceCertificate(),
105106
"incapsula_custom_hsm_certificate": resourceCustomCertificateHsm(),
106107
"incapsula_data_center": resourceDataCenter(),
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package incapsula
2+
3+
import (
4+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
5+
)
6+
7+
func resourceCertificateSigningRequest() *schema.Resource {
8+
return &schema.Resource{
9+
Create: resourceCertificateSigningRequestCreate,
10+
Read: resourceCertificateSigningRequestRead,
11+
Update: resourceCertificateSigningRequestUpdate,
12+
Delete: resourceCertificateSigningRequestDelete,
13+
14+
Schema: map[string]*schema.Schema{
15+
// Required Arguments
16+
"site_id": {
17+
Description: "Numeric identifier of the site to operate on.",
18+
Type: schema.TypeString,
19+
Required: true,
20+
ForceNew: true,
21+
},
22+
// Optional Arguments
23+
"domain": {
24+
Description: "common name. For example: example.com.",
25+
Type: schema.TypeString,
26+
Optional: true,
27+
},
28+
"email": {
29+
Description: "Email address. For example: joe@example.com.",
30+
Type: schema.TypeString,
31+
Optional: true,
32+
},
33+
"country": {
34+
Description: "The two-letter ISO code for the country where your organization is located.",
35+
Type: schema.TypeString,
36+
Optional: true,
37+
},
38+
"state": {
39+
Description: "The state/region where your organization is located. This should not be abbreviated.",
40+
Type: schema.TypeString,
41+
Optional: true,
42+
},
43+
"city": {
44+
Description: "The city where your organization is located.",
45+
Type: schema.TypeString,
46+
Optional: true,
47+
},
48+
"organization": {
49+
Description: "The legal name of your organization. This should not be abbreviated or include suffixes such as Inc., Corp., or LLC.",
50+
Type: schema.TypeString,
51+
Optional: true,
52+
},
53+
"organization_unit": {
54+
Description: "The division of your organization handling the certificate. For example, IT Department.",
55+
Type: schema.TypeString,
56+
Optional: true,
57+
},
58+
// Computed Arguments
59+
"csr_content": {
60+
Description: "The certificate request data.",
61+
Type: schema.TypeString,
62+
Computed: true,
63+
},
64+
},
65+
}
66+
}
67+
68+
func resourceCertificateSigningRequestCreate(d *schema.ResourceData, m interface{}) error {
69+
client := m.(*Client)
70+
certificateSigningRequestResponse, err := client.CreateCertificateSigningRequest(
71+
d.Get("site_id").(string),
72+
d.Get("domain").(string),
73+
d.Get("email").(string),
74+
d.Get("country").(string),
75+
d.Get("state").(string),
76+
d.Get("city").(string),
77+
d.Get("organization").(string),
78+
d.Get("organization_unit").(string),
79+
)
80+
81+
if err != nil {
82+
return err
83+
}
84+
85+
d.Set("csr_content", certificateSigningRequestResponse.CsrContent)
86+
87+
d.SetId(d.Get("site_id").(string))
88+
89+
return nil
90+
}
91+
92+
func resourceCertificateSigningRequestRead(d *schema.ResourceData, m interface{}) error {
93+
return nil
94+
}
95+
96+
func resourceCertificateSigningRequestUpdate(d *schema.ResourceData, m interface{}) error {
97+
if d.HasChange("domain") ||
98+
d.HasChange("email") ||
99+
d.HasChange("country") ||
100+
d.HasChange("state") ||
101+
d.HasChange("city") ||
102+
d.HasChange("organization") ||
103+
d.HasChange("organization_unit") {
104+
return resourceCertificateSigningRequestCreate(d, m)
105+
}
106+
return nil
107+
}
108+
109+
func resourceCertificateSigningRequestDelete(d *schema.ResourceData, m interface{}) error {
110+
return nil
111+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
---
2+
subcategory: "Provider Reference"
3+
layout: "incapsula"
4+
page_title: "incapsula_certificate_signing_request"
5+
description: |-
6+
Provides a Incapsula Certificate Signing Request resource.
7+
---
8+
9+
# incapsula_certificate_signing_request
10+
11+
Provides a Incapsula Certificate Signing Request resource.
12+
13+
## Example Usage
14+
15+
```hcl
16+
resource "incapsula_certificate_signing_request" "certificate-signing-request" {
17+
site_id = incapsula_site.example-site.id
18+
domain = "sandwich.au"
19+
email = "test@sandwich.au"
20+
country = "AU"
21+
state = "QLD"
22+
city = "BNE"
23+
organization = "Tacos Pty Ltd"
24+
organization_unit = "Kitchen"
25+
}
26+
```
27+
28+
## Argument Reference
29+
30+
The following arguments are supported:
31+
32+
* `site_id` - (Required) Numeric identifier of the site to operate on.
33+
* `domain` - (Optional) The common name. For example: `example.com`
34+
* `email` - (Optional) The Email address. For example: `joe@example.com`
35+
* `country` - (Optional) The two-letter ISO code for the country where your organization is located.
36+
* `state` - (Optional) The state/region where your organization is located. This should not be abbreviated.
37+
* `city` - (Optional) The city where your organization is located.
38+
* `organization` - (Optional) The legal name of your organization. This should not be abbreviated or include suffixes such as Inc., Corp., or LLC.
39+
* `organization_unit` - (Optional) The division of your organization handling the certificate. For example, IT Department.
40+
41+
## Attributes Reference
42+
43+
The following attributes are exported:
44+
45+
* `id` - (String) At the moment, only one active certificate can be stored. This exported value is always set to `site_id`.
46+
* `csr_content` - (String) The certificate request data.

0 commit comments

Comments
 (0)