2018-03-05 19:54:04 +00:00
|
|
|
package acme
|
|
|
|
|
|
|
|
import (
|
2018-11-14 09:18:03 +00:00
|
|
|
"context"
|
2018-03-05 19:54:04 +00:00
|
|
|
"crypto"
|
|
|
|
"crypto/rand"
|
|
|
|
"crypto/rsa"
|
|
|
|
"crypto/x509"
|
|
|
|
|
|
|
|
"github.com/containous/traefik/log"
|
2019-01-07 17:30:06 +00:00
|
|
|
"github.com/xenolf/lego/certcrypto"
|
|
|
|
"github.com/xenolf/lego/registration"
|
2018-03-05 19:54:04 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Account is used to store lets encrypt registration info
|
|
|
|
type Account struct {
|
|
|
|
Email string
|
2019-01-07 17:30:06 +00:00
|
|
|
Registration *registration.Resource
|
2018-03-05 19:54:04 +00:00
|
|
|
PrivateKey []byte
|
2019-01-07 17:30:06 +00:00
|
|
|
KeyType certcrypto.KeyType
|
2018-03-05 19:54:04 +00:00
|
|
|
}
|
|
|
|
|
2018-03-26 12:12:03 +00:00
|
|
|
const (
|
|
|
|
// RegistrationURLPathV1Regexp is a regexp which match ACME registration URL in the V1 format
|
2018-04-17 21:20:33 +00:00
|
|
|
RegistrationURLPathV1Regexp = `^.*/acme/reg/\d+$`
|
2018-03-26 12:12:03 +00:00
|
|
|
)
|
|
|
|
|
2018-03-05 19:54:04 +00:00
|
|
|
// NewAccount creates an account
|
2018-11-14 09:18:03 +00:00
|
|
|
func NewAccount(ctx context.Context, email string, keyTypeValue string) (*Account, error) {
|
|
|
|
keyType := GetKeyType(ctx, keyTypeValue)
|
2018-05-16 09:44:03 +00:00
|
|
|
|
2018-03-05 19:54:04 +00:00
|
|
|
// Create a user. New accounts need an email and private key to start
|
|
|
|
privateKey, err := rsa.GenerateKey(rand.Reader, 4096)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return &Account{
|
|
|
|
Email: email,
|
|
|
|
PrivateKey: x509.MarshalPKCS1PrivateKey(privateKey),
|
2018-05-16 09:44:03 +00:00
|
|
|
KeyType: keyType,
|
2018-03-05 19:54:04 +00:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetEmail returns email
|
|
|
|
func (a *Account) GetEmail() string {
|
|
|
|
return a.Email
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetRegistration returns lets encrypt registration resource
|
2019-01-07 17:30:06 +00:00
|
|
|
func (a *Account) GetRegistration() *registration.Resource {
|
2018-03-05 19:54:04 +00:00
|
|
|
return a.Registration
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetPrivateKey returns private key
|
|
|
|
func (a *Account) GetPrivateKey() crypto.PrivateKey {
|
2018-11-14 09:18:03 +00:00
|
|
|
privateKey, err := x509.ParsePKCS1PrivateKey(a.PrivateKey)
|
|
|
|
if err != nil {
|
|
|
|
log.WithoutContext().WithField(log.ProviderName, "acme").
|
|
|
|
Errorf("Cannot unmarshal private key %+v: %v", a.PrivateKey, err)
|
|
|
|
return nil
|
2018-03-05 19:54:04 +00:00
|
|
|
}
|
|
|
|
|
2018-11-14 09:18:03 +00:00
|
|
|
return privateKey
|
2018-03-05 19:54:04 +00:00
|
|
|
}
|
2018-05-16 09:44:03 +00:00
|
|
|
|
|
|
|
// GetKeyType used to determine which algo to used
|
2019-01-07 17:30:06 +00:00
|
|
|
func GetKeyType(ctx context.Context, value string) certcrypto.KeyType {
|
2018-11-14 09:18:03 +00:00
|
|
|
logger := log.FromContext(ctx)
|
|
|
|
|
2018-05-16 09:44:03 +00:00
|
|
|
switch value {
|
|
|
|
case "EC256":
|
2019-01-07 17:30:06 +00:00
|
|
|
return certcrypto.EC256
|
2018-05-16 09:44:03 +00:00
|
|
|
case "EC384":
|
2019-01-07 17:30:06 +00:00
|
|
|
return certcrypto.EC384
|
2018-05-16 09:44:03 +00:00
|
|
|
case "RSA2048":
|
2019-01-07 17:30:06 +00:00
|
|
|
return certcrypto.RSA2048
|
2018-05-16 09:44:03 +00:00
|
|
|
case "RSA4096":
|
2019-01-07 17:30:06 +00:00
|
|
|
return certcrypto.RSA4096
|
2018-05-16 09:44:03 +00:00
|
|
|
case "RSA8192":
|
2019-01-07 17:30:06 +00:00
|
|
|
return certcrypto.RSA8192
|
2018-07-03 10:44:04 +00:00
|
|
|
case "":
|
2019-01-07 17:30:06 +00:00
|
|
|
logger.Infof("The key type is empty. Use default key type %v.", certcrypto.RSA4096)
|
|
|
|
return certcrypto.RSA4096
|
2018-05-16 09:44:03 +00:00
|
|
|
default:
|
2019-01-07 17:30:06 +00:00
|
|
|
logger.Infof("Unable to determine the key type value %q: falling back on %v.", value, certcrypto.RSA4096)
|
|
|
|
return certcrypto.RSA4096
|
2018-05-16 09:44:03 +00:00
|
|
|
}
|
|
|
|
}
|