diff --git a/authority/provisioner/aws.go b/authority/provisioner/aws.go index 8d6cefe8..6d2f9f9c 100644 --- a/authority/provisioner/aws.go +++ b/authority/provisioner/aws.go @@ -468,6 +468,12 @@ func (p *AWS) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOption, } doc := claims.document + signOptions := []SignOption{} + + // Enforce host certificate. + defaults := SignSSHOptions{ + CertType: SSHHostCert, + } // Validated principals. principals := []string{ @@ -475,21 +481,14 @@ func (p *AWS) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOption, fmt.Sprintf("ip-%s.%s.compute.internal", strings.Replace(doc.PrivateIP, ".", "-", -1), doc.Region), } - // Default to cert type to host - defaults := SignSSHOptions{ - CertType: SSHHostCert, - } - defaultTemplate := sshutil.DefaultIIDCertificate - // Only enforce known principals if disable custom sans is true. if p.DisableCustomSANs { defaults.Principals = principals - defaultTemplate = sshutil.DefaultCertificate - } - - // Validate user options - signOptions := []SignOption{ - sshCertOptionsValidator(defaults), + } else { + // Check that at least one principal is sent in the request. + signOptions = append(signOptions, &sshCertOptionsRequireValidator{ + Principals: true, + }) } // Certificate templates. @@ -498,13 +497,15 @@ func (p *AWS) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOption, data.SetToken(v) } - templateOptions, err := CustomSSHTemplateOptions(p.Options, data, defaultTemplate) + templateOptions, err := CustomSSHTemplateOptions(p.Options, data, sshutil.DefaultIIDCertificate) if err != nil { return nil, errs.Wrap(http.StatusInternalServerError, err, "aws.AuthorizeSSHSign") } signOptions = append(signOptions, templateOptions) return append(signOptions, + // Validate user SignSSHOptions. + sshCertOptionsValidator(defaults), // Set the validity bounds if not set. &sshDefaultDuration{p.claimer}, // Validate public key diff --git a/authority/provisioner/azure.go b/authority/provisioner/azure.go index 7d1ef226..2121c86b 100644 --- a/authority/provisioner/azure.go +++ b/authority/provisioner/azure.go @@ -340,24 +340,24 @@ func (p *Azure) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOptio return nil, errs.Wrap(http.StatusInternalServerError, err, "azure.AuthorizeSSHSign") } - // Validated principals - principals := []string{name} + signOptions := []SignOption{} - // Default options and template + // Enforce host certificate. defaults := SignSSHOptions{ CertType: SSHHostCert, } - defaultTemplate := sshutil.DefaultIIDCertificate + + // Validated principals. + principals := []string{name} // Only enforce known principals if disable custom sans is true. if p.DisableCustomSANs { defaults.Principals = principals - defaultTemplate = sshutil.DefaultCertificate - } - - // Validate user options - signOptions := []SignOption{ - sshCertOptionsValidator(defaults), + } else { + // Check that at least one principal is sent in the request. + signOptions = append(signOptions, &sshCertOptionsRequireValidator{ + Principals: true, + }) } // Certificate templates. @@ -366,13 +366,15 @@ func (p *Azure) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOptio data.SetToken(v) } - templateOptions, err := CustomSSHTemplateOptions(p.Options, data, defaultTemplate) + templateOptions, err := CustomSSHTemplateOptions(p.Options, data, sshutil.DefaultIIDCertificate) if err != nil { return nil, errs.Wrap(http.StatusInternalServerError, err, "azure.AuthorizeSSHSign") } signOptions = append(signOptions, templateOptions) return append(signOptions, + // Validate user SignSSHOptions. + sshCertOptionsValidator(defaults), // Set the validity bounds if not set. &sshDefaultDuration{p.claimer}, // Validate public key diff --git a/authority/provisioner/gcp.go b/authority/provisioner/gcp.go index e2c783ba..e9a854ae 100644 --- a/authority/provisioner/gcp.go +++ b/authority/provisioner/gcp.go @@ -379,28 +379,27 @@ func (p *GCP) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOption, } ce := claims.Google.ComputeEngine + signOptions := []SignOption{} - // Validated principals + // Enforce host certificate. + defaults := SignSSHOptions{ + CertType: SSHHostCert, + } + + // Validated principals. 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), } - // Default options and template - defaults := SignSSHOptions{ - CertType: SSHHostCert, - } - defaultTemplate := sshutil.DefaultIIDCertificate - // Only enforce known principals if disable custom sans is true. if p.DisableCustomSANs { defaults.Principals = principals - defaultTemplate = sshutil.DefaultCertificate - } - - // Validate user options - signOptions := []SignOption{ - sshCertOptionsValidator(defaults), + } else { + // Check that at least one principal is sent in the request. + signOptions = append(signOptions, &sshCertOptionsRequireValidator{ + Principals: true, + }) } // Certificate templates. @@ -409,13 +408,15 @@ func (p *GCP) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOption, data.SetToken(v) } - templateOptions, err := CustomSSHTemplateOptions(p.Options, data, defaultTemplate) + templateOptions, err := CustomSSHTemplateOptions(p.Options, data, sshutil.DefaultIIDCertificate) if err != nil { return nil, errs.Wrap(http.StatusInternalServerError, err, "gcp.AuthorizeSSHSign") } signOptions = append(signOptions, templateOptions) return append(signOptions, + // Validate user SignSSHOptions. + sshCertOptionsValidator(defaults), // Set the validity bounds if not set. &sshDefaultDuration{p.claimer}, // Validate public key diff --git a/authority/provisioner/sign_ssh_options.go b/authority/provisioner/sign_ssh_options.go index 8c6000f0..279c2ae1 100644 --- a/authority/provisioner/sign_ssh_options.go +++ b/authority/provisioner/sign_ssh_options.go @@ -306,7 +306,7 @@ type sshCertOptionsRequireValidator struct { Principals bool } -func (v sshCertOptionsRequireValidator) Valid(got SignSSHOptions) error { +func (v *sshCertOptionsRequireValidator) Valid(got SignSSHOptions) error { switch { case v.CertType && got.CertType == "": return errors.New("ssh certificate certType cannot be empty")