Add support for Let's Encrypt Certificates. (#165)

* Add support for Let's Encrypt Certificates.

* Update CHANGELOG with applied changes.

* Update changelog
This commit is contained in:
Wioletta Holownia 2018-05-08 16:40:21 -04:00 committed by GitHub
parent e6249e5059
commit c5c6644acf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 138 additions and 46 deletions

View File

@ -1,5 +1,10 @@
# Change Log # Change Log
## [v1.2.0] - 2018-05-08
- #166 Remove support for Go 1.6 - @iheanyi
- #165 Add support for Let's Encrypt Certificates - @viola
## [v1.1.3] - 2018-03-07 ## [v1.1.3] - 2018-03-07
- #156 Handle non-json errors from the API - @aknuds1 - #156 Handle non-json errors from the API - @aknuds1

View File

@ -19,19 +19,24 @@ type CertificatesService interface {
// Certificate represents a DigitalOcean certificate configuration. // Certificate represents a DigitalOcean certificate configuration.
type Certificate struct { type Certificate struct {
ID string `json:"id,omitempty"` ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
NotAfter string `json:"not_after,omitempty"` DNSNames []string `json:"dns_names,omitempty"`
SHA1Fingerprint string `json:"sha1_fingerprint,omitempty"` NotAfter string `json:"not_after,omitempty"`
Created string `json:"created_at,omitempty"` SHA1Fingerprint string `json:"sha1_fingerprint,omitempty"`
Created string `json:"created_at,omitempty"`
State string `json:"state,omitempty"`
Type string `json:"type,omitempty"`
} }
// CertificateRequest represents configuration for a new certificate. // CertificateRequest represents configuration for a new certificate.
type CertificateRequest struct { type CertificateRequest struct {
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
PrivateKey string `json:"private_key,omitempty"` DNSNames []string `json:"dns_names,omitempty"`
LeafCertificate string `json:"leaf_certificate,omitempty"` PrivateKey string `json:"private_key,omitempty"`
CertificateChain string `json:"certificate_chain,omitempty"` LeafCertificate string `json:"leaf_certificate,omitempty"`
CertificateChain string `json:"certificate_chain,omitempty"`
Type string `json:"type,omitempty"`
} }
type certificateRoot struct { type certificateRoot struct {

View File

@ -15,9 +15,15 @@ var certJSONResponse = `
"certificate": { "certificate": {
"id": "892071a0-bb95-49bc-8021-3afd67a210bf", "id": "892071a0-bb95-49bc-8021-3afd67a210bf",
"name": "web-cert-01", "name": "web-cert-01",
"dns_names": [
"somedomain.com",
"api.somedomain.com"
],
"not_after": "2017-02-22T00:23:00Z", "not_after": "2017-02-22T00:23:00Z",
"sha1_fingerprint": "dfcc9f57d86bf58e321c2c6c31c7a971be244ac7", "sha1_fingerprint": "dfcc9f57d86bf58e321c2c6c31c7a971be244ac7",
"created_at": "2017-02-08T16:02:37Z" "created_at": "2017-02-08T16:02:37Z",
"state": "verified",
"type": "custom"
} }
} }
` `
@ -27,17 +33,26 @@ var certsJSONResponse = `
"certificates": [ "certificates": [
{ {
"id": "892071a0-bb95-49bc-8021-3afd67a210bf", "id": "892071a0-bb95-49bc-8021-3afd67a210bf",
"name": "web-cert-01", "name": "web-cert-01",
"dns_names": [
"somedomain.com",
"api.somedomain.com"
],
"not_after": "2017-02-22T00:23:00Z", "not_after": "2017-02-22T00:23:00Z",
"sha1_fingerprint": "dfcc9f57d86bf58e321c2c6c31c7a971be244ac7", "sha1_fingerprint": "dfcc9f57d86bf58e321c2c6c31c7a971be244ac7",
"created_at": "2017-02-08T16:02:37Z" "created_at": "2017-02-08T16:02:37Z",
"state": "verified",
"type": "custom"
}, },
{ {
"id": "992071a0-bb95-49bc-8021-3afd67a210bf", "id": "992071a0-bb95-49bc-8021-3afd67a210bf",
"name": "web-cert-02", "name": "web-cert-02",
"dns_names":["example.com"],
"not_after": "2017-02-22T00:23:00Z", "not_after": "2017-02-22T00:23:00Z",
"sha1_fingerprint": "cfcc9f57d86bf58e321c2c6c31c7a971be244ac7", "sha1_fingerprint": "cfcc9f57d86bf58e321c2c6c31c7a971be244ac7",
"created_at": "2017-02-08T16:02:37Z" "created_at": "2017-02-08T16:02:37Z",
"state": "pending",
"type": "lets_encrypt"
} }
], ],
"links": {}, "links": {},
@ -67,9 +82,12 @@ func TestCertificates_Get(t *testing.T) {
expected := &Certificate{ expected := &Certificate{
ID: "892071a0-bb95-49bc-8021-3afd67a210bf", ID: "892071a0-bb95-49bc-8021-3afd67a210bf",
Name: "web-cert-01", Name: "web-cert-01",
DNSNames: []string{"somedomain.com", "api.somedomain.com"},
NotAfter: "2017-02-22T00:23:00Z", NotAfter: "2017-02-22T00:23:00Z",
SHA1Fingerprint: "dfcc9f57d86bf58e321c2c6c31c7a971be244ac7", SHA1Fingerprint: "dfcc9f57d86bf58e321c2c6c31c7a971be244ac7",
Created: "2017-02-08T16:02:37Z", Created: "2017-02-08T16:02:37Z",
State: "verified",
Type: "custom",
} }
assert.Equal(t, expected, certificate) assert.Equal(t, expected, certificate)
@ -95,16 +113,22 @@ func TestCertificates_List(t *testing.T) {
{ {
ID: "892071a0-bb95-49bc-8021-3afd67a210bf", ID: "892071a0-bb95-49bc-8021-3afd67a210bf",
Name: "web-cert-01", Name: "web-cert-01",
DNSNames: []string{"somedomain.com", "api.somedomain.com"},
NotAfter: "2017-02-22T00:23:00Z", NotAfter: "2017-02-22T00:23:00Z",
SHA1Fingerprint: "dfcc9f57d86bf58e321c2c6c31c7a971be244ac7", SHA1Fingerprint: "dfcc9f57d86bf58e321c2c6c31c7a971be244ac7",
Created: "2017-02-08T16:02:37Z", Created: "2017-02-08T16:02:37Z",
State: "verified",
Type: "custom",
}, },
{ {
ID: "992071a0-bb95-49bc-8021-3afd67a210bf", ID: "992071a0-bb95-49bc-8021-3afd67a210bf",
Name: "web-cert-02", Name: "web-cert-02",
DNSNames: []string{"example.com"},
NotAfter: "2017-02-22T00:23:00Z", NotAfter: "2017-02-22T00:23:00Z",
SHA1Fingerprint: "cfcc9f57d86bf58e321c2c6c31c7a971be244ac7", SHA1Fingerprint: "cfcc9f57d86bf58e321c2c6c31c7a971be244ac7",
Created: "2017-02-08T16:02:37Z", Created: "2017-02-08T16:02:37Z",
State: "pending",
Type: "lets_encrypt",
}, },
} }
@ -112,44 +136,102 @@ func TestCertificates_List(t *testing.T) {
} }
func TestCertificates_Create(t *testing.T) { func TestCertificates_Create(t *testing.T) {
setup() tests := []struct {
defer teardown() desc string
createRequest *CertificateRequest
createRequest := &CertificateRequest{ certJSONResponse string
Name: "web-cert-01", expectedCertificate *Certificate
PrivateKey: "-----BEGIN PRIVATE KEY-----", }{
LeafCertificate: "-----BEGIN CERTIFICATE-----", {
CertificateChain: "-----BEGIN CERTIFICATE-----", desc: "creates custom certificate",
createRequest: &CertificateRequest{
Name: "web-cert-01",
PrivateKey: "-----BEGIN PRIVATE KEY-----",
LeafCertificate: "-----BEGIN CERTIFICATE-----",
CertificateChain: "-----BEGIN CERTIFICATE-----",
},
certJSONResponse: `{
"certificate": {
"id": "892071a0-bb95-49bc-8021-3afd67a210bf",
"name": "custom-cert",
"dns_names":[],
"not_after": "2017-02-22T00:23:00Z",
"sha1_fingerprint": "dfcc9f57d86bf58e321c2c6c31c7a971be244ac7",
"created_at": "2017-02-08T16:02:37Z",
"state": "verified",
"type": "custom"
}
}`,
expectedCertificate: &Certificate{
ID: "892071a0-bb95-49bc-8021-3afd67a210bf",
Name: "custom-cert",
DNSNames: []string{},
NotAfter: "2017-02-22T00:23:00Z",
SHA1Fingerprint: "dfcc9f57d86bf58e321c2c6c31c7a971be244ac7",
Created: "2017-02-08T16:02:37Z",
State: "verified",
Type: "custom",
},
},
{
desc: "creates let's encrypt certificate",
createRequest: &CertificateRequest{
Name: "lets-encrypt-cert",
DNSNames: []string{"example.com", "api.example.com"},
Type: "lets_encrypt",
},
certJSONResponse: `{
"certificate": {
"id": "91bce928-a983-4c97-a5ee-78c585bf798d",
"name": "lets-encrypt-cert",
"dns_names":["example.com", "api.example.com"],
"not_after": "2022-01-26T15:50:00Z",
"sha1_fingerprint": "2e3c2ba8016faf80f431700ff2865ef6dba30a81",
"created_at": "2017-08-23T20:42:46Z",
"state": "pending",
"type": "lets_encrypt"
}
}`,
expectedCertificate: &Certificate{
ID: "91bce928-a983-4c97-a5ee-78c585bf798d",
Name: "lets-encrypt-cert",
DNSNames: []string{"example.com", "api.example.com"},
NotAfter: "2022-01-26T15:50:00Z",
SHA1Fingerprint: "2e3c2ba8016faf80f431700ff2865ef6dba30a81",
Created: "2017-08-23T20:42:46Z",
State: "pending",
Type: "lets_encrypt",
},
},
} }
urlStr := "/v2/certificates" for _, test := range tests {
mux.HandleFunc(urlStr, func(w http.ResponseWriter, r *http.Request) { t.Run(test.desc, func(t *testing.T) {
v := new(CertificateRequest) setup()
err := json.NewDecoder(r.Body).Decode(v) defer teardown()
if err != nil {
t.Fatal(err)
}
testMethod(t, r, http.MethodPost) urlStr := "/v2/certificates"
assert.Equal(t, createRequest, v) mux.HandleFunc(urlStr, func(w http.ResponseWriter, r *http.Request) {
v := new(CertificateRequest)
err := json.NewDecoder(r.Body).Decode(v)
if err != nil {
t.Fatal(err)
}
fmt.Fprint(w, certJSONResponse) testMethod(t, r, http.MethodPost)
}) assert.Equal(t, test.createRequest, v)
certificate, _, err := client.Certificates.Create(ctx, createRequest) fmt.Fprint(w, test.certJSONResponse)
if err != nil { })
t.Errorf("Certificates.Create returned error: %v", err)
certificate, _, err := client.Certificates.Create(ctx, test.createRequest)
if err != nil {
t.Errorf("Certificates.Create returned error: %v", err)
}
assert.Equal(t, test.expectedCertificate, certificate)
})
} }
expected := &Certificate{
ID: "892071a0-bb95-49bc-8021-3afd67a210bf",
Name: "web-cert-01",
NotAfter: "2017-02-22T00:23:00Z",
SHA1Fingerprint: "dfcc9f57d86bf58e321c2c6c31c7a971be244ac7",
Created: "2017-02-08T16:02:37Z",
}
assert.Equal(t, expected, certificate)
} }
func TestCertificates_Delete(t *testing.T) { func TestCertificates_Delete(t *testing.T) {