-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathssl.go
More file actions
92 lines (75 loc) · 2.94 KB
/
Copy pathssl.go
File metadata and controls
92 lines (75 loc) · 2.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package directadmin
import (
"errors"
"fmt"
"net/http"
"net/url"
"github.com/spf13/cast"
)
// ACMEConfig is a domain's automatic TLS (ACME) configuration.
type ACMEConfig struct {
DNSEnvironment map[string]string `json:"dnsEnvironment" yaml:"dnsEnvironment"`
DNSProvider string `json:"dnsProvider" yaml:"dnsProvider"`
Enabled bool `json:"enabled" yaml:"enabled"`
KeyType string `json:"keyType" yaml:"keyType"` // e.g. "ec256", "rsa2048".
PreferWildcard bool `json:"preferWildcard" yaml:"preferWildcard"`
Provider string `json:"provider" yaml:"provider"` // e.g. "letsencrypt".
SkipDNSNames []string `json:"skipDNSNames" yaml:"skipDNSNames"`
}
// normalize fills nil maps/slices, which DA rejects when sent as null.
func (a ACMEConfig) normalize() ACMEConfig {
if a.DNSEnvironment == nil {
a.DNSEnvironment = map[string]string{}
}
if a.SkipDNSNames == nil {
a.SkipDNSNames = []string{}
}
return a
}
// IssueSSL (user) requests a lets encrypt certificate for the given hostnames.
func (c *UserContext) IssueSSL(domain string, hostnamesToCertify ...string) error {
var response apiGenericResponse
if len(hostnamesToCertify) == 0 {
return errors.New("at least one hostname is required for the certificate")
}
body := url.Values{
"type": {"create"},
"request": {"letsencrypt"},
"name": {hostnamesToCertify[0]},
"domain": {domain},
"keysize": {"secp384r1"},
"encryption": {"sha256"},
"wildcard": {"no"},
"background": {"auto"},
"action": {"save"},
"acme_provider": {"letsencrypt"},
}
for index, certDomain := range hostnamesToCertify {
body.Set("le_select"+cast.ToString(index), certDomain)
}
if _, err := c.makeRequestOld(http.MethodPost, "API_SSL", body, &response); err != nil {
return err
}
if response.Success != "Certificate and Key Saved." {
return fmt.Errorf("failed to issue SSL certificate: %v", response.Result)
}
return nil
}
// ProvisionCerts (user) triggers ACME certificate provisioning for the given domain
// using its saved ACMEConfig. DirectAdmin does this synchronously and it can take
// several minutes, so the API needs a suitably long timeout. The raw response body
// is returned as its shape varies by provider.
func (c *UserContext) ProvisionCerts(domain string) ([]byte, error) {
resp, err := c.makeRequestNew(http.MethodPost, "domain-tls/"+domain+"/provision-certs", nil, nil)
if err != nil {
return nil, fmt.Errorf("failed to provision certificates for %v: %w", domain, err)
}
return resp, nil
}
// SetACMEConfig (user) replaces the ACME config for the given domain.
func (c *UserContext) SetACMEConfig(domain string, config ACMEConfig) error {
if _, err := c.makeRequestNew(http.MethodPut, "domain-tls/"+domain+"/acme-config", config.normalize(), nil); err != nil {
return fmt.Errorf("failed to set ACME config for %v: %w", domain, err)
}
return nil
}