Add identity certificate in ssh response.

This commit is contained in:
Mariano Cano 2019-11-20 11:51:25 -08:00
parent af6f6b4a85
commit 3fda081e42
4 changed files with 80 additions and 32 deletions

View file

@ -29,14 +29,15 @@ type SSHAuthority interface {
// SSHSignRequest is the request body of an SSH certificate request.
type SSHSignRequest struct {
PublicKey []byte `json:"publicKey"` //base64 encoded
OTT string `json:"ott"`
CertType string `json:"certType,omitempty"`
Principals []string `json:"principals,omitempty"`
ValidAfter TimeDuration `json:"validAfter,omitempty"`
ValidBefore TimeDuration `json:"validBefore,omitempty"`
AddUserPublicKey []byte `json:"addUserPublicKey,omitempty"`
KeyID string `json:"keyID"`
PublicKey []byte `json:"publicKey"` // base64 encoded
OTT string `json:"ott"`
CertType string `json:"certType,omitempty"`
Principals []string `json:"principals,omitempty"`
ValidAfter TimeDuration `json:"validAfter,omitempty"`
ValidBefore TimeDuration `json:"validBefore,omitempty"`
AddUserPublicKey []byte `json:"addUserPublicKey,omitempty"`
KeyID string `json:"keyID"`
IdentityCSR CertificateRequest `json:"identityCSR,omitempty"`
}
// Validate validates the SSHSignRequest.
@ -49,14 +50,21 @@ func (s *SSHSignRequest) Validate() error {
case len(s.OTT) == 0:
return errors.New("missing or empty ott")
default:
// Validate identity signature if provided
if s.IdentityCSR.CertificateRequest != nil {
if err := s.IdentityCSR.CertificateRequest.CheckSignature(); err != nil {
return errors.Wrap(err, "invalid csr")
}
}
return nil
}
}
// SSHSignResponse is the response object that returns the SSH certificate.
type SSHSignResponse struct {
Certificate SSHCertificate `json:"crt"`
AddUserCertificate *SSHCertificate `json:"addUserCrt,omitempty"`
Certificate SSHCertificate `json:"crt"`
AddUserCertificate *SSHCertificate `json:"addUserCrt,omitempty"`
IdentityCertificate []Certificate `json:"identityCrt,omitempty"`
}
// SSHRootsResponse represents the response object that returns the SSH user and
@ -292,11 +300,33 @@ func (h *caHandler) SSHSign(w http.ResponseWriter, r *http.Request) {
addUserCertificate = &SSHCertificate{addUserCert}
}
w.WriteHeader(http.StatusCreated)
JSON(w, &SSHSignResponse{
Certificate: SSHCertificate{cert},
AddUserCertificate: addUserCertificate,
})
// Sign identity certificate if available.
var identityCertificate []Certificate
if cr := body.IdentityCSR.CertificateRequest; cr != nil {
opts := provisioner.Options{
NotBefore: body.ValidAfter,
NotAfter: body.ValidBefore,
}
ctx := authority.NewContextWithSkipTokenReuse(context.Background())
ctx = provisioner.NewContextWithMethod(ctx, provisioner.SignMethod)
signOpts, err := h.Authority.Authorize(ctx, body.OTT)
if err != nil {
WriteError(w, Unauthorized(err))
return
}
certChain, err := h.Authority.Sign(cr, opts, signOpts...)
if err != nil {
WriteError(w, Forbidden(err))
return
}
identityCertificate = certChainToPEM(certChain)
}
JSONStatus(w, &SSHSignResponse{
Certificate: SSHCertificate{cert},
AddUserCertificate: addUserCertificate,
IdentityCertificate: identityCertificate,
}, http.StatusCreated)
}
// SSHRoots is an HTTP handler that returns the SSH public keys for user and host