Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Merge branch 'master' into herman/wasm-signals-and-offline-mode
  • Loading branch information
hslatman committed Jul 25, 2022
commit bf9ffea9a6c06f5ddf2bdc82bb7d5ce977f1cfff
2 changes: 1 addition & 1 deletion command/ca/renew.go
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ func newRenewer(ctx *cli.Context, caURL string, cert tls.Certificate, rootFile s
return nil, errors.Errorf("error parsing CA URL: %s", client.GetCaURL())
}

return renewerPkg.New(client, tr, cert.PrivateKey, isOffline, cert, u), nil
return renewerPkg.New(client, tr, cert.PrivateKey, isOffline, cert, u, ctx.Bool("mtls")), nil
}

func tlsLoadX509KeyPair(certFile, keyFile, passFile string) (tls.Certificate, error) {
Expand Down
50 changes: 47 additions & 3 deletions internal/renewer/renewer.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"crypto/rand"
"crypto/tls"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"log"
"net/http"
Expand All @@ -15,6 +16,8 @@ import (
"github.com/pkg/errors"
"github.com/smallstep/certificates/api"
"github.com/smallstep/cli/crypto/pemutil"
"github.com/smallstep/cli/jose"
"github.com/smallstep/cli/token"
"github.com/smallstep/cli/utils"
caclient "github.com/smallstep/cli/utils/cautils/client"
"go.step.sm/cli-utils/errs"
Expand All @@ -27,21 +30,27 @@ type Renewer struct {
offline bool
cert tls.Certificate
caURL *url.URL
mtls bool
}

func New(client caclient.CaClient, tr *http.Transport, key crypto.PrivateKey, offline bool, cert tls.Certificate, caURL *url.URL) *Renewer {
func New(client caclient.CaClient, tr *http.Transport, key crypto.PrivateKey, offline bool, cert tls.Certificate, caURL *url.URL, useMTLS bool) *Renewer {
return &Renewer{
client: client,
transport: tr,
key: key,
offline: offline,
cert: cert,
caURL: caURL,
mtls: useMTLS,
}
}

func (r *Renewer) Renew(outFile string) (*api.SignResponse, error) {
resp, err := r.client.Renew(r.transport)
func (r *Renewer) Renew(outFile string) (resp *api.SignResponse, err error) {
if !r.mtls || time.Now().After(r.cert.Leaf.NotAfter) {
resp, err = r.RenewWithToken(r.cert)
} else {
resp, err = r.client.Renew(r.transport)
}
if err != nil {
return nil, errors.Wrap(err, "error renewing certificate")
}
Expand Down Expand Up @@ -138,3 +147,38 @@ func (r *Renewer) RenewAndPrepareNext(outFile string, expiresIn, renewPeriod tim
Info.Printf("%s certificate renewed, next in %s", resp.ServerPEM.Certificate.Subject.CommonName, next.Round(time.Second))
return next, nil
}

// RenewWithToken creates an authorization token with the given certificate and
// attempts to renew the given certificate. It can be used to renew expired
// certificates.
func (r *Renewer) RenewWithToken(cert tls.Certificate) (*api.SignResponse, error) {
claims, err := token.NewClaims(
token.WithAudience(r.caURL.ResolveReference(&url.URL{Path: "/renew"}).String()),
token.WithIssuer("step-ca-client/1.0"),
token.WithSubject(cert.Leaf.Subject.CommonName),
)
if err != nil {
return nil, errors.Wrap(err, "error creating authorization token")
}
var x5c []string
for _, b := range cert.Certificate {
x5c = append(x5c, base64.StdEncoding.EncodeToString(b))
}
if claims.ExtraHeaders == nil {
claims.ExtraHeaders = make(map[string]interface{})
}
claims.ExtraHeaders[jose.X5cInsecureKey] = x5c

tok, err := claims.Sign("", cert.PrivateKey)
if err != nil {
return nil, errors.Wrap(err, "error signing authorization token")
}

// Remove existing certificate from the transport. And close keep-alive
// connections. When daemon is used we don't want to re-use the connection
// that did not include a certificate.
r.transport.TLSClientConfig.Certificates = nil
defer r.transport.CloseIdleConnections()

return r.client.RenewWithToken(tok)
}
1 change: 1 addition & 0 deletions utils/cautils/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
type CaClient interface {
Sign(req *api.SignRequest) (*api.SignResponse, error)
Renew(tr http.RoundTripper) (*api.SignResponse, error)
RenewWithToken(ott string) (*api.SignResponse, error)
Revoke(req *api.RevokeRequest, tr http.RoundTripper) (*api.RevokeResponse, error)
Rekey(req *api.RekeyRequest, tr http.RoundTripper) (*api.SignResponse, error)
SSHSign(req *api.SSHSignRequest) (*api.SSHSignResponse, error)
Expand Down
You are viewing a condensed version of this merge commit. You can view the full changes here.