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
18 changes: 10 additions & 8 deletions lib/auth/windows/certificate_authority.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,9 @@ func (c *CertificateStoreClient) Update(ctx context.Context) error {
// have to do it here.
//
// TODO(zmb3): support multiple CA certs per cluster (such as with HSMs).
caType := types.UserCA
ca, err := c.cfg.AccessPoint.GetCertAuthority(ctx, types.CertAuthID{
Type: types.UserCA,
Type: caType,
DomainName: c.cfg.ClusterName,
}, false)
if err != nil {
Expand Down Expand Up @@ -90,7 +91,7 @@ func (c *CertificateStoreClient) Update(ctx context.Context) error {
if err := c.updateCAInNTAuthStore(ctx, caDER); err != nil {
return trace.Wrap(err, "updating NTAuth store over LDAP: %v", err)
}
if err := c.updateCRL(ctx, crlDER); err != nil {
if err := c.updateCRL(ctx, crlDER, caType); err != nil {
return trace.Wrap(err, "updating CRL over LDAP: %v", err)
}
return nil
Expand Down Expand Up @@ -156,7 +157,7 @@ func (c *CertificateStoreClient) updateCAInNTAuthStore(ctx context.Context, caDE
return nil
}

func (c *CertificateStoreClient) updateCRL(ctx context.Context, crlDER []byte) error {
func (c *CertificateStoreClient) updateCRL(ctx context.Context, crlDER []byte, caType types.CertAuthType) error {
// Publish the CRL for current cluster CA. For trusted clusters, their
// respective windows_desktop_services will publish CRLs of their CAs so we
// don't have to do it here.
Expand All @@ -165,12 +166,13 @@ func (c *CertificateStoreClient) updateCRL(ctx context.Context, crlDER []byte) e
// another nested container with the CA name, I think, and then multiple
// separate CRL objects in that container.
//
// We name our parent container "Teleport" and the CRL object is named
// after the Teleport cluster name. For example, CRL for cluster "prod"
// will be placed at:
// We name our parent container based on the CA type (for example, for User
// CA, it is called "Teleport"), and the CRL object is named after the
// Teleport cluster name. So, for instance, CRL for cluster "prod" and User
// CA will be placed at:
// ... > CDP > Teleport > prod
Comment thread
gabrielcorado marked this conversation as resolved.
containerDN := crlContainerDN(c.cfg.LDAPConfig)
crlDN := crlDN(c.cfg.ClusterName, c.cfg.LDAPConfig)
containerDN := crlContainerDN(c.cfg.LDAPConfig, caType)
crlDN := crlDN(c.cfg.ClusterName, c.cfg.LDAPConfig, caType)

// Create the parent container.
if err := c.cfg.LC.CreateContainer(containerDN); err != nil {
Expand Down
22 changes: 18 additions & 4 deletions lib/auth/windows/ldap.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import (

"github.com/go-ldap/ldap/v3"
"github.com/gravitational/trace"

"github.com/gravitational/teleport/api/types"
)

// LDAPConfig contains parameters for connecting to an LDAP server.
Expand Down Expand Up @@ -276,10 +278,22 @@ func CombineLDAPFilters(filters []string) string {
return "(&" + strings.Join(filters, "") + ")"
}

func crlContainerDN(config LDAPConfig) string {
return "CN=Teleport,CN=CDP,CN=Public Key Services,CN=Services,CN=Configuration," + config.DomainDN()
func crlContainerDN(config LDAPConfig, caType types.CertAuthType) string {
return fmt.Sprintf("CN=%s,CN=CDP,CN=Public Key Services,CN=Services,CN=Configuration,%s", crlKeyName(caType), config.DomainDN())
}

func crlDN(clusterName string, config LDAPConfig, caType types.CertAuthType) string {
return "CN=" + clusterName + "," + crlContainerDN(config, caType)
}

func crlDN(clusterName string, config LDAPConfig) string {
return "CN=" + clusterName + "," + crlContainerDN(config)
// crlKeyName returns the appropriate LDAP key given the CA type.
//
// Note: UserCA must use "Teleport" to keep backwards compatibility.
func crlKeyName(caType types.CertAuthType) string {
switch caType {
case types.DatabaseCA:
return "TeleportDB"
default:
return "Teleport"
}
}
5 changes: 4 additions & 1 deletion lib/auth/windows/windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ func getCertRequest(req *GenerateCredentialsRequest) (*certRequest, error) {
// CRLs in it. Each service can also handle RDP connections for a different
// domain, with the assumption that some other windows_desktop_service
// published a CRL there.
crlDN := crlDN(req.ClusterName, req.LDAPConfig)
crlDN := crlDN(req.ClusterName, req.LDAPConfig, req.CAType)
return &certRequest{csrPEM: csrPEM, crlEndpoint: fmt.Sprintf("ldap:///%s?certificateRevocationList?base?objectClass=cRLDistributionPoint", crlDN), keyDER: keyDER}, nil
}

Expand Down Expand Up @@ -142,6 +142,9 @@ type GenerateCredentialsRequest struct {
LDAPConfig LDAPConfig
// AuthClient is the windows AuthInterface
AuthClient AuthInterface
// CAType is the certificate authority type used to generate the certificate.
// This is used to proper generate the CRL LDAP path.
CAType types.CertAuthType
}

// GenerateWindowsDesktopCredentials generates a private key / certificate pair for the given
Expand Down
20 changes: 18 additions & 2 deletions lib/auth/windows/windows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,23 +139,39 @@ func TestGenerateCredentials(t *testing.T) {

func TestCRLDN(t *testing.T) {
for _, test := range []struct {
name string
clusterName string
crlDN string
caType types.CertAuthType
}{
{
name: "test cluster name",
clusterName: "test",
crlDN: "CN=test,CN=Teleport,CN=CDP,CN=Public Key Services,CN=Services,CN=Configuration,DC=test,DC=goteleport,DC=com",
},
{
name: "full cluster name",
clusterName: "cluster.goteleport.com",
crlDN: "CN=cluster.goteleport.com,CN=Teleport,CN=CDP,CN=Public Key Services,CN=Services,CN=Configuration,DC=test,DC=goteleport,DC=com",
},
{
name: "database CA",
clusterName: "cluster.goteleport.com",
caType: types.DatabaseCA,
crlDN: "CN=cluster.goteleport.com,CN=TeleportDB,CN=CDP,CN=Public Key Services,CN=Services,CN=Configuration,DC=test,DC=goteleport,DC=com",
},
{
name: "user CA",
clusterName: "cluster.goteleport.com",
caType: types.UserCA,
crlDN: "CN=cluster.goteleport.com,CN=Teleport,CN=CDP,CN=Public Key Services,CN=Services,CN=Configuration,DC=test,DC=goteleport,DC=com",
},
} {
t.Run(test.clusterName, func(t *testing.T) {
t.Run(test.name, func(t *testing.T) {
cfg := LDAPConfig{
Domain: "test.goteleport.com",
}
require.Equal(t, test.crlDN, crlDN(test.clusterName, cfg))
require.Equal(t, test.crlDN, crlDN(test.clusterName, cfg, test.caType))
})
}
}
2 changes: 2 additions & 0 deletions lib/srv/db/sqlserver/kinit/kinit.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/jcmturner/gokrb5/v8/credentials"
"github.com/sirupsen/logrus"

"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/lib/auth/windows"
)

Expand Down Expand Up @@ -208,6 +209,7 @@ func (d *DBCertGetter) GetCertificateBytes(ctx context.Context) (*WindowsCAAndKe
}

certPEM, keyPEM, caCerts, err := windows.CertKeyPEM(ctx, &windows.GenerateCredentialsRequest{
CAType: types.DatabaseCA,
Username: d.UserName,
Domain: d.RealmName,
TTL: certTTL,
Expand Down
1 change: 1 addition & 0 deletions lib/srv/desktop/windows_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -1140,6 +1140,7 @@ func (s *WindowsService) generateUserCert(ctx context.Context, username string,
// https://docs.microsoft.com/en-us/windows/security/identity-protection/smart-cards/smart-card-certificate-requirements-and-enumeration
func (s *WindowsService) generateCredentials(ctx context.Context, username, domain string, ttl time.Duration, activeDirectorySID string) (certDER, keyDER []byte, err error) {
return windows.GenerateWindowsDesktopCredentials(ctx, &windows.GenerateCredentialsRequest{
CAType: types.UserCA,
Username: username,
Domain: domain,
TTL: ttl,
Expand Down
1 change: 1 addition & 0 deletions tool/tctl/common/auth_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ func (a *AuthCommand) generateWindowsCert(ctx context.Context, clusterAPI auth.C
}

certDER, _, err := windows.GenerateWindowsDesktopCredentials(ctx, &windows.GenerateCredentialsRequest{
CAType: types.UserCA,
Username: a.windowsUser,
Domain: a.windowsDomain,
ActiveDirectorySID: a.windowsSID,
Expand Down