Skip to content

Commit 6c2f5b0

Browse files
authored
Merge branch 'smallstep:master' into master
2 parents f64ebf3 + d9aaa75 commit 6c2f5b0

File tree

9 files changed

+143
-105
lines changed

9 files changed

+143
-105
lines changed

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,17 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
2525

2626
---
2727

28+
## [unreleased] - aaaa-bb-cc
29+
30+
### Added
31+
32+
- Add support for using key usage, extended key usage, and basic constraints
33+
from certificate requests in certificate templates (smallstep/crypto#767)
34+
2835
## [0.28.3] - 2025-03-17
2936

3037
- dependabot updates
3138

32-
3339
## [0.28.2] - 2025-02-20
3440

3541
### Added

api/api.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,7 @@ func LogCertificate(w http.ResponseWriter, cert *x509.Certificate) {
552552
"serial": cert.SerialNumber.String(),
553553
"subject": cert.Subject.CommonName,
554554
"issuer": cert.Issuer.CommonName,
555+
"sans": fmtSans(cert),
555556
"valid-from": cert.NotBefore.Format(time.RFC3339),
556557
"valid-to": cert.NotAfter.Format(time.RFC3339),
557558
"public-key": fmtPublicKey(cert),
@@ -625,6 +626,31 @@ func ParseCursor(r *http.Request) (cursor string, limit int, err error) {
625626
return
626627
}
627628

629+
func fmtSans(cert *x509.Certificate) map[string][]string {
630+
sans := make(map[string][]string)
631+
if len(cert.DNSNames) > 0 {
632+
sans["dns"] = cert.DNSNames
633+
}
634+
if len(cert.EmailAddresses) > 0 {
635+
sans["email"] = cert.EmailAddresses
636+
}
637+
if size := len(cert.IPAddresses); size > 0 {
638+
ips := make([]string, size)
639+
for i, ip := range cert.IPAddresses {
640+
ips[i] = ip.String()
641+
}
642+
sans["ip"] = ips
643+
}
644+
if size := len(cert.URIs); size > 0 {
645+
uris := make([]string, size)
646+
for i, u := range cert.URIs {
647+
uris[i] = u.String()
648+
}
649+
sans["uri"] = uris
650+
}
651+
return sans
652+
}
653+
628654
func fmtPublicKey(cert *x509.Certificate) string {
629655
var params string
630656
switch pk := cert.PublicKey.(type) {

authority/meter.go

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,26 @@ package authority
22

33
import (
44
"crypto"
5+
"crypto/x509"
56
"io"
67

78
"go.step.sm/crypto/kms"
89
kmsapi "go.step.sm/crypto/kms/apiv1"
10+
"golang.org/x/crypto/ssh"
911

1012
"github.com/smallstep/certificates/authority/provisioner"
1113
)
1214

1315
// Meter wraps the set of defined callbacks for metrics gatherers.
1416
type Meter interface {
1517
// X509Signed is called whenever an X509 certificate is signed.
16-
X509Signed(provisioner.Interface, error)
18+
X509Signed([]*x509.Certificate, provisioner.Interface, error)
1719

1820
// X509Renewed is called whenever an X509 certificate is renewed.
19-
X509Renewed(provisioner.Interface, error)
21+
X509Renewed([]*x509.Certificate, provisioner.Interface, error)
2022

2123
// X509Rekeyed is called whenever an X509 certificate is rekeyed.
22-
X509Rekeyed(provisioner.Interface, error)
24+
X509Rekeyed([]*x509.Certificate, provisioner.Interface, error)
2325

2426
// X509WebhookAuthorized is called whenever an X509 authoring webhook is called.
2527
X509WebhookAuthorized(provisioner.Interface, error)
@@ -28,13 +30,13 @@ type Meter interface {
2830
X509WebhookEnriched(provisioner.Interface, error)
2931

3032
// SSHSigned is called whenever an SSH certificate is signed.
31-
SSHSigned(provisioner.Interface, error)
33+
SSHSigned(*ssh.Certificate, provisioner.Interface, error)
3234

3335
// SSHRenewed is called whenever an SSH certificate is renewed.
34-
SSHRenewed(provisioner.Interface, error)
36+
SSHRenewed(*ssh.Certificate, provisioner.Interface, error)
3537

3638
// SSHRekeyed is called whenever an SSH certificate is rekeyed.
37-
SSHRekeyed(provisioner.Interface, error)
39+
SSHRekeyed(*ssh.Certificate, provisioner.Interface, error)
3840

3941
// SSHWebhookAuthorized is called whenever an SSH authoring webhook is called.
4042
SSHWebhookAuthorized(provisioner.Interface, error)
@@ -49,17 +51,17 @@ type Meter interface {
4951
// noopMeter implements a noop [Meter].
5052
type noopMeter struct{}
5153

52-
func (noopMeter) SSHRekeyed(provisioner.Interface, error) {}
53-
func (noopMeter) SSHRenewed(provisioner.Interface, error) {}
54-
func (noopMeter) SSHSigned(provisioner.Interface, error) {}
55-
func (noopMeter) SSHWebhookAuthorized(provisioner.Interface, error) {}
56-
func (noopMeter) SSHWebhookEnriched(provisioner.Interface, error) {}
57-
func (noopMeter) X509Rekeyed(provisioner.Interface, error) {}
58-
func (noopMeter) X509Renewed(provisioner.Interface, error) {}
59-
func (noopMeter) X509Signed(provisioner.Interface, error) {}
60-
func (noopMeter) X509WebhookAuthorized(provisioner.Interface, error) {}
61-
func (noopMeter) X509WebhookEnriched(provisioner.Interface, error) {}
62-
func (noopMeter) KMSSigned(error) {}
54+
func (noopMeter) SSHRekeyed(*ssh.Certificate, provisioner.Interface, error) {}
55+
func (noopMeter) SSHRenewed(*ssh.Certificate, provisioner.Interface, error) {}
56+
func (noopMeter) SSHSigned(*ssh.Certificate, provisioner.Interface, error) {}
57+
func (noopMeter) SSHWebhookAuthorized(provisioner.Interface, error) {}
58+
func (noopMeter) SSHWebhookEnriched(provisioner.Interface, error) {}
59+
func (noopMeter) X509Rekeyed([]*x509.Certificate, provisioner.Interface, error) {}
60+
func (noopMeter) X509Renewed([]*x509.Certificate, provisioner.Interface, error) {}
61+
func (noopMeter) X509Signed([]*x509.Certificate, provisioner.Interface, error) {}
62+
func (noopMeter) X509WebhookAuthorized(provisioner.Interface, error) {}
63+
func (noopMeter) X509WebhookEnriched(provisioner.Interface, error) {}
64+
func (noopMeter) KMSSigned(error) {}
6365

6466
type instrumentedKeyManager struct {
6567
kms.KeyManager

authority/provisioner/options_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ func TestTemplateOptions(t *testing.T) {
189189

190190
func TestCustomTemplateOptions(t *testing.T) {
191191
csr := parseCertificateRequest(t, "testdata/certs/ecdsa.csr")
192-
csrCertificate := `{"version":0,"subject":{"commonName":"foo"},"rawSubject":"MA4xDDAKBgNVBAMTA2Zvbw==","dnsNames":["foo"],"emailAddresses":null,"ipAddresses":null,"uris":null,"sans":null,"extensions":[{"id":"2.5.29.17","critical":false,"value":"MAWCA2Zvbw=="}],"signatureAlgorithm":""}`
192+
csrCertificate := `{"version":0,"subject":{"commonName":"foo"},"rawSubject":"MA4xDDAKBgNVBAMTA2Zvbw==","dnsNames":["foo"],"emailAddresses":null,"ipAddresses":null,"uris":null,"sans":null,"extensions":[{"id":"2.5.29.17","critical":false,"value":"MAWCA2Zvbw=="}],"keyUsage":null,"extKeyUsage":[],"unknownExtKeyUsage":null,"basicConstraints":null,"signatureAlgorithm":""}`
193193
data := x509util.TemplateData{
194194
x509util.SubjectKey: x509util.Subject{
195195
CommonName: "foobar",

authority/ssh.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ func (a *Authority) GetSSHBastion(ctx context.Context, user, hostname string) (*
149149
// SignSSH creates a signed SSH certificate with the given public key and options.
150150
func (a *Authority) SignSSH(ctx context.Context, key ssh.PublicKey, opts provisioner.SignSSHOptions, signOpts ...provisioner.SignOption) (*ssh.Certificate, error) {
151151
cert, prov, err := a.signSSH(ctx, key, opts, signOpts...)
152-
a.meter.SSHSigned(prov, err)
152+
a.meter.SSHSigned(cert, prov, err)
153153
return cert, err
154154
}
155155

@@ -337,7 +337,7 @@ func (a *Authority) isAllowedToSignSSHCertificate(cert *ssh.Certificate) error {
337337
// RenewSSH creates a signed SSH certificate using the old SSH certificate as a template.
338338
func (a *Authority) RenewSSH(ctx context.Context, oldCert *ssh.Certificate) (*ssh.Certificate, error) {
339339
cert, prov, err := a.renewSSH(ctx, oldCert)
340-
a.meter.SSHRenewed(prov, err)
340+
a.meter.SSHRenewed(cert, prov, err)
341341
return cert, err
342342
}
343343

@@ -408,7 +408,7 @@ func (a *Authority) renewSSH(ctx context.Context, oldCert *ssh.Certificate) (*ss
408408
// RekeySSH creates a signed SSH certificate using the old SSH certificate as a template.
409409
func (a *Authority) RekeySSH(ctx context.Context, oldCert *ssh.Certificate, pub ssh.PublicKey, signOpts ...provisioner.SignOption) (*ssh.Certificate, error) {
410410
cert, prov, err := a.rekeySSH(ctx, oldCert, pub, signOpts...)
411-
a.meter.SSHRekeyed(prov, err)
411+
a.meter.SSHRekeyed(cert, prov, err)
412412
return cert, err
413413
}
414414

authority/tls.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Sign
118118
// request, taking the provided context.Context.
119119
func (a *Authority) SignWithContext(ctx context.Context, csr *x509.CertificateRequest, signOpts provisioner.SignOptions, extraOpts ...provisioner.SignOption) ([]*x509.Certificate, error) {
120120
chain, prov, err := a.signX509(ctx, csr, signOpts, extraOpts...)
121-
a.meter.X509Signed(prov, err)
121+
a.meter.X509Signed(chain, prov, err)
122122
return chain, err
123123
}
124124

@@ -372,9 +372,9 @@ func (a *Authority) Rekey(oldCert *x509.Certificate, pk crypto.PublicKey) ([]*x5
372372
func (a *Authority) RenewContext(ctx context.Context, oldCert *x509.Certificate, pk crypto.PublicKey) ([]*x509.Certificate, error) {
373373
chain, prov, err := a.renewContext(ctx, oldCert, pk)
374374
if pk == nil {
375-
a.meter.X509Renewed(prov, err)
375+
a.meter.X509Renewed(chain, prov, err)
376376
} else {
377-
a.meter.X509Rekeyed(prov, err)
377+
a.meter.X509Rekeyed(chain, prov, err)
378378
}
379379
return chain, err
380380
}

go.mod

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ require (
1717
github.com/google/go-tpm v0.9.5
1818
github.com/google/uuid v1.6.0
1919
github.com/googleapis/gax-go/v2 v2.14.2
20-
github.com/hashicorp/vault/api v1.16.0
21-
github.com/hashicorp/vault/api/auth/approle v0.9.0
22-
github.com/hashicorp/vault/api/auth/aws v0.9.0
23-
github.com/hashicorp/vault/api/auth/kubernetes v0.9.0
20+
github.com/hashicorp/vault/api v1.20.0
21+
github.com/hashicorp/vault/api/auth/approle v0.10.0
22+
github.com/hashicorp/vault/api/auth/aws v0.10.0
23+
github.com/hashicorp/vault/api/auth/kubernetes v0.10.0
2424
github.com/newrelic/go-agent/v3 v3.39.0
2525
github.com/pkg/errors v0.9.1
2626
github.com/prometheus/client_golang v1.22.0
@@ -29,35 +29,35 @@ require (
2929
github.com/slackhq/nebula v1.9.5
3030
github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262
3131
github.com/smallstep/cli-utils v0.12.1
32-
github.com/smallstep/go-attestation v0.4.4-0.20240109183208-413678f90935
32+
github.com/smallstep/go-attestation v0.4.4-0.20241119153605-2306d5b464ca
3333
github.com/smallstep/linkedca v0.23.0
3434
github.com/smallstep/nosql v0.7.0
3535
github.com/smallstep/pkcs7 v0.2.1
3636
github.com/smallstep/scep v0.0.0-20240926084937-8cf1ca453101
3737
github.com/stretchr/testify v1.10.0
3838
github.com/urfave/cli v1.22.16
39-
go.step.sm/crypto v0.63.0
39+
go.step.sm/crypto v0.66.0
4040
go.uber.org/mock v0.5.2
4141
golang.org/x/crypto v0.38.0
42-
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394
42+
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0
4343
golang.org/x/net v0.40.0
44-
google.golang.org/api v0.233.0
45-
google.golang.org/grpc v1.72.1
44+
google.golang.org/api v0.236.0
45+
google.golang.org/grpc v1.73.0
4646
google.golang.org/protobuf v1.36.6
4747
)
4848

4949
require (
5050
cloud.google.com/go v0.120.0 // indirect
5151
cloud.google.com/go/auth v0.16.1 // indirect
5252
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
53-
cloud.google.com/go/compute/metadata v0.6.0 // indirect
53+
cloud.google.com/go/compute/metadata v0.7.0 // indirect
5454
cloud.google.com/go/iam v1.5.2 // indirect
55-
cloud.google.com/go/kms v1.21.2 // indirect
55+
cloud.google.com/go/kms v1.22.0 // indirect
5656
dario.cat/mergo v1.0.1 // indirect
5757
filippo.io/edwards25519 v1.1.0 // indirect
5858
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 // indirect
5959
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 // indirect
60-
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0 // indirect
60+
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.0 // indirect
6161
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect
6262
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0 // indirect
6363
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 // indirect
@@ -118,7 +118,7 @@ require (
118118
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect
119119
github.com/hashicorp/go-sockaddr v1.0.2 // indirect
120120
github.com/hashicorp/go-uuid v1.0.2 // indirect
121-
github.com/hashicorp/hcl v1.0.0 // indirect
121+
github.com/hashicorp/hcl v1.0.1-vault-7 // indirect
122122
github.com/huandu/xstrings v1.5.0 // indirect
123123
github.com/jackc/pgpassfile v1.0.0 // indirect
124124
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
@@ -164,10 +164,10 @@ require (
164164
golang.org/x/sys v0.33.0 // indirect
165165
golang.org/x/text v0.25.0 // indirect
166166
golang.org/x/time v0.11.0 // indirect
167-
golang.org/x/tools v0.31.0 // indirect
167+
golang.org/x/tools v0.33.0 // indirect
168168
google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2 // indirect
169169
google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2 // indirect
170-
google.golang.org/genproto/googleapis/rpc v0.0.0-20250505200425-f936aa4a68b2 // indirect
170+
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect
171171
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 // indirect
172172
gopkg.in/yaml.v3 v3.0.1 // indirect
173173
)

0 commit comments

Comments
 (0)