forked from TrueCloudLab/certificates
Add multiuse capability to k8ssa provisioners
This commit is contained in:
parent
499d698c75
commit
946094d2b7
6 changed files with 62 additions and 25 deletions
|
@ -35,6 +35,7 @@ type SSHSignRequest struct {
|
|||
ValidAfter TimeDuration `json:"validAfter,omitempty"`
|
||||
ValidBefore TimeDuration `json:"validBefore,omitempty"`
|
||||
AddUserPublicKey []byte `json:"addUserPublicKey,omitempty"`
|
||||
KeyID string `json:"keyID"`
|
||||
}
|
||||
|
||||
// Validate validates the SSHSignRequest.
|
||||
|
@ -239,6 +240,7 @@ func (h *caHandler) SSHSign(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
opts := provisioner.SSHOptions{
|
||||
CertType: body.CertType,
|
||||
KeyID: body.KeyID,
|
||||
Principals: body.Principals,
|
||||
ValidBefore: body.ValidBefore,
|
||||
ValidAfter: body.ValidAfter,
|
||||
|
|
|
@ -180,8 +180,7 @@ func (p *JWK) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOption,
|
|||
if !p.claimer.IsSSHCAEnabled() {
|
||||
return nil, errors.Errorf("ssh ca is disabled for provisioner %s", p.GetID())
|
||||
}
|
||||
// TODO: fix audiences
|
||||
claims, err := p.authorizeToken(token, p.audiences.Sign)
|
||||
claims, err := p.authorizeToken(token, p.audiences.SSHSign)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -192,8 +191,6 @@ func (p *JWK) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOption,
|
|||
signOptions := []SignOption{
|
||||
// validates user's SSHOptions with the ones in the token
|
||||
sshCertificateOptionsValidator(*opts),
|
||||
// set the key id to the token subject
|
||||
sshCertificateKeyIDModifier(claims.Subject),
|
||||
}
|
||||
|
||||
t := now()
|
||||
|
@ -219,6 +216,8 @@ func (p *JWK) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOption,
|
|||
&sshDefaultExtensionModifier{},
|
||||
// Set the validity bounds if not set.
|
||||
sshDefaultValidityModifier(p.claimer),
|
||||
// Validate that the keyID is equivalent to the token subject.
|
||||
sshCertKeyIDValidator(claims.Subject),
|
||||
// Validate public key
|
||||
&sshDefaultPublicKeyValidator{},
|
||||
// Validate the validity period.
|
||||
|
@ -230,7 +229,6 @@ func (p *JWK) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOption,
|
|||
|
||||
// AuthorizeSSHRevoke returns nil if the token is valid, false otherwise.
|
||||
func (p *JWK) AuthorizeSSHRevoke(ctx context.Context, token string) error {
|
||||
// TODO fix audience.
|
||||
_, err := p.authorizeToken(token, p.audiences.SSHRevoke)
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -212,11 +212,6 @@ func (p *K8sSA) AuthorizeSign(ctx context.Context, token string) ([]SignOption,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// Check for SSH sign-ing request.
|
||||
if MethodFromContext(ctx) == SignSSHMethod {
|
||||
return nil, errors.New("ssh certificates not enabled for k8s ServiceAccount provisioners")
|
||||
}
|
||||
|
||||
return []SignOption{
|
||||
// modifiers / withOptions
|
||||
newProvisionerExtensionOption(TypeK8sSA, p.Name, ""),
|
||||
|
@ -227,14 +222,41 @@ func (p *K8sSA) AuthorizeSign(ctx context.Context, token string) ([]SignOption,
|
|||
}, nil
|
||||
}
|
||||
|
||||
// AuthorizeRenewal returns an error if the renewal is disabled.
|
||||
func (p *K8sSA) AuthorizeRenewal(cert *x509.Certificate) error {
|
||||
// AuthorizeRenew returns an error if the renewal is disabled.
|
||||
func (p *K8sSA) AuthorizeRenew(ctx context.Context, cert *x509.Certificate) error {
|
||||
if p.claimer.IsDisableRenewal() {
|
||||
return errors.Errorf("renew is disabled for provisioner %s", p.GetID())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AuthorizeSSHSign validates an request for an SSH certificate.
|
||||
func (p *K8sSA) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOption, error) {
|
||||
if !p.claimer.IsSSHCAEnabled() {
|
||||
return nil, errors.Errorf("authorizeSSHSign: ssh ca is disabled for provisioner %s", p.GetID())
|
||||
}
|
||||
_, err := p.authorizeToken(token, p.audiences.SSHSign)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "authorizeSSHSign")
|
||||
}
|
||||
|
||||
// Default to a user certificate with no principals if not set
|
||||
signOptions := []SignOption{sshCertificateDefaultsModifier{CertType: SSHUserCert}}
|
||||
|
||||
return append(signOptions,
|
||||
// Set the default extensions.
|
||||
&sshDefaultExtensionModifier{},
|
||||
// Set the validity bounds if not set.
|
||||
sshDefaultValidityModifier(p.claimer),
|
||||
// Validate public key
|
||||
&sshDefaultPublicKeyValidator{},
|
||||
// Validate the validity period.
|
||||
&sshCertificateValidityValidator{p.claimer},
|
||||
// Require and validate all the default fields in the SSH certificate.
|
||||
&sshCertificateDefaultValidator{},
|
||||
), nil
|
||||
}
|
||||
|
||||
/*
|
||||
func checkAccess(authz kauthz.AuthorizationV1Interface) error {
|
||||
r := &kauthzApi.SelfSubjectAccessReview{
|
||||
|
|
|
@ -322,7 +322,7 @@ func (o *OIDC) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOption
|
|||
return nil, err
|
||||
}
|
||||
signOptions := []SignOption{
|
||||
// set the key id to the token subject
|
||||
// set the key id to the token email
|
||||
sshCertificateKeyIDModifier(claims.Email),
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ type SSHCertificateOptionsValidator interface {
|
|||
// SSHOptions contains the options that can be passed to the SignSSH method.
|
||||
type SSHOptions struct {
|
||||
CertType string `json:"certType"`
|
||||
KeyID string `json:"keyID"`
|
||||
Principals []string `json:"principals"`
|
||||
ValidAfter TimeDuration `json:"validAfter,omitempty"`
|
||||
ValidBefore TimeDuration `json:"validBefore,omitempty"`
|
||||
|
@ -70,6 +71,8 @@ func (o SSHOptions) Modify(cert *ssh.Certificate) error {
|
|||
default:
|
||||
return errors.Errorf("ssh certificate has an unknown type: %s", o.CertType)
|
||||
}
|
||||
|
||||
cert.KeyId = o.KeyID
|
||||
cert.ValidPrincipals = o.Principals
|
||||
if !o.ValidAfter.IsZero() {
|
||||
cert.ValidAfter = uint64(o.ValidAfter.Time().Unix())
|
||||
|
@ -373,6 +376,17 @@ func (v sshDefaultPublicKeyValidator) Valid(cert *ssh.Certificate) error {
|
|||
}
|
||||
}
|
||||
|
||||
// sshCertKeyIDValidator implements a validator for the KeyId attribute.
|
||||
type sshCertKeyIDValidator string
|
||||
|
||||
// Valid returns an error if the given certificate does not contain the necessary fields.
|
||||
func (v sshCertKeyIDValidator) Valid(cert *ssh.Certificate) error {
|
||||
if string(v) != cert.KeyId {
|
||||
return errors.Errorf("invalid ssh certificate KeyId; want %s, but got %s", string(v), cert.KeyId)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// sshCertTypeUInt32
|
||||
func sshCertTypeUInt32(ct string) uint32 {
|
||||
switch ct {
|
||||
|
|
|
@ -183,14 +183,6 @@ func (p *X5C) AuthorizeSign(ctx context.Context, token string) ([]SignOption, er
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// Check for SSH sign-ing request.
|
||||
if MethodFromContext(ctx) == SignSSHMethod {
|
||||
if !p.claimer.IsSSHCAEnabled() {
|
||||
return nil, errors.Errorf("ssh ca is disabled for provisioner %s", p.GetID())
|
||||
}
|
||||
return p.authorizeSSHSign(claims)
|
||||
}
|
||||
|
||||
// NOTE: This is for backwards compatibility with older versions of cli
|
||||
// and certificates. Older versions added the token subject as the only SAN
|
||||
// in a CSR by default.
|
||||
|
@ -222,8 +214,17 @@ func (p *X5C) AuthorizeRenew(ctx context.Context, cert *x509.Certificate) error
|
|||
return nil
|
||||
}
|
||||
|
||||
// authorizeSSHSign returns the list of SignOption for a SignSSH request.
|
||||
func (p *X5C) authorizeSSHSign(claims *x5cPayload) ([]SignOption, error) {
|
||||
// AuthorizeSSHSign returns the list of SignOption for a SignSSH request.
|
||||
func (p *X5C) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOption, error) {
|
||||
if !p.claimer.IsSSHCAEnabled() {
|
||||
return nil, errors.Errorf("ssh ca is disabled for provisioner %s", p.GetID())
|
||||
}
|
||||
|
||||
claims, err := p.authorizeToken(token, p.audiences.SSHSign)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if claims.Step == nil || claims.Step.SSH == nil {
|
||||
return nil, errors.New("authorization token must be an SSH provisioning token")
|
||||
}
|
||||
|
@ -231,8 +232,6 @@ func (p *X5C) authorizeSSHSign(claims *x5cPayload) ([]SignOption, error) {
|
|||
signOptions := []SignOption{
|
||||
// validates user's SSHOptions with the ones in the token
|
||||
sshCertificateOptionsValidator(*opts),
|
||||
// set the key id to the token subject
|
||||
sshCertificateKeyIDModifier(claims.Subject),
|
||||
}
|
||||
|
||||
// Add modifiers from custom claims
|
||||
|
@ -258,6 +257,8 @@ func (p *X5C) authorizeSSHSign(claims *x5cPayload) ([]SignOption, error) {
|
|||
&sshDefaultExtensionModifier{},
|
||||
// Checks the validity bounds, and set the validity if has not been set.
|
||||
sshLimitValidityModifier(p.claimer, claims.chains[0][0].NotAfter),
|
||||
// set the key id to the token subject
|
||||
sshCertKeyIDValidator(claims.Subject),
|
||||
// Validate public key.
|
||||
&sshDefaultPublicKeyValidator{},
|
||||
// Validate the validity period.
|
||||
|
|
Loading…
Reference in a new issue