Skip to content

Commit

Permalink
Support for claiming existing certificate + Store certificate in Volume
Browse files Browse the repository at this point in the history
* Adds a new required "certificate name" parameter (backward
compatible): When there is an existing certificate by that name it will
be overwritten with a renewed certificate
* fullchain.pem and privatekey.pem are now stored in a Volume under /etc/letsencrypt/production/certificates/. This is until we find a better way to share the private key with other services.
  • Loading branch information
Jan Broer committed Mar 31, 2016
1 parent 46f12b3 commit 2a91bcf
Show file tree
Hide file tree
Showing 12 changed files with 252 additions and 164 deletions.
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ MAINTAINER Jan Broer <[email protected]>

RUN apk add --no-cache ca-certificates

ENV LETSENCRYPT_RELEASE v0.2.5
ENV LETSENCRYPT_RELEASE v0.2.6

ADD https://github.com/janeczku/rancher-letsencrypt/releases/download/${LETSENCRYPT_RELEASE}/rancher-letsencrypt-linux-amd64.tar.gz /tmp/rancher-letsencrypt.tar.gz

RUN tar -zxvf /tmp/rancher-letsencrypt.tar.gz -C /usr/bin \
&& chmod +x /usr/bin/rancher-letsencrypt

Expand Down
3 changes: 3 additions & 0 deletions Dockerfile.dev
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ MAINTAINER Jan Broer <[email protected]>
RUN apk add --no-cache ca-certificates

ADD build/rancher-letsencrypt-linux-amd64 /usr/bin/rancher-letsencrypt

RUN chmod +x /usr/bin/rancher-letsencrypt

VOLUME /etc/letsencrypt

ENV DEBUG=true

ENTRYPOINT ["/usr/bin/rancher-letsencrypt"]
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ dockerhub: image
docker push $(DOCKER_IMAGE):$(VERSION)

image:
docker build -t $(DOCKER_IMAGE):$(VERSION) -f Dockerfile.dev .
docker build -t $(DOCKER_IMAGE):dev-$(SHA) -f Dockerfile.dev .

version:
@echo $(VERSION) $(SHA)
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v0.2.5
v0.2.6
30 changes: 19 additions & 11 deletions context.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
)

const (
DESCRIPTION = "Created by Let's Encrypt Certificate Manager"
CERT_DESCRIPTION = "Created by Let's Encrypt Certificate Manager"
ISSUER_PRODUCTION = "Let's Encrypt"
ISSUER_STAGING = "fake CA"
PREFIX_PROD = "[LE] "
Expand All @@ -38,12 +38,13 @@ func (c *Context) InitContext() {
cattleUrl := getEnvOption("CATTLE_URL", true)
cattleApiKey := getEnvOption("CATTLE_ACCESS_KEY", true)
cattleSecretKey := getEnvOption("CATTLE_SECRET_KEY", true)
debug := getEnvOption("DEBUG", false)
debugParam := getEnvOption("DEBUG", false)
eulaParam := getEnvOption("EULA", false)
apiVerParam := getEnvOption("API_VERSION", true)
emailParam := getEnvOption("EMAIL", true)
domainParam := getEnvOption("DOMAINS", true)
keyTypeParam := getEnvOption("PUBLIC_KEY_TYPE", true)
certNameParam := getEnvOption("CERT_NAME", false)
timeParam := getEnvOption("RENEWAL_TIME", true)
providerParam := getEnvOption("PROVIDER", true)

Expand All @@ -63,18 +64,26 @@ func (c *Context) InitContext() {
logrus.Fatalf("Invalid value for RENEWAL_TIME: %s", timeParam)
}

var serverURI string
var certAutoName string

switch apiVerParam {
case "Production":
serverURI = letsencrypt.PRODUCTION_URI
c.RancherCertName = PREFIX_PROD + c.Domains[0]
certAutoName = PREFIX_PROD + c.Domains[0]
case "Sandbox":
serverURI = letsencrypt.STAGING_URI
c.RancherCertName = PREFIX_STAGING + c.Domains[0]
certAutoName = PREFIX_STAGING + c.Domains[0]
default:
logrus.Fatalf("Invalid value for API_VERSION: %s", apiVerParam)
}

apiVersion := letsencrypt.ApiVersion(apiVerParam)
keyType := letsencrypt.KeyType(keyTypeParam)

if len(certNameParam) != 0 {
c.RancherCertName = certNameParam
} else {
c.RancherCertName = certAutoName
}

c.Rancher, err = rancher.NewClient(cattleUrl, cattleApiKey, cattleSecretKey)
if err != nil {
logrus.Fatalf("Rancher client: %v", err)
Expand All @@ -92,19 +101,18 @@ func (c *Context) InitContext() {
DynCustomerName: os.Getenv("DYN_CUSTOMER_NAME"),
DynUserName: os.Getenv("DYN_USER_NAME"),
DynPassword: os.Getenv("DYN_PASSWORD"),
AwsRegionName: "us-east-1",
}

c.Acme, err = letsencrypt.NewClient(emailParam, keyTypeParam, serverURI, providerOpts)
c.Acme, err = letsencrypt.NewClient(emailParam, keyType, apiVersion, providerOpts)
if err != nil {
logrus.Fatalf("LetsEncrypt client: %v", err)
}

// Enable debug/test mode
if strings.EqualFold(debug, "true") {
if strings.EqualFold(debugParam, "true") {
logrus.SetLevel(logrus.DebugLevel)
c.Debug = true
c.Acme.EnableDebugLogging()
c.Acme.EnableDebug()
}
}

Expand Down
25 changes: 18 additions & 7 deletions letsencrypt/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,25 @@ import (
"io/ioutil"
"os"
"path"
"strings"

"github.com/Sirupsen/logrus"
lego "github.com/xenolf/lego/acme"
)

type Account struct {
Email string `json:"email"`
key crypto.PrivateKey
Email string `json:"email"`
Registration *lego.RegistrationResource `json:"registrations"`

key crypto.PrivateKey
path string
}

// NewAccount creates a new or gets a stored LE account for the given email
func NewAccount(email string, keyType lego.KeyType) (*Account, error) {
keyFile := path.Join(configPath(), email+".key")
accountFile := path.Join(configPath(), email+".json")
func NewAccount(email string, apiVer ApiVersion, keyType lego.KeyType) (*Account, error) {
accPath := accountPath(email, apiVer)
keyFile := path.Join(accPath, "account.key")
accountFile := path.Join(accPath, "account.json")

var privKey crypto.PrivateKey
if _, err := os.Stat(keyFile); os.IsNotExist(err) {
Expand All @@ -39,7 +43,7 @@ func NewAccount(email string, keyType lego.KeyType) (*Account, error) {
}

if _, err := os.Stat(accountFile); os.IsNotExist(err) {
return &Account{Email: email, key: privKey}, nil
return &Account{Email: email, key: privKey, path: accPath}, nil
}

fileBytes, err := ioutil.ReadFile(accountFile)
Expand All @@ -54,6 +58,7 @@ func NewAccount(email string, keyType lego.KeyType) (*Account, error) {
}

acc.key = privKey
acc.path = accPath
return &acc, nil
}

Expand All @@ -63,7 +68,7 @@ func (a *Account) Save() error {
if err != nil {
return err
}
accountFile := path.Join(configPath(), a.Email+".json")
accountFile := path.Join(a.path, "account.json")
return ioutil.WriteFile(accountFile, jsonBytes, 0700)
}

Expand All @@ -83,3 +88,9 @@ func (a *Account) GetPrivateKey() crypto.PrivateKey {
func (a *Account) GetRegistration() *lego.RegistrationResource {
return a.Registration
}

func accountPath(email string, apiVer ApiVersion) string {
path := path.Join(ConfigDir, strings.ToLower(string(apiVer)), "accounts", email)
maybeCreatePath(path)
return path
}
Loading

0 comments on commit 2a91bcf

Please sign in to comment.