Skip to content

Commit

Permalink
set default algorithm suite when other auth pref fields are set
Browse files Browse the repository at this point in the history
  • Loading branch information
nklaassen committed Oct 22, 2024
1 parent 3672bc6 commit ef6da39
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 71 deletions.
3 changes: 3 additions & 0 deletions api/types/authentication.go
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,9 @@ type SignatureAlgorithmSuiteParams struct {
// brand new cluster or after resetting the auth preference.
func (c *AuthPreferenceV2) SetDefaultSignatureAlgorithmSuite(params SignatureAlgorithmSuiteParams) {
switch {
case c.Spec.SignatureAlgorithmSuite != SignatureAlgorithmSuite_SIGNATURE_ALGORITHM_SUITE_UNSPECIFIED && c.Metadata.Labels[OriginLabel] != OriginDefaults:
// If the suite is set and it's not a default value, return.
return
case params.FIPS:
c.SetSignatureAlgorithmSuite(SignatureAlgorithmSuite_SIGNATURE_ALGORITHM_SUITE_FIPS_V1)
case params.UsingHSMOrKMS || params.Cloud:
Expand Down
15 changes: 7 additions & 8 deletions lib/auth/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -791,14 +791,13 @@ func initializeAuthPreference(ctx context.Context, asrv *Server, newAuthPref typ
if storedAuthPref == nil {
log.Infof("Creating cluster auth preference: %v.", newAuthPref)

if newAuthPref.Origin() == types.OriginDefaults {
// Set a default signature algorithm suite for a new cluster.
newAuthPref.SetDefaultSignatureAlgorithmSuite(types.SignatureAlgorithmSuiteParams{
FIPS: asrv.fips,
UsingHSMOrKMS: asrv.keyStore.UsingHSMOrKMS(),
Cloud: modules.GetModules().Features().Cloud,
})
}
// Set a default signature algorithm suite for a new cluster.
newAuthPref = newAuthPref.Clone()
newAuthPref.SetDefaultSignatureAlgorithmSuite(types.SignatureAlgorithmSuiteParams{
FIPS: asrv.fips,
UsingHSMOrKMS: asrv.keyStore.UsingHSMOrKMS(),
Cloud: modules.GetModules().Features().Cloud,
})

_, err := asrv.CreateAuthPreference(ctx, newAuthPref)
if trace.IsAlreadyExists(err) {
Expand Down
144 changes: 81 additions & 63 deletions lib/auth/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,17 @@ func TestBadIdentity(t *testing.T) {
func TestSignatureAlgorithmSuite(t *testing.T) {
ctx := context.Background()

suiteName := func(suite types.SignatureAlgorithmSuite) string {
suiteName, err := suite.MarshalText()
require.NoError(t, err)
return string(suiteName)
}

assertSuitesEqual := func(t *testing.T, expected, actual types.SignatureAlgorithmSuite) {
t.Helper()
assert.Equal(t, suiteName(expected), suiteName(actual))
}

modules.SetTestModules(t, &modules.TestModules{
TestFeatures: modules.Features{
Entitlements: map[entitlements.EntitlementKind]modules.EntitlementInfo{
Expand All @@ -181,12 +192,16 @@ func TestSignatureAlgorithmSuite(t *testing.T) {
},
})

setupInitConfig := func(t *testing.T, fips, hsm bool) InitConfig {
setupInitConfig := func(t *testing.T, capOrigin string, fips, hsm bool) InitConfig {
cfg := setupConfig(t)
cfg.FIPS = fips
if hsm {
cfg.KeyStoreConfig = keystore.HSMTestConfig(t)
}
cfg.AuthPreference.SetOrigin(capOrigin)
if capOrigin != types.OriginDefaults {
cfg.AuthPreference.SetSignatureAlgorithmSuite(types.SignatureAlgorithmSuite_SIGNATURE_ALGORITHM_SUITE_UNSPECIFIED)
}
// Pre-generate all CAs to keep tests fast esp. with SoftHSM.
for _, caType := range types.CertAuthTypes {
cfg.BootstrapResources = append(cfg.BootstrapResources, suite.NewTestCAWithConfig(suite.TestCAConfig{
Expand Down Expand Up @@ -245,73 +260,76 @@ func TestSignatureAlgorithmSuite(t *testing.T) {
// suite should never overwrite a persisted signature algorithm suite for an
// existing cluster, even if that was also a default.
t.Run("init", func(t *testing.T) {
for desc, tc := range testCases {
t.Run(desc, func(t *testing.T) {
if tc.cloud {
modules.SetTestModules(t, &modules.TestModules{
TestFeatures: modules.Features{
Cloud: true,
Entitlements: map[entitlements.EntitlementKind]modules.EntitlementInfo{
entitlements.HSM: {Enabled: true},
},
},
for _, origin := range []string{types.OriginDefaults, types.OriginConfigFile} {
t.Run(origin, func(t *testing.T) {
for desc, tc := range testCases {
t.Run(desc, func(t *testing.T) {
if tc.cloud {
modules.SetTestModules(t, &modules.TestModules{
TestFeatures: modules.Features{
Cloud: true,
Entitlements: map[entitlements.EntitlementKind]modules.EntitlementInfo{
entitlements.HSM: {Enabled: true},
},
},
})
}

// Assert that a fresh cluster with no signature_algorithm_suite
// configured gets the expected default suite, whether
// or not anything else in the cluster auth preference is set.
cfg := setupInitConfig(t, origin, tc.fips, tc.hsm)
authServer, err := Init(ctx, cfg)
require.NoError(t, err)
t.Cleanup(func() { authServer.Close() })
authPref, err := authServer.GetAuthPreference(ctx)
require.NoError(t, err)
assert.Equal(t, origin, authPref.GetMetadata().Labels[types.OriginLabel])
assertSuitesEqual(t, tc.expectDefaultSuite, authPref.GetSignatureAlgorithmSuite())

// In the stored cluster_auth_preference, reset the
// signature_algorithm_suite to unspecified (still with
// the same origin) to mimic an older cluster with the old
// defaults, in the next step it will be "upgraded".
authPref.SetSignatureAlgorithmSuite(types.SignatureAlgorithmSuite_SIGNATURE_ALGORITHM_SUITE_UNSPECIFIED)
_, err = authServer.UpsertAuthPreference(ctx, authPref)
require.NoError(t, err)
authPref, err = authServer.GetAuthPreference(ctx)
require.NoError(t, err)
// Sanity check it persisted.
assert.Equal(t, origin, authPref.GetMetadata().Labels[types.OriginLabel])
assertSuitesEqual(t, types.SignatureAlgorithmSuite_SIGNATURE_ALGORITHM_SUITE_UNSPECIFIED, authPref.GetSignatureAlgorithmSuite())

// Start a second brand new auth server sharing the same
// backend and config. The new auth starting up should
// apply the new default auth preference and persist it
// to the backend, but it should not modify the existing
// signature algorithm suite even though it's
// unspecified. This is meant to test that a v16 auth
// server upgraded to v17 will still have an unspecified
// signature algorithm suite and won't get a new one
// until explicitly opting in.
authServer, err = Init(ctx, cfg)
require.NoError(t, err)
t.Cleanup(func() { authServer.Close() })
authPref, err = authServer.GetAuthPreference(ctx)
require.NoError(t, err)
assert.Equal(t, origin, authPref.GetMetadata().Labels[types.OriginLabel])
assertSuitesEqual(t, types.SignatureAlgorithmSuite_SIGNATURE_ALGORITHM_SUITE_UNSPECIFIED, authPref.GetSignatureAlgorithmSuite())

// Assert that the selected algorithm is RSA2048 when the suite is
// unspecified.
alg, err := cryptosuites.AlgorithmForKey(ctx,
cryptosuites.GetCurrentSuiteFromAuthPreference(authServer),
cryptosuites.UserTLS)
require.NoError(t, err)
assert.Equal(t, cryptosuites.RSA2048.String(), alg.String())
})
}
// Assert that a fresh cluster gets expected default suite.
cfg := setupInitConfig(t, tc.fips, tc.hsm)
authServer, err := Init(ctx, cfg)
require.NoError(t, err)
t.Cleanup(func() { authServer.Close() })
authPref, err := authServer.GetAuthPreference(ctx)
require.NoError(t, err)
assert.Equal(t, types.OriginDefaults, authPref.GetMetadata().Labels[types.OriginLabel])
assert.Equal(t, tc.expectDefaultSuite, authPref.GetSignatureAlgorithmSuite())

// Reset to unspecified suite and persist (still with
// OriginDefaults) to mimic an older cluster with the old defaults
// that later gets upgraded.
authPref.SetSignatureAlgorithmSuite(types.SignatureAlgorithmSuite_SIGNATURE_ALGORITHM_SUITE_UNSPECIFIED)
_, err = authServer.UpsertAuthPreference(ctx, authPref)
require.NoError(t, err)
authPref, err = authServer.GetAuthPreference(ctx)
require.NoError(t, err)
// Sanity check it persisted as a default.
assert.Equal(t, types.OriginDefaults, authPref.GetMetadata().Labels[types.OriginLabel])
assert.Equal(t, types.SignatureAlgorithmSuite_SIGNATURE_ALGORITHM_SUITE_UNSPECIFIED, authPref.GetSignatureAlgorithmSuite())

// Start a second brand new auth server sharing the same config and
// backend. The new auth starting up would apply the new default
// auth preference and persist it to the backend, but it should not
// modify the existing signature algorithm suite even though it's
// unspecified. This is meant to test that a v16 auth server
// upgraded to v17 will still have an unspecified signature
// algorithm suite and won't get a new one until explicitly opting
// in.
authServer, err = Init(ctx, cfg)
require.NoError(t, err)
t.Cleanup(func() { authServer.Close() })
authPref, err = authServer.GetAuthPreference(ctx)
require.NoError(t, err)
assert.Equal(t, types.OriginDefaults, authPref.GetMetadata().Labels[types.OriginLabel])
assert.Equal(t, types.SignatureAlgorithmSuite_SIGNATURE_ALGORITHM_SUITE_UNSPECIFIED, authPref.GetSignatureAlgorithmSuite())

// Assert that the selected algorithm is RSA2048 when the suite is
// unspecified.
alg, err := cryptosuites.AlgorithmForKey(ctx,
cryptosuites.GetCurrentSuiteFromAuthPreference(authServer),
cryptosuites.UserTLS)
require.NoError(t, err)
require.Equal(t, cryptosuites.RSA2048, alg)
})
}
})

suiteName := func(suite types.SignatureAlgorithmSuite) string {
suiteName, err := suite.MarshalText()
require.NoError(t, err)
return string(suiteName)
}

// Test that the auth preference cannot be upserted with a signature
// algorithm suite incompatible with the cluster FIPS and HSM settings.
t.Run("upsert", func(t *testing.T) {
Expand Down Expand Up @@ -371,7 +389,7 @@ func TestSignatureAlgorithmSuite(t *testing.T) {
authPref, err = clt.GetAuthPreference(ctx)
require.NoError(t, err)
assert.Equal(t, types.OriginDefaults, authPref.GetMetadata().Labels[types.OriginLabel])
assert.Equal(t, tc.expectDefaultSuite, authPref.GetSignatureAlgorithmSuite())
assertSuitesEqual(t, tc.expectDefaultSuite, authPref.GetSignatureAlgorithmSuite())
})
}
})
Expand Down

0 comments on commit ef6da39

Please sign in to comment.