mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2024-11-14 12:15:06 +08:00
cd61c2c766
* Remove deprecated io/ioutil * fixup! * fixup!
136 lines
3.6 KiB
Go
136 lines
3.6 KiB
Go
package acme
|
|
|
|
import (
|
|
"crypto/x509"
|
|
"encoding/json"
|
|
"encoding/pem"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/go-acme/lego/certificate"
|
|
)
|
|
|
|
// directoryStorage implements storage in a local file directory
|
|
type directoryStorage string
|
|
|
|
// filename for certificate / key / json file
|
|
func (d directoryStorage) certFile(name, ext string) string {
|
|
return filepath.Join(d.certDir(name), name+"."+ext)
|
|
}
|
|
func (d directoryStorage) certDir(name string) string {
|
|
return filepath.Join(string(d), "certificates", name)
|
|
}
|
|
|
|
func (d directoryStorage) accountDirectory(acmeHost string) string {
|
|
return filepath.Join(string(d), ".letsencrypt", acmeHost)
|
|
}
|
|
|
|
func (d directoryStorage) accountFile(acmeHost string) string {
|
|
return filepath.Join(d.accountDirectory(acmeHost), "account.json")
|
|
}
|
|
func (d directoryStorage) accountKeyFile(acmeHost string) string {
|
|
return filepath.Join(d.accountDirectory(acmeHost), "account.key")
|
|
}
|
|
|
|
const perms os.FileMode = 0600
|
|
const dirPerms os.FileMode = 0700
|
|
|
|
func (d directoryStorage) GetCertificate(name string) (*certificate.Resource, error) {
|
|
f, err := os.Open(d.certFile(name, "json"))
|
|
if err != nil && os.IsNotExist(err) {
|
|
// if json does not exist, nothing does
|
|
return nil, nil
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer f.Close()
|
|
dec := json.NewDecoder(f)
|
|
cr := &certificate.Resource{}
|
|
if err = dec.Decode(cr); err != nil {
|
|
return nil, err
|
|
}
|
|
// load cert
|
|
crtBytes, err := os.ReadFile(d.certFile(name, "crt"))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
cr.Certificate = crtBytes
|
|
return cr, nil
|
|
}
|
|
|
|
func (d directoryStorage) StoreCertificate(name string, cert *certificate.Resource) error {
|
|
// make sure actual cert data never gets into metadata json
|
|
if err := os.MkdirAll(d.certDir(name), dirPerms); err != nil {
|
|
return err
|
|
}
|
|
pub := cert.Certificate
|
|
cert.Certificate = nil
|
|
priv := cert.PrivateKey
|
|
cert.PrivateKey = nil
|
|
combined := []byte(string(pub) + "\n" + string(priv))
|
|
jDAt, err := json.MarshalIndent(cert, "", " ")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err = os.WriteFile(d.certFile(name, "json"), jDAt, perms); err != nil {
|
|
return err
|
|
}
|
|
if err = os.WriteFile(d.certFile(name, "crt"), pub, perms); err != nil {
|
|
return err
|
|
}
|
|
if err = os.WriteFile(d.certFile(name, "pem"), combined, perms); err != nil {
|
|
return err
|
|
}
|
|
return os.WriteFile(d.certFile(name, "key"), priv, perms)
|
|
}
|
|
|
|
func (d directoryStorage) GetAccount(acmeHost string) (*Account, error) {
|
|
f, err := os.Open(d.accountFile(acmeHost))
|
|
if err != nil && os.IsNotExist(err) {
|
|
return nil, nil
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer f.Close()
|
|
dec := json.NewDecoder(f)
|
|
acct := &Account{}
|
|
if err = dec.Decode(acct); err != nil {
|
|
return nil, err
|
|
}
|
|
keyBytes, err := os.ReadFile(d.accountKeyFile(acmeHost))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
keyBlock, _ := pem.Decode(keyBytes)
|
|
if keyBlock == nil {
|
|
return nil, fmt.Errorf("error decoding account private key")
|
|
}
|
|
acct.key, err = x509.ParseECPrivateKey(keyBlock.Bytes)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return acct, nil
|
|
}
|
|
|
|
func (d directoryStorage) StoreAccount(acmeHost string, account *Account) error {
|
|
if err := os.MkdirAll(d.accountDirectory(acmeHost), dirPerms); err != nil {
|
|
return err
|
|
}
|
|
acctBytes, err := json.MarshalIndent(account, "", " ")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err = os.WriteFile(d.accountFile(acmeHost), acctBytes, perms); err != nil {
|
|
return err
|
|
}
|
|
keyBytes, err := x509.MarshalECPrivateKey(account.key)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
pemKey := &pem.Block{Type: "EC PRIVATE KEY", Bytes: keyBytes}
|
|
pemBytes := pem.EncodeToMemory(pemKey)
|
|
return os.WriteFile(d.accountKeyFile(acmeHost), pemBytes, perms)
|
|
}
|