Ejemplo n.º 1
0
// initialCAHandler is an HTTP handler that accepts a JSON blob in the
// same format as the CSR endpoint; this blob should contain the
// identity information for the CA's root key. This endpoint is not
// suitable for creating intermediate certificates.
func initialCAHandler(w http.ResponseWriter, r *http.Request) error {
	log.Info("setting up initial CA handler")
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		log.Warningf("failed to read request body: %v", err)
		return errors.NewBadRequest(err)
	}

	req := new(csr.CertificateRequest)
	req.KeyRequest = csr.NewBasicKeyRequest()
	err = json.Unmarshal(body, req)
	if err != nil {
		log.Warningf("failed to unmarshal request: %v", err)
		return errors.NewBadRequest(err)
	}

	cert, _, key, err := initca.New(req)
	if err != nil {
		log.Warningf("failed to initialise new CA: %v", err)
		return err
	}

	response := api.NewSuccessResponse(&NewCA{string(key), string(cert)})

	enc := json.NewEncoder(w)
	err = enc.Encode(response)
	return err
}
Ejemplo n.º 2
0
// RefreshKeys will make sure the Transport has loaded keys and has a
// valid certificate. It will handle any persistence, check that the
// certificate is valid (i.e. that its expiry date is within the
// Before date), and handle certificate reissuance as needed.
func (tr *Transport) RefreshKeys() (err error) {
	if !tr.Provider.Ready() {
		log.Debug("key and certificate aren't ready, loading")
		err = tr.Provider.Load()
		if err != nil && err != kp.ErrCertificateUnavailable {
			log.Debugf("failed to load keypair: %v", err)
			kr := tr.Identity.Request.KeyRequest
			if kr == nil {
				kr = csr.NewBasicKeyRequest()
			}

			err = tr.Provider.Generate(kr.Algo(), kr.Size())
			if err != nil {
				log.Debugf("failed to generate key: %v", err)
				return
			}
		}
	}

	lifespan := tr.Lifespan()
	if lifespan < tr.Before {
		log.Debugf("transport's certificate is out of date (lifespan %s)", lifespan)
		req, err := tr.Provider.CertificateRequest(tr.Identity.Request)
		if err != nil {
			log.Debugf("couldn't get a CSR: %v", err)
			return err
		}

		log.Debug("requesting certificate from CA")
		cert, err := tr.CA.SignCSR(req)
		if err != nil {
			log.Debugf("failed to get the certificate signed: %v", err)
			return err
		}

		log.Debug("giving the certificate to the provider")
		err = tr.Provider.SetCertificatePEM(cert)
		if err != nil {
			log.Debugf("failed to set the provider's certificate: %v", err)
			return err
		}

		log.Debug("storing the certificate")
		err = tr.Provider.Store()
		if err != nil {
			log.Debugf("the provider failed to store the certificate: %v", err)
			return err
		}
	}

	return nil
}
Ejemplo n.º 3
0
func genkeyMain(args []string, c cli.Config) (err error) {
	csrFile, args, err := cli.PopFirstArgument(args)
	if err != nil {
		return
	}

	csrFileBytes, err := cli.ReadStdin(csrFile)
	if err != nil {
		return
	}

	req := csr.CertificateRequest{
		KeyRequest: csr.NewBasicKeyRequest(),
	}
	err = json.Unmarshal(csrFileBytes, &req)
	if err != nil {
		return
	}

	if c.IsCA {
		var key, csrPEM, cert []byte
		cert, csrPEM, key, err = initca.New(&req)
		if err != nil {
			return
		}

		cli.PrintCert(key, csrPEM, cert)
	} else {
		if req.CA != nil {
			err = errors.New("ca section only permitted in initca")
			return
		}

		var key, csrPEM []byte
		g := &csr.Generator{Validator: Validator}
		csrPEM, key, err = g.ProcessRequest(&req)
		if err != nil {
			key = nil
			return
		}

		cli.PrintCert(key, csrPEM, nil)
	}
	return nil
}
Ejemplo n.º 4
0
// Handle responds to requests for the CA to generate a new private
// key and certificate request on behalf of the client. The format for
// these requests is documented in the API documentation.
func (g *Handler) Handle(w http.ResponseWriter, r *http.Request) error {
	log.Info("request for CSR")
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		log.Warningf("failed to read request body: %v", err)
		return errors.NewBadRequest(err)
	}

	req := new(csr.CertificateRequest)
	req.KeyRequest = csr.NewBasicKeyRequest()
	err = json.Unmarshal(body, req)
	if err != nil {
		log.Warningf("failed to unmarshal request: %v", err)
		return errors.NewBadRequest(err)
	}

	if req.CA != nil {
		log.Warningf("request received with CA section")
		return errors.NewBadRequestString("ca section only permitted in initca")
	}

	csr, key, err := g.generator.ProcessRequest(req)
	if err != nil {
		log.Warningf("failed to process CSR: %v", err)
		// The validator returns a *cfssl/errors.HttpError
		return err
	}

	sum, err := computeSum(csr)
	if err != nil {
		return errors.NewBadRequest(err)
	}

	// Both key and csr are returned PEM-encoded.
	response := api.NewSuccessResponse(&CertRequest{
		Key:  string(key),
		CSR:  string(csr),
		Sums: map[string]Sum{"certificate_request": sum},
	})
	w.Header().Set("Content-Type", "application/json")
	enc := json.NewEncoder(w)
	err = enc.Encode(response)
	return err
}
Ejemplo n.º 5
0
func TestCSRValidate(t *testing.T) {
	req := &csr.CertificateRequest{
		Names: []csr.Name{
			{
				C:  "US",
				ST: "California",
				L:  "San Francisco",
				O:  "CloudFlare",
				OU: "Systems Engineering",
			},
		},
		CN:         "cloudflare.com",
		Hosts:      []string{},
		KeyRequest: csr.NewBasicKeyRequest(),
	}
	err := CSRValidate(req)
	if err != nil {
		t.Fatal("There should be not an error for missing Hosts parameter")
	}
}
Ejemplo n.º 6
0
func csrData(t *testing.T) *bytes.Reader {
	req := &csr.CertificateRequest{
		Names: []csr.Name{
			{
				C:  "US",
				ST: "California",
				L:  "San Francisco",
				O:  "CloudFlare",
				OU: "Systems Engineering",
			},
		},
		CN:         "cloudflare.com",
		Hosts:      []string{"cloudflare.com"},
		KeyRequest: csr.NewBasicKeyRequest(),
	}
	csrBytes, err := json.Marshal(req)
	if err != nil {
		t.Fatal(err)
	}
	return bytes.NewReader(csrBytes)
}
Ejemplo n.º 7
0
func gencertMain(args []string, c cli.Config) error {
	if c.RenewCA {
		log.Infof("re-generate a CA certificate from CA cert and key")
		cert, err := initca.RenewFromPEM(c.CAFile, c.CAKeyFile)
		if err != nil {
			log.Errorf("%v\n", err)
			return err
		}
		cli.PrintCert(nil, nil, cert)
		return nil
	}

	csrJSONFile, args, err := cli.PopFirstArgument(args)
	if err != nil {
		return err
	}

	csrJSONFileBytes, err := cli.ReadStdin(csrJSONFile)
	if err != nil {
		return err
	}

	req := csr.CertificateRequest{
		KeyRequest: csr.NewBasicKeyRequest(),
	}
	err = json.Unmarshal(csrJSONFileBytes, &req)
	if err != nil {
		return err
	}
	switch {
	case c.IsCA:
		var key, csrPEM, cert []byte
		if c.CAKeyFile != "" {
			log.Infof("re-generate a CA certificate from CSR and CA key")
			cert, csrPEM, err = initca.NewFromPEM(&req, c.CAKeyFile)
			if err != nil {
				log.Errorf("%v\n", err)
				return err
			}
		} else {
			log.Infof("generating a new CA key and certificate from CSR")
			cert, csrPEM, key, err = initca.New(&req)
			if err != nil {
				return err
			}

		}
		cli.PrintCert(key, csrPEM, cert)

	default:
		if req.CA != nil {
			err = errors.New("ca section only permitted in initca")
			return err
		}

		// Remote can be forced on the command line or in the config
		if c.Remote == "" && c.CFG == nil {
			if c.CAFile == "" {
				log.Error("need a CA certificate (provide one with -ca)")
				return nil
			}

			if c.CAKeyFile == "" {
				log.Error("need a CA key (provide one with -ca-key)")
				return nil
			}
		}

		var key, csrBytes []byte
		g := &csr.Generator{Validator: genkey.Validator}
		csrBytes, key, err = g.ProcessRequest(&req)
		if err != nil {
			key = nil
			return err
		}

		s, err := sign.SignerFromConfig(c)
		if err != nil {
			return err
		}

		var cert []byte
		req := signer.SignRequest{
			Request: string(csrBytes),
			Hosts:   signer.SplitHosts(c.Hostname),
			Profile: c.Profile,
			Label:   c.Label,
		}

		cert, err = s.Sign(req)
		if err != nil {
			return err
		}

		// This follows the Baseline Requirements for the Issuance and
		// Management of Publicly-Trusted Certificates, v.1.1.6, from the CA/Browser
		// Forum (https://cabforum.org). Specifically, section 10.2.3 ("Information
		// Requirements"), states:
		//
		// "Applicant information MUST include, but not be limited to, at least one
		// Fully-Qualified Domain Name or IP address to be included in the Certificate’s
		// SubjectAltName extension."
		if len(req.Hosts) == 0 {
			log.Warning(generator.CSRNoHostMessage)
		}

		cli.PrintCert(key, csrBytes, cert)
	}
	return nil
}