Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,953 changes: 1,032 additions & 921 deletions api/client/proto/authservice.pb.go

Large diffs are not rendered by default.

14 changes: 12 additions & 2 deletions api/proto/teleport/legacy/client/proto/authservice.proto
Original file line number Diff line number Diff line change
Expand Up @@ -1089,7 +1089,14 @@ message DatabaseCertRequest {
Extensions CertificateExtensions = 6 [(gogoproto.jsontag) = "certificate_extensions"];

// CRLEndpoint is a certificate revocation list distribution point. Required for Windows smartcard certs.
string CRLEndpoint = 7 [(gogoproto.jsontag) = "crl_endpoint"];
// DEPRECATED: use CRLDomain instead.
string CRLEndpoint = 7 [
(gogoproto.jsontag) = "crl_endpoint",
deprecated = true
];

// CRLDomain is the Active Directory domain where CRLs are published.
string CRLDomain = 8 [(gogoproto.jsontag) = "crl_domain"];
}

// DatabaseCertResponse contains the signed certificate.
Expand Down Expand Up @@ -1682,9 +1689,12 @@ message WindowsDesktopCertRequest {
// CSR is the request to sign in PEM format.
bytes CSR = 1;
// CRLEndpoint is the address of the CRL for this certificate.
string CRLEndpoint = 2;
// DEPRECATED: use CRLDomain instead.
string CRLEndpoint = 2 [deprecated = true];
// TTL is the certificate validity period.
int64 TTL = 3 [(gogoproto.casttype) = "Duration"];
// CRLDomain is the Active Directory domain where CRLs are published.
string CRLDomain = 4;
}

// WindowsDesktopCertResponse contains the signed Windows RDP certificate.
Expand Down
13 changes: 13 additions & 0 deletions api/proto/teleport/legacy/types/events/events.proto
Original file line number Diff line number Diff line change
Expand Up @@ -3959,6 +3959,19 @@ message CertificateCreate {
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];

// CertificateAuthority holds information about the issuer of the certificate.
CertificateAuthority CertificateAuthority = 5 [(gogoproto.jsontag) = "certificate_authority"];
}

// CertificateAuthority holds information about the issuer of the certificate.
message CertificateAuthority {
// Type of the cert authority
string Type = 1 [(gogoproto.jsontag) = "type,omitempty"];
// Domain of the cert authority
string Domain = 2 [(gogoproto.jsontag) = "domain,omitempty"];
// SubjectKeyID is BASE32-encoded subject key ID from authority certificate
string SubjectKeyID = 3 [(gogoproto.jsontag) = "subject_key_id,omitempty"];
}

// RenewableCertificateGenerationMismatch is emitted when a renewable
Expand Down
2 changes: 2 additions & 0 deletions api/proto/teleport/legacy/types/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -1237,6 +1237,8 @@ message TLSKeyPair {
bytes Key = 2 [(gogoproto.jsontag) = "key,omitempty"];
// KeyType is the type of the Key.
PrivateKeyType KeyType = 3 [(gogoproto.jsontag) = "key_type,omitempty"];
// CRL is an empty DER-encoded revocation list.
bytes CRL = 4 [(gogoproto.jsontag) = "crl"];
}

// JWTKeyPair is a PEM encoded keypair used for signing JWT tokens.
Expand Down
1 change: 1 addition & 0 deletions api/types/authority.go
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,7 @@ func (k *TLSKeyPair) Clone() *TLSKeyPair {
KeyType: k.KeyType,
Key: slices.Clone(k.Key),
Cert: slices.Clone(k.Cert),
CRL: slices.Clone(k.CRL),
}
}

Expand Down
3,061 changes: 1,693 additions & 1,368 deletions api/types/events/events.pb.go

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions api/types/trust.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package types

import (
"fmt"
"slices"
"strings"
"time"

Expand Down Expand Up @@ -72,7 +73,8 @@ const (
)

// CertAuthTypes lists all certificate authority types.
var CertAuthTypes = []CertAuthType{HostCA,
var CertAuthTypes = []CertAuthType{
HostCA,
UserCA,
DatabaseCA,
DatabaseClientCA,
Expand Down Expand Up @@ -127,10 +129,8 @@ const authTypeNotSupported string = "authority type is not supported"

// Check checks if certificate authority type value is correct
func (c CertAuthType) Check() error {
for _, caType := range CertAuthTypes {
if c == caType {
return nil
}
if slices.Contains(CertAuthTypes, c) {
return nil
}

return trace.BadParameter("%q %s", c, authTypeNotSupported)
Expand Down
4,230 changes: 2,139 additions & 2,091 deletions api/types/types.pb.go

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ You will need to repeat these steps if you rotate Teleport's database certificat
$ tctl auth crl --type=db_client > db-ca.crl
```

If you use HSM, there are multiple CRLs that have to be exported.
This can be done by running:

```code
$ tctl auth crl --type=db_client --out=<file_prefix>
```

1. Transfer the `db-ca.cer` and `db-ca.crl` files to a Windows machine where you can manage your group policy.

### Create a GPO and import the Teleport CA
Expand Down Expand Up @@ -173,6 +180,12 @@ Teleport CRL to your Active Directory domain (using the path to the exported
certutil -dspublish -f <PathToCRLFile.crl> TeleportDB
```

If you use HSM, run commands printed at the end of the CRL export. They will be in the form of:

```powershell
certutil -dspublish -f <PathToCRLFile.crl> TeleportDB <CRLCommonName>
```

<Admonition type="tip">
To avoid waiting until the certificate propagates, you can force the CA
retrieval from LDAP after importing the CA and CRL with the command:
Expand Down
7 changes: 5 additions & 2 deletions integrations/event-handler/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ require (
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/sql/armsql v1.2.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/subscription/armsubscription v1.2.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect
github.com/BurntSushi/toml v1.5.0 // indirect
github.com/MakeNowJust/heredoc v1.0.0 // indirect
Expand Down Expand Up @@ -139,13 +140,15 @@ require (
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/fxamacker/cbor/v2 v2.8.0 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect
github.com/go-chi/chi v4.1.2+incompatible // indirect
github.com/go-chi/chi/v5 v5.2.1 // indirect
github.com/go-errors/errors v1.4.2 // indirect
github.com/go-gorp/gorp/v3 v3.1.0 // indirect
github.com/go-jose/go-jose/v3 v3.0.4 // indirect
github.com/go-jose/go-jose/v4 v4.0.5 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-jose/go-jose/v4 v4.1.1 // indirect
github.com/go-ldap/ldap/v3 v3.4.11 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/analysis v0.23.0 // indirect
github.com/go-openapi/errors v0.22.1 // indirect
Expand Down
10 changes: 6 additions & 4 deletions integrations/event-handler/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAu
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0=
github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30=
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7VVbI0o4wBRNQIgn917usHWOd6VAffYI=
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
Expand Down Expand Up @@ -328,13 +330,13 @@ github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs
github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw=
github.com/go-jose/go-jose/v3 v3.0.4 h1:Wp5HA7bLQcKnf6YYao/4kpRpVMp/yf6+pJKV8WFSaNY=
github.com/go-jose/go-jose/v3 v3.0.4/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
github.com/go-jose/go-jose/v4 v4.1.1 h1:JYhSgy4mXXzAdF3nUx3ygx347LRXJRrpgyU3adRmkAI=
github.com/go-jose/go-jose/v4 v4.1.1/go.mod h1:BdsZGqgdO3b6tTc6LSE56wcDbMMLuPsw5d4ZD5f94kA=
github.com/go-ldap/ldap/v3 v3.4.11 h1:4k0Yxweg+a3OyBLjdYn5OKglv18JNvfDykSoI8bW0gU=
github.com/go-ldap/ldap/v3 v3.4.11/go.mod h1:bY7t0FLK8OAVpp/vV6sSlpz3EQDGcQwc8pF0ujLgKvM=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/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-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
Expand Down
28 changes: 17 additions & 11 deletions lib/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ import (
"crypto/rand"
"crypto/subtle"
"crypto/x509"
"encoding/base32"
"encoding/pem"
"errors"
"fmt"
"io"
"log/slog"
"maps"
"math/big"
mathrand "math/rand/v2"
"net"
"os"
Expand Down Expand Up @@ -3094,7 +3094,7 @@ func (a *Server) augmentUserCertificates(
}

// Issue audit event on success, same as [Server.generateCert].
a.emitCertCreateEvent(ctx, newIdentity, notAfter)
a.emitCertCreateEvent(ctx, tlsCA, newIdentity, notAfter)

return &proto.Certs{
SSH: newAuthorizedKey,
Expand Down Expand Up @@ -3502,6 +3502,7 @@ func generateCert(ctx context.Context, a *Server, req certRequest, caType types.
}

var signedTLSCert []byte
var tlsIssuer *tlsca.CertAuthority
if req.tlsPublicKey != nil {
tlsCryptoPubKey, err := keys.ParsePublicKey(req.tlsPublicKey)
if err != nil {
Expand Down Expand Up @@ -3529,9 +3530,10 @@ func generateCert(ctx context.Context, a *Server, req certRequest, caType types.
if err != nil {
return nil, trace.Wrap(err)
}
tlsIssuer = tlsCA
}

a.emitCertCreateEvent(ctx, &identity, notAfter)
a.emitCertCreateEvent(ctx, tlsIssuer, &identity, notAfter)

// create certs struct to return to user
certs := &proto.Certs{
Expand Down Expand Up @@ -3706,9 +3708,17 @@ func (a *Server) getSigningCAs(ctx context.Context, domainName string, caType ty
return tlsCA, sshSigner, ca, nil
}

func (a *Server) emitCertCreateEvent(ctx context.Context, identity *tlsca.Identity, notAfter time.Time) {
func (a *Server) emitCertCreateEvent(ctx context.Context, issuer *tlsca.CertAuthority, identity *tlsca.Identity, notAfter time.Time) {
eventIdentity := identity.GetEventIdentity()
eventIdentity.Expires = notAfter
var certAuthority *apievents.CertificateAuthority
if issuer != nil {
certAuthority = &apievents.CertificateAuthority{
Type: string(types.UserCA),
Domain: issuer.Cert.Issuer.CommonName,
SubjectKeyID: base32.HexEncoding.EncodeToString(issuer.Cert.SubjectKeyId),
}
}
if err := a.emitter.EmitAuditEvent(a.closeCtx, &apievents.CertificateCreate{
Metadata: apievents.Metadata{
Type: events.CertificateCreateEvent,
Expand All @@ -3721,6 +3731,7 @@ func (a *Server) emitCertCreateEvent(ctx context.Context, identity *tlsca.Identi
// fetched. Need to propagate user-agent from HTTP calls.
UserAgent: trimUserAgent(metadata.UserAgentFromContext(ctx)),
},
CertificateAuthority: certAuthority,
}); err != nil {
a.logger.WarnContext(ctx, "Failed to emit certificate create event", "error", err)
}
Expand Down Expand Up @@ -6626,13 +6637,8 @@ func (a *Server) GenerateCertAuthorityCRL(ctx context.Context, caType types.Cert
if err != nil {
return nil, trace.Wrap(err)
}
// Empty CRL valid for 1yr.
template := &x509.RevocationList{
Number: big.NewInt(1),
ThisUpdate: time.Now().Add(-1 * time.Minute), // 1 min in the past to account for clock skew.
NextUpdate: time.Now().Add(365 * 24 * time.Hour),
}
crl, err := x509.CreateRevocationList(rand.Reader, template, tlsAuthority.Cert, tlsAuthority.Signer)

crl, err := keystore.GenerateCRL(tlsAuthority.Cert, tlsAuthority.Signer)
if err != nil {
return nil, trace.Wrap(err)
}
Expand Down
5 changes: 5 additions & 0 deletions lib/auth/auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2588,9 +2588,14 @@ func TestGenerateUserCertWithCertExtension(t *testing.T) {
ClientMetadata: apievents.ClientMetadata{
UserAgent: "test-user-agent/1.0",
},
CertificateAuthority: &apievents.CertificateAuthority{
Type: "user",
Domain: "test.localhost",
},
},
lastEvent.(*apievents.CertificateCreate),
cmpopts.IgnoreFields(apievents.Identity{}, "Logins", "Expires"),
cmpopts.IgnoreFields(apievents.CertificateAuthority{}, "SubjectKeyID"),
))
}

Expand Down
5 changes: 5 additions & 0 deletions lib/auth/bot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -498,10 +498,15 @@ func TestRegisterBotInstance(t *testing.T) {
BotName: "test",
BotInstanceID: ident.BotInstanceID,
},
CertificateAuthority: &events.CertificateAuthority{
Type: "user",
Domain: "localhost",
},
},
cmpopts.IgnoreFields(events.Metadata{}, "Time"),
cmpopts.IgnoreFields(events.Identity{}, "Logins", "Expires"),
cmpopts.IgnoreFields(events.ClientMetadata{}, "UserAgent"),
cmpopts.IgnoreFields(events.CertificateAuthority{}, "SubjectKeyID"),
cmpopts.EquateEmpty(),
),
)
Expand Down
19 changes: 17 additions & 2 deletions lib/auth/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import (
"github.com/gravitational/teleport/lib/modules"
"github.com/gravitational/teleport/lib/services"
"github.com/gravitational/teleport/lib/tlsca"
"github.com/gravitational/teleport/lib/winpki"
)

// GenerateDatabaseCert generates client certificate used by a database
Expand Down Expand Up @@ -155,14 +156,28 @@ func (a *Server) generateDatabaseCert(ctx context.Context, req *proto.DatabaseCe
Subject: csr.Subject,
NotAfter: a.clock.Now().UTC().Add(req.TTL.Get()),
}

if req.CertificateExtensions == proto.DatabaseCertRequest_WINDOWS_SMARTCARD {
// Pass through ExtKeyUsage (which we need for Smartcard Logon usage)
// and SubjectAltName (which we need for otherName SAN, not supported
// out of the box in crypto/x509) extensions only.
certReq.ExtraExtensions = filterExtensions(a.CloseContext(), a.logger, csr.Extensions, oidExtKeyUsage, oidSubjectAltName, oidADUserMapping)
certReq.KeyUsage = x509.KeyUsageDigitalSignature
// CRL is required for Windows smartcard certs.
certReq.CRLDistributionPoints = []string{req.CRLEndpoint}
// CRL Distribution Points (CDP) are required for Windows smartcard certs.
// The CDP is computed here by the auth server issuing the cert and not provided
// by the client because the CDP is based on the identity of the issuer, which is
// necessary in order to support clusters with multiple issuing certs (HSMs).
// If there's only 1 active key we don't include SKID in CDP for backward compatibility.
if req.CRLDomain != "" {
includeSKID := len(ca.GetActiveKeys().TLS) > 1
cdp := winpki.CRLDistributionPoint(req.CRLDomain, types.DatabaseClientCA, tlsCA, includeSKID)
certReq.CRLDistributionPoints = []string{cdp}
} else if req.CRLEndpoint != "" {
// legacy clients will specify CRL endpoint instead of CRL domain
// DELETE IN v20 (zmb3)
certReq.CRLDistributionPoints = []string{req.CRLEndpoint}
a.logger.DebugContext(ctx, "Generating Database cert with legacy CDP")
}
} else {
// Include provided server names as SANs in the certificate, CommonName
// has been deprecated since Go 1.15:
Expand Down
24 changes: 19 additions & 5 deletions lib/auth/desktop.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import (
"github.com/gravitational/teleport/lib/modules"
"github.com/gravitational/teleport/lib/tlsca"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/teleport/lib/winpki"
)

// GenerateWindowsDesktopCert generates client certificate for Windows RDP
Expand All @@ -48,6 +49,12 @@ func (a *Server) GenerateWindowsDesktopCert(ctx context.Context, req *proto.Wind
return nil, trace.AccessDenied(
"this Teleport cluster is not licensed for desktop access, please contact the cluster administrator")
}

limitExceeded, err := a.desktopsLimitExceeded(ctx)
if err != nil {
return nil, trace.Wrap(err)
}

csr, err := tlsca.ParseCertificateRequestPEM(req.CSR)
if err != nil {
return nil, trace.Wrap(err)
Expand All @@ -71,6 +78,7 @@ func (a *Server) GenerateWindowsDesktopCert(ctx context.Context, req *proto.Wind
if err != nil {
return nil, trace.Wrap(err)
}

// See https://docs.microsoft.com/en-us/troubleshoot/windows-server/windows-security/enabling-smart-card-logon-third-party-certification-authorities
// for cert requirements for Windows authn.
certReq := tlsca.CertificateRequest{
Expand All @@ -85,14 +93,20 @@ func (a *Server) GenerateWindowsDesktopCert(ctx context.Context, req *proto.Wind
// CRL Distribution Points (CDP) are required for Windows smartcard certs
// for users wanting to RDP. They are not required for the service account
// cert that Teleport itself uses to authenticate for LDAP.
if req.CRLEndpoint != "" {
//
// The CDP is computed here by the auth server issuing the cert and not provided
// by the client because the CDP is based on the identity of the issuer, which is
// necessary in order to support clusters with multiple issuing certs (HSMs).
if req.CRLDomain != "" {
cdp := winpki.CRLDistributionPoint(req.CRLDomain, types.UserCA, tlsCA, true)
certReq.CRLDistributionPoints = []string{cdp}
} else if req.CRLEndpoint != "" {
// legacy clients will specify CRL endpoint instead of CRL domain
// DELETE IN v21 (zmb3)
certReq.CRLDistributionPoints = []string{req.CRLEndpoint}
a.logger.DebugContext(ctx, "Generating Windows desktop cert with legacy CDP")
}

limitExceeded, err := a.desktopsLimitExceeded(ctx)
if err != nil {
return nil, trace.Wrap(err)
}
certReq.ExtraExtensions = append(certReq.ExtraExtensions, pkix.Extension{
Id: tlsca.LicenseOID,
Value: []byte(modules.GetModules().BuildType()),
Expand Down
Loading
Loading