mirror of
https://github.com/smallstep/certificates.git
synced 2024-10-31 03:20:16 +00:00
Merge branch 'master' into allow_external_x509_ca_service_intf
This commit is contained in:
commit
ac773ff44e
@ -104,6 +104,9 @@ type Authority struct {
|
||||
|
||||
// If true, do not output initialization logs
|
||||
quietInit bool
|
||||
|
||||
// Called whenever applicable, in order to instrument the authority.
|
||||
meter Meter
|
||||
}
|
||||
|
||||
// Info contains information about the authority.
|
||||
@ -126,6 +129,7 @@ func New(cfg *config.Config, opts ...Option) (*Authority, error) {
|
||||
config: cfg,
|
||||
certificates: new(sync.Map),
|
||||
validateSCEP: true,
|
||||
meter: noopMeter{},
|
||||
}
|
||||
|
||||
// Apply options.
|
||||
@ -134,6 +138,9 @@ func New(cfg *config.Config, opts ...Option) (*Authority, error) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if a.keyManager != nil {
|
||||
a.keyManager = &instrumentedKeyManager{a.keyManager, a.meter}
|
||||
}
|
||||
|
||||
if !a.skipInit {
|
||||
// Initialize authority from options or configuration.
|
||||
@ -151,6 +158,7 @@ func NewEmbedded(opts ...Option) (*Authority, error) {
|
||||
a := &Authority{
|
||||
config: &config.Config{},
|
||||
certificates: new(sync.Map),
|
||||
meter: noopMeter{},
|
||||
}
|
||||
|
||||
// Apply options.
|
||||
@ -159,6 +167,9 @@ func NewEmbedded(opts ...Option) (*Authority, error) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if a.keyManager != nil {
|
||||
a.keyManager = &instrumentedKeyManager{a.keyManager, a.meter}
|
||||
}
|
||||
|
||||
// Validate required options
|
||||
switch {
|
||||
@ -337,6 +348,8 @@ func (a *Authority) init() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.keyManager = &instrumentedKeyManager{a.keyManager, a.meter}
|
||||
}
|
||||
|
||||
// Initialize linkedca client if necessary. On a linked RA, the issuer
|
||||
|
@ -286,16 +286,16 @@ func (a *Authority) authorizeRevoke(ctx context.Context, token string) error {
|
||||
// extra extension cannot be found, authorize the renewal by default.
|
||||
//
|
||||
// TODO(mariano): should we authorize by default?
|
||||
func (a *Authority) authorizeRenew(ctx context.Context, cert *x509.Certificate) error {
|
||||
func (a *Authority) authorizeRenew(ctx context.Context, cert *x509.Certificate) (provisioner.Interface, error) {
|
||||
serial := cert.SerialNumber.String()
|
||||
var opts = []interface{}{errs.WithKeyVal("serialNumber", serial)}
|
||||
|
||||
isRevoked, err := a.IsRevoked(serial)
|
||||
if err != nil {
|
||||
return errs.Wrap(http.StatusInternalServerError, err, "authority.authorizeRenew", opts...)
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err, "authority.authorizeRenew", opts...)
|
||||
}
|
||||
if isRevoked {
|
||||
return errs.Unauthorized("authority.authorizeRenew: certificate has been revoked", opts...)
|
||||
return nil, errs.Unauthorized("authority.authorizeRenew: certificate has been revoked", opts...)
|
||||
}
|
||||
p, err := a.LoadProvisionerByCertificate(cert)
|
||||
if err != nil {
|
||||
@ -305,13 +305,13 @@ func (a *Authority) authorizeRenew(ctx context.Context, cert *x509.Certificate)
|
||||
// returns the noop provisioner if this happens, and it allows
|
||||
// certificate renewals.
|
||||
if p, ok = a.provisioners.LoadByCertificate(cert); !ok {
|
||||
return errs.Unauthorized("authority.authorizeRenew: provisioner not found", opts...)
|
||||
return nil, errs.Unauthorized("authority.authorizeRenew: provisioner not found", opts...)
|
||||
}
|
||||
}
|
||||
if err := p.AuthorizeRenew(ctx, cert); err != nil {
|
||||
return errs.Wrap(http.StatusInternalServerError, err, "authority.authorizeRenew", opts...)
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err, "authority.authorizeRenew", opts...)
|
||||
}
|
||||
return nil
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// authorizeSSHCertificate returns an error if the given certificate is revoked.
|
||||
|
@ -876,7 +876,7 @@ func TestAuthority_authorizeRenew(t *testing.T) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
tc := genTestCase(t)
|
||||
|
||||
err := tc.auth.authorizeRenew(context.Background(), tc.cert)
|
||||
_, err := tc.auth.authorizeRenew(context.Background(), tc.cert)
|
||||
if err != nil {
|
||||
if assert.NotNil(t, tc.err) {
|
||||
var sc render.StatusCodedError
|
||||
|
@ -83,6 +83,7 @@ type Config struct {
|
||||
Templates *templates.Templates `json:"templates,omitempty"`
|
||||
CommonName string `json:"commonName,omitempty"`
|
||||
CRL *CRLConfig `json:"crl,omitempty"`
|
||||
MetricsAddress string `json:"metricsAddress,omitempty"`
|
||||
SkipValidation bool `json:"-"`
|
||||
|
||||
// Keeps record of the filename the Config is read from
|
||||
@ -327,6 +328,12 @@ func (c *Config) Validate() error {
|
||||
return errors.Errorf("invalid address %s", c.Address)
|
||||
}
|
||||
|
||||
if addr := c.MetricsAddress; addr != "" {
|
||||
if _, _, err := net.SplitHostPort(addr); err != nil {
|
||||
return errors.Errorf("invalid metrics address %q", c.Address)
|
||||
}
|
||||
}
|
||||
|
||||
if c.TLS == nil {
|
||||
c.TLS = &DefaultTLSOptions
|
||||
} else {
|
||||
|
87
authority/meter.go
Normal file
87
authority/meter.go
Normal file
@ -0,0 +1,87 @@
|
||||
package authority
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"io"
|
||||
|
||||
"go.step.sm/crypto/kms"
|
||||
kmsapi "go.step.sm/crypto/kms/apiv1"
|
||||
|
||||
"github.com/smallstep/certificates/authority/provisioner"
|
||||
)
|
||||
|
||||
// Meter wraps the set of defined callbacks for metrics gatherers.
|
||||
type Meter interface {
|
||||
// X509Signed is called whenever an X509 certificate is signed.
|
||||
X509Signed(provisioner.Interface, error)
|
||||
|
||||
// X509Renewed is called whenever an X509 certificate is renewed.
|
||||
X509Renewed(provisioner.Interface, error)
|
||||
|
||||
// X509Rekeyed is called whenever an X509 certificate is rekeyed.
|
||||
X509Rekeyed(provisioner.Interface, error)
|
||||
|
||||
// X509WebhookAuthorized is called whenever an X509 authoring webhook is called.
|
||||
X509WebhookAuthorized(provisioner.Interface, error)
|
||||
|
||||
// X509WebhookEnriched is called whenever an X509 enriching webhook is called.
|
||||
X509WebhookEnriched(provisioner.Interface, error)
|
||||
|
||||
// SSHSigned is called whenever an SSH certificate is signed.
|
||||
SSHSigned(provisioner.Interface, error)
|
||||
|
||||
// SSHRenewed is called whenever an SSH certificate is renewed.
|
||||
SSHRenewed(provisioner.Interface, error)
|
||||
|
||||
// SSHRekeyed is called whenever an SSH certificate is rekeyed.
|
||||
SSHRekeyed(provisioner.Interface, error)
|
||||
|
||||
// SSHWebhookAuthorized is called whenever an SSH authoring webhook is called.
|
||||
SSHWebhookAuthorized(provisioner.Interface, error)
|
||||
|
||||
// SSHWebhookEnriched is called whenever an SSH enriching webhook is called.
|
||||
SSHWebhookEnriched(provisioner.Interface, error)
|
||||
|
||||
// KMSSigned is called per KMS signer signature.
|
||||
KMSSigned(error)
|
||||
}
|
||||
|
||||
// noopMeter implements a noop [Meter].
|
||||
type noopMeter struct{}
|
||||
|
||||
func (noopMeter) SSHRekeyed(provisioner.Interface, error) {}
|
||||
func (noopMeter) SSHRenewed(provisioner.Interface, error) {}
|
||||
func (noopMeter) SSHSigned(provisioner.Interface, error) {}
|
||||
func (noopMeter) SSHWebhookAuthorized(provisioner.Interface, error) {}
|
||||
func (noopMeter) SSHWebhookEnriched(provisioner.Interface, error) {}
|
||||
func (noopMeter) X509Rekeyed(provisioner.Interface, error) {}
|
||||
func (noopMeter) X509Renewed(provisioner.Interface, error) {}
|
||||
func (noopMeter) X509Signed(provisioner.Interface, error) {}
|
||||
func (noopMeter) X509WebhookAuthorized(provisioner.Interface, error) {}
|
||||
func (noopMeter) X509WebhookEnriched(provisioner.Interface, error) {}
|
||||
func (noopMeter) KMSSigned(error) {}
|
||||
|
||||
type instrumentedKeyManager struct {
|
||||
kms.KeyManager
|
||||
meter Meter
|
||||
}
|
||||
|
||||
func (i *instrumentedKeyManager) CreateSigner(req *kmsapi.CreateSignerRequest) (s crypto.Signer, err error) {
|
||||
if s, err = i.KeyManager.CreateSigner(req); err == nil {
|
||||
s = &instrumentedKMSSigner{s, i.meter}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
type instrumentedKMSSigner struct {
|
||||
crypto.Signer
|
||||
meter Meter
|
||||
}
|
||||
|
||||
func (i *instrumentedKMSSigner) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) (signature []byte, err error) {
|
||||
signature, err = i.Signer.Sign(rand, digest, opts)
|
||||
i.meter.KMSSigned(err)
|
||||
|
||||
return
|
||||
}
|
@ -390,3 +390,16 @@ func readCertificateBundle(pemCerts []byte) ([]*x509.Certificate, error) {
|
||||
}
|
||||
return certs, nil
|
||||
}
|
||||
|
||||
// WithMeter is an option that sets the authority's [Meter] to the provided one.
|
||||
func WithMeter(m Meter) Option {
|
||||
if m == nil {
|
||||
m = noopMeter{}
|
||||
}
|
||||
|
||||
return func(a *Authority) (_ error) {
|
||||
a.meter = m
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
# https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/verify-signature.html
|
||||
# https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/regions-certs.html use RSA format
|
||||
|
||||
# default certificate for "other regions"
|
||||
-----BEGIN CERTIFICATE-----
|
||||
@ -245,3 +246,19 @@ M2BPuH769wcOsqfFZcMKEysSFK91tVtUb1soFwH4/Lb/T0PqNrvtEwD1Nva5k0h2
|
||||
xZhNNRmDuhOhW1K9wCcnHGRBwY5t4lYL6hNV6hcrqYwGMjTjcAjBG2yMgznSNFle
|
||||
Rwi/S3BFXISixNx9cILu
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
# certificate for ca-west-1
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICMzCCAZygAwIBAgIGAYPou9weMA0GCSqGSIb3DQEBBQUAMFwxCzAJBgNVBAYT
|
||||
AlVTMRkwFwYDVQQIDBBXYXNoaW5ndG9uIFN0YXRlMRAwDgYDVQQHDAdTZWF0dGxl
|
||||
MSAwHgYDVQQKDBdBbWF6b24gV2ViIFNlcnZpY2VzIExMQzAgFw0yMjEwMTgwMTM2
|
||||
MDlaGA8yMjAxMTAxODAxMzYwOVowXDELMAkGA1UEBhMCVVMxGTAXBgNVBAgMEFdh
|
||||
c2hpbmd0b24gU3RhdGUxEDAOBgNVBAcMB1NlYXR0bGUxIDAeBgNVBAoMF0FtYXpv
|
||||
biBXZWIgU2VydmljZXMgTExDMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDK
|
||||
1kIcG5Q6adBXQM75GldfTSiXl7tn54p10TnspI0ErDdb2B6q2Ji/v4XBVH13ZCMg
|
||||
qlRHMqV8AWI5iO6gFn2A9sN3AZXTMqwtZeiDdebq3k6Wt7ieYvpXTg0qvgsjQIov
|
||||
RZWaBDBJy9x8C2hW+w9lMQjFHkJ7Jy/PHCJ69EzebQIDAQABMA0GCSqGSIb3DQEB
|
||||
BQUAA4GBAGe9Snkz1A6rHBH6/5kDtYvtPYwhx2sXNxztbhkXErFk40Nw5l459NZx
|
||||
EeudxJBLoCkkSgYjhRcOZ/gvDVtWG7qyb6fAqgoisyAbk8K9LzxSim2S1nmT9vD8
|
||||
4B/t/VvwQBylc+ej8kRxMH7fquZLp7IXfmtBzyUqu6Dpbne+chG2
|
||||
-----END CERTIFICATE-----
|
@ -896,5 +896,5 @@ func TestAWS_HardcodedCertificates(t *testing.T) {
|
||||
assert.True(t, cert.NotAfter.After(time.Now()))
|
||||
certs = append(certs, cert)
|
||||
}
|
||||
assert.Len(t, 14, certs, "expected 14 certificates in aws_certificates.pem")
|
||||
assert.Len(t, 15, certs, "expected 15 certificates in aws_certificates.pem")
|
||||
}
|
||||
|
148
authority/ssh.go
148
authority/ssh.go
@ -146,7 +146,13 @@ func (a *Authority) GetSSHBastion(ctx context.Context, user, hostname string) (*
|
||||
}
|
||||
|
||||
// SignSSH creates a signed SSH certificate with the given public key and options.
|
||||
func (a *Authority) SignSSH(_ context.Context, key ssh.PublicKey, opts provisioner.SignSSHOptions, signOpts ...provisioner.SignOption) (*ssh.Certificate, error) {
|
||||
func (a *Authority) SignSSH(ctx context.Context, key ssh.PublicKey, opts provisioner.SignSSHOptions, signOpts ...provisioner.SignOption) (*ssh.Certificate, error) {
|
||||
cert, prov, err := a.signSSH(ctx, key, opts, signOpts...)
|
||||
a.meter.SSHSigned(prov, err)
|
||||
return cert, err
|
||||
}
|
||||
|
||||
func (a *Authority) signSSH(_ context.Context, key ssh.PublicKey, opts provisioner.SignSSHOptions, signOpts ...provisioner.SignOption) (*ssh.Certificate, provisioner.Interface, error) {
|
||||
var (
|
||||
certOptions []sshutil.Option
|
||||
mods []provisioner.SSHCertModifier
|
||||
@ -155,7 +161,7 @@ func (a *Authority) SignSSH(_ context.Context, key ssh.PublicKey, opts provision
|
||||
|
||||
// Validate given options.
|
||||
if err := opts.Validate(); err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Set backdate with the configured value
|
||||
@ -184,7 +190,7 @@ func (a *Authority) SignSSH(_ context.Context, key ssh.PublicKey, opts provision
|
||||
// validate the given SSHOptions
|
||||
case provisioner.SSHCertOptionsValidator:
|
||||
if err := o.Valid(opts); err != nil {
|
||||
return nil, errs.BadRequestErr(err, "error validating ssh certificate options")
|
||||
return nil, prov, errs.BadRequestErr(err, "error validating ssh certificate options")
|
||||
}
|
||||
|
||||
// call webhooks
|
||||
@ -192,7 +198,7 @@ func (a *Authority) SignSSH(_ context.Context, key ssh.PublicKey, opts provision
|
||||
webhookCtl = o
|
||||
|
||||
default:
|
||||
return nil, errs.InternalServer("authority.SignSSH: invalid extra option type %T", o)
|
||||
return nil, prov, errs.InternalServer("authority.SignSSH: invalid extra option type %T", o)
|
||||
}
|
||||
}
|
||||
|
||||
@ -205,8 +211,8 @@ func (a *Authority) SignSSH(_ context.Context, key ssh.PublicKey, opts provision
|
||||
}
|
||||
|
||||
// Call enriching webhooks
|
||||
if err := callEnrichingWebhooksSSH(webhookCtl, cr); err != nil {
|
||||
return nil, errs.ApplyOptions(
|
||||
if err := a.callEnrichingWebhooksSSH(prov, webhookCtl, cr); err != nil {
|
||||
return nil, prov, errs.ApplyOptions(
|
||||
errs.ForbiddenErr(err, err.Error()),
|
||||
errs.WithKeyVal("signOptions", signOpts),
|
||||
)
|
||||
@ -216,20 +222,21 @@ func (a *Authority) SignSSH(_ context.Context, key ssh.PublicKey, opts provision
|
||||
certificate, err := sshutil.NewCertificate(cr, certOptions...)
|
||||
if err != nil {
|
||||
var te *sshutil.TemplateError
|
||||
if errors.As(err, &te) {
|
||||
return nil, errs.ApplyOptions(
|
||||
switch {
|
||||
case errors.As(err, &te):
|
||||
return nil, prov, errs.ApplyOptions(
|
||||
errs.BadRequestErr(err, err.Error()),
|
||||
errs.WithKeyVal("signOptions", signOpts),
|
||||
)
|
||||
}
|
||||
case strings.HasPrefix(err.Error(), "error unmarshaling certificate"):
|
||||
// explicitly check for unmarshaling errors, which are most probably caused by JSON template syntax errors
|
||||
if strings.HasPrefix(err.Error(), "error unmarshaling certificate") {
|
||||
return nil, errs.InternalServerErr(templatingError(err),
|
||||
return nil, prov, errs.InternalServerErr(templatingError(err),
|
||||
errs.WithKeyVal("signOptions", signOpts),
|
||||
errs.WithMessage("error applying certificate template"),
|
||||
)
|
||||
default:
|
||||
return nil, prov, errs.Wrap(http.StatusInternalServerError, err, "authority.SignSSH")
|
||||
}
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err, "authority.SignSSH")
|
||||
}
|
||||
|
||||
// Get actual *ssh.Certificate and continue with provisioner modifiers.
|
||||
@ -238,13 +245,13 @@ func (a *Authority) SignSSH(_ context.Context, key ssh.PublicKey, opts provision
|
||||
// Use SignSSHOptions to modify the certificate validity. It will be later
|
||||
// checked or set if not defined.
|
||||
if err := opts.ModifyValidity(certTpl); err != nil {
|
||||
return nil, errs.BadRequestErr(err, err.Error())
|
||||
return nil, prov, errs.BadRequestErr(err, err.Error())
|
||||
}
|
||||
|
||||
// Use provisioner modifiers.
|
||||
for _, m := range mods {
|
||||
if err := m.Modify(certTpl, opts); err != nil {
|
||||
return nil, errs.ForbiddenErr(err, "error creating ssh certificate")
|
||||
return nil, prov, errs.ForbiddenErr(err, "error creating ssh certificate")
|
||||
}
|
||||
}
|
||||
|
||||
@ -253,32 +260,32 @@ func (a *Authority) SignSSH(_ context.Context, key ssh.PublicKey, opts provision
|
||||
switch certTpl.CertType {
|
||||
case ssh.UserCert:
|
||||
if a.sshCAUserCertSignKey == nil {
|
||||
return nil, errs.NotImplemented("authority.SignSSH: user certificate signing is not enabled")
|
||||
return nil, prov, errs.NotImplemented("authority.SignSSH: user certificate signing is not enabled")
|
||||
}
|
||||
signer = a.sshCAUserCertSignKey
|
||||
case ssh.HostCert:
|
||||
if a.sshCAHostCertSignKey == nil {
|
||||
return nil, errs.NotImplemented("authority.SignSSH: host certificate signing is not enabled")
|
||||
return nil, prov, errs.NotImplemented("authority.SignSSH: host certificate signing is not enabled")
|
||||
}
|
||||
signer = a.sshCAHostCertSignKey
|
||||
default:
|
||||
return nil, errs.InternalServer("authority.SignSSH: unexpected ssh certificate type: %d", certTpl.CertType)
|
||||
return nil, prov, errs.InternalServer("authority.SignSSH: unexpected ssh certificate type: %d", certTpl.CertType)
|
||||
}
|
||||
|
||||
// Check if authority is allowed to sign the certificate
|
||||
if err := a.isAllowedToSignSSHCertificate(certTpl); err != nil {
|
||||
var ee *errs.Error
|
||||
if errors.As(err, &ee) {
|
||||
return nil, ee
|
||||
return nil, prov, ee
|
||||
}
|
||||
return nil, errs.InternalServerErr(err,
|
||||
return nil, prov, errs.InternalServerErr(err,
|
||||
errs.WithMessage("authority.SignSSH: error creating ssh certificate"),
|
||||
)
|
||||
}
|
||||
|
||||
// Send certificate to webhooks for authorization
|
||||
if err := callAuthorizingWebhooksSSH(webhookCtl, certificate, certTpl); err != nil {
|
||||
return nil, errs.ApplyOptions(
|
||||
if err := a.callAuthorizingWebhooksSSH(prov, webhookCtl, certificate, certTpl); err != nil {
|
||||
return nil, prov, errs.ApplyOptions(
|
||||
errs.ForbiddenErr(err, "authority.SignSSH: error signing certificate"),
|
||||
)
|
||||
}
|
||||
@ -286,21 +293,21 @@ func (a *Authority) SignSSH(_ context.Context, key ssh.PublicKey, opts provision
|
||||
// Sign certificate.
|
||||
cert, err := sshutil.CreateCertificate(certTpl, signer)
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err, "authority.SignSSH: error signing certificate")
|
||||
return nil, prov, errs.Wrap(http.StatusInternalServerError, err, "authority.SignSSH: error signing certificate")
|
||||
}
|
||||
|
||||
// User provisioners validators.
|
||||
for _, v := range validators {
|
||||
if err := v.Valid(cert, opts); err != nil {
|
||||
return nil, errs.ForbiddenErr(err, "error validating ssh certificate")
|
||||
return nil, prov, errs.ForbiddenErr(err, "error validating ssh certificate")
|
||||
}
|
||||
}
|
||||
|
||||
if err = a.storeSSHCertificate(prov, cert); err != nil && !errors.Is(err, db.ErrNotImplemented) {
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err, "authority.SignSSH: error storing certificate in db")
|
||||
if err := a.storeSSHCertificate(prov, cert); err != nil && !errors.Is(err, db.ErrNotImplemented) {
|
||||
return nil, prov, errs.Wrap(http.StatusInternalServerError, err, "authority.SignSSH: error storing certificate in db")
|
||||
}
|
||||
|
||||
return cert, nil
|
||||
return cert, prov, nil
|
||||
}
|
||||
|
||||
// isAllowedToSignSSHCertificate checks if the Authority is allowed to sign the SSH certificate.
|
||||
@ -310,12 +317,18 @@ func (a *Authority) isAllowedToSignSSHCertificate(cert *ssh.Certificate) error {
|
||||
|
||||
// RenewSSH creates a signed SSH certificate using the old SSH certificate as a template.
|
||||
func (a *Authority) RenewSSH(ctx context.Context, oldCert *ssh.Certificate) (*ssh.Certificate, error) {
|
||||
cert, prov, err := a.renewSSH(ctx, oldCert)
|
||||
a.meter.SSHRenewed(prov, err)
|
||||
return cert, err
|
||||
}
|
||||
|
||||
func (a *Authority) renewSSH(ctx context.Context, oldCert *ssh.Certificate) (*ssh.Certificate, provisioner.Interface, error) {
|
||||
if oldCert.ValidAfter == 0 || oldCert.ValidBefore == 0 {
|
||||
return nil, errs.BadRequest("cannot renew a certificate without validity period")
|
||||
return nil, nil, errs.BadRequest("cannot renew a certificate without validity period")
|
||||
}
|
||||
|
||||
if err := a.authorizeSSHCertificate(ctx, oldCert); err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Attempt to extract the provisioner from the token.
|
||||
@ -348,36 +361,41 @@ func (a *Authority) RenewSSH(ctx context.Context, oldCert *ssh.Certificate) (*ss
|
||||
switch certTpl.CertType {
|
||||
case ssh.UserCert:
|
||||
if a.sshCAUserCertSignKey == nil {
|
||||
return nil, errs.NotImplemented("renewSSH: user certificate signing is not enabled")
|
||||
return nil, prov, errs.NotImplemented("renewSSH: user certificate signing is not enabled")
|
||||
}
|
||||
signer = a.sshCAUserCertSignKey
|
||||
case ssh.HostCert:
|
||||
if a.sshCAHostCertSignKey == nil {
|
||||
return nil, errs.NotImplemented("renewSSH: host certificate signing is not enabled")
|
||||
return nil, prov, errs.NotImplemented("renewSSH: host certificate signing is not enabled")
|
||||
}
|
||||
signer = a.sshCAHostCertSignKey
|
||||
default:
|
||||
return nil, errs.InternalServer("renewSSH: unexpected ssh certificate type: %d", certTpl.CertType)
|
||||
return nil, prov, errs.InternalServer("renewSSH: unexpected ssh certificate type: %d", certTpl.CertType)
|
||||
}
|
||||
|
||||
// Sign certificate.
|
||||
cert, err := sshutil.CreateCertificate(certTpl, signer)
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err, "signSSH: error signing certificate")
|
||||
return nil, prov, errs.Wrap(http.StatusInternalServerError, err, "signSSH: error signing certificate")
|
||||
}
|
||||
|
||||
if err = a.storeRenewedSSHCertificate(prov, oldCert, cert); err != nil && !errors.Is(err, db.ErrNotImplemented) {
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err, "renewSSH: error storing certificate in db")
|
||||
if err := a.storeRenewedSSHCertificate(prov, oldCert, cert); err != nil && !errors.Is(err, db.ErrNotImplemented) {
|
||||
return nil, prov, errs.Wrap(http.StatusInternalServerError, err, "renewSSH: error storing certificate in db")
|
||||
}
|
||||
|
||||
return cert, nil
|
||||
return cert, prov, nil
|
||||
}
|
||||
|
||||
// RekeySSH creates a signed SSH certificate using the old SSH certificate as a template.
|
||||
func (a *Authority) RekeySSH(ctx context.Context, oldCert *ssh.Certificate, pub ssh.PublicKey, signOpts ...provisioner.SignOption) (*ssh.Certificate, error) {
|
||||
var validators []provisioner.SSHCertValidator
|
||||
cert, prov, err := a.rekeySSH(ctx, oldCert, pub, signOpts...)
|
||||
a.meter.SSHRekeyed(prov, err)
|
||||
return cert, err
|
||||
}
|
||||
|
||||
func (a *Authority) rekeySSH(ctx context.Context, oldCert *ssh.Certificate, pub ssh.PublicKey, signOpts ...provisioner.SignOption) (*ssh.Certificate, provisioner.Interface, error) {
|
||||
var prov provisioner.Interface
|
||||
var validators []provisioner.SSHCertValidator
|
||||
for _, op := range signOpts {
|
||||
switch o := op.(type) {
|
||||
// Capture current provisioner
|
||||
@ -387,16 +405,16 @@ func (a *Authority) RekeySSH(ctx context.Context, oldCert *ssh.Certificate, pub
|
||||
case provisioner.SSHCertValidator:
|
||||
validators = append(validators, o)
|
||||
default:
|
||||
return nil, errs.InternalServer("rekeySSH; invalid extra option type %T", o)
|
||||
return nil, prov, errs.InternalServer("rekeySSH; invalid extra option type %T", o)
|
||||
}
|
||||
}
|
||||
|
||||
if oldCert.ValidAfter == 0 || oldCert.ValidBefore == 0 {
|
||||
return nil, errs.BadRequest("cannot rekey a certificate without validity period")
|
||||
return nil, prov, errs.BadRequest("cannot rekey a certificate without validity period")
|
||||
}
|
||||
|
||||
if err := a.authorizeSSHCertificate(ctx, oldCert); err != nil {
|
||||
return nil, err
|
||||
return nil, prov, err
|
||||
}
|
||||
|
||||
backdate := a.config.AuthorityConfig.Backdate.Duration
|
||||
@ -423,37 +441,37 @@ func (a *Authority) RekeySSH(ctx context.Context, oldCert *ssh.Certificate, pub
|
||||
switch cert.CertType {
|
||||
case ssh.UserCert:
|
||||
if a.sshCAUserCertSignKey == nil {
|
||||
return nil, errs.NotImplemented("rekeySSH; user certificate signing is not enabled")
|
||||
return nil, prov, errs.NotImplemented("rekeySSH; user certificate signing is not enabled")
|
||||
}
|
||||
signer = a.sshCAUserCertSignKey
|
||||
case ssh.HostCert:
|
||||
if a.sshCAHostCertSignKey == nil {
|
||||
return nil, errs.NotImplemented("rekeySSH; host certificate signing is not enabled")
|
||||
return nil, prov, errs.NotImplemented("rekeySSH; host certificate signing is not enabled")
|
||||
}
|
||||
signer = a.sshCAHostCertSignKey
|
||||
default:
|
||||
return nil, errs.BadRequest("unexpected certificate type '%d'", cert.CertType)
|
||||
return nil, prov, errs.BadRequest("unexpected certificate type '%d'", cert.CertType)
|
||||
}
|
||||
|
||||
var err error
|
||||
// Sign certificate.
|
||||
cert, err = sshutil.CreateCertificate(cert, signer)
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err, "signSSH: error signing certificate")
|
||||
return nil, prov, errs.Wrap(http.StatusInternalServerError, err, "signSSH: error signing certificate")
|
||||
}
|
||||
|
||||
// Apply validators from provisioner.
|
||||
for _, v := range validators {
|
||||
if err := v.Valid(cert, provisioner.SignSSHOptions{Backdate: backdate}); err != nil {
|
||||
return nil, errs.ForbiddenErr(err, "error validating ssh certificate")
|
||||
return nil, prov, errs.ForbiddenErr(err, "error validating ssh certificate")
|
||||
}
|
||||
}
|
||||
|
||||
if err = a.storeRenewedSSHCertificate(prov, oldCert, cert); err != nil && !errors.Is(err, db.ErrNotImplemented) {
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err, "rekeySSH; error storing certificate in db")
|
||||
if err := a.storeRenewedSSHCertificate(prov, oldCert, cert); err != nil && !errors.Is(err, db.ErrNotImplemented) {
|
||||
return nil, prov, errs.Wrap(http.StatusInternalServerError, err, "rekeySSH; error storing certificate in db")
|
||||
}
|
||||
|
||||
return cert, nil
|
||||
return cert, prov, nil
|
||||
}
|
||||
|
||||
func (a *Authority) storeSSHCertificate(prov provisioner.Interface, cert *ssh.Certificate) error {
|
||||
@ -653,28 +671,36 @@ func (a *Authority) getAddUserCommand(principal string) string {
|
||||
return strings.ReplaceAll(cmd, "<principal>", principal)
|
||||
}
|
||||
|
||||
func callEnrichingWebhooksSSH(webhookCtl webhookController, cr sshutil.CertificateRequest) error {
|
||||
func (a *Authority) callEnrichingWebhooksSSH(prov provisioner.Interface, webhookCtl webhookController, cr sshutil.CertificateRequest) (err error) {
|
||||
if webhookCtl == nil {
|
||||
return nil
|
||||
return
|
||||
}
|
||||
whEnrichReq, err := webhook.NewRequestBody(
|
||||
|
||||
var whEnrichReq *webhook.RequestBody
|
||||
if whEnrichReq, err = webhook.NewRequestBody(
|
||||
webhook.WithSSHCertificateRequest(cr),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
); err == nil {
|
||||
err = webhookCtl.Enrich(whEnrichReq)
|
||||
|
||||
a.meter.SSHWebhookEnriched(prov, err)
|
||||
}
|
||||
return webhookCtl.Enrich(whEnrichReq)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func callAuthorizingWebhooksSSH(webhookCtl webhookController, cert *sshutil.Certificate, certTpl *ssh.Certificate) error {
|
||||
func (a *Authority) callAuthorizingWebhooksSSH(prov provisioner.Interface, webhookCtl webhookController, cert *sshutil.Certificate, certTpl *ssh.Certificate) (err error) {
|
||||
if webhookCtl == nil {
|
||||
return nil
|
||||
return
|
||||
}
|
||||
whAuthBody, err := webhook.NewRequestBody(
|
||||
|
||||
var whAuthBody *webhook.RequestBody
|
||||
if whAuthBody, err = webhook.NewRequestBody(
|
||||
webhook.WithSSHCertificate(cert, certTpl),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
); err == nil {
|
||||
err = webhookCtl.Authorize(whAuthBody)
|
||||
|
||||
a.meter.SSHWebhookAuthorized(prov, err)
|
||||
}
|
||||
return webhookCtl.Authorize(whAuthBody)
|
||||
|
||||
return
|
||||
}
|
||||
|
165
authority/tls.go
165
authority/tls.go
@ -93,6 +93,12 @@ func withDefaultASN1DN(def *config.ASN1DN) provisioner.CertificateModifierFunc {
|
||||
|
||||
// Sign creates a signed certificate from a certificate signing request.
|
||||
func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.SignOptions, extraOpts ...provisioner.SignOption) ([]*x509.Certificate, error) {
|
||||
chain, prov, err := a.signX509(csr, signOpts, extraOpts...)
|
||||
a.meter.X509Signed(prov, err)
|
||||
return chain, err
|
||||
}
|
||||
|
||||
func (a *Authority) signX509(csr *x509.CertificateRequest, signOpts provisioner.SignOptions, extraOpts ...provisioner.SignOption) ([]*x509.Certificate, provisioner.Interface, error) {
|
||||
var (
|
||||
certOptions []x509util.Option
|
||||
certValidators []provisioner.CertificateValidator
|
||||
@ -100,9 +106,9 @@ func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Sign
|
||||
certEnforcers []provisioner.CertificateEnforcer
|
||||
)
|
||||
|
||||
opts := []interface{}{errs.WithKeyVal("csr", csr), errs.WithKeyVal("signOptions", signOpts)}
|
||||
opts := []any{errs.WithKeyVal("csr", csr), errs.WithKeyVal("signOptions", signOpts)}
|
||||
if err := csr.CheckSignature(); err != nil {
|
||||
return nil, errs.ApplyOptions(
|
||||
return nil, nil, errs.ApplyOptions(
|
||||
errs.BadRequestErr(err, "invalid certificate request"),
|
||||
opts...,
|
||||
)
|
||||
@ -111,10 +117,12 @@ func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Sign
|
||||
// Set backdate with the configured value
|
||||
signOpts.Backdate = a.config.AuthorityConfig.Backdate.Duration
|
||||
|
||||
var prov provisioner.Interface
|
||||
var pInfo *casapi.ProvisionerInfo
|
||||
var attData *provisioner.AttestationData
|
||||
var webhookCtl webhookController
|
||||
var (
|
||||
prov provisioner.Interface
|
||||
pInfo *casapi.ProvisionerInfo
|
||||
attData *provisioner.AttestationData
|
||||
webhookCtl webhookController
|
||||
)
|
||||
for _, op := range extraOpts {
|
||||
switch k := op.(type) {
|
||||
// Capture current provisioner
|
||||
@ -132,7 +140,7 @@ func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Sign
|
||||
// Validate the given certificate request.
|
||||
case provisioner.CertificateRequestValidator:
|
||||
if err := k.Valid(csr); err != nil {
|
||||
return nil, errs.ApplyOptions(
|
||||
return nil, prov, errs.ApplyOptions(
|
||||
errs.ForbiddenErr(err, "error validating certificate request"),
|
||||
opts...,
|
||||
)
|
||||
@ -159,45 +167,46 @@ func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Sign
|
||||
webhookCtl = k
|
||||
|
||||
default:
|
||||
return nil, errs.InternalServer("authority.Sign; invalid extra option type %T", append([]interface{}{k}, opts...)...)
|
||||
return nil, prov, errs.InternalServer("authority.Sign; invalid extra option type %T", append([]any{k}, opts...)...)
|
||||
}
|
||||
}
|
||||
|
||||
if err := callEnrichingWebhooksX509(webhookCtl, attData, csr); err != nil {
|
||||
return nil, errs.ApplyOptions(
|
||||
if err := a.callEnrichingWebhooksX509(prov, webhookCtl, attData, csr); err != nil {
|
||||
return nil, prov, errs.ApplyOptions(
|
||||
errs.ForbiddenErr(err, err.Error()),
|
||||
errs.WithKeyVal("csr", csr),
|
||||
errs.WithKeyVal("signOptions", signOpts),
|
||||
)
|
||||
}
|
||||
|
||||
cert, err := x509util.NewCertificate(csr, certOptions...)
|
||||
crt, err := x509util.NewCertificate(csr, certOptions...)
|
||||
if err != nil {
|
||||
var te *x509util.TemplateError
|
||||
if errors.As(err, &te) {
|
||||
return nil, errs.ApplyOptions(
|
||||
switch {
|
||||
case errors.As(err, &te):
|
||||
return nil, prov, errs.ApplyOptions(
|
||||
errs.BadRequestErr(err, err.Error()),
|
||||
errs.WithKeyVal("csr", csr),
|
||||
errs.WithKeyVal("signOptions", signOpts),
|
||||
)
|
||||
}
|
||||
case strings.HasPrefix(err.Error(), "error unmarshaling certificate"):
|
||||
// explicitly check for unmarshaling errors, which are most probably caused by JSON template (syntax) errors
|
||||
if strings.HasPrefix(err.Error(), "error unmarshaling certificate") {
|
||||
return nil, errs.InternalServerErr(templatingError(err),
|
||||
return nil, prov, errs.InternalServerErr(templatingError(err),
|
||||
errs.WithKeyVal("csr", csr),
|
||||
errs.WithKeyVal("signOptions", signOpts),
|
||||
errs.WithMessage("error applying certificate template"),
|
||||
)
|
||||
default:
|
||||
return nil, prov, errs.Wrap(http.StatusInternalServerError, err, "authority.Sign", opts...)
|
||||
}
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err, "authority.Sign", opts...)
|
||||
}
|
||||
|
||||
// Certificate modifiers before validation
|
||||
leaf := cert.GetCertificate()
|
||||
leaf := crt.GetCertificate()
|
||||
|
||||
// Set default subject
|
||||
if err := withDefaultASN1DN(a.config.AuthorityConfig.Template).Modify(leaf, signOpts); err != nil {
|
||||
return nil, errs.ApplyOptions(
|
||||
return nil, prov, errs.ApplyOptions(
|
||||
errs.ForbiddenErr(err, "error creating certificate"),
|
||||
opts...,
|
||||
)
|
||||
@ -205,7 +214,7 @@ func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Sign
|
||||
|
||||
for _, m := range certModifiers {
|
||||
if err := m.Modify(leaf, signOpts); err != nil {
|
||||
return nil, errs.ApplyOptions(
|
||||
return nil, prov, errs.ApplyOptions(
|
||||
errs.ForbiddenErr(err, "error creating certificate"),
|
||||
opts...,
|
||||
)
|
||||
@ -215,7 +224,7 @@ func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Sign
|
||||
// Certificate validation.
|
||||
for _, v := range certValidators {
|
||||
if err := v.Valid(leaf, signOpts); err != nil {
|
||||
return nil, errs.ApplyOptions(
|
||||
return nil, prov, errs.ApplyOptions(
|
||||
errs.ForbiddenErr(err, "error validating certificate"),
|
||||
opts...,
|
||||
)
|
||||
@ -224,8 +233,8 @@ func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Sign
|
||||
|
||||
// Certificate modifiers after validation
|
||||
for _, m := range certEnforcers {
|
||||
if err := m.Enforce(leaf); err != nil {
|
||||
return nil, errs.ApplyOptions(
|
||||
if err = m.Enforce(leaf); err != nil {
|
||||
return nil, prov, errs.ApplyOptions(
|
||||
errs.ForbiddenErr(err, "error creating certificate"),
|
||||
opts...,
|
||||
)
|
||||
@ -234,8 +243,8 @@ func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Sign
|
||||
|
||||
// Process injected modifiers after validation
|
||||
for _, m := range a.x509Enforcers {
|
||||
if err := m.Enforce(leaf); err != nil {
|
||||
return nil, errs.ApplyOptions(
|
||||
if err = m.Enforce(leaf); err != nil {
|
||||
return nil, prov, errs.ApplyOptions(
|
||||
errs.ForbiddenErr(err, "error creating certificate"),
|
||||
opts...,
|
||||
)
|
||||
@ -243,12 +252,12 @@ func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Sign
|
||||
}
|
||||
|
||||
// Check if authority is allowed to sign the certificate
|
||||
if err := a.isAllowedToSignX509Certificate(leaf); err != nil {
|
||||
if err = a.isAllowedToSignX509Certificate(leaf); err != nil {
|
||||
var ee *errs.Error
|
||||
if errors.As(err, &ee) {
|
||||
return nil, errs.ApplyOptions(ee, opts...)
|
||||
return nil, prov, errs.ApplyOptions(ee, opts...)
|
||||
}
|
||||
return nil, errs.InternalServerErr(err,
|
||||
return nil, prov, errs.InternalServerErr(err,
|
||||
errs.WithKeyVal("csr", csr),
|
||||
errs.WithKeyVal("signOptions", signOpts),
|
||||
errs.WithMessage("error creating certificate"),
|
||||
@ -256,8 +265,8 @@ func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Sign
|
||||
}
|
||||
|
||||
// Send certificate to webhooks for authorization
|
||||
if err := callAuthorizingWebhooksX509(webhookCtl, cert, leaf, attData); err != nil {
|
||||
return nil, errs.ApplyOptions(
|
||||
if err := a.callAuthorizingWebhooksX509(prov, webhookCtl, crt, leaf, attData); err != nil {
|
||||
return nil, prov, errs.ApplyOptions(
|
||||
errs.ForbiddenErr(err, "error creating certificate"),
|
||||
opts...,
|
||||
)
|
||||
@ -265,6 +274,7 @@ func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Sign
|
||||
|
||||
// Sign certificate
|
||||
lifetime := leaf.NotAfter.Sub(leaf.NotBefore.Add(signOpts.Backdate))
|
||||
|
||||
resp, err := a.x509CAService.CreateCertificate(&casapi.CreateCertificateRequest{
|
||||
Template: leaf,
|
||||
CSR: csr,
|
||||
@ -273,23 +283,22 @@ func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Sign
|
||||
Provisioner: pInfo,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err, "authority.Sign; error creating certificate", opts...)
|
||||
return nil, prov, errs.Wrap(http.StatusInternalServerError, err, "authority.Sign; error creating certificate", opts...)
|
||||
}
|
||||
|
||||
fullchain := append([]*x509.Certificate{resp.Certificate}, resp.CertificateChain...)
|
||||
chain := append([]*x509.Certificate{resp.Certificate}, resp.CertificateChain...)
|
||||
|
||||
// Wrap provisioner with extra information.
|
||||
// Wrap provisioner with extra information, if not nil
|
||||
if prov != nil {
|
||||
prov = wrapProvisioner(prov, attData)
|
||||
}
|
||||
|
||||
// Store certificate in the db.
|
||||
if err = a.storeCertificate(prov, fullchain); err != nil {
|
||||
if !errors.Is(err, db.ErrNotImplemented) {
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err,
|
||||
"authority.Sign; error storing certificate in db", opts...)
|
||||
}
|
||||
if err := a.storeCertificate(prov, chain); err != nil && !errors.Is(err, db.ErrNotImplemented) {
|
||||
return nil, prov, errs.Wrap(http.StatusInternalServerError, err, "authority.Sign; error storing certificate in db", opts...)
|
||||
}
|
||||
|
||||
return fullchain, nil
|
||||
return chain, prov, nil
|
||||
}
|
||||
|
||||
// isAllowedToSignX509Certificate checks if the Authority is allowed
|
||||
@ -337,14 +346,25 @@ func (a *Authority) Rekey(oldCert *x509.Certificate, pk crypto.PublicKey) ([]*x5
|
||||
// of rekey), and 'NotBefore/NotAfter' (the validity duration of the new
|
||||
// certificate should be equal to the old one, but starting 'now').
|
||||
func (a *Authority) RenewContext(ctx context.Context, oldCert *x509.Certificate, pk crypto.PublicKey) ([]*x509.Certificate, error) {
|
||||
chain, prov, err := a.renewContext(ctx, oldCert, pk)
|
||||
if pk == nil {
|
||||
a.meter.X509Renewed(prov, err)
|
||||
} else {
|
||||
a.meter.X509Rekeyed(prov, err)
|
||||
}
|
||||
return chain, err
|
||||
}
|
||||
|
||||
func (a *Authority) renewContext(ctx context.Context, oldCert *x509.Certificate, pk crypto.PublicKey) ([]*x509.Certificate, provisioner.Interface, error) {
|
||||
isRekey := (pk != nil)
|
||||
opts := []errs.Option{
|
||||
errs.WithKeyVal("serialNumber", oldCert.SerialNumber.String()),
|
||||
}
|
||||
|
||||
// Check step provisioner extensions
|
||||
if err := a.authorizeRenew(ctx, oldCert); err != nil {
|
||||
return nil, errs.StatusCodeError(http.StatusInternalServerError, err, opts...)
|
||||
prov, err := a.authorizeRenew(ctx, oldCert)
|
||||
if err != nil {
|
||||
return nil, prov, errs.StatusCodeError(http.StatusInternalServerError, err, opts...)
|
||||
}
|
||||
|
||||
// Durations
|
||||
@ -414,16 +434,18 @@ func (a *Authority) RenewContext(ctx context.Context, oldCert *x509.Certificate,
|
||||
//
|
||||
// TODO(hslatman,maraino): consider adding policies too and consider if
|
||||
// RenewSSH should check policies.
|
||||
if err := a.constraintsEngine.ValidateCertificate(newCert); err != nil {
|
||||
if err = a.constraintsEngine.ValidateCertificate(newCert); err != nil {
|
||||
var ee *errs.Error
|
||||
if errors.As(err, &ee) {
|
||||
return nil, errs.StatusCodeError(ee.StatusCode(), err, opts...)
|
||||
}
|
||||
return nil, errs.InternalServerErr(err,
|
||||
switch {
|
||||
case errors.As(err, &ee):
|
||||
return nil, prov, errs.StatusCodeError(ee.StatusCode(), err, opts...)
|
||||
default:
|
||||
return nil, prov, errs.InternalServerErr(err,
|
||||
errs.WithKeyVal("serialNumber", oldCert.SerialNumber.String()),
|
||||
errs.WithMessage("error renewing certificate"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// The token can optionally be in the context. If the CA is running in RA
|
||||
// mode, this can be used to renew a certificate.
|
||||
@ -436,17 +458,16 @@ func (a *Authority) RenewContext(ctx context.Context, oldCert *x509.Certificate,
|
||||
Token: token,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.StatusCodeError(http.StatusInternalServerError, err, opts...)
|
||||
return nil, prov, errs.StatusCodeError(http.StatusInternalServerError, err, opts...)
|
||||
}
|
||||
|
||||
fullchain := append([]*x509.Certificate{resp.Certificate}, resp.CertificateChain...)
|
||||
if err = a.storeRenewedCertificate(oldCert, fullchain); err != nil {
|
||||
if !errors.Is(err, db.ErrNotImplemented) {
|
||||
return nil, errs.StatusCodeError(http.StatusInternalServerError, err, opts...)
|
||||
}
|
||||
chain := append([]*x509.Certificate{resp.Certificate}, resp.CertificateChain...)
|
||||
|
||||
if err = a.storeRenewedCertificate(oldCert, chain); err != nil && !errors.Is(err, db.ErrNotImplemented) {
|
||||
return nil, prov, errs.StatusCodeError(http.StatusInternalServerError, err, opts...)
|
||||
}
|
||||
|
||||
return fullchain, nil
|
||||
return chain, prov, nil
|
||||
}
|
||||
|
||||
// storeCertificate allows to use an extension of the db.AuthDB interface that
|
||||
@ -952,42 +973,52 @@ func templatingError(err error) error {
|
||||
return errors.Wrap(cause, "error applying certificate template")
|
||||
}
|
||||
|
||||
func callEnrichingWebhooksX509(webhookCtl webhookController, attData *provisioner.AttestationData, csr *x509.CertificateRequest) error {
|
||||
func (a *Authority) callEnrichingWebhooksX509(prov provisioner.Interface, webhookCtl webhookController, attData *provisioner.AttestationData, csr *x509.CertificateRequest) (err error) {
|
||||
if webhookCtl == nil {
|
||||
return nil
|
||||
return
|
||||
}
|
||||
|
||||
var attested *webhook.AttestationData
|
||||
if attData != nil {
|
||||
attested = &webhook.AttestationData{
|
||||
PermanentIdentifier: attData.PermanentIdentifier,
|
||||
}
|
||||
}
|
||||
whEnrichReq, err := webhook.NewRequestBody(
|
||||
|
||||
var whEnrichReq *webhook.RequestBody
|
||||
if whEnrichReq, err = webhook.NewRequestBody(
|
||||
webhook.WithX509CertificateRequest(csr),
|
||||
webhook.WithAttestationData(attested),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
); err == nil {
|
||||
err = webhookCtl.Enrich(whEnrichReq)
|
||||
|
||||
a.meter.X509WebhookEnriched(prov, err)
|
||||
}
|
||||
return webhookCtl.Enrich(whEnrichReq)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func callAuthorizingWebhooksX509(webhookCtl webhookController, cert *x509util.Certificate, leaf *x509.Certificate, attData *provisioner.AttestationData) error {
|
||||
func (a *Authority) callAuthorizingWebhooksX509(prov provisioner.Interface, webhookCtl webhookController, cert *x509util.Certificate, leaf *x509.Certificate, attData *provisioner.AttestationData) (err error) {
|
||||
if webhookCtl == nil {
|
||||
return nil
|
||||
return
|
||||
}
|
||||
|
||||
var attested *webhook.AttestationData
|
||||
if attData != nil {
|
||||
attested = &webhook.AttestationData{
|
||||
PermanentIdentifier: attData.PermanentIdentifier,
|
||||
}
|
||||
}
|
||||
whAuthBody, err := webhook.NewRequestBody(
|
||||
|
||||
var whAuthBody *webhook.RequestBody
|
||||
if whAuthBody, err = webhook.NewRequestBody(
|
||||
webhook.WithX509Certificate(cert, leaf),
|
||||
webhook.WithAttestationData(attested),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
); err == nil {
|
||||
err = webhookCtl.Authorize(whAuthBody)
|
||||
|
||||
a.meter.X509WebhookAuthorized(prov, err)
|
||||
}
|
||||
return webhookCtl.Authorize(whAuthBody)
|
||||
|
||||
return
|
||||
}
|
||||
|
30
ca/ca.go
30
ca/ca.go
@ -28,6 +28,7 @@ import (
|
||||
"github.com/smallstep/certificates/authority/config"
|
||||
"github.com/smallstep/certificates/cas/apiv1"
|
||||
"github.com/smallstep/certificates/db"
|
||||
"github.com/smallstep/certificates/internal/metrix"
|
||||
"github.com/smallstep/certificates/logging"
|
||||
"github.com/smallstep/certificates/monitoring"
|
||||
"github.com/smallstep/certificates/scep"
|
||||
@ -134,6 +135,7 @@ type CA struct {
|
||||
config *config.Config
|
||||
srv *server.Server
|
||||
insecureSrv *server.Server
|
||||
metricsSrv *server.Server
|
||||
opts *options
|
||||
renewer *TLSRenewer
|
||||
compactStop chan struct{}
|
||||
@ -176,6 +178,12 @@ func (ca *CA) Init(cfg *config.Config) (*CA, error) {
|
||||
opts = append(opts, authority.WithX509CAService(ca.opts.x509CAService))
|
||||
}
|
||||
|
||||
var meter *metrix.Meter
|
||||
if ca.config.MetricsAddress != "" {
|
||||
meter = metrix.New()
|
||||
opts = append(opts, authority.WithMeter(meter))
|
||||
}
|
||||
|
||||
webhookTransport := http.DefaultTransport.(*http.Transport).Clone()
|
||||
opts = append(opts, authority.WithWebhookClient(&http.Client{Transport: webhookTransport}))
|
||||
|
||||
@ -331,6 +339,13 @@ func (ca *CA) Init(cfg *config.Config) (*CA, error) {
|
||||
}
|
||||
}
|
||||
|
||||
if meter != nil {
|
||||
ca.metricsSrv = server.New(ca.config.MetricsAddress, meter, nil)
|
||||
ca.metricsSrv.BaseContext = func(net.Listener) context.Context {
|
||||
return baseContext
|
||||
}
|
||||
}
|
||||
|
||||
return ca, nil
|
||||
}
|
||||
|
||||
@ -417,6 +432,14 @@ func (ca *CA) Run() error {
|
||||
}()
|
||||
}
|
||||
|
||||
if ca.metricsSrv != nil {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
errs <- ca.metricsSrv.ListenAndServe()
|
||||
}()
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
@ -493,6 +516,13 @@ func (ca *CA) Reload() error {
|
||||
}
|
||||
}
|
||||
|
||||
if ca.metricsSrv != nil {
|
||||
if err = ca.metricsSrv.Reload(newCA.metricsSrv); err != nil {
|
||||
logContinue("Reload failed because metrics server could not be replaced.")
|
||||
return errors.Wrap(err, "error reloading metrics server")
|
||||
}
|
||||
}
|
||||
|
||||
if err = ca.srv.Reload(newCA.srv); err != nil {
|
||||
logContinue("Reload failed because server could not be replaced.")
|
||||
return errors.Wrap(err, "error reloading server")
|
||||
|
@ -251,7 +251,8 @@ To get a linked authority token:
|
||||
ca.WithSSHUserPassword(sshUserPassword),
|
||||
ca.WithIssuerPassword(issuerPassword),
|
||||
ca.WithLinkedCAToken(token),
|
||||
ca.WithQuiet(quiet))
|
||||
ca.WithQuiet(quiet),
|
||||
)
|
||||
if err != nil {
|
||||
fatal(err)
|
||||
}
|
||||
|
74
go.mod
74
go.mod
@ -3,8 +3,8 @@ module github.com/smallstep/certificates
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
cloud.google.com/go/longrunning v0.5.4
|
||||
cloud.google.com/go/security v1.15.4
|
||||
cloud.google.com/go/longrunning v0.5.5
|
||||
cloud.google.com/go/security v1.15.5
|
||||
github.com/Masterminds/sprig/v3 v3.2.3
|
||||
github.com/dgraph-io/badger v1.6.2
|
||||
github.com/dgraph-io/badger/v2 v2.2007.4
|
||||
@ -14,13 +14,14 @@ require (
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/google/go-cmp v0.6.0
|
||||
github.com/google/go-tpm v0.9.0
|
||||
github.com/google/uuid v1.5.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/googleapis/gax-go/v2 v2.12.0
|
||||
github.com/hashicorp/vault/api v1.10.0
|
||||
github.com/hashicorp/vault/api/auth/approle v0.5.0
|
||||
github.com/hashicorp/vault/api v1.12.0
|
||||
github.com/hashicorp/vault/api/auth/approle v0.6.0
|
||||
github.com/hashicorp/vault/api/auth/kubernetes v0.5.0
|
||||
github.com/newrelic/go-agent/v3 v3.29.0
|
||||
github.com/newrelic/go-agent/v3 v3.29.1
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/client_golang v1.18.0
|
||||
github.com/rs/xid v1.5.0
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/slackhq/nebula v1.6.1
|
||||
@ -32,18 +33,18 @@ require (
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/urfave/cli v1.22.14
|
||||
go.step.sm/cli-utils v0.8.0
|
||||
go.step.sm/crypto v0.41.0
|
||||
go.step.sm/crypto v0.43.0
|
||||
go.step.sm/linkedca v0.20.1
|
||||
golang.org/x/crypto v0.18.0
|
||||
golang.org/x/crypto v0.19.0
|
||||
golang.org/x/exp v0.0.0-20230310171629-522b1b587ee0
|
||||
golang.org/x/net v0.20.0
|
||||
google.golang.org/api v0.156.0
|
||||
google.golang.org/grpc v1.60.1
|
||||
golang.org/x/net v0.21.0
|
||||
google.golang.org/api v0.160.0
|
||||
google.golang.org/grpc v1.61.0
|
||||
google.golang.org/protobuf v1.32.0
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.111.0 // indirect
|
||||
cloud.google.com/go v0.112.0 // indirect
|
||||
cloud.google.com/go/compute v1.23.3 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||
cloud.google.com/go/iam v1.1.5 // indirect
|
||||
@ -51,15 +52,29 @@ require (
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.0 // indirect
|
||||
github.com/ThalesIgnite/crypto11 v1.2.5 // indirect
|
||||
github.com/aws/aws-sdk-go v1.49.17 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.24.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/config v1.26.6 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.16.16 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.11 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.7.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/kms v1.27.9 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.18.7 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.7 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.26.7 // indirect
|
||||
github.com/aws/smithy-go v1.19.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cenkalti/backoff/v3 v3.0.0 // indirect
|
||||
github.com/cespare/xxhash v1.1.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
@ -73,11 +88,11 @@ require (
|
||||
github.com/go-kit/kit v0.13.0 // indirect
|
||||
github.com/go-kit/log v0.2.1 // indirect
|
||||
github.com/go-logfmt/logfmt v0.6.0 // indirect
|
||||
github.com/go-logr/logr v1.3.0 // indirect
|
||||
github.com/go-logr/logr v1.4.1 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-piv/piv-go v1.11.0 // indirect
|
||||
github.com/go-sql-driver/mysql v1.7.1 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.2.0 // indirect
|
||||
github.com/golang/glog v1.1.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
@ -107,12 +122,12 @@ require (
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||
github.com/jackc/pgtype v1.14.0 // indirect
|
||||
github.com/jackc/pgx/v4 v4.18.0 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/klauspost/compress v1.16.3 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/manifoldco/promptui v0.9.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
||||
github.com/miekg/pkcs11 v1.1.1 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
@ -120,8 +135,11 @@ require (
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/peterbourgon/diskv/v3 v3.0.1 // indirect
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_model v0.5.0 // indirect
|
||||
github.com/prometheus/common v0.45.0 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/ryanuber/go-glob v1.0.0 // indirect
|
||||
github.com/schollz/jsonstore v1.1.0 // indirect
|
||||
@ -132,19 +150,19 @@ require (
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
go.etcd.io/bbolt v1.3.7 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 // indirect
|
||||
go.opentelemetry.io/otel v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.21.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 // indirect
|
||||
go.opentelemetry.io/otel v1.22.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.22.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.22.0 // indirect
|
||||
golang.org/x/oauth2 v0.16.0 // indirect
|
||||
golang.org/x/sync v0.6.0 // indirect
|
||||
golang.org/x/sys v0.16.0 // indirect
|
||||
golang.org/x/sys v0.17.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
google.golang.org/appengine v1.6.8 // indirect
|
||||
google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 // indirect
|
||||
google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
177
go.sum
177
go.sum
@ -1,6 +1,6 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.111.0 h1:YHLKNupSD1KqjDbQ3+LVdQ81h/UJbJyZG203cEfnQgM=
|
||||
cloud.google.com/go v0.111.0/go.mod h1:0mibmpKP1TyOOFYQY5izo0LnT+ecvOQ0Sg3OdmMiNRU=
|
||||
cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM=
|
||||
cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4=
|
||||
cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk=
|
||||
cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI=
|
||||
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
|
||||
@ -9,26 +9,26 @@ cloud.google.com/go/iam v1.1.5 h1:1jTsCu4bcsNsE4iiqNT5SHwrDRCfRmIaaaVFhRveTJI=
|
||||
cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8=
|
||||
cloud.google.com/go/kms v1.15.5 h1:pj1sRfut2eRbD9pFRjNnPNg/CzJPuQAzUujMIM1vVeM=
|
||||
cloud.google.com/go/kms v1.15.5/go.mod h1:cU2H5jnp6G2TDpUGZyqTCoy1n16fbubHZjmVXSMtwDI=
|
||||
cloud.google.com/go/longrunning v0.5.4 h1:w8xEcbZodnA2BbW6sVirkkoC+1gP8wS57EUUgGS0GVg=
|
||||
cloud.google.com/go/longrunning v0.5.4/go.mod h1:zqNVncI0BOP8ST6XQD1+VcvuShMmq7+xFSzOL++V0dI=
|
||||
cloud.google.com/go/security v1.15.4 h1:sdnh4Islb1ljaNhpIXlIPgb3eYj70QWgPVDKOUYvzJc=
|
||||
cloud.google.com/go/security v1.15.4/go.mod h1:oN7C2uIZKhxCLiAAijKUCuHLZbIt/ghYEo8MqwD/Ty4=
|
||||
cloud.google.com/go/longrunning v0.5.5 h1:GOE6pZFdSrTb4KAiKnXsJBtlE6mEyaW44oKyMILWnOg=
|
||||
cloud.google.com/go/longrunning v0.5.5/go.mod h1:WV2LAxD8/rg5Z1cNW6FJ/ZpX4E4VnDnoTk0yawPBB7s=
|
||||
cloud.google.com/go/security v1.15.5 h1:wTKJQ10j8EYgvE8Y+KhovxDRVDk2iv/OsxZ6GrLP3kE=
|
||||
cloud.google.com/go/security v1.15.5/go.mod h1:KS6X2eG3ynWjqcIX976fuToN5juVkF6Ra6c7MPnldtc=
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M=
|
||||
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1 h1:lGlwhPtrX6EVml1hO0ivjkUxsSyl4dsiw9qcA1k/3IQ=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1/go.mod h1:RKUqNu35KJYcVG/fqTRqmuXJZYNhYkBrnC/hX7yGbTA=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 h1:BMAjVKJM0U/CYF27gA0ZMmXGkOcvfFtD0oHVZ1TIPRI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0/go.mod h1:1fXstnBMas5kzG+S3q8UoJcmyU6nUeunJcMDHcRYHhs=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1 h1:sO0/P7g68FrryJzljemN+6GTssUXdANk6aJ7T1ZxnsQ=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1/go.mod h1:h8hyGFDsU5HMivxiS2iYFZsgDbU9OnnJ163x5UGVKYo=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1 h1:6oNBlSdi1QqM1PNW7FPA6xOGA5UNsXnkaYZz9vdPGhA=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1/go.mod h1:s4kgfzA0covAXNicZHDMN58jExvcng2mC/DepXiF1EI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0 h1:m/sWOGCREuSBqg2htVQTBY8nOZpyajYztF0vUvSZTuM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0/go.mod h1:Pu5Zksi2KrU7LPbZbNINx6fuVrUp/ffvpxdDj+i8LeE=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 h1:FbH3BbSb4bvGluTesZZ+ttN/MDsnMmQP36OSnDuSXqw=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1/go.mod h1:9V2j0jn9jDEkCkv8w/bKTNppX/d0FVA1ud77xCIP4KA=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 h1:WpB/QDNLpMw72xHJc34BNNykqSOeEJDAWkhf0u12/Jk=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 h1:DzHpqpoJVaCgOUdVHxE8QB52S6NiVdDQvGlny1qvPqA=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||
@ -44,8 +44,36 @@ github.com/ThalesIgnite/crypto11 v1.2.5 h1:1IiIIEqYmBvUYFeMnHqRft4bwf/O36jryEUpY
|
||||
github.com/ThalesIgnite/crypto11 v1.2.5/go.mod h1:ILDKtnCKiQ7zRoNxcp36Y1ZR8LBPmR2E23+wTQe/MlE=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/aws/aws-sdk-go v1.49.17 h1:Cc+7LgPjKeJkF2SdNo1IkpQ5Dfl9HCZEVw9OP3CPuEI=
|
||||
github.com/aws/aws-sdk-go v1.49.17/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
|
||||
github.com/aws/aws-sdk-go-v2 v1.24.1 h1:xAojnj+ktS95YZlDf0zxWBkbFtymPeDP+rvUQIH3uAU=
|
||||
github.com/aws/aws-sdk-go-v2 v1.24.1/go.mod h1:LNh45Br1YAkEKaAqvmE1m8FUx6a5b/V0oAKV7of29b4=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.26.6 h1:Z/7w9bUqlRI0FFQpetVuFYEsjzE3h7fpU6HuGmfPL/o=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.26.6/go.mod h1:uKU6cnDmYCvJ+pxO9S4cWDb2yWWIH5hra+32hVh1MI4=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.16.16 h1:8q6Rliyv0aUFAVtzaldUEcS+T5gbadPbWdV1WcAddK8=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.16.16/go.mod h1:UHVZrdUsv63hPXFo1H7c5fEneoVo9UXiz36QG1GEPi0=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.11 h1:c5I5iH+DZcH3xOIMlz3/tCKJDaHFwYEmxvlh2fAcFo8=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.11/go.mod h1:cRrYDYAMUohBJUtUnOhydaMHtiK/1NZ0Otc9lIb6O0Y=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.10 h1:vF+Zgd9s+H4vOXd5BMaPWykta2a6Ih0AKLq/X6NYKn4=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.10/go.mod h1:6BkRjejp/GR4411UGqkX8+wFMbFbqsUIimfK4XjOKR4=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.10 h1:nYPe006ktcqUji8S2mqXf9c/7NdiKriOwMvWQHgYztw=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.10/go.mod h1:6UV4SZkVvmODfXKql4LCbaZUpF7HO2BX38FgBf9ZOLw=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.7.3 h1:n3GDfwqF2tzEkXlv5cuy4iy7LpKDtqDMcNLfZDu9rls=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.7.3/go.mod h1:6fQQgfuGmw8Al/3M2IgIllycxV7ZW7WCdVSqfBeUiCY=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 h1:/b31bi3YVNlkzkBrm9LfpaKoaYZUxIAj4sHfOTmLfqw=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4/go.mod h1:2aGXHFmbInwgP9ZfpmdIfOELL79zhdNYNmReK8qDfdQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.10 h1:DBYTXwIGQSGs9w4jKm60F5dmCQ3EEruxdc0MFh+3EY4=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.10/go.mod h1:wohMUQiFdzo0NtxbBg0mSRGZ4vL3n0dKjLTINdcIino=
|
||||
github.com/aws/aws-sdk-go-v2/service/kms v1.27.9 h1:W9PbZAZAEcelhhjb7KuwUtf+Lbc+i7ByYJRuWLlnxyQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/kms v1.27.9/go.mod h1:2tFmR7fQnOdQlM2ZCEPpFnBIQD1U8wmXmduBgZbOag0=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.18.7 h1:eajuO3nykDPdYicLlP3AGgOyVN3MOlFmZv7WGTuJPow=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.18.7/go.mod h1:+mJNDdF+qiUlNKNC3fxn74WWNN+sOiGOEImje+3ScPM=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.7 h1:QPMJf+Jw8E1l7zqhZmMlFw6w1NmfkfiSK8mS4zOx3BA=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.7/go.mod h1:ykf3COxYI0UJmxcfcxcVuz7b6uADi1FkiUz6Eb7AgM8=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.26.7 h1:NzO4Vrau795RkUdSHKEwiR01FaGzGOH1EETJ+5QHnm0=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.26.7/go.mod h1:6h2YuIoxaMSCFf5fi1EgZAwdfkGMgDY+DVfa61uLe4U=
|
||||
github.com/aws/smithy-go v1.19.0 h1:KWFKQV80DpP3vJrrA9sVAHQ5gc2z8i4EzrLhLlWXcBM=
|
||||
github.com/aws/smithy-go v1.19.0/go.mod h1:NukqUGpCZIILqqiV0NIjeFh24kd/FAa4beRb6nbIUPE=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c=
|
||||
github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
|
||||
@ -66,7 +94,7 @@ github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04=
|
||||
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k=
|
||||
github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101 h1:7To3pQ+pZo0i3dsWEbinPNFs5gPSBOsJtx3wTT94VBY=
|
||||
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
|
||||
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
@ -124,8 +152,8 @@ github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KE
|
||||
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
|
||||
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
|
||||
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
||||
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-piv/piv-go v1.11.0 h1:5vAaCdRTFSIW4PeqMbnsDlUZ7odMYWnHBDGdmtU/Zhg=
|
||||
@ -138,8 +166,8 @@ github.com/go-test/deep v1.0.2 h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw=
|
||||
github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
|
||||
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
|
||||
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE=
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo=
|
||||
github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ=
|
||||
@ -196,8 +224,8 @@ github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
|
||||
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
|
||||
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
|
||||
github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas=
|
||||
@ -227,10 +255,11 @@ github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0S
|
||||
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/vault/api v1.10.0 h1:/US7sIjWN6Imp4o/Rj1Ce2Nr5bki/AXi9vAW3p2tOJQ=
|
||||
github.com/hashicorp/vault/api v1.10.0/go.mod h1:jo5Y/ET+hNyz+JnKDt8XLAdKs+AM0G5W0Vp1IrFI8N8=
|
||||
github.com/hashicorp/vault/api/auth/approle v0.5.0 h1:a1TK6VGwYqSAfkmX4y4dJ4WBxMU5dStIZqScW4EPXR8=
|
||||
github.com/hashicorp/vault/api/auth/approle v0.5.0/go.mod h1:CHOQIA1AZACfjTzHggmyfiOZ+xCSKNRFqe48FTCzH0k=
|
||||
github.com/hashicorp/vault/api v1.12.0 h1:meCpJSesvzQyao8FCOgk2fGdoADAnbDu2WPJN1lDLJ4=
|
||||
github.com/hashicorp/vault/api v1.12.0/go.mod h1:si+lJCYO7oGkIoNPAN8j3azBLTn9SjMGS+jFaHd1Cck=
|
||||
github.com/hashicorp/vault/api/auth/approle v0.6.0 h1:ELfFFQlTM/e97WJKu1HvNFa7lQ3tlTwwzrR1NJE1V7Y=
|
||||
github.com/hashicorp/vault/api/auth/approle v0.6.0/go.mod h1:CCoIl1xBC3lAWpd1HV+0ovk76Z8b8Mdepyk21h3pGk0=
|
||||
github.com/hashicorp/vault/api/auth/kubernetes v0.5.0 h1:CXO0fD7M3iCGovP/UApeHhPcH4paDFKcu7AjEXi94rI=
|
||||
github.com/hashicorp/vault/api/auth/kubernetes v0.5.0/go.mod h1:afrElBIO9Q4sHFVuVWgNevG4uAs1bT2AZFA9aEiI608=
|
||||
github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4=
|
||||
@ -287,10 +316,6 @@ github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0f
|
||||
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||
github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY=
|
||||
@ -328,6 +353,8 @@ github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcME
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
|
||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/miekg/pkcs11 v1.0.3-0.20190429190417-a667d056470f/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
|
||||
@ -347,23 +374,31 @@ github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
|
||||
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
|
||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/newrelic/go-agent/v3 v3.29.0 h1:Bc1D3DoOkpJs6aIzhOjUp+yIKJ2RfZ+LMQemZOs9t9k=
|
||||
github.com/newrelic/go-agent/v3 v3.29.0/go.mod h1:9utrgxlSryNqRrTvII2XBL+0lpofXbqXApvVWPpbzUg=
|
||||
github.com/newrelic/go-agent/v3 v3.29.1 h1:OINNRev5ImiyRq0IUYwhfTmtqQgQFYyDNQEtbRFAi+k=
|
||||
github.com/newrelic/go-agent/v3 v3.29.1/go.mod h1:9utrgxlSryNqRrTvII2XBL+0lpofXbqXApvVWPpbzUg=
|
||||
github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/peterbourgon/diskv/v3 v3.0.1 h1:x06SQA46+PKIUftmEujdwSEpIx8kR+M9eLYsUxeYveU=
|
||||
github.com/peterbourgon/diskv/v3 v3.0.1/go.mod h1:kJ5Ny7vLdARGU3WUuy6uzO6T0nb/2gWcT1JiBvRmb5o=
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
|
||||
github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
|
||||
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
|
||||
github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM=
|
||||
github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY=
|
||||
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
||||
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
|
||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
@ -442,21 +477,21 @@ go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
|
||||
go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo=
|
||||
go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc=
|
||||
go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo=
|
||||
go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4=
|
||||
go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM=
|
||||
go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o=
|
||||
go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc=
|
||||
go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 h1:UNQQKPfTDe1J81ViolILjTKPr9WetKW6uei2hFgJmFs=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 h1:sv9kVfal0MK0wBMCOGr+HeJm9v803BkJxGrk2au7j08=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0/go.mod h1:SK2UL73Zy1quvRPonmOmRDiWk1KBV3LyIeeIxcEApWw=
|
||||
go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y=
|
||||
go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI=
|
||||
go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg=
|
||||
go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY=
|
||||
go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8=
|
||||
go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0=
|
||||
go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo=
|
||||
go.step.sm/cli-utils v0.8.0 h1:b/Tc1/m3YuQq+u3ghTFP7Dz5zUekZj6GUmd5pCvkEXQ=
|
||||
go.step.sm/cli-utils v0.8.0/go.mod h1:S77aISrC0pKuflqiDfxxJlUbiXcAanyJ4POOnzFSxD4=
|
||||
go.step.sm/crypto v0.41.0 h1:cv1zSLsAUKurAmoG559fmtMTCaK0CrbLgSI1pmI/ITc=
|
||||
go.step.sm/crypto v0.41.0/go.mod h1:BBkqzupJdsSZ8LrPNyfqN81DMtahOenTk66tVgPmDvI=
|
||||
go.step.sm/crypto v0.43.0 h1:siTS/iiqaX4qBUeTxVyag5I2rijuKOMDkXSnrKcei7s=
|
||||
go.step.sm/crypto v0.43.0/go.mod h1:iKrtuRbFlqimEG/+fWSu7kcZzl4Bd/+w5xkuqA5OSic=
|
||||
go.step.sm/linkedca v0.20.1 h1:bHDn1+UG1NgRrERkWbbCiAIvv4lD5NOFaswPDTyO5vU=
|
||||
go.step.sm/linkedca v0.20.1/go.mod h1:Vaq4+Umtjh7DLFI1KuIxeo598vfBzgSYZUjgVJ7Syxw=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
@ -484,8 +519,10 @@ golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5y
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20230310171629-522b1b587ee0 h1:LGJsf5LRplCck6jUCH3dBL2dmycNruWNF5xugkSlfXw=
|
||||
golang.org/x/exp v0.0.0-20230310171629-522b1b587ee0/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
@ -497,6 +534,7 @@ golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKG
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@ -511,8 +549,10 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
|
||||
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
|
||||
@ -521,6 +561,7 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@ -544,22 +585,28 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||
golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
@ -569,6 +616,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
@ -588,14 +637,15 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
|
||||
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.156.0 h1:yloYcGbBtVYjLKQe4enCunxvwn3s2w/XPrrhVf6MsvQ=
|
||||
google.golang.org/api v0.156.0/go.mod h1:bUSmn4KFO0Q+69zo9CNIDp4Psi6BqM0np0CbzKRSiSY=
|
||||
google.golang.org/api v0.160.0 h1:SEspjXHVqE1m5a1fRy8JFB+5jSu+V0GEDKDghF3ttO4=
|
||||
google.golang.org/api v0.160.0/go.mod h1:0mu0TpK33qnydLvWqbImq2b1eQ5FHRSDCBzAxX9ZHyw=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
|
||||
@ -603,19 +653,19 @@ google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJ
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 h1:YJ5pD9rF8o9Qtta0Cmy9rdBwkSjrTCT6XTiUQVOtIos=
|
||||
google.golang.org/genproto v0.0.0-20231212172506-995d672761c0/go.mod h1:l/k7rMz0vFTBPy+tFSGvXEd3z+BcoG1k7EHbqm+YBsY=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0 h1:s1w3X6gQxwrLEpxnLd/qXTVLgQE2yXwaOaoa6IlY/+o=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0/go.mod h1:CAny0tYF+0/9rmDB9fahA9YLzX3+AEVl1qXbv5hhj6c=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 h1:6G8oQ016D88m1xAKljMlBOOGWDZkes4kMhgGFlf8WcQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917/go.mod h1:xtjpI3tXFPP051KaWnhvxkiubL/6dJ18vLVf7q2pTOU=
|
||||
google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac h1:ZL/Teoy/ZGnzyrqK/Optxxp2pmVh+fmJ97slxSRyzUg=
|
||||
google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:+Rvu7ElI+aLzyDQhpHMFMMltsD6m7nqpuWDd2CwJw3k=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe h1:0poefMBYvYbs7g5UkjS6HcxBPaTRAmznle9jnxYoAI8=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe h1:bQnxqljG/wqi4NTXu2+DJ3n7APcEA882QZ1JvhQAq9o=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU=
|
||||
google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM=
|
||||
google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0=
|
||||
google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
@ -631,12 +681,11 @@ google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7
|
||||
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
|
196
internal/metrix/meter.go
Normal file
196
internal/metrix/meter.go
Normal file
@ -0,0 +1,196 @@
|
||||
// Package metrix implements stats-related functionality.
|
||||
package metrix
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/smallstep/certificates/authority/provisioner"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
// New initializes and returns a new [Meter].
|
||||
func New() (m *Meter) {
|
||||
initializedAt := time.Now()
|
||||
|
||||
m = &Meter{
|
||||
uptime: prometheus.NewGaugeFunc(
|
||||
prometheus.GaugeOpts(opts(
|
||||
"",
|
||||
"uptime_seconds",
|
||||
"Number of seconds since service start",
|
||||
)),
|
||||
func() float64 {
|
||||
return float64(time.Since(initializedAt) / time.Second)
|
||||
},
|
||||
),
|
||||
ssh: newProvisionerInstruments("ssh"),
|
||||
x509: newProvisionerInstruments("x509"),
|
||||
kms: &kms{
|
||||
signed: prometheus.NewCounter(prometheus.CounterOpts(opts("kms", "signed", "Number of KMS-backed signatures"))),
|
||||
errors: prometheus.NewCounter(prometheus.CounterOpts(opts("kms", "errors", "Number of KMS-related errors"))),
|
||||
},
|
||||
}
|
||||
|
||||
reg := prometheus.NewRegistry()
|
||||
|
||||
reg.MustRegister(
|
||||
m.uptime,
|
||||
m.ssh.rekeyed,
|
||||
m.ssh.renewed,
|
||||
m.ssh.signed,
|
||||
m.x509.rekeyed,
|
||||
m.x509.renewed,
|
||||
m.x509.signed,
|
||||
m.kms.signed,
|
||||
m.kms.errors,
|
||||
)
|
||||
|
||||
h := promhttp.HandlerFor(reg, promhttp.HandlerOpts{
|
||||
Registry: reg,
|
||||
Timeout: 5 * time.Second,
|
||||
MaxRequestsInFlight: 10,
|
||||
})
|
||||
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle("/metrics", h)
|
||||
m.Handler = mux
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Meter wraps the functionality of a Prometheus-compatible HTTP handler.
|
||||
type Meter struct {
|
||||
http.Handler
|
||||
|
||||
uptime prometheus.GaugeFunc
|
||||
ssh *provisionerInstruments
|
||||
x509 *provisionerInstruments
|
||||
kms *kms
|
||||
}
|
||||
|
||||
// SSHRekeyed implements [authority.Meter] for [Meter].
|
||||
func (m *Meter) SSHRekeyed(p provisioner.Interface, err error) {
|
||||
incrProvisionerCounter(m.ssh.rekeyed, p, err)
|
||||
}
|
||||
|
||||
// SSHRenewed implements [authority.Meter] for [Meter].
|
||||
func (m *Meter) SSHRenewed(p provisioner.Interface, err error) {
|
||||
incrProvisionerCounter(m.ssh.renewed, p, err)
|
||||
}
|
||||
|
||||
// SSHSigned implements [authority.Meter] for [Meter].
|
||||
func (m *Meter) SSHSigned(p provisioner.Interface, err error) {
|
||||
incrProvisionerCounter(m.ssh.signed, p, err)
|
||||
}
|
||||
|
||||
// SSHAuthorized implements [authority.Meter] for [Meter].
|
||||
func (m *Meter) SSHWebhookAuthorized(p provisioner.Interface, err error) {
|
||||
incrProvisionerCounter(m.ssh.webhookAuthorized, p, err)
|
||||
}
|
||||
|
||||
// SSHEnriched implements [authority.Meter] for [Meter].
|
||||
func (m *Meter) SSHWebhookEnriched(p provisioner.Interface, err error) {
|
||||
incrProvisionerCounter(m.ssh.webhookEnriched, p, err)
|
||||
}
|
||||
|
||||
// X509Rekeyed implements [authority.Meter] for [Meter].
|
||||
func (m *Meter) X509Rekeyed(p provisioner.Interface, err error) {
|
||||
incrProvisionerCounter(m.x509.rekeyed, p, err)
|
||||
}
|
||||
|
||||
// X509Renewed implements [authority.Meter] for [Meter].
|
||||
func (m *Meter) X509Renewed(p provisioner.Interface, err error) {
|
||||
incrProvisionerCounter(m.x509.renewed, p, err)
|
||||
}
|
||||
|
||||
// X509Signed implements [authority.Meter] for [Meter].
|
||||
func (m *Meter) X509Signed(p provisioner.Interface, err error) {
|
||||
incrProvisionerCounter(m.x509.signed, p, err)
|
||||
}
|
||||
|
||||
// X509Authorized implements [authority.Meter] for [Meter].
|
||||
func (m *Meter) X509WebhookAuthorized(p provisioner.Interface, err error) {
|
||||
incrProvisionerCounter(m.x509.webhookAuthorized, p, err)
|
||||
}
|
||||
|
||||
// X509Enriched implements [authority.Meter] for [Meter].
|
||||
func (m *Meter) X509WebhookEnriched(p provisioner.Interface, err error) {
|
||||
incrProvisionerCounter(m.x509.webhookEnriched, p, err)
|
||||
}
|
||||
|
||||
func incrProvisionerCounter(cv *prometheus.CounterVec, p provisioner.Interface, err error) {
|
||||
var name string
|
||||
if p != nil {
|
||||
name = p.GetName()
|
||||
}
|
||||
|
||||
cv.WithLabelValues(name, strconv.FormatBool(err == nil)).Inc()
|
||||
}
|
||||
|
||||
// KMSSigned implements [authority.Meter] for [Meter].
|
||||
func (m *Meter) KMSSigned(err error) {
|
||||
if err == nil {
|
||||
m.kms.signed.Inc()
|
||||
} else {
|
||||
m.kms.errors.Inc()
|
||||
}
|
||||
}
|
||||
|
||||
// provisionerInstruments wraps the counters exported by provisioners.
|
||||
type provisionerInstruments struct {
|
||||
rekeyed *prometheus.CounterVec
|
||||
renewed *prometheus.CounterVec
|
||||
signed *prometheus.CounterVec
|
||||
|
||||
webhookAuthorized *prometheus.CounterVec
|
||||
webhookEnriched *prometheus.CounterVec
|
||||
}
|
||||
|
||||
func newProvisionerInstruments(subsystem string) *provisionerInstruments {
|
||||
return &provisionerInstruments{
|
||||
rekeyed: newCounterVec(subsystem, "rekeyed_total", "Number of certificates rekeyed",
|
||||
"provisioner",
|
||||
"success",
|
||||
),
|
||||
renewed: newCounterVec(subsystem, "renewed_total", "Number of certificates renewed",
|
||||
"provisioner",
|
||||
"success",
|
||||
),
|
||||
signed: newCounterVec(subsystem, "signed_total", "Number of certificates signed",
|
||||
"provisioner",
|
||||
"success",
|
||||
),
|
||||
webhookAuthorized: newCounterVec(subsystem, "webhook_authorized_total", "Number of authorizing webhooks called",
|
||||
"provisioner",
|
||||
"success",
|
||||
),
|
||||
webhookEnriched: newCounterVec(subsystem, "webhook_enriched_total", "Number of enriching webhooks called",
|
||||
"provisioner",
|
||||
"success",
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
type kms struct {
|
||||
signed prometheus.Counter
|
||||
errors prometheus.Counter
|
||||
}
|
||||
|
||||
func newCounterVec(subsystem, name, help string, labels ...string) *prometheus.CounterVec {
|
||||
opts := opts(subsystem, name, help)
|
||||
|
||||
return prometheus.NewCounterVec(prometheus.CounterOpts(opts), labels)
|
||||
}
|
||||
|
||||
func opts(subsystem, name, help string) prometheus.Opts {
|
||||
return prometheus.Opts{
|
||||
Namespace: "step_ca",
|
||||
Subsystem: subsystem,
|
||||
Name: name,
|
||||
Help: help,
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user