bundle.go 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. // Package bundle implements the HTTP handler for the bundle command.
  2. package bundle
  3. import (
  4. "net/http"
  5. "github.com/cloudflare/cfssl/api"
  6. "github.com/cloudflare/cfssl/bundler"
  7. "github.com/cloudflare/cfssl/errors"
  8. "github.com/cloudflare/cfssl/log"
  9. )
  10. // Handler accepts requests for either remote or uploaded
  11. // certificates to be bundled, and returns a certificate bundle (or
  12. // error).
  13. type Handler struct {
  14. bundler *bundler.Bundler
  15. }
  16. // NewHandler creates a new bundler that uses the root bundle and
  17. // intermediate bundle in the trust chain.
  18. func NewHandler(caBundleFile, intBundleFile string) (http.Handler, error) {
  19. var err error
  20. b := new(Handler)
  21. if b.bundler, err = bundler.NewBundler(caBundleFile, intBundleFile); err != nil {
  22. return nil, err
  23. }
  24. log.Info("bundler API ready")
  25. return api.HTTPHandler{Handler: b, Methods: []string{"POST"}}, nil
  26. }
  27. // Handle implements an http.Handler interface for the bundle handler.
  28. func (h *Handler) Handle(w http.ResponseWriter, r *http.Request) error {
  29. blob, matched, err := api.ProcessRequestFirstMatchOf(r,
  30. [][]string{
  31. {"certificate"},
  32. {"domain"},
  33. })
  34. if err != nil {
  35. log.Warningf("invalid request: %v", err)
  36. return err
  37. }
  38. flavor := blob["flavor"]
  39. bf := bundler.Ubiquitous
  40. if flavor != "" {
  41. bf = bundler.BundleFlavor(flavor)
  42. }
  43. log.Infof("request for flavor %v", bf)
  44. var result *bundler.Bundle
  45. switch matched[0] {
  46. case "domain":
  47. bundle, err := h.bundler.BundleFromRemote(blob["domain"], blob["ip"], bf)
  48. if err != nil {
  49. log.Warningf("couldn't bundle from remote: %v", err)
  50. return err
  51. }
  52. result = bundle
  53. case "certificate":
  54. bundle, err := h.bundler.BundleFromPEMorDER([]byte(blob["certificate"]), []byte(blob["private_key"]), bf, "")
  55. if err != nil {
  56. log.Warning("bad PEM certificate or private key")
  57. return err
  58. }
  59. serverName := blob["domain"]
  60. ip := blob["ip"]
  61. if serverName != "" {
  62. err := bundle.Cert.VerifyHostname(serverName)
  63. if err != nil {
  64. return errors.Wrap(errors.CertificateError, errors.VerifyFailed, err)
  65. }
  66. }
  67. if ip != "" {
  68. err := bundle.Cert.VerifyHostname(ip)
  69. if err != nil {
  70. return errors.Wrap(errors.CertificateError, errors.VerifyFailed, err)
  71. }
  72. }
  73. result = bundle
  74. }
  75. log.Info("wrote response")
  76. return api.SendResponse(w, result)
  77. }