forked from TrueCloudLab/certificates
Set default SSH options if no user options are given.
This commit is contained in:
parent
c17375a10a
commit
a8f4ad1b8e
6 changed files with 67 additions and 27 deletions
|
@ -448,13 +448,18 @@ func (p *AWS) authorizeSSHSign(claims *awsPayload) ([]SignOption, error) {
|
|||
sshCertificateKeyIDModifier(claims.Subject),
|
||||
}
|
||||
|
||||
signOptions = append(signOptions, &sshCertificateOptionsValidator{&SSHOptions{
|
||||
// Default to host + known IPs/hostnames
|
||||
defaults := SSHOptions{
|
||||
CertType: SSHHostCert,
|
||||
Principals: []string{
|
||||
doc.PrivateIP,
|
||||
fmt.Sprintf("ip-%s.%s.compute.internal", strings.Replace(doc.PrivateIP, ".", "-", -1), doc.Region),
|
||||
},
|
||||
}})
|
||||
}
|
||||
// Validate user options
|
||||
signOptions = append(signOptions, sshCertificateOptionsValidator(defaults))
|
||||
// Set defaults if not given as user options
|
||||
signOptions = append(signOptions, sshCertificateDefaultsModifier(defaults))
|
||||
|
||||
return append(signOptions,
|
||||
// set the default extensions
|
||||
|
|
|
@ -308,10 +308,15 @@ func (p *Azure) authorizeSSHSign(claims azurePayload, name string) ([]SignOption
|
|||
sshCertificateKeyIDModifier(name),
|
||||
}
|
||||
|
||||
signOptions = append(signOptions, &sshCertificateOptionsValidator{&SSHOptions{
|
||||
// Default to host + known hostnames
|
||||
defaults := SSHOptions{
|
||||
CertType: SSHHostCert,
|
||||
Principals: []string{name},
|
||||
}})
|
||||
}
|
||||
// Validate user options
|
||||
signOptions = append(signOptions, sshCertificateOptionsValidator(defaults))
|
||||
// Set defaults if not given as user options
|
||||
signOptions = append(signOptions, sshCertificateDefaultsModifier(defaults))
|
||||
|
||||
return append(signOptions,
|
||||
// set the default extensions
|
||||
|
|
|
@ -360,13 +360,18 @@ func (p *GCP) authorizeSSHSign(claims *gcpPayload) ([]SignOption, error) {
|
|||
sshCertificateKeyIDModifier(ce.InstanceName),
|
||||
}
|
||||
|
||||
signOptions = append(signOptions, &sshCertificateOptionsValidator{&SSHOptions{
|
||||
// Default to host + known hostnames
|
||||
defaults := SSHOptions{
|
||||
CertType: SSHHostCert,
|
||||
Principals: []string{
|
||||
fmt.Sprintf("%s.c.%s.internal", ce.InstanceName, ce.ProjectID),
|
||||
fmt.Sprintf("%s.%s.c.%s.internal", ce.InstanceName, ce.Zone, ce.ProjectID),
|
||||
},
|
||||
}})
|
||||
}
|
||||
// Validate user options
|
||||
signOptions = append(signOptions, sshCertificateOptionsValidator(defaults))
|
||||
// Set defaults if not given as user options
|
||||
signOptions = append(signOptions, sshCertificateDefaultsModifier(defaults))
|
||||
|
||||
return append(signOptions,
|
||||
// set the default extensions
|
||||
|
|
|
@ -178,7 +178,7 @@ func (p *JWK) authorizeSSHSign(claims *jwtPayload) ([]SignOption, error) {
|
|||
opts := claims.Step.SSH
|
||||
signOptions := []SignOption{
|
||||
// validates user's SSHOptions with the ones in the token
|
||||
&sshCertificateOptionsValidator{opts},
|
||||
sshCertificateOptionsValidator(*opts),
|
||||
// set the key id to the token subject
|
||||
sshCertificateKeyIDModifier(claims.Subject),
|
||||
}
|
||||
|
@ -197,6 +197,9 @@ func (p *JWK) authorizeSSHSign(claims *jwtPayload) ([]SignOption, error) {
|
|||
signOptions = append(signOptions, sshCertificateValidBeforeModifier(opts.ValidBefore.RelativeTime(t).Unix()))
|
||||
}
|
||||
|
||||
// Default to a user certificate with no principals if not set
|
||||
signOptions = append(signOptions, sshCertificateDefaultsModifier{CertType: SSHUserCert})
|
||||
|
||||
return append(signOptions,
|
||||
// set the default extensions
|
||||
&sshDefaultExtensionModifier{},
|
||||
|
|
|
@ -303,20 +303,25 @@ func (o *OIDC) authorizeSSHSign(claims *openIDPayload) ([]SignOption, error) {
|
|||
sshCertificateKeyIDModifier(claims.Email),
|
||||
}
|
||||
|
||||
// Non-admins are only able to sign user certificates
|
||||
if o.IsAdmin(claims.Email) {
|
||||
signOptions = append(signOptions, &sshCertificateOptionsValidator{})
|
||||
} else {
|
||||
name := SanitizeSSHUserPrincipal(claims.Email)
|
||||
if !sshUserRegex.MatchString(name) {
|
||||
return nil, errors.Errorf("invalid principal '%s' from email address '%s'", name, claims.Email)
|
||||
}
|
||||
signOptions = append(signOptions, &sshCertificateOptionsValidator{&SSHOptions{
|
||||
CertType: SSHUserCert,
|
||||
Principals: []string{name},
|
||||
}})
|
||||
name := SanitizeSSHUserPrincipal(claims.Email)
|
||||
if !sshUserRegex.MatchString(name) {
|
||||
return nil, errors.Errorf("invalid principal '%s' from email address '%s'", name, claims.Email)
|
||||
}
|
||||
|
||||
// Admin users will default to user + name but they can be changed by the
|
||||
// user options. Non-admins are only able to sign user certificates.
|
||||
defaults := SSHOptions{
|
||||
CertType: SSHUserCert,
|
||||
Principals: []string{name},
|
||||
}
|
||||
|
||||
if !o.IsAdmin(claims.Email) {
|
||||
signOptions = append(signOptions, sshCertificateOptionsValidator(defaults))
|
||||
}
|
||||
|
||||
// Default to a user with name as principal if not set
|
||||
signOptions = append(signOptions, sshCertificateDefaultsModifier(defaults))
|
||||
|
||||
return append(signOptions,
|
||||
// set the default extensions
|
||||
&sshDefaultExtensionModifier{},
|
||||
|
|
|
@ -143,6 +143,27 @@ func (m sshCertificateValidBeforeModifier) Modify(cert *ssh.Certificate) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// sshCertificateDefaultModifier implements a SSHCertificateModifier that
|
||||
// modifies the certificate with the given options if they are not set.
|
||||
type sshCertificateDefaultsModifier SSHOptions
|
||||
|
||||
// Modify implements the SSHCertificateModifier interface.
|
||||
func (m sshCertificateDefaultsModifier) Modify(cert *ssh.Certificate) error {
|
||||
if cert.CertType == 0 {
|
||||
cert.CertType = sshCertTypeUInt32(m.CertType)
|
||||
}
|
||||
if len(cert.ValidPrincipals) == 0 {
|
||||
cert.ValidPrincipals = m.Principals
|
||||
}
|
||||
if cert.ValidAfter == 0 && !m.ValidAfter.IsZero() {
|
||||
cert.ValidAfter = uint64(m.ValidAfter.Unix())
|
||||
}
|
||||
if cert.ValidBefore == 0 && !m.ValidBefore.IsZero() {
|
||||
cert.ValidBefore = uint64(m.ValidBefore.Unix())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// sshDefaultExtensionModifier implements an SSHCertificateModifier that sets
|
||||
// the default extensions in an SSH certificate.
|
||||
type sshDefaultExtensionModifier struct{}
|
||||
|
@ -212,17 +233,13 @@ func (m *sshCertificateValidityModifier) Modify(cert *ssh.Certificate) error {
|
|||
|
||||
// sshCertificateOptionsValidator validates the user SSHOptions with the ones
|
||||
// usually present in the token.
|
||||
type sshCertificateOptionsValidator struct {
|
||||
Want *SSHOptions
|
||||
}
|
||||
type sshCertificateOptionsValidator SSHOptions
|
||||
|
||||
// Valid implements SSHCertificateOptionsValidator and returns nil if both
|
||||
// SSHOptions match.
|
||||
func (v *sshCertificateOptionsValidator) Valid(got SSHOptions) error {
|
||||
if v.Want == nil {
|
||||
return nil
|
||||
}
|
||||
return v.Want.match(got)
|
||||
func (v sshCertificateOptionsValidator) Valid(got SSHOptions) error {
|
||||
want := SSHOptions(v)
|
||||
return want.match(got)
|
||||
}
|
||||
|
||||
// sshCertificateDefaultValidator implements a simple validator for all the
|
||||
|
|
Loading…
Reference in a new issue