forked from TrueCloudLab/certificates
scep: remove Interface and the dependency to pkg/errors (#872)
* scep: documented the package * scep/api: removed some top level constants * scep: removed dependency to pkg/errors * scep/api: documented the package
This commit is contained in:
parent
bca74cb6a7
commit
a852223717
3 changed files with 35 additions and 54 deletions
|
@ -1,3 +1,4 @@
|
|||
// Package api implements a SCEP HTTP server.
|
||||
package api
|
||||
|
||||
import (
|
||||
|
@ -31,12 +32,6 @@ const (
|
|||
|
||||
const maxPayloadSize = 2 << 20
|
||||
|
||||
const (
|
||||
certChainHeader = "application/x-x509-ca-ra-cert"
|
||||
leafHeader = "application/x-x509-ca-cert"
|
||||
pkiOperationHeader = "application/x-pki-message"
|
||||
)
|
||||
|
||||
// request is a SCEP server request.
|
||||
type request struct {
|
||||
Operation string
|
||||
|
@ -54,17 +49,19 @@ type response struct {
|
|||
|
||||
// handler is the SCEP request handler.
|
||||
type handler struct {
|
||||
Auth scep.Interface
|
||||
auth *scep.Authority
|
||||
}
|
||||
|
||||
// New returns a new SCEP API router.
|
||||
func New(scepAuth scep.Interface) api.RouterHandler {
|
||||
return &handler{scepAuth}
|
||||
func New(auth *scep.Authority) api.RouterHandler {
|
||||
return &handler{
|
||||
auth: auth,
|
||||
}
|
||||
}
|
||||
|
||||
// Route traffic and implement the Router interface.
|
||||
func (h *handler) Route(r api.Router) {
|
||||
getLink := h.Auth.GetLinkExplicit
|
||||
getLink := h.auth.GetLinkExplicit
|
||||
r.MethodFunc(http.MethodGet, getLink("{provisionerName}/*", false, nil), h.lookupProvisioner(h.Get))
|
||||
r.MethodFunc(http.MethodGet, getLink("{provisionerName}", false, nil), h.lookupProvisioner(h.Get))
|
||||
r.MethodFunc(http.MethodPost, getLink("{provisionerName}/*", false, nil), h.lookupProvisioner(h.Post))
|
||||
|
@ -192,7 +189,7 @@ func (h *handler) lookupProvisioner(next http.HandlerFunc) http.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
p, err := h.Auth.LoadProvisionerByName(provisionerName)
|
||||
p, err := h.auth.LoadProvisionerByName(provisionerName)
|
||||
if err != nil {
|
||||
fail(w, err)
|
||||
return
|
||||
|
@ -213,7 +210,7 @@ func (h *handler) lookupProvisioner(next http.HandlerFunc) http.HandlerFunc {
|
|||
// GetCACert returns the CA certificates in a SCEP response
|
||||
func (h *handler) GetCACert(ctx context.Context) (response, error) {
|
||||
|
||||
certs, err := h.Auth.GetCACertificates(ctx)
|
||||
certs, err := h.auth.GetCACertificates(ctx)
|
||||
if err != nil {
|
||||
return response{}, err
|
||||
}
|
||||
|
@ -246,7 +243,7 @@ func (h *handler) GetCACert(ctx context.Context) (response, error) {
|
|||
// GetCACaps returns the CA capabilities in a SCEP response
|
||||
func (h *handler) GetCACaps(ctx context.Context) (response, error) {
|
||||
|
||||
caps := h.Auth.GetCACaps(ctx)
|
||||
caps := h.auth.GetCACaps(ctx)
|
||||
|
||||
res := response{
|
||||
Operation: opnGetCACaps,
|
||||
|
@ -283,7 +280,7 @@ func (h *handler) PKIOperation(ctx context.Context, req request) (response, erro
|
|||
P7: p7,
|
||||
}
|
||||
|
||||
if err := h.Auth.DecryptPKIEnvelope(ctx, msg); err != nil {
|
||||
if err := h.auth.DecryptPKIEnvelope(ctx, msg); err != nil {
|
||||
return response{}, err
|
||||
}
|
||||
|
||||
|
@ -296,7 +293,7 @@ func (h *handler) PKIOperation(ctx context.Context, req request) (response, erro
|
|||
// a certificate exists; then it will use RenewalReq. Adding the challenge check here may be a small breaking change for clients.
|
||||
// We'll have to see how it works out.
|
||||
if msg.MessageType == microscep.PKCSReq || msg.MessageType == microscep.RenewalReq {
|
||||
challengeMatches, err := h.Auth.MatchChallengePassword(ctx, msg.CSRReqMessage.ChallengePassword)
|
||||
challengeMatches, err := h.auth.MatchChallengePassword(ctx, msg.CSRReqMessage.ChallengePassword)
|
||||
if err != nil {
|
||||
return h.createFailureResponse(ctx, csr, msg, microscep.BadRequest, errors.New("error when checking password"))
|
||||
}
|
||||
|
@ -314,7 +311,7 @@ func (h *handler) PKIOperation(ctx context.Context, req request) (response, erro
|
|||
// Authentication by the (self-signed) certificate with an optional challenge is required; supporting renewals incl. verification
|
||||
// of the client cert is not.
|
||||
|
||||
certRep, err := h.Auth.SignCSR(ctx, csr, msg)
|
||||
certRep, err := h.auth.SignCSR(ctx, csr, msg)
|
||||
if err != nil {
|
||||
return h.createFailureResponse(ctx, csr, msg, microscep.BadRequest, fmt.Errorf("error when signing new certificate: %w", err))
|
||||
}
|
||||
|
@ -354,7 +351,7 @@ func fail(w http.ResponseWriter, err error) {
|
|||
}
|
||||
|
||||
func (h *handler) createFailureResponse(ctx context.Context, csr *x509.CertificateRequest, msg *scep.PKIMessage, info microscep.FailInfo, failError error) (response, error) {
|
||||
certRepMsg, err := h.Auth.CreateFailureResponse(ctx, csr, msg, scep.FailInfoName(info), failError.Error())
|
||||
certRepMsg, err := h.auth.CreateFailureResponse(ctx, csr, msg, scep.FailInfoName(info), failError.Error())
|
||||
if err != nil {
|
||||
return response{}, err
|
||||
}
|
||||
|
@ -367,14 +364,14 @@ func (h *handler) createFailureResponse(ctx context.Context, csr *x509.Certifica
|
|||
|
||||
func contentHeader(r response) string {
|
||||
switch r.Operation {
|
||||
case opnGetCACert:
|
||||
if r.CACertNum > 1 {
|
||||
return certChainHeader
|
||||
}
|
||||
return leafHeader
|
||||
case opnPKIOperation:
|
||||
return pkiOperationHeader
|
||||
default:
|
||||
return "text/plain"
|
||||
case opnGetCACert:
|
||||
if r.CACertNum > 1 {
|
||||
return "application/x-x509-ca-ra-cert"
|
||||
}
|
||||
return "application/x-x509-ca-cert"
|
||||
case opnPKIOperation:
|
||||
return "application/x-pki-message"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,33 +4,19 @@ import (
|
|||
"context"
|
||||
"crypto/subtle"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/smallstep/certificates/authority/provisioner"
|
||||
|
||||
microx509util "github.com/micromdm/scep/v2/cryptoutil/x509util"
|
||||
microscep "github.com/micromdm/scep/v2/scep"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"go.mozilla.org/pkcs7"
|
||||
|
||||
"go.step.sm/crypto/x509util"
|
||||
|
||||
"github.com/smallstep/certificates/authority/provisioner"
|
||||
)
|
||||
|
||||
// Interface is the SCEP authority interface.
|
||||
type Interface interface {
|
||||
LoadProvisionerByName(string) (provisioner.Interface, error)
|
||||
GetLinkExplicit(provName string, absoluteLink bool, baseURL *url.URL, inputs ...string) string
|
||||
|
||||
GetCACertificates(ctx context.Context) ([]*x509.Certificate, error)
|
||||
DecryptPKIEnvelope(ctx context.Context, msg *PKIMessage) error
|
||||
SignCSR(ctx context.Context, csr *x509.CertificateRequest, msg *PKIMessage) (*PKIMessage, error)
|
||||
CreateFailureResponse(ctx context.Context, csr *x509.CertificateRequest, msg *PKIMessage, info FailInfoName, infoText string) (*PKIMessage, error)
|
||||
MatchChallengePassword(ctx context.Context, password string) (bool, error)
|
||||
GetCACaps(ctx context.Context) []string
|
||||
}
|
||||
|
||||
// Authority is the layer that handles all SCEP interactions.
|
||||
type Authority struct {
|
||||
prefix string
|
||||
|
@ -180,12 +166,12 @@ func (a *Authority) DecryptPKIEnvelope(ctx context.Context, msg *PKIMessage) err
|
|||
|
||||
p7c, err := pkcs7.Parse(msg.P7.Content)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error parsing pkcs7 content")
|
||||
return fmt.Errorf("error parsing pkcs7 content: %w", err)
|
||||
}
|
||||
|
||||
envelope, err := p7c.Decrypt(a.intermediateCertificate, a.service.decrypter)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error decrypting encrypted pkcs7 content")
|
||||
return fmt.Errorf("error decrypting encrypted pkcs7 content: %w", err)
|
||||
}
|
||||
|
||||
msg.pkiEnvelope = envelope
|
||||
|
@ -194,19 +180,19 @@ func (a *Authority) DecryptPKIEnvelope(ctx context.Context, msg *PKIMessage) err
|
|||
case microscep.CertRep:
|
||||
certs, err := microscep.CACerts(msg.pkiEnvelope)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error extracting CA certs from pkcs7 degenerate data")
|
||||
return fmt.Errorf("error extracting CA certs from pkcs7 degenerate data: %w", err)
|
||||
}
|
||||
msg.CertRepMessage.Certificate = certs[0]
|
||||
return nil
|
||||
case microscep.PKCSReq, microscep.UpdateReq, microscep.RenewalReq:
|
||||
csr, err := x509.ParseCertificateRequest(msg.pkiEnvelope)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "parse CSR from pkiEnvelope")
|
||||
return fmt.Errorf("parse CSR from pkiEnvelope: %w", err)
|
||||
}
|
||||
// check for challengePassword
|
||||
cp, err := microx509util.ParseChallengePassword(msg.pkiEnvelope)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "parse challenge password in pkiEnvelope")
|
||||
return fmt.Errorf("parse challenge password in pkiEnvelope: %w", err)
|
||||
}
|
||||
msg.CSRReqMessage = µscep.CSRReqMessage{
|
||||
RawDecrypted: msg.pkiEnvelope,
|
||||
|
@ -215,7 +201,7 @@ func (a *Authority) DecryptPKIEnvelope(ctx context.Context, msg *PKIMessage) err
|
|||
}
|
||||
return nil
|
||||
case microscep.GetCRL, microscep.GetCert, microscep.CertPoll:
|
||||
return errors.Errorf("not implemented")
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -274,19 +260,19 @@ func (a *Authority) SignCSR(ctx context.Context, csr *x509.CertificateRequest, m
|
|||
ctx = provisioner.NewContextWithMethod(ctx, provisioner.SignMethod)
|
||||
signOps, err := p.AuthorizeSign(ctx, "")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error retrieving authorization options from SCEP provisioner")
|
||||
return nil, fmt.Errorf("error retrieving authorization options from SCEP provisioner: %w", err)
|
||||
}
|
||||
|
||||
opts := provisioner.SignOptions{}
|
||||
templateOptions, err := provisioner.TemplateOptions(p.GetOptions(), data)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error creating template options from SCEP provisioner")
|
||||
return nil, fmt.Errorf("error creating template options from SCEP provisioner: %w", err)
|
||||
}
|
||||
signOps = append(signOps, templateOptions)
|
||||
|
||||
certChain, err := a.signAuth.Sign(csr, opts, signOps...)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error generating certificate for order")
|
||||
return nil, fmt.Errorf("error generating certificate for order: %w", err)
|
||||
}
|
||||
|
||||
// take the issued certificate (only); https://tools.ietf.org/html/rfc8894#section-3.3.2
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// Package scep implements Simple Certificate Enrollment Protocol related functionality.
|
||||
package scep
|
||||
|
||||
import (
|
||||
|
@ -5,9 +6,6 @@ import (
|
|||
"encoding/asn1"
|
||||
|
||||
microscep "github.com/micromdm/scep/v2/scep"
|
||||
|
||||
//"github.com/smallstep/certificates/scep/pkcs7"
|
||||
|
||||
"go.mozilla.org/pkcs7"
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in a new issue