Skip to content

Commit

Permalink
Add custom piv slot to cluster auth preference.
Browse files Browse the repository at this point in the history
  • Loading branch information
Joerger committed Sep 20, 2023
1 parent 98df1e6 commit 3504aa1
Show file tree
Hide file tree
Showing 8 changed files with 1,540 additions and 1,455 deletions.
2 changes: 2 additions & 0 deletions api/client/webclient/webclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,8 @@ type AuthenticationSettings struct {
Github *GithubSettings `json:"github,omitempty"`
// PrivateKeyPolicy contains the cluster-wide private key policy.
PrivateKeyPolicy keys.PrivateKeyPolicy `json:"private_key_policy"`
// PIVSlot specifies a specific PIV slot to use with hardware key support.
PIVSlot string `json:"piv_slot"`
// DeviceTrustDisabled provides a clue to Teleport clients on whether to avoid
// device authentication.
// Deprecated: Use DeviceTrust.Disabled instead.
Expand Down
3 changes: 3 additions & 0 deletions api/profile/profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ type Profile struct {

// PrivateKeyPolicy is a key policy enforced for this profile.
PrivateKeyPolicy keys.PrivateKeyPolicy `yaml:"private_key_policy"`

// PIVSlot is a specific piv slot that Teleport clients should use for hardware key support.
PIVSlot string `yaml:"piv_slot"`
}

// Copy returns a shallow copy of p, or nil if p is nil.
Expand Down
4 changes: 4 additions & 0 deletions api/proto/teleport/legacy/types/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -1818,6 +1818,10 @@ message AuthPreferenceSpecV2 {
// Okta is a set of options related to the Okta service in Teleport.
// Requires Teleport Enterprise.
OktaOptions Okta = 17 [(gogoproto.jsontag) = "okta,omitempty"];

// PIVSlot is a PIV slot that Teleport clients should use instead of the
// default based on private key policy. For example, "9a" or "9e".
string PIVSlot = 18 [(gogoproto.jsontag) = "piv_slot,omitempty"];
}

// U2F defines settings for U2F device.
Expand Down
7 changes: 7 additions & 0 deletions api/types/authentication.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ type AuthPreference interface {
GetRequireMFAType() RequireMFAType
// GetPrivateKeyPolicy returns the configured private key policy for the cluster.
GetPrivateKeyPolicy() keys.PrivateKeyPolicy
// GetPIVSlot returns the configured piv slot for the cluster.
GetPIVSlot() string

// GetDisconnectExpiredCert returns disconnect expired certificate setting
GetDisconnectExpiredCert() bool
Expand Down Expand Up @@ -392,6 +394,11 @@ func (c *AuthPreferenceV2) GetPrivateKeyPolicy() keys.PrivateKeyPolicy {
}
}

// GetPIVSlot returns the configured piv slot for the cluster.
func (c *AuthPreferenceV2) GetPIVSlot() string {
return c.Spec.PIVSlot
}

// GetDisconnectExpiredCert returns disconnect expired certificate setting
func (c *AuthPreferenceV2) GetDisconnectExpiredCert() bool {
return c.Spec.DisconnectExpiredCert.Value
Expand Down
2,960 changes: 1,505 additions & 1,455 deletions api/types/types.pb.go

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions lib/client/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,7 @@ func (c *Config) LoadProfile(ps ProfileStore, proxyAddr string) error {
c.AuthConnector = profile.AuthConnector
c.LoadAllCAs = profile.LoadAllCAs
c.PrivateKeyPolicy = profile.PrivateKeyPolicy
c.PIVSlot = profile.PIVSlot
c.AuthenticatorAttachment, err = parseMFAMode(profile.MFAMode)
if err != nil {
return trace.BadParameter("unable to parse mfa mode in user profile: %v.", err)
Expand Down Expand Up @@ -752,6 +753,7 @@ func (c *Config) Profile() *profile.Profile {
MFAMode: c.AuthenticatorAttachment.String(),
LoadAllCAs: c.LoadAllCAs,
PrivateKeyPolicy: c.PrivateKeyPolicy,
PIVSlot: c.PIVSlot,
}
}

Expand Down Expand Up @@ -4451,6 +4453,7 @@ func (tc *TeleportClient) applyProxySettings(proxySettings webclient.ProxySettin
// authentication settings, overriding existing fields in tc.
func (tc *TeleportClient) applyAuthSettings(authSettings webclient.AuthenticationSettings) {
tc.LoadAllCAs = authSettings.LoadAllCAs
tc.PIVSlot = authSettings.PIVSlot

// Update the private key policy from auth settings if it is stricter than the saved setting.
if authSettings.PrivateKeyPolicy != "" && authSettings.PrivateKeyPolicy.VerifyPolicy(tc.PrivateKeyPolicy) != nil {
Expand Down
12 changes: 12 additions & 0 deletions lib/config/fileconf.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import (
"github.com/gravitational/teleport/api/types/installers"
apiutils "github.com/gravitational/teleport/api/utils"
awsapiutils "github.com/gravitational/teleport/api/utils/aws"
"github.com/gravitational/teleport/api/utils/keys"
"github.com/gravitational/teleport/api/utils/tlsutils"
"github.com/gravitational/teleport/lib/backend"
"github.com/gravitational/teleport/lib/client"
Expand Down Expand Up @@ -1287,6 +1288,10 @@ type AuthenticationConfig struct {

// DefaultSessionTTL is the default cluster max session ttl
DefaultSessionTTL types.Duration `yaml:"default_session_ttl"`

// PIVSlot is a PIV slot that Teleport clients should use instead of the
// default based on private key policy. For example, "9a" or "9e".
PIVSlot string `yaml:"piv_slot,omitempty"`
}

// Parse returns valid types.AuthPreference instance.
Expand Down Expand Up @@ -1317,6 +1322,12 @@ func (a *AuthenticationConfig) Parse() (types.AuthPreference, error) {
}
}

if a.PIVSlot != "" {
if err = keys.ValidatePIVSlotKey(a.PIVSlot); err != nil {
return nil, trace.Wrap(err, "failed to parse piv_slot")
}
}

return types.NewAuthPreferenceFromConfigFile(types.AuthPreferenceSpecV2{
Type: a.Type,
SecondFactor: a.SecondFactor,
Expand All @@ -1330,6 +1341,7 @@ func (a *AuthenticationConfig) Parse() (types.AuthPreference, error) {
AllowHeadless: a.Headless,
DeviceTrust: dt,
DefaultSessionTTL: a.DefaultSessionTTL,
PIVSlot: a.PIVSlot,
})
}

Expand Down
4 changes: 4 additions & 0 deletions lib/web/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -1003,6 +1003,7 @@ func localSettings(cap types.AuthPreference) (webclient.AuthenticationSettings,
AllowHeadless: cap.GetAllowHeadless(),
Local: &webclient.LocalSettings{},
PrivateKeyPolicy: cap.GetPrivateKeyPolicy(),
PIVSlot: cap.GetPIVSlot(),
DeviceTrustDisabled: deviceTrustDisabled(cap),
DeviceTrust: deviceTrustSettings(cap),
}
Expand Down Expand Up @@ -1044,6 +1045,7 @@ func oidcSettings(connector types.OIDCConnector, cap types.AuthPreference) webcl
SecondFactor: cap.GetSecondFactor(),
PreferredLocalMFA: cap.GetPreferredLocalMFA(),
PrivateKeyPolicy: cap.GetPrivateKeyPolicy(),
PIVSlot: cap.GetPIVSlot(),
DeviceTrustDisabled: deviceTrustDisabled(cap),
DeviceTrust: deviceTrustSettings(cap),
}
Expand All @@ -1060,6 +1062,7 @@ func samlSettings(connector types.SAMLConnector, cap types.AuthPreference) webcl
SecondFactor: cap.GetSecondFactor(),
PreferredLocalMFA: cap.GetPreferredLocalMFA(),
PrivateKeyPolicy: cap.GetPrivateKeyPolicy(),
PIVSlot: cap.GetPIVSlot(),
DeviceTrustDisabled: deviceTrustDisabled(cap),
DeviceTrust: deviceTrustSettings(cap),
}
Expand All @@ -1076,6 +1079,7 @@ func githubSettings(connector types.GithubConnector, cap types.AuthPreference) w
SecondFactor: cap.GetSecondFactor(),
PreferredLocalMFA: cap.GetPreferredLocalMFA(),
PrivateKeyPolicy: cap.GetPrivateKeyPolicy(),
PIVSlot: cap.GetPIVSlot(),
DeviceTrustDisabled: deviceTrustDisabled(cap),
DeviceTrust: deviceTrustSettings(cap),
}
Expand Down

0 comments on commit 3504aa1

Please sign in to comment.