Vendor cfssl and cfssljson
This commit is contained in:
294
vendor/github.com/cloudflare/cfssl/api/signhandler/signhandler.go
generated
vendored
Normal file
294
vendor/github.com/cloudflare/cfssl/api/signhandler/signhandler.go
generated
vendored
Normal file
@@ -0,0 +1,294 @@
|
||||
// Package signhandler provides the handlers for signers.
|
||||
package signhandler
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"net/http"
|
||||
|
||||
"github.com/cloudflare/cfssl/api"
|
||||
"github.com/cloudflare/cfssl/auth"
|
||||
"github.com/cloudflare/cfssl/bundler"
|
||||
"github.com/cloudflare/cfssl/errors"
|
||||
"github.com/cloudflare/cfssl/log"
|
||||
"github.com/cloudflare/cfssl/signer"
|
||||
)
|
||||
|
||||
// NoBundlerMessage is used to alert the user that the server does not have a bundler initialized.
|
||||
const NoBundlerMessage = `This request requires a bundler, but one is not initialized for the API server.`
|
||||
|
||||
// A Handler accepts requests with a hostname and certficate
|
||||
// parameter (which should be PEM-encoded) and returns a new signed
|
||||
// certificate. It includes upstream servers indexed by their
|
||||
// profile name.
|
||||
type Handler struct {
|
||||
signer signer.Signer
|
||||
bundler *bundler.Bundler
|
||||
}
|
||||
|
||||
// NewHandlerFromSigner generates a new Handler directly from
|
||||
// an existing signer.
|
||||
func NewHandlerFromSigner(signer signer.Signer) (h *api.HTTPHandler, err error) {
|
||||
policy := signer.Policy()
|
||||
if policy == nil {
|
||||
err = errors.New(errors.PolicyError, errors.InvalidPolicy)
|
||||
return
|
||||
}
|
||||
|
||||
// Sign will only respond for profiles that have no auth provider.
|
||||
// So if all of the profiles require authentication, we return an error.
|
||||
haveUnauth := (policy.Default.Provider == nil)
|
||||
for _, profile := range policy.Profiles {
|
||||
haveUnauth = haveUnauth || (profile.Provider == nil)
|
||||
}
|
||||
|
||||
if !haveUnauth {
|
||||
err = errors.New(errors.PolicyError, errors.InvalidPolicy)
|
||||
return
|
||||
}
|
||||
|
||||
return &api.HTTPHandler{
|
||||
Handler: &Handler{
|
||||
signer: signer,
|
||||
},
|
||||
Methods: []string{"POST"},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SetBundler allows injecting an optional Bundler into the Handler.
|
||||
func (h *Handler) SetBundler(caBundleFile, intBundleFile string) (err error) {
|
||||
h.bundler, err = bundler.NewBundler(caBundleFile, intBundleFile)
|
||||
return err
|
||||
}
|
||||
|
||||
// This type is meant to be unmarshalled from JSON so that there can be a
|
||||
// hostname field in the API
|
||||
// TODO: Change the API such that the normal struct can be used.
|
||||
type jsonSignRequest struct {
|
||||
Hostname string `json:"hostname"`
|
||||
Hosts []string `json:"hosts"`
|
||||
Request string `json:"certificate_request"`
|
||||
Subject *signer.Subject `json:"subject,omitempty"`
|
||||
Profile string `json:"profile"`
|
||||
Label string `json:"label"`
|
||||
Serial *big.Int `json:"serial,omitempty"`
|
||||
Bundle bool `json:"bundle"`
|
||||
}
|
||||
|
||||
func jsonReqToTrue(js jsonSignRequest) signer.SignRequest {
|
||||
sub := new(signer.Subject)
|
||||
if js.Subject == nil {
|
||||
sub = nil
|
||||
} else {
|
||||
// make a copy
|
||||
*sub = *js.Subject
|
||||
}
|
||||
|
||||
if js.Hostname != "" {
|
||||
return signer.SignRequest{
|
||||
Hosts: signer.SplitHosts(js.Hostname),
|
||||
Subject: sub,
|
||||
Request: js.Request,
|
||||
Profile: js.Profile,
|
||||
Label: js.Label,
|
||||
Serial: js.Serial,
|
||||
}
|
||||
}
|
||||
|
||||
return signer.SignRequest{
|
||||
Hosts: js.Hosts,
|
||||
Subject: sub,
|
||||
Request: js.Request,
|
||||
Profile: js.Profile,
|
||||
Label: js.Label,
|
||||
Serial: js.Serial,
|
||||
}
|
||||
}
|
||||
|
||||
// Handle responds to requests for the CA to sign the certificate request
|
||||
// present in the "certificate_request" parameter for the host named
|
||||
// in the "hostname" parameter. The certificate should be PEM-encoded. If
|
||||
// provided, subject information from the "subject" parameter will be used
|
||||
// in place of the subject information from the CSR.
|
||||
func (h *Handler) Handle(w http.ResponseWriter, r *http.Request) error {
|
||||
log.Info("signature request received")
|
||||
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.Body.Close()
|
||||
|
||||
var req jsonSignRequest
|
||||
|
||||
err = json.Unmarshal(body, &req)
|
||||
if err != nil {
|
||||
return errors.NewBadRequestString("Unable to parse sign request")
|
||||
}
|
||||
|
||||
signReq := jsonReqToTrue(req)
|
||||
|
||||
if req.Request == "" {
|
||||
return errors.NewBadRequestString("missing parameter 'certificate_request'")
|
||||
}
|
||||
|
||||
var cert []byte
|
||||
profile, err := signer.Profile(h.signer, req.Profile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if profile.Provider != nil {
|
||||
log.Error("profile requires authentication")
|
||||
return errors.NewBadRequestString("authentication required")
|
||||
}
|
||||
|
||||
cert, err = h.signer.Sign(signReq)
|
||||
if err != nil {
|
||||
log.Warningf("failed to sign request: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
result := map[string]interface{}{"certificate": string(cert)}
|
||||
if req.Bundle {
|
||||
if h.bundler == nil {
|
||||
return api.SendResponseWithMessage(w, result, NoBundlerMessage,
|
||||
errors.New(errors.PolicyError, errors.InvalidRequest).ErrorCode)
|
||||
}
|
||||
|
||||
bundle, err := h.bundler.BundleFromPEMorDER(cert, nil, bundler.Optimal, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result["bundle"] = bundle
|
||||
}
|
||||
log.Info("wrote response")
|
||||
return api.SendResponse(w, result)
|
||||
}
|
||||
|
||||
// An AuthHandler verifies and signs incoming signature requests.
|
||||
type AuthHandler struct {
|
||||
signer signer.Signer
|
||||
bundler *bundler.Bundler
|
||||
}
|
||||
|
||||
// NewAuthHandlerFromSigner creates a new AuthHandler from the signer
|
||||
// that is passed in.
|
||||
func NewAuthHandlerFromSigner(signer signer.Signer) (http.Handler, error) {
|
||||
policy := signer.Policy()
|
||||
if policy == nil {
|
||||
return nil, errors.New(errors.PolicyError, errors.InvalidPolicy)
|
||||
}
|
||||
|
||||
if policy.Default == nil && policy.Profiles == nil {
|
||||
return nil, errors.New(errors.PolicyError, errors.InvalidPolicy)
|
||||
}
|
||||
|
||||
// AuthSign will not respond for profiles that have no auth provider.
|
||||
// So if there are no profiles with auth providers in this policy,
|
||||
// we return an error.
|
||||
haveAuth := (policy.Default.Provider != nil)
|
||||
for _, profile := range policy.Profiles {
|
||||
if haveAuth {
|
||||
break
|
||||
}
|
||||
haveAuth = (profile.Provider != nil)
|
||||
}
|
||||
|
||||
if !haveAuth {
|
||||
return nil, errors.New(errors.PolicyError, errors.InvalidPolicy)
|
||||
}
|
||||
|
||||
return &api.HTTPHandler{
|
||||
Handler: &AuthHandler{
|
||||
signer: signer,
|
||||
},
|
||||
Methods: []string{"POST"},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SetBundler allows injecting an optional Bundler into the Handler.
|
||||
func (h *AuthHandler) SetBundler(caBundleFile, intBundleFile string) (err error) {
|
||||
h.bundler, err = bundler.NewBundler(caBundleFile, intBundleFile)
|
||||
return err
|
||||
}
|
||||
|
||||
// Handle receives the incoming request, validates it, and processes it.
|
||||
func (h *AuthHandler) Handle(w http.ResponseWriter, r *http.Request) error {
|
||||
log.Info("signature request received")
|
||||
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
log.Errorf("failed to read response body: %v", err)
|
||||
return err
|
||||
}
|
||||
r.Body.Close()
|
||||
|
||||
var aReq auth.AuthenticatedRequest
|
||||
err = json.Unmarshal(body, &aReq)
|
||||
if err != nil {
|
||||
log.Errorf("failed to unmarshal authenticated request: %v", err)
|
||||
return errors.NewBadRequest(err)
|
||||
}
|
||||
|
||||
var req jsonSignRequest
|
||||
err = json.Unmarshal(aReq.Request, &req)
|
||||
if err != nil {
|
||||
log.Errorf("failed to unmarshal request from authenticated request: %v", err)
|
||||
return errors.NewBadRequestString("Unable to parse authenticated sign request")
|
||||
}
|
||||
|
||||
// Sanity checks to ensure that we have a valid policy. This
|
||||
// should have been checked in NewAuthHandler.
|
||||
policy := h.signer.Policy()
|
||||
if policy == nil {
|
||||
log.Critical("signer was initialised without a signing policy")
|
||||
return errors.NewBadRequestString("invalid policy")
|
||||
}
|
||||
|
||||
profile, err := signer.Profile(h.signer, req.Profile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if profile.Provider == nil {
|
||||
log.Error("profile has no authentication provider")
|
||||
return errors.NewBadRequestString("no authentication provider")
|
||||
}
|
||||
|
||||
if !profile.Provider.Verify(&aReq) {
|
||||
log.Warning("received authenticated request with invalid token")
|
||||
return errors.NewBadRequestString("invalid token")
|
||||
}
|
||||
|
||||
signReq := jsonReqToTrue(req)
|
||||
|
||||
if signReq.Request == "" {
|
||||
return errors.NewBadRequestString("missing parameter 'certificate_request'")
|
||||
}
|
||||
|
||||
cert, err := h.signer.Sign(signReq)
|
||||
if err != nil {
|
||||
log.Errorf("signature failed: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
result := map[string]interface{}{"certificate": string(cert)}
|
||||
if req.Bundle {
|
||||
if h.bundler == nil {
|
||||
return api.SendResponseWithMessage(w, result, NoBundlerMessage,
|
||||
errors.New(errors.PolicyError, errors.InvalidRequest).ErrorCode)
|
||||
}
|
||||
|
||||
bundle, err := h.bundler.BundleFromPEMorDER(cert, nil, bundler.Optimal, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result["bundle"] = bundle
|
||||
}
|
||||
log.Info("wrote response")
|
||||
return api.SendResponse(w, result)
|
||||
}
|
Reference in New Issue
Block a user