Skip to content

Commit

Permalink
feat: added certificate to load-balancer (#396)
Browse files Browse the repository at this point in the history
  • Loading branch information
alekc authored Mar 4, 2020
1 parent 6766e4e commit 5b311ef
Show file tree
Hide file tree
Showing 6 changed files with 461 additions and 0 deletions.
29 changes: 29 additions & 0 deletions scaleway/helpers_lb.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,10 +200,39 @@ func expandLbHCHTTPS(raw interface{}) *lb.HealthCheckHTTPSConfig {
if raw == nil || len(raw.([]interface{})) != 1 {
return nil
}

rawMap := raw.([]interface{})[0].(map[string]interface{})
return &lb.HealthCheckHTTPSConfig{
URI: rawMap["uri"].(string),
Method: rawMap["method"].(string),
Code: expandInt32Ptr(rawMap["code"]),
}
}

func expandLbLetsEncrypt(raw interface{}) *lb.CreateCertificateRequestLetsencryptConfig {
if raw == nil || len(raw.([]interface{})) != 1 {
return nil
}

rawMap := raw.([]interface{})[0].(map[string]interface{})
alternativeNames := rawMap["subject_alternative_name"].([]interface{})
config := &lb.CreateCertificateRequestLetsencryptConfig{
CommonName: rawMap["common_name"].(string),
}
for _, alternativeName := range alternativeNames {
config.SubjectAlternativeName = append(config.SubjectAlternativeName, alternativeName.(string))
}
return config
}

func expandLbCustomCertificate(raw interface{}) *lb.CreateCertificateRequestCustomCertificate {
if raw == nil || len(raw.([]interface{})) != 1 {
return nil
}

rawMap := raw.([]interface{})[0].(map[string]interface{})
config := &lb.CreateCertificateRequestCustomCertificate{
CertificateChain: rawMap["certificate_chain"].(string),
}
return config
}
1 change: 1 addition & 0 deletions scaleway/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ func Provider() terraform.ResourceProvider {
"scaleway_k8s_pool_beta": resourceScalewayK8SPoolBeta(),
"scaleway_lb_beta": resourceScalewayLbBeta(),
"scaleway_lb_backend_beta": resourceScalewayLbBackendBeta(),
"scaleway_lb_certificate_beta": resourceScalewayLbCertificateBeta(),
"scaleway_lb_frontend_beta": resourceScalewayLbFrontendBeta(),
"scaleway_registry_namespace_beta": resourceScalewayRegistryNamespaceBeta(),
"scaleway_rdb_instance_beta": resourceScalewayRdbInstanceBeta(),
Expand Down
201 changes: 201 additions & 0 deletions scaleway/resource_lb_certificate_beta.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
package scaleway

import (
"errors"

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/scaleway/scaleway-sdk-go/api/lb/v1"
)

func resourceScalewayLbCertificateBeta() *schema.Resource {
return &schema.Resource{
Create: resourceScalewayLbCertificateBetaCreate,
Read: resourceScalewayLbCertificateBetaRead,
Update: resourceScalewayLbCertificateBetaUpdate,
Delete: resourceScalewayLbCertificateBetaDelete,
SchemaVersion: 0,
Schema: map[string]*schema.Schema{
"lb_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: "The load-balancer ID",
},
"name": {
Type: schema.TypeString,
Description: "The name of the load-balancer certificate",
Optional: true,
Computed: true,
},
"letsencrypt": {
ConflictsWith: []string{"custom_certificate"},
MaxItems: 1,
Description: "The Let's Encrypt type certificate configuration",
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"common_name": {
Type: schema.TypeString,
Required: true,
Description: "The main domain name of the certificate",
},
"subject_alternative_name": {
Type: schema.TypeList,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Optional: true,
Description: "The alternative domain names of the certificate",
},
},
},
},
"custom_certificate": {
ConflictsWith: []string{"letsencrypt"},
MaxItems: 1,
Type: schema.TypeList,
Description: "The custom type certificate type configuration",
Optional: true,
ForceNew: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"certificate_chain": {
Type: schema.TypeString,
Required: true,
Description: "The full PEM-formatted certificate chain",
},
},
},
},

// Readonly attributes
"common_name": {
Type: schema.TypeString,
Computed: true,
Description: "The main domain name of the certificate",
},
"subject_alternative_name": {
Type: schema.TypeString,
Computed: true,
Description: "The alternative domain names of the certificate",
},
"fingerprint": {
Type: schema.TypeString,
Computed: true,
Description: "The identifier (SHA-1) of the certificate",
},
"not_valid_before": {
Type: schema.TypeString,
Computed: true,
Description: "The not valid before validity bound timestamp",
},
"not_valid_after": {
Type: schema.TypeString,
Computed: true,
Description: "The not valid after validity bound timestamp",
},
"status": {
Type: schema.TypeString,
Computed: true,
Description: "The status of certificate",
},
},
}
}

func resourceScalewayLbCertificateBetaCreate(d *schema.ResourceData, m interface{}) error {
region, lbID, err := parseRegionalID(d.Get("lb_id").(string))
if err != nil {
return err
}

createReq := &lb.CreateCertificateRequest{
Region: region,
LbID: lbID,
Name: expandOrGenerateString(d.Get("name"), "lb-cert"),
Letsencrypt: expandLbLetsEncrypt(d.Get("letsencrypt")),
CustomCertificate: expandLbCustomCertificate(d.Get("custom_certificate")),
}
if createReq.Letsencrypt == nil && createReq.CustomCertificate == nil {
return errors.New("you need to define either letsencrypt or custom_certificate configuration")
}

lbAPI := lbAPI(m)
res, err := lbAPI.CreateCertificate(createReq)
if err != nil {
return err
}

d.SetId(newRegionalId(region, res.ID))

return resourceScalewayLbCertificateBetaRead(d, m)
}

func resourceScalewayLbCertificateBetaRead(d *schema.ResourceData, m interface{}) error {
lbAPI, region, ID, err := lbAPIWithRegionAndID(m, d.Id())
if err != nil {
return err
}

res, err := lbAPI.GetCertificate(&lb.GetCertificateRequest{
CertificateID: ID,
Region: region,
})

if err != nil {
if is404Error(err) {
d.SetId("")
return nil
}
return err
}

_ = d.Set("name", res.Name)
_ = d.Set("common_name", res.CommonName)
_ = d.Set("subject_alternative_name", res.SubjectAlternativeName)
_ = d.Set("fingerprint", res.Fingerprint)
_ = d.Set("not_valid_before", flattenTime(&res.NotValidBefore))
_ = d.Set("not_valid_after", flattenTime(&res.NotValidAfter))
_ = d.Set("status", res.Status)
return nil
}

func resourceScalewayLbCertificateBetaUpdate(d *schema.ResourceData, m interface{}) error {
lbAPI, region, ID, err := lbAPIWithRegionAndID(m, d.Id())
if err != nil {
return err
}

req := &lb.UpdateCertificateRequest{
CertificateID: ID,
Region: region,
Name: d.Get("name").(string),
}

_, err = lbAPI.UpdateCertificate(req)
if err != nil {
return err
}

return resourceScalewayLbCertificateBetaRead(d, m)
}

func resourceScalewayLbCertificateBetaDelete(d *schema.ResourceData, m interface{}) error {
lbAPI, region, ID, err := lbAPIWithRegionAndID(m, d.Id())
if err != nil {
return err
}

err = lbAPI.DeleteCertificate(&lb.DeleteCertificateRequest{
Region: region,
CertificateID: ID,
})

if err != nil && !is404Error(err) {
return err
}

return nil
}
141 changes: 141 additions & 0 deletions scaleway/resource_lb_certificate_beta_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package scaleway

import (
"testing"

"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
)

func TestAccScalewayLbCertificateBeta(t *testing.T) {
/**
* Note regarding the usage of xip.io
* See the discussion on https://github.com/terraform-providers/terraform-provider-scaleway/pull/396
* Long story short, scaleway API will not permit you to request a certificate in case common name is not pointed
* to the load balancer IP (which is unknown before creating it). In production, this can be overcome by introducing
* an additional step which creates a DNS record and depending on it, but for test purposes, xip.io is an ideal solution.
*/
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckScalewayLbBetaDestroy,
Steps: []resource.TestStep{
{
Config: `
resource scaleway_lb_beta lb01 {
name = "test-lb"
type = "lb-s"
}
resource scaleway_lb_certificate_beta cert01 {
lb_id = scaleway_lb_beta.lb01.id
name = "test-cert"
letsencrypt {
common_name = "${scaleway_lb_beta.lb01.ip_address}.xip.io"
}
}
`,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("scaleway_lb_certificate_beta.cert01", "name", "test-cert"),
resource.TestCheckResourceAttr("scaleway_lb_certificate_beta.cert01", "letsencrypt.#", "1"),
),
},
{
Config: `
resource scaleway_lb_beta lb01 {
name = "test-lb"
type = "lb-s"
}
resource scaleway_lb_certificate_beta cert01 {
lb_id = scaleway_lb_beta.lb01.id
name = "test-cert-new"
letsencrypt {
common_name = "${scaleway_lb_beta.lb01.ip_address}.xip.io"
}
}
`,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("scaleway_lb_certificate_beta.cert01", "name", "test-cert-new"),
),
},
{
Config: `
resource scaleway_lb_beta lb01 {
name = "test-lb"
type = "lb-s"
}
resource scaleway_lb_certificate_beta cert01 {
lb_id = scaleway_lb_beta.lb01.id
name = "test-cert"
letsencrypt {
common_name = "${scaleway_lb_beta.lb01.ip_address}.xip.io"
subject_alternative_name = [
"sub1.${scaleway_lb_beta.lb01.ip_address}.xip.io",
"sub2.${scaleway_lb_beta.lb01.ip_address}.xip.io"
]
}
}
`,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("scaleway_lb_certificate_beta.cert01", "name", "test-cert"),
resource.TestCheckResourceAttr("scaleway_lb_certificate_beta.cert01", "letsencrypt.#", "1"),
resource.TestCheckResourceAttr("scaleway_lb_certificate_beta.cert01", "letsencrypt.0.subject_alternative_name.#", "2"),
),
},
{
Config: `
resource scaleway_lb_beta lb01 {
name = "test-lb"
type = "lb-s"
}
resource scaleway_lb_certificate_beta cert01 {
lb_id = scaleway_lb_beta.lb01.id
name = "test-custom-cert"
custom_certificate {
certificate_chain = <<EOF
-----BEGIN CERTIFICATE REQUEST-----
MIIBZTCBzwIBADAmMQwwCgYDVQQKDANCYXIxFjAUBgNVBAMMDSouZXhhbXBsZS5j
b20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKM8iE+6xpL9ps2x/W/+0wf3
+5Kgcwl+AoqUTNmAT6eaLfj3PMtdAmN+IcGsYXK2F1FENAdfHd70m4mSBoMJeq+F
a2ZEYp+RlFQqldTBSUBld48z9DNkbNmb0cMyVmntnKhPZ5wjNjgsYee2Leesm2lx
Gw2BCpDxGLBmwKFca3bTAgMBAAGgADANBgkqhkiG9w0BAQsFAAOBgQBbelf1jYNX
Y+AbCpbsySJ32iDtlrZkcIDHMlRIefnoXnO8B1RiEY0SU/n/b2tFCAcvkhq0whKj
RPOH6lzT0x3lWxI+C6xpVyURlljHPygVRbD3fig1rFnH3sI2IE3fJEbGJdmmHacA
BRgm3RR+HWWLKB0ygUbOtZk0BLBUqPK+WQ==
-----END CERTIFICATE REQUEST-----
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCjPIhPusaS/abNsf1v/tMH9/uSoHMJfgKKlEzZgE+nmi349zzL
XQJjfiHBrGFythdRRDQHXx3e9JuJkgaDCXqvhWtmRGKfkZRUKpXUwUlAZXePM/Qz
ZGzZm9HDMlZp7ZyoT2ecIzY4LGHnti3nrJtpcRsNgQqQ8RiwZsChXGt20wIDAQAB
AoGBAINGbhU4jvOtW9T2fGvyEgLJkp7zvC/5D9Akvbz5LJYML0aWhmTB0ubyi/E2
UVQwToZDhFgdTWd9bgxvzB7bo7Z1kiKWTXQSUDTjC3fchE12UU+1/s0LGh9B1cpV
YqFAu7QNG4maXdZ2h+u+T7dioHslS74PFCBExClkwDiUsdcRAkEAzufrw6zgC0R3
x6OMaaPsH2oX9KfR0+Kxj2m02TnwyFPSrSlIGfoSVtU5wBkvCwTBx/IPY70vNw3f
fPacJNldGwJBAMn3/2nqMJUhR3U7bZA3lI+T1z01D7dLbvCafh3oHTYRAbHO2f0z
k1uhn1+2r9QICwaugZwvx7biCfT3rTqXAKkCQGbINwphWnq+bHI0AJCJ6cZBQd07
cLS9LE99x2URr1cUrNdwZmzhGTMhgSq4V/I1Tr4wtQxq8oV60saVC0QS5nkCQQDI
W2NfuNlVN9xhqgC4zspr3KfrqlXa6dQ2j6yJEpjX5+scby3Fh4Kpph4qn1qyJwB5
MmiVfrjK7lYeVA3fT6lxAkAc1QlmGapJ3w9996v6OZ3UqNBzsHsMmze/zGemdMfc
VaSSB5OL7dZ8fLoJctv9EwgIBM3LFhSgAm9ASPHHR9fp
-----END RSA PRIVATE KEY-----
----BEGIN TRUSTED CERTIFICATE-----
MIIBmTCCAQICCQCb2NiBTIlkeTANBgkqhkiG9w0BAQUFADARMQ8wDQYDVQQKDAZG
b29CYXIwHhcNMjAwMzAzMTYwODQ4WhcNMzAwMzAxMTYwODQ4WjARMQ8wDQYDVQQK
DAZGb29CYXIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALba1p/3sJ3E2J0J
Wa6N4Zw9aBAq4OedYszUCYqviG6XiCKZPeI1skfD9bef4pYG67R5OcccCsjwqfT4
HkwKj/2SG4VsJZpvVr9S1uOeiA70KywB9GvuiLZUflrDEy4IEA0s6UBALRgXllX+
QbnE8VC9brzgepQwO6tTU1Vjo9s9AgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAelXe
TxdxZWXZFldVl7LUS39lsc9CRgIcLbmk/s23zs92zyJcYvarulx2ku4Zrp507RzT
hPrE4kljWeyQnwIXeOSg5UZrsRtRxUTDLBtOrL3PmFZhBaDShSc+1DS4U/kjy/k+
F+6t5ymALbasChWwC7FFgSsF5PtGP4PxZHFdXiE=
-----END TRUSTED CERTIFICATE-----
EOF
}
}
`,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("scaleway_lb_certificate_beta.cert01", "name", "test-custom-cert"),
resource.TestCheckResourceAttr("scaleway_lb_certificate_beta.cert01", "custom_certificate.#", "1"),
),
},
},
})
}
Loading

0 comments on commit 5b311ef

Please sign in to comment.