Skip to content

Commit

Permalink
Implement SubjectTransformer
Browse files Browse the repository at this point in the history
This makes it possible to replace cert subjects with wildcards, for example

Related: #280
  • Loading branch information
mholt committed Apr 8, 2024
1 parent 52cbe73 commit b29d2a0
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 5 deletions.
1 change: 1 addition & 0 deletions certificates.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ func expiresAt(cert *x509.Certificate) time.Time {
//
// This method is safe for concurrent use.
func (cfg *Config) CacheManagedCertificate(ctx context.Context, domain string) (Certificate, error) {
domain = cfg.transformSubject(ctx, nil, domain)
cert, err := cfg.loadManagedCertificate(ctx, domain)
if err != nil {
return cert, err
Expand Down
35 changes: 30 additions & 5 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,17 @@ type Config struct {
// storage is properly configured and has sufficient
// space, you can disable this check to reduce I/O
// if that is expensive for you.
// EXPERIMENTAL: Option subject to change or removal.
// EXPERIMENTAL: Subject to change or removal.
DisableStorageCheck bool

// SubjectTransformer is a hook that can transform the
// subject (SAN) of a certificate being loaded or issued.
// For example, a common use case is to replace the
// left-most label with an asterisk (*) to become a
// wildcard certificate.
// EXPERIMENTAL: Subject to change or removal.
SubjectTransformer func(ctx context.Context, domain string) string

// Set a logger to enable logging. If not set,
// a default logger will be created.
Logger *zap.Logger
Expand Down Expand Up @@ -485,6 +493,10 @@ func (cfg *Config) obtainCert(ctx context.Context, name string, interactive bool
return fmt.Errorf("no issuers configured; impossible to obtain or check for existing certificate in storage")
}

log := cfg.Logger.Named("obtain")

name = cfg.transformSubject(ctx, log, name)

// if storage has all resources for this certificate, obtain is a no-op
if cfg.storageHasCertResourcesAnyIssuer(ctx, name) {
return nil
Expand All @@ -497,8 +509,6 @@ func (cfg *Config) obtainCert(ctx context.Context, name string, interactive bool
return fmt.Errorf("failed storage check: %v - storage is probably misconfigured", err)
}

log := cfg.Logger.Named("obtain")

log.Info("acquiring lock", zap.String("identifier", name))

// ensure idempotency of the obtain operation for this name
Expand Down Expand Up @@ -736,15 +746,17 @@ func (cfg *Config) renewCert(ctx context.Context, name string, force, interactiv
return fmt.Errorf("no issuers configured; impossible to renew or check existing certificate in storage")
}

log := cfg.Logger.Named("renew")

name = cfg.transformSubject(ctx, log, name)

// ensure storage is writeable and readable
// TODO: this is not necessary every time; should only perform check once every so often for each storage, which may require some global state...
err := cfg.checkStorage(ctx)
if err != nil {
return fmt.Errorf("failed storage check: %v - storage is probably misconfigured", err)
}

log := cfg.Logger.Named("renew")

log.Info("acquiring lock", zap.String("identifier", name))

// ensure idempotency of the renew operation for this name
Expand Down Expand Up @@ -1083,6 +1095,19 @@ func (cfg *Config) getChallengeInfo(ctx context.Context, identifier string) (Cha
return Challenge{Challenge: chalInfo}, true, nil
}

func (cfg *Config) transformSubject(ctx context.Context, logger *zap.Logger, name string) string {
if cfg.SubjectTransformer == nil {
return name
}
transformedName := cfg.SubjectTransformer(ctx, name)
if logger != nil && transformedName != name {
logger.Debug("transformed subject name",
zap.String("original", name),
zap.String("transformed", transformedName))
}
return transformedName
}

// checkStorage tests the storage by writing random bytes
// to a random key, and then loading those bytes and
// comparing the loaded value. If this fails, the provided
Expand Down

0 comments on commit b29d2a0

Please sign in to comment.