mirror of
https://github.com/gravitational/teleport
synced 2024-10-21 01:34:01 +00:00
api dependency reduction - ssh (#5379)
Move Cert Authority methods out of api to remove dependency on crypto/ssh.
This commit is contained in:
parent
74f7c801da
commit
efe91c4def
|
@ -21,8 +21,6 @@ import (
|
|||
"fmt"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
|
||||
"github.com/gravitational/teleport/api/constants"
|
||||
"github.com/gravitational/teleport/api/defaults"
|
||||
"github.com/gravitational/teleport/api/utils"
|
||||
|
@ -70,10 +68,6 @@ type CertAuthority interface {
|
|||
SetCheckingKeys([][]byte) error
|
||||
// AddRole adds a role to ca role list
|
||||
AddRole(name string)
|
||||
// Checkers returns public keys that can be used to check cert authorities
|
||||
Checkers() ([]ssh.PublicKey, error)
|
||||
// Signers returns a list of signers that could be used to sign keys
|
||||
Signers() ([]ssh.Signer, error)
|
||||
// String returns human readable version of the CertAuthority
|
||||
String() string
|
||||
// SetTLSKeyPairs sets TLS key pairs
|
||||
|
@ -89,9 +83,9 @@ type CertAuthority interface {
|
|||
// SetRotation sets rotation state.
|
||||
SetRotation(Rotation)
|
||||
// GetSigningAlg returns the signing algorithm used by signing keys.
|
||||
GetSigningAlg() string
|
||||
GetSigningAlg() CertAuthoritySpecV2_SigningAlgType
|
||||
// SetSigningAlg sets the signing algorithm used by signing keys.
|
||||
SetSigningAlg(string)
|
||||
SetSigningAlg(CertAuthoritySpecV2_SigningAlgType)
|
||||
// Clone returns a copy of the cert authority object.
|
||||
Clone() CertAuthority
|
||||
}
|
||||
|
@ -348,71 +342,14 @@ func (ca *CertAuthorityV2) ID() *CertAuthID {
|
|||
return &CertAuthID{DomainName: ca.Spec.ClusterName, Type: ca.Spec.Type}
|
||||
}
|
||||
|
||||
// Checkers returns public keys that can be used to check cert authorities
|
||||
func (ca *CertAuthorityV2) Checkers() ([]ssh.PublicKey, error) {
|
||||
out := make([]ssh.PublicKey, 0, len(ca.Spec.CheckingKeys))
|
||||
for _, keyBytes := range ca.Spec.CheckingKeys {
|
||||
key, _, _, _, err := ssh.ParseAuthorizedKey(keyBytes)
|
||||
if err != nil {
|
||||
return nil, trace.BadParameter("invalid authority public key (len=%d): %v", len(keyBytes), err)
|
||||
}
|
||||
out = append(out, key)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Signers returns a list of signers that could be used to sign keys.
|
||||
func (ca *CertAuthorityV2) Signers() ([]ssh.Signer, error) {
|
||||
out := make([]ssh.Signer, 0, len(ca.Spec.SigningKeys))
|
||||
for _, keyBytes := range ca.Spec.SigningKeys {
|
||||
signer, err := ssh.ParsePrivateKey(keyBytes)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
signer = utils.AlgSigner(signer, ca.GetSigningAlg())
|
||||
out = append(out, signer)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// GetSigningAlg returns the CA's signing algorithm type
|
||||
func (ca *CertAuthorityV2) GetSigningAlg() string {
|
||||
switch ca.Spec.SigningAlg {
|
||||
// UNKNOWN algorithm can come from a cluster that existed before SigningAlg
|
||||
// field was added. Default to RSA-SHA1 to match the implicit algorithm
|
||||
// used in those clusters.
|
||||
case CertAuthoritySpecV2_RSA_SHA1, CertAuthoritySpecV2_UNKNOWN:
|
||||
return ssh.SigAlgoRSA
|
||||
case CertAuthoritySpecV2_RSA_SHA2_256:
|
||||
return ssh.SigAlgoRSASHA2256
|
||||
case CertAuthoritySpecV2_RSA_SHA2_512:
|
||||
return ssh.SigAlgoRSASHA2512
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// ParseSigningAlg converts the SSH signature algorithm strings to the
|
||||
// corresponding proto enum value.
|
||||
//
|
||||
// alg should be one of ssh.SigAlgo* If it's not one of those
|
||||
// constants, CertAuthoritySpecV2_UNKNOWN is returned.
|
||||
func ParseSigningAlg(alg string) CertAuthoritySpecV2_SigningAlgType {
|
||||
switch alg {
|
||||
case ssh.SigAlgoRSA:
|
||||
return CertAuthoritySpecV2_RSA_SHA1
|
||||
case ssh.SigAlgoRSASHA2256:
|
||||
return CertAuthoritySpecV2_RSA_SHA2_256
|
||||
case ssh.SigAlgoRSASHA2512:
|
||||
return CertAuthoritySpecV2_RSA_SHA2_512
|
||||
default:
|
||||
return CertAuthoritySpecV2_UNKNOWN
|
||||
}
|
||||
func (ca *CertAuthorityV2) GetSigningAlg() CertAuthoritySpecV2_SigningAlgType {
|
||||
return ca.Spec.SigningAlg
|
||||
}
|
||||
|
||||
// SetSigningAlg sets the CA's signing algorith type
|
||||
func (ca *CertAuthorityV2) SetSigningAlg(alg string) {
|
||||
ca.Spec.SigningAlg = ParseSigningAlg(alg)
|
||||
func (ca *CertAuthorityV2) SetSigningAlg(alg CertAuthoritySpecV2_SigningAlgType) {
|
||||
ca.Spec.SigningAlg = alg
|
||||
}
|
||||
|
||||
// CheckAndSetDefaults checks and set default values for any missing fields.
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
Copyright 2021 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
// AlgSigner wraps a provided ssh.Signer to ensure signature algorithm
|
||||
// compatibility with OpenSSH.
|
||||
//
|
||||
// Right now it allows forcing SHA-2 signatures with RSA keys, instead of the
|
||||
// default SHA-1 used by x/crypto/ssh. See
|
||||
// https://www.openssh.com/txt/release-8.2 for context.
|
||||
//
|
||||
// If the provided Signer is not an RSA key or does not implement
|
||||
// ssh.AlgorithmSigner, it's returned as is.
|
||||
//
|
||||
// DELETE IN 5.0: assuming https://github.com/golang/go/issues/37278 is fixed
|
||||
// by then and we pull in the fix. Also delete all call sites.
|
||||
func AlgSigner(s ssh.Signer, alg string) ssh.Signer {
|
||||
if alg == "" {
|
||||
return s
|
||||
}
|
||||
if s.PublicKey().Type() != ssh.KeyAlgoRSA && s.PublicKey().Type() != ssh.CertAlgoRSAv01 {
|
||||
return s
|
||||
}
|
||||
as, ok := s.(ssh.AlgorithmSigner)
|
||||
if !ok {
|
||||
return s
|
||||
}
|
||||
return fixedAlgorithmSigner{
|
||||
AlgorithmSigner: as,
|
||||
alg: alg,
|
||||
}
|
||||
}
|
||||
|
||||
type fixedAlgorithmSigner struct {
|
||||
ssh.AlgorithmSigner
|
||||
alg string
|
||||
}
|
||||
|
||||
func (s fixedAlgorithmSigner) SignWithAlgorithm(rand io.Reader, data []byte, alg string) (*ssh.Signature, error) {
|
||||
if alg == "" {
|
||||
alg = s.alg
|
||||
}
|
||||
return s.AlgorithmSigner.SignWithAlgorithm(rand, data, alg)
|
||||
}
|
||||
|
||||
func (s fixedAlgorithmSigner) Sign(rand io.Reader, data []byte) (*ssh.Signature, error) {
|
||||
return s.AlgorithmSigner.SignWithAlgorithm(rand, data, s.alg)
|
||||
}
|
|
@ -57,6 +57,7 @@ import (
|
|||
"github.com/gravitational/teleport/lib/services"
|
||||
"github.com/gravitational/teleport/lib/session"
|
||||
"github.com/gravitational/teleport/lib/srv"
|
||||
"github.com/gravitational/teleport/lib/sshutils"
|
||||
"github.com/gravitational/teleport/lib/utils"
|
||||
"github.com/gravitational/teleport/lib/utils/testlog"
|
||||
|
||||
|
@ -3898,11 +3899,11 @@ func (s *IntSuite) TestRotateChangeSigningAlg(c *check.C) {
|
|||
assertSigningAlg := func(svc *service.TeleportProcess, alg string) {
|
||||
hostCA, err := svc.GetAuthServer().GetCertAuthority(services.CertAuthID{Type: services.HostCA, DomainName: Site}, false)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(hostCA.GetSigningAlg(), check.Equals, alg)
|
||||
c.Assert(sshutils.GetSigningAlgName(hostCA), check.Equals, alg)
|
||||
|
||||
userCA, err := svc.GetAuthServer().GetCertAuthority(services.CertAuthID{Type: services.UserCA, DomainName: Site}, false)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(userCA.GetSigningAlg(), check.Equals, alg)
|
||||
c.Assert(sshutils.GetSigningAlgName(userCA), check.Equals, alg)
|
||||
}
|
||||
|
||||
rotate := func(svc *service.TeleportProcess, mode string) *service.TeleportProcess {
|
||||
|
|
|
@ -394,7 +394,7 @@ func (a *Server) GenerateHostCert(hostPublicKey []byte, hostID, nodeName string,
|
|||
// create and sign!
|
||||
return a.Authority.GenerateHostCert(services.HostCertParams{
|
||||
PrivateCASigningKey: caPrivateKey,
|
||||
CASigningAlg: ca.GetSigningAlg(),
|
||||
CASigningAlg: sshutils.GetSigningAlgName(ca),
|
||||
PublicHostKey: hostPublicKey,
|
||||
HostID: hostID,
|
||||
NodeName: nodeName,
|
||||
|
@ -634,7 +634,7 @@ func (a *Server) generateUserCert(req certRequest) (*certs, error) {
|
|||
}
|
||||
sshCert, err := a.Authority.GenerateUserCert(services.UserCertParams{
|
||||
PrivateCASigningKey: privateKey,
|
||||
CASigningAlg: ca.GetSigningAlg(),
|
||||
CASigningAlg: sshutils.GetSigningAlgName(ca),
|
||||
PublicUserKey: req.publicKey,
|
||||
Username: req.user.GetName(),
|
||||
AllowedLogins: allowedLogins,
|
||||
|
@ -1238,7 +1238,7 @@ func (a *Server) GenerateServerKeys(req GenerateServerKeysRequest) (*PackedKeys,
|
|||
// generate hostSSH certificate
|
||||
hostSSHCert, err := a.Authority.GenerateHostCert(services.HostCertParams{
|
||||
PrivateCASigningKey: caPrivateKey,
|
||||
CASigningAlg: ca.GetSigningAlg(),
|
||||
CASigningAlg: sshutils.GetSigningAlgName(ca),
|
||||
PublicHostKey: pubSSHKey,
|
||||
HostID: req.HostID,
|
||||
NodeName: req.NodeName,
|
||||
|
|
|
@ -343,7 +343,7 @@ func Init(cfg InitConfig, opts ...ServerOption) (*Server, error) {
|
|||
ClusterName: cfg.ClusterName.GetClusterName(),
|
||||
Type: services.UserCA,
|
||||
SigningKeys: [][]byte{priv},
|
||||
SigningAlg: services.ParseSigningAlg(sigAlg),
|
||||
SigningAlg: sshutils.ParseSigningAlg(sigAlg),
|
||||
CheckingKeys: [][]byte{pub},
|
||||
TLSKeyPairs: []services.TLSKeyPair{{Cert: certPEM, Key: keyPEM}},
|
||||
},
|
||||
|
@ -403,7 +403,7 @@ func Init(cfg InitConfig, opts ...ServerOption) (*Server, error) {
|
|||
ClusterName: cfg.ClusterName.GetClusterName(),
|
||||
Type: services.HostCA,
|
||||
SigningKeys: [][]byte{priv},
|
||||
SigningAlg: services.ParseSigningAlg(sigAlg),
|
||||
SigningAlg: sshutils.ParseSigningAlg(sigAlg),
|
||||
CheckingKeys: [][]byte{pub},
|
||||
TLSKeyPairs: []services.TLSKeyPair{{Cert: certPEM, Key: keyPEM}},
|
||||
},
|
||||
|
|
|
@ -31,6 +31,7 @@ import (
|
|||
"github.com/gravitational/teleport/lib/backend/lite"
|
||||
"github.com/gravitational/teleport/lib/defaults"
|
||||
"github.com/gravitational/teleport/lib/services"
|
||||
"github.com/gravitational/teleport/lib/sshutils"
|
||||
"github.com/gravitational/teleport/lib/utils"
|
||||
|
||||
"github.com/gravitational/trace"
|
||||
|
@ -351,12 +352,12 @@ func (s *AuthInitSuite) TestCASigningAlg(c *C) {
|
|||
hostCAs, err := auth.GetCertAuthorities(services.HostCA, false)
|
||||
c.Assert(err, IsNil)
|
||||
for _, ca := range hostCAs {
|
||||
c.Assert(ca.GetSigningAlg(), Equals, alg)
|
||||
c.Assert(sshutils.GetSigningAlgName(ca), Equals, alg)
|
||||
}
|
||||
userCAs, err := auth.GetCertAuthorities(services.UserCA, false)
|
||||
c.Assert(err, IsNil)
|
||||
for _, ca := range userCAs {
|
||||
c.Assert(ca.GetSigningAlg(), Equals, alg)
|
||||
c.Assert(sshutils.GetSigningAlgName(ca), Equals, alg)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import (
|
|||
"github.com/gravitational/teleport/lib/defaults"
|
||||
"github.com/gravitational/teleport/lib/jwt"
|
||||
"github.com/gravitational/teleport/lib/services"
|
||||
"github.com/gravitational/teleport/lib/sshutils"
|
||||
"github.com/gravitational/teleport/lib/tlsca"
|
||||
"github.com/gravitational/teleport/lib/utils"
|
||||
|
||||
|
@ -611,7 +612,7 @@ func startNewRotation(req rotationReq, ca services.CertAuthority) error {
|
|||
// explicitly set in the config file. If the config file doesn't set a value,
|
||||
// preserve the signing algorithm of the existing CA.
|
||||
if req.caSigningAlg != nil {
|
||||
ca.SetSigningAlg(*req.caSigningAlg)
|
||||
sshutils.SetSigningAlgName(ca, *req.caSigningAlg)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -234,7 +234,7 @@ func (a *Agent) checkHostSignature(hostport string, remote net.Addr, key ssh.Pub
|
|||
return trace.Wrap(err, "failed to fetch remote certs")
|
||||
}
|
||||
for _, ca := range cas {
|
||||
checkers, err := ca.Checkers()
|
||||
checkers, err := sshutils.GetCheckers(ca)
|
||||
if err != nil {
|
||||
return trace.BadParameter("error parsing key: %v", err)
|
||||
}
|
||||
|
|
|
@ -704,7 +704,7 @@ func (s *server) getTrustedCAKeysByID(id services.CertAuthID) ([]ssh.PublicKey,
|
|||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
return ca.Checkers()
|
||||
return sshutils.GetCheckers(ca)
|
||||
}
|
||||
|
||||
func (s *server) keyAuth(conn ssh.ConnMetadata, key ssh.PublicKey) (perm *ssh.Permissions, err error) {
|
||||
|
|
|
@ -26,11 +26,12 @@ import (
|
|||
"github.com/gravitational/teleport/api/types/wrappers"
|
||||
"github.com/gravitational/teleport/lib/defaults"
|
||||
"github.com/gravitational/teleport/lib/jwt"
|
||||
"github.com/gravitational/teleport/lib/sshutils"
|
||||
"github.com/gravitational/teleport/lib/tlsca"
|
||||
"github.com/gravitational/teleport/lib/utils"
|
||||
"github.com/jonboulle/clockwork"
|
||||
|
||||
"github.com/gravitational/trace"
|
||||
"github.com/jonboulle/clockwork"
|
||||
"github.com/tstranex/u2f"
|
||||
)
|
||||
|
||||
|
@ -93,10 +94,10 @@ func checkUserOrHostCA(ca CertAuthority) error {
|
|||
if len(ca.GetTLSKeyPairs()) == 0 {
|
||||
return trace.BadParameter("certificate authority missing TLS key pairs")
|
||||
}
|
||||
if _, err := ca.Checkers(); err != nil {
|
||||
if _, err := sshutils.GetCheckers(ca); err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
if _, err := ca.Signers(); err != nil {
|
||||
if _, err := sshutils.GetSigners(ca); err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
// This is to force users to migrate
|
||||
|
|
|
@ -172,7 +172,6 @@ var (
|
|||
RemoveCASecrets = types.RemoveCASecrets
|
||||
MarshalCertRoles = types.MarshalCertRoles
|
||||
UnmarshalCertRoles = types.UnmarshalCertRoles
|
||||
ParseSigningAlg = types.ParseSigningAlg
|
||||
RotationSchema = types.RotationSchema
|
||||
)
|
||||
|
||||
|
|
|
@ -409,7 +409,7 @@ func (h *AuthHandlers) authorityForCert(caType services.CertAuthType, key ssh.Pu
|
|||
// find the one that signed our certificate
|
||||
var ca services.CertAuthority
|
||||
for i := range cas {
|
||||
checkers, err := cas[i].Checkers()
|
||||
checkers, err := sshutils.GetCheckers(cas[i])
|
||||
if err != nil {
|
||||
h.Warnf("%v", err)
|
||||
return nil, trace.Wrap(err)
|
||||
|
|
91
lib/sshutils/authority.go
Normal file
91
lib/sshutils/authority.go
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
Copyright 2021 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package sshutils
|
||||
|
||||
import (
|
||||
"github.com/gravitational/teleport/api/types"
|
||||
|
||||
"github.com/gravitational/trace"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
// GetCheckers returns public keys that can be used to check cert authorities
|
||||
func GetCheckers(ca types.CertAuthority) ([]ssh.PublicKey, error) {
|
||||
out := make([]ssh.PublicKey, 0, len(ca.GetCheckingKeys()))
|
||||
for _, keyBytes := range ca.GetCheckingKeys() {
|
||||
key, _, _, _, err := ssh.ParseAuthorizedKey(keyBytes)
|
||||
if err != nil {
|
||||
return nil, trace.BadParameter("invalid authority public key (len=%d): %v", len(keyBytes), err)
|
||||
}
|
||||
out = append(out, key)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// GetSigners returns a list of signers that could be used to sign keys.
|
||||
func GetSigners(ca types.CertAuthority) ([]ssh.Signer, error) {
|
||||
out := make([]ssh.Signer, 0, len(ca.GetSigningKeys()))
|
||||
for _, keyBytes := range ca.GetSigningKeys() {
|
||||
signer, err := ssh.ParsePrivateKey(keyBytes)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
signer = AlgSigner(signer, GetSigningAlgName(ca))
|
||||
out = append(out, signer)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// GetSigningAlgName returns the CA's signing algorithm type
|
||||
func GetSigningAlgName(ca types.CertAuthority) string {
|
||||
switch ca.GetSigningAlg() {
|
||||
// UNKNOWN algorithm can come from a cluster that existed before SigningAlg
|
||||
// field was added. Default to RSA-SHA1 to match the implicit algorithm
|
||||
// used in those clusters.
|
||||
case types.CertAuthoritySpecV2_RSA_SHA1, types.CertAuthoritySpecV2_UNKNOWN:
|
||||
return ssh.SigAlgoRSA
|
||||
case types.CertAuthoritySpecV2_RSA_SHA2_256:
|
||||
return ssh.SigAlgoRSASHA2256
|
||||
case types.CertAuthoritySpecV2_RSA_SHA2_512:
|
||||
return ssh.SigAlgoRSASHA2512
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// SetSigningAlgName sets the signing algorithm type for the given CA
|
||||
func SetSigningAlgName(ca types.CertAuthority, alg string) {
|
||||
ca.SetSigningAlg(ParseSigningAlg(alg))
|
||||
}
|
||||
|
||||
// ParseSigningAlg converts the name of the SSH signature algorithm to the
|
||||
// corresponding proto enum value.
|
||||
//
|
||||
// alg should be one of ssh.SigAlgo* constants. If it's not one of those
|
||||
// constants, types.CertAuthoritySpecV2_UNKNOWN is returned.
|
||||
func ParseSigningAlg(alg string) types.CertAuthoritySpecV2_SigningAlgType {
|
||||
switch alg {
|
||||
case ssh.SigAlgoRSA:
|
||||
return types.CertAuthoritySpecV2_RSA_SHA1
|
||||
case ssh.SigAlgoRSASHA2256:
|
||||
return types.CertAuthoritySpecV2_RSA_SHA2_256
|
||||
case ssh.SigAlgoRSASHA2512:
|
||||
return types.CertAuthoritySpecV2_RSA_SHA2_512
|
||||
default:
|
||||
return types.CertAuthoritySpecV2_UNKNOWN
|
||||
}
|
||||
}
|
|
@ -18,17 +18,57 @@ package sshutils
|
|||
|
||||
import (
|
||||
"crypto"
|
||||
"io"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
|
||||
"github.com/gravitational/teleport/api/utils"
|
||||
|
||||
"github.com/gravitational/trace"
|
||||
)
|
||||
|
||||
// AlgSigner has been moved to /api/utils, and is now
|
||||
// imported here for backwards compatibility. DELETE IN 7.0.0
|
||||
var AlgSigner = utils.AlgSigner
|
||||
// AlgSigner wraps the provided ssh.Signer to ensure signature algorithm
|
||||
// compatibility with OpenSSH.
|
||||
//
|
||||
// Right now it allows forcing SHA-2 signatures with RSA keys, instead of the
|
||||
// default SHA-1 used by x/crypto/ssh. See
|
||||
// https://www.openssh.com/txt/release-8.2 for context.
|
||||
//
|
||||
// If the provided Signer is not an RSA key or does not implement
|
||||
// ssh.AlgorithmSigner, it's returned as is.
|
||||
//
|
||||
// DELETE IN 5.0: assuming https://github.com/golang/go/issues/37278 is fixed
|
||||
// by then and we pull in the fix. Also delete all call sites.
|
||||
func AlgSigner(s ssh.Signer, alg string) ssh.Signer {
|
||||
if alg == "" {
|
||||
return s
|
||||
}
|
||||
if s.PublicKey().Type() != ssh.KeyAlgoRSA && s.PublicKey().Type() != ssh.CertAlgoRSAv01 {
|
||||
return s
|
||||
}
|
||||
as, ok := s.(ssh.AlgorithmSigner)
|
||||
if !ok {
|
||||
return s
|
||||
}
|
||||
return fixedAlgorithmSigner{
|
||||
AlgorithmSigner: as,
|
||||
alg: alg,
|
||||
}
|
||||
}
|
||||
|
||||
type fixedAlgorithmSigner struct {
|
||||
ssh.AlgorithmSigner
|
||||
alg string
|
||||
}
|
||||
|
||||
func (s fixedAlgorithmSigner) SignWithAlgorithm(rand io.Reader, data []byte, alg string) (*ssh.Signature, error) {
|
||||
if alg == "" {
|
||||
alg = s.alg
|
||||
}
|
||||
return s.AlgorithmSigner.SignWithAlgorithm(rand, data, alg)
|
||||
}
|
||||
|
||||
func (s fixedAlgorithmSigner) Sign(rand io.Reader, data []byte) (*ssh.Signature, error) {
|
||||
return s.AlgorithmSigner.SignWithAlgorithm(rand, data, s.alg)
|
||||
}
|
||||
|
||||
// NewSigner returns new ssh Signer from private key + certificate pair. The
|
||||
// signer can be used to create "auth methods" i.e. login into Teleport SSH
|
||||
|
|
Loading…
Reference in a new issue