feat: Birth.
This commit is contained in:
parent
4a15068035
commit
4ca0745cbd
107
dumper.go
Normal file
107
dumper.go
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"encoding/pem"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/xenolf/lego/certcrypto"
|
||||||
|
"github.com/xenolf/lego/registration"
|
||||||
|
)
|
||||||
|
|
||||||
|
// StoredData represents the data managed by the Store
|
||||||
|
type StoredData struct {
|
||||||
|
Account *Account
|
||||||
|
Certificates []*Certificate
|
||||||
|
HTTPChallenges map[string]map[string][]byte
|
||||||
|
TLSChallenges map[string]*Certificate
|
||||||
|
}
|
||||||
|
|
||||||
|
// Certificate is a struct which contains all data needed from an ACME certificate
|
||||||
|
type Certificate struct {
|
||||||
|
Domain Domain
|
||||||
|
Certificate []byte
|
||||||
|
Key []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// Domain holds a domain name with SANs
|
||||||
|
type Domain struct {
|
||||||
|
Main string
|
||||||
|
SANs []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Account is used to store lets encrypt registration info
|
||||||
|
type Account struct {
|
||||||
|
Email string
|
||||||
|
Registration *registration.Resource
|
||||||
|
PrivateKey []byte
|
||||||
|
KeyType certcrypto.KeyType
|
||||||
|
}
|
||||||
|
|
||||||
|
func dump(acmeFile, dumpPath string) error {
|
||||||
|
f, err := os.Open(acmeFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
data := StoredData{}
|
||||||
|
if err = json.NewDecoder(f).Decode(&data); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = os.RemoveAll(dumpPath); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.MkdirAll(filepath.Join(dumpPath, "certs"), 0755)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.MkdirAll(filepath.Join(dumpPath, "private"), 0755)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
privateKeyPem := extractPEMPrivateKey(data.Account)
|
||||||
|
err = ioutil.WriteFile(filepath.Join(dumpPath, "private", "letsencrypt.key"), privateKeyPem, 0666)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, cert := range data.Certificates {
|
||||||
|
err = ioutil.WriteFile(filepath.Join(dumpPath, "private", cert.Domain.Main+".key"), cert.Key, 0666)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(filepath.Join(dumpPath, "certs", cert.Domain.Main+".crt"), cert.Certificate, 0666)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractPEMPrivateKey(account *Account) []byte {
|
||||||
|
var block *pem.Block
|
||||||
|
switch account.KeyType {
|
||||||
|
case certcrypto.RSA2048, certcrypto.RSA4096, certcrypto.RSA8192:
|
||||||
|
block = &pem.Block{
|
||||||
|
Type: "RSA PRIVATE KEY",
|
||||||
|
Bytes: account.PrivateKey,
|
||||||
|
}
|
||||||
|
case certcrypto.EC256, certcrypto.EC384:
|
||||||
|
block = &pem.Block{
|
||||||
|
Type: "EC PRIVATE KEY",
|
||||||
|
Bytes: account.PrivateKey,
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic("unsupported key type")
|
||||||
|
}
|
||||||
|
|
||||||
|
return pem.EncodeToMemory(block)
|
||||||
|
}
|
||||||
11
go.mod
Normal file
11
go.mod
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
module github.com/ldez/treafik-cert-dumper
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/cenkalti/backoff v2.1.1+incompatible // indirect
|
||||||
|
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||||
|
github.com/spf13/cobra v0.0.3
|
||||||
|
github.com/spf13/pflag v1.0.3 // indirect
|
||||||
|
github.com/xenolf/lego v2.2.0+incompatible
|
||||||
|
golang.org/x/crypto v0.0.0-20190208162236-193df9c0f06f // indirect
|
||||||
|
gopkg.in/square/go-jose.v2 v2.2.2 // indirect
|
||||||
|
)
|
||||||
14
go.sum
Normal file
14
go.sum
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
github.com/cenkalti/backoff v2.1.1+incompatible h1:tKJnvO2kl0zmb/jA5UKAt4VoEVw1qxKWjE/Bpp46npY=
|
||||||
|
github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||||
|
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||||
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
|
github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8=
|
||||||
|
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||||
|
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||||
|
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
|
github.com/xenolf/lego v2.2.0+incompatible h1:r4UAcpgPmX3j0aThoVrRM1FFLcvyy08UyGbIwFU4zoQ=
|
||||||
|
github.com/xenolf/lego v2.2.0+incompatible/go.mod h1:fwiGnfsIjG7OHPfOvgK7Y/Qo6+2Ox0iozjNTkZICKbY=
|
||||||
|
golang.org/x/crypto v0.0.0-20190208162236-193df9c0f06f h1:ETU2VEl7TnT5bl7IvuKEzTDpplg5wzGYsOCAPhdoEIg=
|
||||||
|
golang.org/x/crypto v0.0.0-20190208162236-193df9c0f06f/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
gopkg.in/square/go-jose.v2 v2.2.2 h1:orlkJ3myw8CN1nVQHBFfloD+L3egixIa4FvUP6RosSA=
|
||||||
|
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||||
52
main.go
Normal file
52
main.go
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var rootCmd = &cobra.Command{
|
||||||
|
Use: "traefik-certs-dumper",
|
||||||
|
Short: "Dump Let's Encrypt certificates from Traefik",
|
||||||
|
Long: `Dump the content of the "acme.json" file from Traefik to certificates.`,
|
||||||
|
Version: version,
|
||||||
|
}
|
||||||
|
|
||||||
|
var dumpCmd = &cobra.Command{
|
||||||
|
Use: "dump",
|
||||||
|
Short: "Dump Let's Encrypt certificates from Traefik",
|
||||||
|
Long: `Dump the content of the "acme.json" file from Traefik to certificates.`,
|
||||||
|
Run: func(cmd *cobra.Command, _ []string) {
|
||||||
|
acmeFile := cmd.Flag("source").Value.String()
|
||||||
|
dumpPath := cmd.Flag("dest").Value.String()
|
||||||
|
|
||||||
|
err := dump(acmeFile, dumpPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
dumpCmd.Flags().String("source", "./acme.json", "Path to 'acme.json' file.")
|
||||||
|
dumpCmd.Flags().String("dest", "./dump", "Path to store the dump content.")
|
||||||
|
rootCmd.AddCommand(dumpCmd)
|
||||||
|
|
||||||
|
var versionCmd = &cobra.Command{
|
||||||
|
Use: "version",
|
||||||
|
Short: "Display version",
|
||||||
|
Run: func(_ *cobra.Command, _ []string) {
|
||||||
|
displayVersion(rootCmd.Name())
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
rootCmd.AddCommand(versionCmd)
|
||||||
|
|
||||||
|
if err := rootCmd.Execute(); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
23
version.go
Normal file
23
version.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
version = "dev"
|
||||||
|
commit = "I don't remember exactly"
|
||||||
|
date = "I don't remember exactly"
|
||||||
|
)
|
||||||
|
|
||||||
|
func displayVersion(name string) {
|
||||||
|
fmt.Printf(name+`:
|
||||||
|
version : %s
|
||||||
|
commit : %s
|
||||||
|
build date : %s
|
||||||
|
go version : %s
|
||||||
|
go compiler : %s
|
||||||
|
platform : %s/%s
|
||||||
|
`, version, commit, date, runtime.Version(), runtime.Compiler, runtime.GOOS, runtime.GOARCH)
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user