Skip to content

Commit

Permalink
Use CA signing alg from config file on manual rotation
Browse files Browse the repository at this point in the history
This allows users to manually switch to a different algorithm by:
- setting the config file field
- running "tctl auth rotate"

If config file field is not set, existing signing algorithm of the CA is
preserved.
  • Loading branch information
Andrew Lytvynov authored and awly committed Jun 24, 2020
1 parent 6746213 commit d7dc416
Show file tree
Hide file tree
Showing 16 changed files with 91 additions and 44 deletions.
20 changes: 17 additions & 3 deletions integration/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ func NewInstance(cfg InstanceConfig) *TeleInstance {

cert, err := keygen.GenerateHostCert(services.HostCertParams{
PrivateCASigningKey: cfg.Priv,
CASigningAlg: ssh.SigAlgoRSASHA2512,
CASigningAlg: defaults.CASignatureAlgorithm,
PublicHostKey: cfg.Pub,
HostID: cfg.HostID,
NodeName: cfg.NodeName,
Expand Down Expand Up @@ -256,11 +256,25 @@ func (s *InstanceSecrets) GetRoles() []services.Role {
// case we always return hard-coded userCA + hostCA (and they share keys
// for simplicity)
func (s *InstanceSecrets) GetCAs() []services.CertAuthority {
hostCA := services.NewCertAuthority(services.HostCA, s.SiteName, [][]byte{s.PrivKey}, [][]byte{s.PubKey}, []string{})
hostCA := services.NewCertAuthority(
services.HostCA,
s.SiteName,
[][]byte{s.PrivKey},
[][]byte{s.PubKey},
[]string{},
services.CertAuthoritySpecV2_RSA_SHA2_512,
)
hostCA.SetTLSKeyPairs([]services.TLSKeyPair{{Cert: s.TLSCACert, Key: s.PrivKey}})
return []services.CertAuthority{
hostCA,
services.NewCertAuthority(services.UserCA, s.SiteName, [][]byte{s.PrivKey}, [][]byte{s.PubKey}, []string{services.RoleNameForCertAuthority(s.SiteName)}),
services.NewCertAuthority(
services.UserCA,
s.SiteName,
[][]byte{s.PrivKey},
[][]byte{s.PubKey},
[]string{services.RoleNameForCertAuthority(s.SiteName)},
services.CertAuthoritySpecV2_RSA_SHA2_512,
),
}
}

Expand Down
3 changes: 3 additions & 0 deletions lib/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@ type AuthServer struct {
// cipherSuites is a list of ciphersuites that the auth server supports.
cipherSuites []uint16

// caSigningAlg is an SSH signing algorithm to use when generating new CAs.
caSigningAlg *string

// cache is a fast cache that allows auth server
// to use cache for most frequent operations,
// if not set, cache uses itself
Expand Down
15 changes: 12 additions & 3 deletions lib/auth/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ type InitConfig struct {
// CASigningAlg is a signing algorithm used for SSH (certificate and
// handshake) signatures for both host and user CAs. This option only
// affects newly-created CAs.
CASigningAlg string
CASigningAlg *string
}

// Init instantiates and configures an instance of AuthServer
Expand Down Expand Up @@ -320,6 +320,10 @@ func Init(cfg InitConfig, opts ...AuthServerOption) (*AuthServer, error) {
if err != nil {
return nil, trace.Wrap(err)
}
sigAlg := defaults.CASignatureAlgorithm
if cfg.CASigningAlg != nil {
sigAlg = *cfg.CASigningAlg
}

userCA := &services.CertAuthorityV2{
Kind: services.KindCertAuthority,
Expand All @@ -332,7 +336,7 @@ func Init(cfg InitConfig, opts ...AuthServerOption) (*AuthServer, error) {
ClusterName: cfg.ClusterName.GetClusterName(),
Type: services.UserCA,
SigningKeys: [][]byte{priv},
SigningAlg: services.ParseSigningAlg(cfg.CASigningAlg),
SigningAlg: services.ParseSigningAlg(sigAlg),
CheckingKeys: [][]byte{pub},
TLSKeyPairs: []services.TLSKeyPair{{Cert: certPEM, Key: keyPEM}},
},
Expand Down Expand Up @@ -376,6 +380,11 @@ func Init(cfg InitConfig, opts ...AuthServerOption) (*AuthServer, error) {
if err != nil {
return nil, trace.Wrap(err)
}
sigAlg := defaults.CASignatureAlgorithm
if cfg.CASigningAlg != nil {
sigAlg = *cfg.CASigningAlg
}

hostCA = &services.CertAuthorityV2{
Kind: services.KindCertAuthority,
Version: services.V2,
Expand All @@ -387,7 +396,7 @@ func Init(cfg InitConfig, opts ...AuthServerOption) (*AuthServer, error) {
ClusterName: cfg.ClusterName.GetClusterName(),
Type: services.HostCA,
SigningKeys: [][]byte{priv},
SigningAlg: services.ParseSigningAlg(cfg.CASigningAlg),
SigningAlg: services.ParseSigningAlg(sigAlg),
CheckingKeys: [][]byte{pub},
TLSKeyPairs: []services.TLSKeyPair{{Cert: certPEM, Key: keyPEM}},
},
Expand Down
11 changes: 6 additions & 5 deletions lib/auth/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/gravitational/teleport/lib/auth/testauthority"
"github.com/gravitational/teleport/lib/backend"
"github.com/gravitational/teleport/lib/backend/lite"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/services"
"github.com/gravitational/teleport/lib/utils"

Expand Down Expand Up @@ -72,7 +73,7 @@ func (s *AuthInitSuite) TestReadIdentity(c *C) {

cert, err := t.GenerateHostCert(services.HostCertParams{
PrivateCASigningKey: priv,
CASigningAlg: ssh.SigAlgoRSASHA2512,
CASigningAlg: defaults.CASignatureAlgorithm,
PublicHostKey: pub,
HostID: "id1",
NodeName: "node-name",
Expand All @@ -94,7 +95,7 @@ func (s *AuthInitSuite) TestReadIdentity(c *C) {
expiryDate := time.Now().Add(ttl)
bytes, err := t.GenerateHostCert(services.HostCertParams{
PrivateCASigningKey: priv,
CASigningAlg: ssh.SigAlgoRSASHA2512,
CASigningAlg: defaults.CASignatureAlgorithm,
PublicHostKey: pub,
HostID: "id1",
NodeName: "node-name",
Expand Down Expand Up @@ -122,7 +123,7 @@ func (s *AuthInitSuite) TestBadIdentity(c *C) {
// missing authority domain
cert, err := t.GenerateHostCert(services.HostCertParams{
PrivateCASigningKey: priv,
CASigningAlg: ssh.SigAlgoRSASHA2512,
CASigningAlg: defaults.CASignatureAlgorithm,
PublicHostKey: pub,
HostID: "id2",
NodeName: "",
Expand All @@ -138,7 +139,7 @@ func (s *AuthInitSuite) TestBadIdentity(c *C) {
// missing host uuid
cert, err = t.GenerateHostCert(services.HostCertParams{
PrivateCASigningKey: priv,
CASigningAlg: ssh.SigAlgoRSASHA2512,
CASigningAlg: defaults.CASignatureAlgorithm,
PublicHostKey: pub,
HostID: "example.com",
NodeName: "",
Expand All @@ -154,7 +155,7 @@ func (s *AuthInitSuite) TestBadIdentity(c *C) {
// unrecognized role
cert, err = t.GenerateHostCert(services.HostCertParams{
PrivateCASigningKey: priv,
CASigningAlg: ssh.SigAlgoRSASHA2512,
CASigningAlg: defaults.CASignatureAlgorithm,
PublicHostKey: pub,
HostID: "example.com",
NodeName: "",
Expand Down
7 changes: 4 additions & 3 deletions lib/auth/native/native_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (

"github.com/gravitational/teleport"
"github.com/gravitational/teleport/lib/auth/test"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/services"
"github.com/gravitational/teleport/lib/utils"

Expand Down Expand Up @@ -171,7 +172,7 @@ func (s *NativeSuite) TestBuildPrincipals(c *check.C) {
hostCertificateBytes, err := s.suite.A.GenerateHostCert(
services.HostCertParams{
PrivateCASigningKey: caPrivateKey,
CASigningAlg: ssh.SigAlgoRSASHA2512,
CASigningAlg: defaults.CASignatureAlgorithm,
PublicHostKey: hostPublicKey,
HostID: tt.inHostID,
NodeName: tt.inNodeName,
Expand Down Expand Up @@ -219,7 +220,7 @@ func (s *NativeSuite) TestUserCertCompatibility(c *check.C) {

userCertificateBytes, err := s.suite.A.GenerateUserCert(services.UserCertParams{
PrivateCASigningKey: priv,
CASigningAlg: ssh.SigAlgoRSASHA2512,
CASigningAlg: defaults.CASignatureAlgorithm,
PublicUserKey: pub,
Username: "user",
AllowedLogins: []string{"centos", "root"},
Expand All @@ -237,7 +238,7 @@ func (s *NativeSuite) TestUserCertCompatibility(c *check.C) {
userCertificate, ok := publicKey.(*ssh.Certificate)
c.Assert(ok, check.Equals, true, comment)
// Check that the signature algorithm is correct.
c.Assert(userCertificate.Signature.Format, check.Equals, ssh.SigAlgoRSASHA2512)
c.Assert(userCertificate.Signature.Format, check.Equals, defaults.CASignatureAlgorithm)
// check if we added the roles extension
_, ok = userCertificate.Extensions[teleport.CertExtensionTeleportRoles]
c.Assert(ok, check.Equals, tt.outHasRoles, comment)
Expand Down
20 changes: 13 additions & 7 deletions lib/auth/rotate.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ type rotationReq struct {
// privateKey is passed by tests to supply private key for cert authorities
// instead of generating them on each iteration
privateKey []byte
// caSigningAlg is an SSH signing algorithm to use with the new CA.
caSigningAlg *string
}

// RotateCertAuthority starts or restarts certificate authority rotation process.
Expand Down Expand Up @@ -214,13 +216,14 @@ func (a *AuthServer) RotateCertAuthority(req RotateRequest) error {
return trace.Wrap(err)
}
rotated, err := processRotationRequest(rotationReq{
ca: existing,
clock: a.clock,
targetPhase: req.TargetPhase,
schedule: *req.Schedule,
gracePeriod: *req.GracePeriod,
mode: req.Mode,
privateKey: a.privateKey,
ca: existing,
clock: a.clock,
targetPhase: req.TargetPhase,
schedule: *req.Schedule,
gracePeriod: *req.GracePeriod,
mode: req.Mode,
privateKey: a.privateKey,
caSigningAlg: a.caSigningAlg,
})
if err != nil {
return trace.Wrap(err)
Expand Down Expand Up @@ -546,6 +549,9 @@ func startNewRotation(req rotationReq, ca services.CertAuthority) error {
}
ca.SetTLSKeyPairs(keyPairs)
ca.SetRotation(rotation)
if req.caSigningAlg != nil {
ca.SetSigningAlg(*req.caSigningAlg)
}
return nil
}

Expand Down
13 changes: 7 additions & 6 deletions lib/auth/test/suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"time"

"github.com/gravitational/teleport"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/services"
"github.com/gravitational/teleport/lib/sshca"

Expand Down Expand Up @@ -64,7 +65,7 @@ func (s *AuthSuite) GenerateHostCert(c *check.C) {
cert, err := s.A.GenerateHostCert(
services.HostCertParams{
PrivateCASigningKey: priv,
CASigningAlg: ssh.SigAlgoRSASHA2512,
CASigningAlg: defaults.CASignatureAlgorithm,
PublicHostKey: pub,
HostID: "00000000-0000-0000-0000-000000000000",
NodeName: "auth.example.com",
Expand Down Expand Up @@ -95,7 +96,7 @@ func (s *AuthSuite) GenerateUserCert(c *check.C) {

cert, err := s.A.GenerateUserCert(services.UserCertParams{
PrivateCASigningKey: priv,
CASigningAlg: ssh.SigAlgoRSASHA2512,
CASigningAlg: defaults.CASignatureAlgorithm,
PublicUserKey: pub,
Username: "user",
AllowedLogins: []string{"centos", "root"},
Expand Down Expand Up @@ -125,7 +126,7 @@ func (s *AuthSuite) GenerateUserCert(c *check.C) {

_, err = s.A.GenerateUserCert(services.UserCertParams{
PrivateCASigningKey: priv,
CASigningAlg: ssh.SigAlgoRSASHA2512,
CASigningAlg: defaults.CASignatureAlgorithm,
PublicUserKey: pub,
Username: "user",
AllowedLogins: []string{"root"},
Expand All @@ -138,7 +139,7 @@ func (s *AuthSuite) GenerateUserCert(c *check.C) {

_, err = s.A.GenerateUserCert(services.UserCertParams{
PrivateCASigningKey: priv,
CASigningAlg: ssh.SigAlgoRSASHA2512,
CASigningAlg: defaults.CASignatureAlgorithm,
PublicUserKey: pub,
Username: "user",
AllowedLogins: []string{"root"},
Expand All @@ -151,7 +152,7 @@ func (s *AuthSuite) GenerateUserCert(c *check.C) {

_, err = s.A.GenerateUserCert(services.UserCertParams{
PrivateCASigningKey: priv,
CASigningAlg: ssh.SigAlgoRSASHA2512,
CASigningAlg: defaults.CASignatureAlgorithm,
PublicUserKey: pub,
Username: "user",
AllowedLogins: []string{"root"},
Expand All @@ -165,7 +166,7 @@ func (s *AuthSuite) GenerateUserCert(c *check.C) {
inRoles := []string{"role-1", "role-2"}
cert, err = s.A.GenerateUserCert(services.UserCertParams{
PrivateCASigningKey: priv,
CASigningAlg: ssh.SigAlgoRSASHA2512,
CASigningAlg: defaults.CASignatureAlgorithm,
PublicUserKey: pub,
Username: "user",
AllowedLogins: []string{"root"},
Expand Down
5 changes: 3 additions & 2 deletions lib/client/keyagent_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (

"github.com/gravitational/teleport"
"github.com/gravitational/teleport/lib/auth/testauthority"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/fixtures"
"github.com/gravitational/teleport/lib/services"
"github.com/gravitational/teleport/lib/sshutils"
Expand Down Expand Up @@ -239,7 +240,7 @@ func (s *KeyAgentTestSuite) TestHostCertVerification(c *check.C) {
c.Assert(err, check.IsNil)
hostCertBytes, err := keygen.GenerateHostCert(services.HostCertParams{
PrivateCASigningKey: caPriv,
CASigningAlg: ssh.SigAlgoRSASHA2512,
CASigningAlg: defaults.CASignatureAlgorithm,
PublicHostKey: hostPub,
HostID: "5ff40d80-9007-4f28-8f49-7d4fda2f574d",
NodeName: "server01",
Expand Down Expand Up @@ -430,7 +431,7 @@ func (s *KeyAgentTestSuite) makeKey(username string, allowedLogins []string, ttl

certificate, err := keygen.GenerateUserCert(services.UserCertParams{
PrivateCASigningKey: pemBytes,
CASigningAlg: ssh.SigAlgoRSASHA2512,
CASigningAlg: defaults.CASignatureAlgorithm,
PublicUserKey: publicKey,
Username: username,
AllowedLogins: allowedLogins,
Expand Down
2 changes: 1 addition & 1 deletion lib/client/keystore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ func (s *KeyStoreTestSuite) makeSignedKey(c *check.C, makeExpired bool) *Key {

cert, err = s.keygen.GenerateUserCert(services.UserCertParams{
PrivateCASigningKey: CAPriv,
CASigningAlg: ssh.SigAlgoRSASHA2512,
CASigningAlg: defaults.CASignatureAlgorithm,
PublicUserKey: pub,
Username: username,
AllowedLogins: allowedLogins,
Expand Down
2 changes: 1 addition & 1 deletion lib/config/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ func ApplyFileConfig(fc *FileConfig, cfg *service.Config) error {
if fc.MACAlgorithms != nil {
cfg.MACAlgorithms = fc.MACAlgorithms
}
if fc.CASignatureAlgorithm != "" {
if fc.CASignatureAlgorithm != nil {
cfg.CASignatureAlgorithm = fc.CASignatureAlgorithm
}

Expand Down
6 changes: 3 additions & 3 deletions lib/config/fileconf.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,8 +349,8 @@ func (conf *FileConfig) Check() error {
return trace.BadParameter("MAC algorithm %q is not supported; supported algorithms: %q", m, sc.MACs)
}
}
if conf.CASignatureAlgorithm != "" && !utils.SliceContainsStr(validCASigAlgos, conf.CASignatureAlgorithm) {
return trace.BadParameter("CA signature algorithm %q is not supported; supported algorithms: %q", conf.CASignatureAlgorithm, validCASigAlgos)
if conf.CASignatureAlgorithm != nil && !utils.SliceContainsStr(validCASigAlgos, *conf.CASignatureAlgorithm) {
return trace.BadParameter("CA signature algorithm %q is not supported; supported algorithms: %q", *conf.CASignatureAlgorithm, validCASigAlgos)
}

return nil
Expand Down Expand Up @@ -412,7 +412,7 @@ type Global struct {
// CASignatureAlgorithm is an SSH Certificate Authority (CA) signature
// algorithm that the server uses for signing user and host certificates.
// If omitted, the default will be used.
CASignatureAlgorithm string `yaml:"ca_signature_algo,omitempty"`
CASignatureAlgorithm *string `yaml:"ca_signature_algo,omitempty"`

// CAPin is the SKPI hash of the CA used to verify the Auth Server.
CAPin string `yaml:"ca_pin"`
Expand Down
5 changes: 5 additions & 0 deletions lib/defaults/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/gravitational/teleport"
"github.com/gravitational/teleport/lib/limiter"
"github.com/gravitational/teleport/lib/utils"
"golang.org/x/crypto/ssh"
)

// Default port numbers used by all teleport tools
Expand Down Expand Up @@ -345,6 +346,10 @@ var (

// NodeQueueSize is node service queue size
NodeQueueSize = 128

// CASignatureAlgorithm is the default signing algorithm to use when
// creating new SSH CAs.
CASignatureAlgorithm = ssh.SigAlgoRSASHA2512
)

// Default connection limits, they can be applied separately on any of the Teleport
Expand Down
3 changes: 1 addition & 2 deletions lib/service/cfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ type Config struct {
// CASignatureAlgorithm is an SSH Certificate Authority (CA) signature
// algorithm that the server uses for signing user and host certificates.
// If omitted, the default will be used.
CASignatureAlgorithm string
CASignatureAlgorithm *string

// DiagnosticAddr is an address for diagnostic and healthz endpoint service
DiagnosticAddr utils.NetAddr
Expand Down Expand Up @@ -484,7 +484,6 @@ func ApplyDefaults(cfg *Config) {
cfg.Ciphers = sc.Ciphers
cfg.KEXAlgorithms = kex
cfg.MACAlgorithms = macs
cfg.CASignatureAlgorithm = ssh.SigAlgoRSASHA2512

// Auth service defaults.
cfg.Auth.Enabled = true
Expand Down
Loading

0 comments on commit d7dc416

Please sign in to comment.