acme

package module
v0.0.0-...-5354071 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 29, 2025 License: ISC Imports: 34 Imported by: 0

README

go-acme

Introduction

The go-acme library contains a client for the ACME protocol and aims to simplify the creation of servers with automatic TLS certificate management.

Usage

Refer to the Go package documentation for information about the API.

See the acme program for a practical use case.

Licensing

Go-acme is open source software distributed under the ISC license.

Contributions

Bug reporting

I am thankful for any bug report. Feel free to open issues and include as much useful information as possible. I cannot however guarantee that I will fix every bug.

Ideas and feature suggestions

Ideas about current systems and suggestions for new ones are welcome, either on GitHub discussions or by email.

You can also hire me for support or to develop specific features.

Documentation

Index

Constants

View Source
const (
	LetsEncryptDirectoryURI        = "https://acme-v02.api.letsencrypt.org/directory"
	LetsEncryptStagingDirectoryURI = "https://acme-staging-v02.api.letsencrypt.org/directory"
)
View Source
const (
	PebbleDirectoryURI               = "https://localhost:14000/dir"
	PebbleHTTPChallengeSolverAddress = ":5002"
)

Variables

View Source
var (
	ErrAccountNotFound     = errors.New("account not found in data store")
	ErrCertificateNotFound = errors.New("certificate not found in data store")
)
View Source
var ErrVerificationInterrupted = errors.New("verification interrupted")
View Source
var ErrVerificationTimeout = errors.New("verification timeout")
View Source
var PebbleCACertificateData []byte

Functions

func CertificateRenewalTime

func CertificateRenewalTime(data *CertificateData) time.Time

func GenerateECDSAP256PrivateKey

func GenerateECDSAP256PrivateKey() (crypto.Signer, error)

func NewHTTPClient

func NewHTTPClient(caCertPool *x509.CertPool) *http.Client

func PebbleCACertificate

func PebbleCACertificate() *x509.Certificate

func PebbleCACertificatePool

func PebbleCACertificatePool() *x509.CertPool

Types

type Account

type Account struct {
	Status                 string          `json:"status"`
	Contact                []string        `json:"contact,omitempty"`
	TermsOfServiceAgreed   bool            `json:"termsOfServiceAgreed,omitempty"`
	ExternalAccountBinding json.RawMessage `json:"externalAccountBinding,omitempty"`
	Orders                 string          `json:"orders"`
}

type AccountData

type AccountData struct {
	URI            string        `json:"uri"`
	PrivateKey     crypto.Signer `json:"-"`
	PrivateKeyData []byte        `json:"private_key_data"`
}

func (*AccountData) MarshalJSON

func (a *AccountData) MarshalJSON() ([]byte, error)

func (*AccountData) Thumbprint

func (a *AccountData) Thumbprint() (string, error)

func (*AccountData) UnmarshalJSON

func (a *AccountData) UnmarshalJSON(data []byte) error

type AccountPrivateKeyGenerationFunc

type AccountPrivateKeyGenerationFunc func() (crypto.Signer, error)

type Authorization

type Authorization struct {
	Identifier Identifier          `json:"identifier"`
	Status     AuthorizationStatus `json:"status"`
	Expires    *time.Time          `json:"expires,omitempty"`
	Challenges []*Challenge        `json:"challenges"`
	Wildcard   bool                `json:"wildcard,omitempty"`
}

type AuthorizationStatus

type AuthorizationStatus string
const (
	AuthorizationStatusPending     AuthorizationStatus = "pending"
	AuthorizationStatusValid       AuthorizationStatus = "valid"
	AuthorizationStatusInvalid     AuthorizationStatus = "invalid"
	AuthorizationStatusDeactivated AuthorizationStatus = "deactivated"
	AuthorizationStatusExpired     AuthorizationStatus = "expired"
	AuthorizationStatusRevoked     AuthorizationStatus = "revoked"
)

type CertificateData

type CertificateData struct {
	Name string `json:"name"`

	Identifiers []Identifier `json:"identifiers"`
	Validity    int          `json:"validity,omitempty"` // days [1]

	PrivateKey      crypto.Signer       `json:"-"`
	PrivateKeyData  []byte              `json:"private_key"`
	Certificate     []*x509.Certificate `json:"-"`
	CertificateData string              `json:"certificate"`
}

func (*CertificateData) ContainsCertificate

func (c *CertificateData) ContainsCertificate() bool

func (*CertificateData) LeafCertificate

func (c *CertificateData) LeafCertificate() *x509.Certificate

func (*CertificateData) LeafCertificateFingerprint

func (c *CertificateData) LeafCertificateFingerprint(hash crypto.Hash) string

func (*CertificateData) MarshalJSON

func (c *CertificateData) MarshalJSON() ([]byte, error)

func (*CertificateData) TLSCertificate

func (c *CertificateData) TLSCertificate() *tls.Certificate

func (*CertificateData) UnmarshalJSON

func (c *CertificateData) UnmarshalJSON(data []byte) error

type CertificateEvent

type CertificateEvent struct {
	CertificateData *CertificateData
	Error           error
}

type CertificatePrivateKeyGenerationFunc

type CertificatePrivateKeyGenerationFunc func() (crypto.Signer, error)

type CertificateRenewalTimeFunc

type CertificateRenewalTimeFunc func(*CertificateData) time.Time

type CertificateWorker

type CertificateWorker struct {
	Log    *log.Logger
	Client *Client
	// contains filtered or unexported fields
}

type Challenge

type Challenge struct {
	Type      ChallengeType   `json:"type"`
	URL       string          `json:"url"`
	Status    ChallengeStatus `json:"status"`
	Validated *time.Time      `json:"validated,omitempty"`
	Error     *ProblemDetails `json:"error,omitempty"`

	Data any `json:"-"`
}

func (*Challenge) UnmarshalJSON

func (c *Challenge) UnmarshalJSON(data []byte) error

type ChallengeDataDNS01

type ChallengeDataDNS01 struct {
	Token string `json:"token"`
}

type ChallengeDataHTTP01

type ChallengeDataHTTP01 struct {
	Token string `json:"token"`
}

type ChallengeStatus

type ChallengeStatus string
const (
	ChallengeStatusPending    ChallengeStatus = "pending"
	ChallengeStatusProcessing ChallengeStatus = "processing"
	ChallengeStatusValid      ChallengeStatus = "valid"
	ChallengeStatusInvalid    ChallengeStatus = "invalid"
)

type ChallengeType

type ChallengeType string
const (
	ChallengeTypeHTTP01 ChallengeType = "http-01"
	ChallengeTypeDNS01  ChallengeType = "dns-01"
)

type Client

type Client struct {
	Cfg       ClientCfg
	Log       *log.Logger
	Directory *Directory
	// contains filtered or unexported fields
}

func NewClient

func NewClient(cfg ClientCfg) (*Client, error)

func (*Client) Certificate

func (c *Client) Certificate(name string) *CertificateData

func (*Client) GetTLSCertificateFunc

func (c *Client) GetTLSCertificateFunc(name string) GetTLSCertificateFunc

func (*Client) RequestCertificate

func (c *Client) RequestCertificate(ctx context.Context, name string, identifiers []Identifier, validity int) (<-chan *CertificateEvent, error)

func (*Client) Start

func (c *Client) Start(ctx context.Context) error

func (*Client) Stop

func (c *Client) Stop()

func (*Client) WaitForCertificate

func (c *Client) WaitForCertificate(ctx context.Context, name string) *CertificateData

type ClientCfg

type ClientCfg struct {
	Log                           *log.Logger                         `json:"-"`
	HTTPClient                    *http.Client                        `json:"-"`
	DataStore                     DataStore                           `json:"-"`
	GenerateAccountPrivateKey     AccountPrivateKeyGenerationFunc     `json:"-"`
	GenerateCertificatePrivateKey CertificatePrivateKeyGenerationFunc `json:"-"`
	CertificateRenewalTime        CertificateRenewalTimeFunc          `json:"-"`

	UserAgent    string   `json:"user_agent"`
	DirectoryURI string   `json:"directory_uri"`
	ContactURIs  []string `json:"contact_uris"`

	HTTPChallengeSolver *HTTPChallengeSolverCfg `json:"http_challenge_solver,omitempty"`
}

type DataStore

type DataStore interface {
	LoadAccountData() (*AccountData, error)
	StoreAccountData(*AccountData) error

	LoadCertificateData(string) (*CertificateData, error)
	StoreCertificateData(*CertificateData) error
}

type Directory

type Directory struct {
	NewNonce   string `json:"newNonce"`
	NewAccount string `json:"newAccount"`
	NewOrder   string `json:"newOrder"`
	NewAuthz   string `json:"newAuthz,omitempty"`
	RevokeCert string `json:"revokeCert"`
	KeyChange  string `json:"keyChange"`

	Meta DirectoryMetadata `json:"meta"`
}

RFC 8555 7.1.1. Directory

type DirectoryMetadata

type DirectoryMetadata struct {
	TermsOfService          string   `json:"termsOfService,omitempty"`
	Website                 string   `json:"website,omitempty"`
	CAAIdentities           []string `json:"caaIdentities,omitempty"`
	ExternalAccountRequired bool     `json:"externalAccountRequired,omitempty"`
}

type ErrorType

type ErrorType string
const (
	ErrorTypeAccountDoesNotExist     ErrorType = "urn:ietf:params:acme:error:accountDoesNotExist"
	ErrorTypeAlreadyRevoked          ErrorType = "urn:ietf:params:acme:error:alreadyRevoked"
	ErrorTypeBadCSR                  ErrorType = "urn:ietf:params:acme:error:badCSR"
	ErrorTypeBadNonce                ErrorType = "urn:ietf:params:acme:error:badNonce"
	ErrorTypeBadPublicKey            ErrorType = "urn:ietf:params:acme:error:badPublicKey"
	ErrorTypeBadRevocationReason     ErrorType = "urn:ietf:params:acme:error:badRevocationReason"
	ErrorTypeBadSignatureAlgorithm   ErrorType = "urn:ietf:params:acme:error:badSignatureAlgorithm"
	ErrorTypeCAA                     ErrorType = "urn:ietf:params:acme:error:caa"
	ErrorTypeCompound                ErrorType = "urn:ietf:params:acme:error:compound"
	ErrorTypeConnection              ErrorType = "urn:ietf:params:acme:error:connection"
	ErrorTypeDNS                     ErrorType = "urn:ietf:params:acme:error:dns"
	ErrorTypeExternalAccountRequired ErrorType = "urn:ietf:params:acme:error:externalAccountRequired"
	ErrorTypeIncorrectResponse       ErrorType = "urn:ietf:params:acme:error:incorrectResponse"
	ErrorTypeInvalidContact          ErrorType = "urn:ietf:params:acme:error:invalidContact"
	ErrorTypeMalformed               ErrorType = "urn:ietf:params:acme:error:malformed"
	ErrorTypeOrderNotReady           ErrorType = "urn:ietf:params:acme:error:orderNotReady"
	ErrorTypeRateLimited             ErrorType = "urn:ietf:params:acme:error:rateLimited"
	ErrorTypeRejectedIdentifier      ErrorType = "urn:ietf:params:acme:error:rejectedIdentifier"
	ErrorTypeServerInternal          ErrorType = "urn:ietf:params:acme:error:serverInternal"
	ErrorTypeTLS                     ErrorType = "urn:ietf:params:acme:error:tls"
	ErrorTypeUnauthorized            ErrorType = "urn:ietf:params:acme:error:unauthorized"
	ErrorTypeUnsupportedContact      ErrorType = "urn:ietf:params:acme:error:unsupportedContact"
	ErrorTypeUnsupportedIdentifier   ErrorType = "urn:ietf:params:acme:error:unsupportedIdentifier"
	ErrorTypeUserActionRequired      ErrorType = "urn:ietf:params:acme:error:userActionRequired"
)

type FileSystemDataStore

type FileSystemDataStore struct {
	// contains filtered or unexported fields
}

func NewFileSystemDataStore

func NewFileSystemDataStore(rootPath string) (*FileSystemDataStore, error)

func (*FileSystemDataStore) LoadAccountData

func (s *FileSystemDataStore) LoadAccountData() (*AccountData, error)

func (*FileSystemDataStore) LoadCertificateData

func (s *FileSystemDataStore) LoadCertificateData(name string) (*CertificateData, error)

func (*FileSystemDataStore) StoreAccountData

func (s *FileSystemDataStore) StoreAccountData(data *AccountData) error

func (*FileSystemDataStore) StoreCertificateData

func (s *FileSystemDataStore) StoreCertificateData(data *CertificateData) error

type GetTLSCertificateFunc

type GetTLSCertificateFunc func(*tls.ClientHelloInfo) (*tls.Certificate, error)

See the GetCertificate field of tls.Config.

type HTTPChallengeSolver

type HTTPChallengeSolver struct {
	Cfg HTTPChallengeSolverCfg
	Log *log.Logger
	// contains filtered or unexported fields
}

func NewHTTPChallengeSolver

func NewHTTPChallengeSolver(cfg HTTPChallengeSolverCfg) (*HTTPChallengeSolver, error)

func (*HTTPChallengeSolver) ServeHTTP

func (s *HTTPChallengeSolver) ServeHTTP(w http.ResponseWriter, req *http.Request)

func (*HTTPChallengeSolver) Start

func (s *HTTPChallengeSolver) Start(accountThumbprint string) error

func (*HTTPChallengeSolver) Stop

func (s *HTTPChallengeSolver) Stop()

type HTTPChallengeSolverCfg

type HTTPChallengeSolverCfg struct {
	Log               *log.Logger `json:"-"`
	AccountThumbprint string      `json:"-"`

	Address     string `json:"address"`
	UpstreamURI string `json:"upstream_uri,omitempty"`
}

type Identifier

type Identifier struct {
	Type  IdentifierType `json:"type"`
	Value string         `json:"value"`
}

func DNSIdentifier

func DNSIdentifier(value string) Identifier

func (Identifier) String

func (id Identifier) String() string

type IdentifierType

type IdentifierType string
const (
	IdentifierTypeDNS IdentifierType = "dns"
)

type NewAccount

type NewAccount struct {
	Contact                []string        `json:"contact,omitempty"`
	TermsOfServiceAgreed   bool            `json:"termsOfServiceAgreed,omitempty"`
	OnlyReturnExisting     bool            `json:"onlyReturnExisting,omitempty"`
	ExternalAccountBinding json.RawMessage `json:"externalAccountBinding,omitempty"`
}

type NewOrder

type NewOrder struct {
	Identifiers []Identifier `json:"identifiers"`
	NotBefore   *time.Time   `json:"notBefore,omitempty"`
	NotAfter    *time.Time   `json:"notAfter,omitempty"`
}

type Order

type Order struct {
	Status         OrderStatus     `json:"status"`
	Expires        time.Time       `json:"expires"`
	Identifiers    []Identifier    `json:"identifiers"`
	NotBefore      *time.Time      `json:"notBefore,omitempty"`
	NotAfter       *time.Time      `json:"notAfter,omitempty"`
	Error          *ProblemDetails `json:"error,omitempty"`
	Authorizations []string        `json:"authorizations"`
	Finalize       string          `json:"finalize"`
	Certificate    *string         `json:"certificate,omitempty"`
}

type OrderFinalization

type OrderFinalization struct {
	CSR string `json:"csr"`
}

type OrderStatus

type OrderStatus string
const (
	OrderStatusPending    OrderStatus = "pending"
	OrderStatusReady      OrderStatus = "ready"
	OrderStatusProcessing OrderStatus = "processing"
	OrderStatusValid      OrderStatus = "valid"
	OrderStatusInvalid    OrderStatus = "invalid"
)

type ProblemDetails

type ProblemDetails struct {
	// RFC 7807 3.1. Members of a Problem Details Object
	Type     ErrorType `json:"type,omitempty"`
	Title    string    `json:"title,omitempty"`
	Status   int       `json:"status,omitempty"`
	Detail   string    `json:"detail,omitempty"`
	Instance string    `json:"instance,omitempty"`

	// RFC 8555 6.7.1. Subproblems
	Subproblems []ProblemDetails `json:"subproblems,omitempty"`
}

func (*ProblemDetails) Error

func (err *ProblemDetails) Error() string

func (*ProblemDetails) FormatErrorString

func (err *ProblemDetails) FormatErrorString(buf *bytes.Buffer, indent string)

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL