Пример #1
0
// NewBundler creates a new Bundler from the files passed in; these
// files should contain a list of valid root certificates and a list
// of valid intermediate certificates, respectively.
func NewBundler(caBundleFile, intBundleFile string) (*Bundler, error) {
	log.Debug("Loading CA bundle: ", caBundleFile)
	caBundle, err := ioutil.ReadFile(caBundleFile)
	if err != nil {
		log.Errorf("root bundle failed to load: %v", err)
		return nil, errors.Wrap(errors.RootError, errors.ReadFailed, err)
	}

	log.Debug("Loading Intermediate bundle: ", intBundleFile)
	intBundle, err := ioutil.ReadFile(intBundleFile)
	if err != nil {
		log.Errorf("intermediate bundle failed to load: %v", err)
		return nil, errors.Wrap(errors.IntermediatesError, errors.ReadFailed, err)
	}

	if _, err := os.Stat(IntermediateStash); err != nil && os.IsNotExist(err) {
		log.Infof("intermediate stash directory %s doesn't exist, creating", IntermediateStash)
		err = os.MkdirAll(IntermediateStash, 0755)
		if err != nil {
			log.Errorf("failed to create intermediate stash directory %s: %v",
				IntermediateStash, err)
			return nil, err
		}
		log.Infof("intermediate stash directory %s created", IntermediateStash)
	}
	return NewBundlerFromPEM(caBundle, intBundle)

}
Пример #2
0
// signWithCSR creates a new root certificate from signing a X509.CertificateRequest
// by a crypto.Signer.
func signWithCSR(tpl *x509.CertificateRequest, priv crypto.Signer, policy *config.Signing) (cert, csrPEM []byte, err error) {
	if policy == nil {
		policy = CAPolicy()
	}
	csrPEM, err = x509.CreateCertificateRequest(rand.Reader, tpl, priv)
	if err != nil {
		log.Errorf("failed to generate a CSR: %v", err)
		// The use of CertificateError was a matter of some
		// debate; it is the one edge case in which a new
		// error category specifically for CSRs might be
		// useful, but it was deemed that one edge case did
		// not a new category justify.
		err = cferr.Wrap(cferr.CertificateError, cferr.BadRequest, err)
		return
	}

	p := &pem.Block{
		Type:  "CERTIFICATE REQUEST",
		Bytes: csrPEM,
	}
	csrPEM = pem.EncodeToMemory(p)

	s, err := local.NewSigner(priv, nil, signer.DefaultSigAlgo(priv), nil)
	if err != nil {
		log.Errorf("failed to create signer: %v", err)
		return
	}
	s.SetPolicy(policy)

	signReq := signer.SignRequest{Request: string(csrPEM)}
	cert, err = s.Sign(signReq)
	return
}
Пример #3
0
// NewBundlerFromPEM creates a new Bundler from PEM-encoded root certificates and
// intermediate certificates.
func NewBundlerFromPEM(caBundlePEM, intBundlePEM []byte) (*Bundler, error) {
	b := &Bundler{
		RootPool:         x509.NewCertPool(),
		IntermediatePool: x509.NewCertPool(),
		KnownIssuers:     map[string]bool{},
	}

	log.Debug("parsing root certificates from PEM")
	roots, err := helpers.ParseCertificatesPEM(caBundlePEM)
	if err != nil {
		log.Errorf("failed to parse root bundle: %v", err)
		return nil, errors.New(errors.RootError, errors.ParseFailed)
	}

	log.Debug("parse intermediate certificates from PEM")
	var intermediates []*x509.Certificate
	if intermediates, err = helpers.ParseCertificatesPEM(intBundlePEM); err != nil {
		log.Errorf("failed to parse intermediate bundle: %v", err)
		return nil, errors.New(errors.IntermediatesError, errors.ParseFailed)
	}

	log.Debug("building certificate pools")
	for _, c := range roots {
		b.RootPool.AddCert(c)
		b.KnownIssuers[string(c.Signature)] = true
	}

	for _, c := range intermediates {
		b.IntermediatePool.AddCert(c)
		b.KnownIssuers[string(c.Signature)] = true
	}

	log.Debug("bundler set up")
	return b, nil
}
Пример #4
0
// makeBundle opens the file for writing, and listens for incoming
// certificates. These are PEM-encoded and written to file.
func makeBundle(filename string, bundler chan *x509.Certificate) {
	file, err := os.Create(filename)
	if err != nil {
		log.Errorf("%v", err)
		return
	}
	defer file.Close()

	var total int
	for {
		cert, ok := <-bundler
		if !ok {
			break
		}
		block := &pem.Block{
			Type:  "CERTIFICATE",
			Bytes: cert.Raw,
		}
		err = pem.Encode(file, block)
		if err != nil {
			log.Errorf("Failed to write PEM block: %v", err)
			break
		}
		total++
	}
	log.Infof("Wrote %d certificates.", total)
}
Пример #5
0
// NewSourceFromFile reads the named file into an InMemorySource.
// The file read by this function must contain whitespace-separated OCSP
// responses. Each OCSP response must be in base64-encoded DER form (i.e.,
// PEM without headers or whitespace).  Invalid responses are ignored.
// This function pulls the entire file into an InMemorySource.
func NewSourceFromFile(responseFile string) (Source, error) {
	fileContents, err := ioutil.ReadFile(responseFile)
	if err != nil {
		return nil, err
	}

	responsesB64 := regexp.MustCompile("\\s").Split(string(fileContents), -1)
	src := InMemorySource{}
	for _, b64 := range responsesB64 {
		// if the line/space is empty just skip
		if b64 == "" {
			continue
		}
		der, tmpErr := base64.StdEncoding.DecodeString(b64)
		if tmpErr != nil {
			log.Errorf("Base64 decode error on: %s", b64)
			continue
		}

		response, tmpErr := ocsp.ParseResponse(der, nil)
		if tmpErr != nil {
			log.Errorf("OCSP decode error on: %s", b64)
			continue
		}

		src[response.SerialNumber.String()] = der
	}

	log.Infof("Read %d OCSP responses", len(src))
	return src, nil
}
Пример #6
0
// LoadPlatforms reads the file content as a json object array and convert it
// to Platforms.
func LoadPlatforms(filename string) {
	// Attempt to load root certificate metadata
	log.Debug("Loading platform metadata: ", filename)
	bytes, err := ioutil.ReadFile(filename)
	if err != nil {
		log.Errorf("platform metadata failed to load: %v", err)
	}
	var rawPlatforms []Platform
	if bytes != nil {
		err = json.Unmarshal(bytes, &rawPlatforms)
		if err != nil {
			log.Errorf("platform metadata failed to parse: %v", err)
		}
	}

	for _, platform := range rawPlatforms {
		ok := platform.ParseAndLoad()
		if !ok {
			log.Errorf("fail to finalize the parsing of platform metadata:", err)
		} else {
			log.Infof("Platform metadata is loaded: %v %v", platform.Name, len(platform.KeyStore))
			Platforms = append(Platforms, platform)
		}
	}
}
Пример #7
0
// A Responder can process both GET and POST requests.  The mapping
// from an OCSP request to an OCSP response is done by the Source;
// the Responder simply decodes the request, and passes back whatever
// response is provided by the source.
func (rs Responder) ServeHTTP(response http.ResponseWriter, request *http.Request) {
	// Read response from request
	var requestBody []byte
	var err error
	switch request.Method {
	case "GET":
		re := regexp.MustCompile("^.*/")
		base64Request := re.ReplaceAllString(request.RequestURI, "")
		base64Request, err = url.QueryUnescape(base64Request)
		if err != nil {
			return
		}
		requestBody, err = base64.StdEncoding.DecodeString(base64Request)
		if err != nil {
			return
		}
	case "POST":
		requestBody, err = ioutil.ReadAll(request.Body)
		if err != nil {
			response.WriteHeader(http.StatusBadRequest)
			return
		}
	default:
		response.WriteHeader(http.StatusMethodNotAllowed)
		return
	}
	// TODO log request
	b64Body := base64.StdEncoding.EncodeToString(requestBody)
	log.Infof("Received OCSP request: %s", b64Body)

	// All responses after this point will be OCSP.
	// We could check for the content type of the request, but that
	// seems unnecessariliy restrictive.
	response.Header().Add("Content-Type", "application/ocsp-response")

	// Parse response as an OCSP request
	// XXX: This fails if the request contains the nonce extension.
	//      We don't intend to support nonces anyway, but maybe we
	//      should return unauthorizedRequest instead of malformed.
	ocspRequest, err := ocsp.ParseRequest(requestBody)
	if err != nil {
		log.Errorf("Error decoding request body: %s", b64Body)
		response.Write(malformedRequestErrorResponse)
		return
	}

	// Look up OCSP response from source
	ocspResponse, found := rs.Source.Response(ocspRequest)
	if !found {
		log.Errorf("No response found for request: %s", b64Body)
		response.Write(unauthorizedErrorResponse)
		return
	}

	// Write OCSP response to response
	response.WriteHeader(http.StatusOK)
	response.Write(ocspResponse)
}
Пример #8
0
// createAndWriteca.RootCA creates a Certificate authority for a new Swarm Cluster.
// We're copying CreateAndWriteca.RootCA, so we can have smaller key-sizes for tests
func createAndWriteRootCA(rootCN string, paths ca.CertPaths, expiry time.Duration) (ca.RootCA, error) {
	// Create a simple CSR for the CA using the default CA validator and policy
	req := cfcsr.CertificateRequest{
		CN:         rootCN,
		KeyRequest: cfcsr.NewBasicKeyRequest(),
		CA:         &cfcsr.CAConfig{Expiry: ca.RootCAExpiration},
	}

	// Generate the CA and get the certificate and private key
	cert, _, key, err := initca.New(&req)
	if err != nil {
		return ca.RootCA{}, err
	}

	// Convert the key given by initca to an object to create a ca.RootCA
	parsedKey, err := helpers.ParsePrivateKeyPEM(key)
	if err != nil {
		log.Errorf("failed to parse private key: %v", err)
		return ca.RootCA{}, err
	}

	// Convert the certificate into an object to create a ca.RootCA
	parsedCert, err := helpers.ParseCertificatePEM(cert)
	if err != nil {
		return ca.RootCA{}, err
	}

	// Create a Signer out of the private key
	signer, err := local.NewSigner(parsedKey, parsedCert, cfsigner.DefaultSigAlgo(parsedKey), ca.SigningPolicy(expiry))
	if err != nil {
		log.Errorf("failed to create signer: %v", err)
		return ca.RootCA{}, err
	}

	// Ensure directory exists
	err = os.MkdirAll(filepath.Dir(paths.Cert), 0755)
	if err != nil {
		return ca.RootCA{}, err
	}

	// Write the Private Key and Certificate to disk, using decent permissions
	if err := ioutils.AtomicWriteFile(paths.Cert, cert, 0644); err != nil {
		return ca.RootCA{}, err
	}
	if err := ioutils.AtomicWriteFile(paths.Key, key, 0600); err != nil {
		return ca.RootCA{}, err
	}

	// Create a Pool with our Root CA Certificate
	pool := x509.NewCertPool()
	if !pool.AppendCertsFromPEM(cert) {
		return ca.RootCA{}, fmt.Errorf("failed to append certificate to cert pool")
	}

	return ca.RootCA{Signer: signer, Key: key, Cert: cert, Pool: pool}, nil
}
Пример #9
0
// createAndWriteRootCA creates a Certificate authority for a new Swarm Cluster.
// We're copying ca.CreateRootCA, so we can have smaller key-sizes for tests
func createAndWriteRootCA(rootCN string, paths ca.CertPaths, expiry time.Duration) (ca.RootCA, error) {
	cert, key, err := CreateRootCertAndKey(rootCN)
	if err != nil {
		return ca.RootCA{}, err
	}

	// Convert the key given by initca to an object to create a ca.RootCA
	parsedKey, err := helpers.ParsePrivateKeyPEM(key)
	if err != nil {
		log.Errorf("failed to parse private key: %v", err)
		return ca.RootCA{}, err
	}

	// Convert the certificate into an object to create a ca.RootCA
	parsedCert, err := helpers.ParseCertificatePEM(cert)
	if err != nil {
		return ca.RootCA{}, err
	}

	// Create a Signer out of the private key
	signer, err := local.NewSigner(parsedKey, parsedCert, cfsigner.DefaultSigAlgo(parsedKey), ca.SigningPolicy(expiry))
	if err != nil {
		log.Errorf("failed to create signer: %v", err)
		return ca.RootCA{}, err
	}

	// Ensure directory exists
	err = os.MkdirAll(filepath.Dir(paths.Cert), 0755)
	if err != nil {
		return ca.RootCA{}, err
	}

	// Write the Private Key and Certificate to disk, using decent permissions
	if err := ioutils.AtomicWriteFile(paths.Cert, cert, 0644); err != nil {
		return ca.RootCA{}, err
	}
	if err := ioutils.AtomicWriteFile(paths.Key, key, 0600); err != nil {
		return ca.RootCA{}, err
	}

	// Create a Pool with our Root CA Certificate
	pool := x509.NewCertPool()
	if !pool.AppendCertsFromPEM(cert) {
		return ca.RootCA{}, errors.New("failed to append certificate to cert pool")
	}

	return ca.RootCA{
		Signer: signer,
		Key:    key,
		Cert:   cert,
		Pool:   pool,
		Digest: digest.FromBytes(cert),
	}, nil
}
Пример #10
0
// registerHandlers instantiates various handlers and assoicate them to corresponding endpoints.
func registerHandlers() error {
	log.Info("Setting up signer endpoint")
	signHandler, err := api.NewSignHandler(Config.caFile, Config.caKeyFile)
	if err != nil {
		log.Warningf("endpoint '/api/v1/cfssl/sign' is disabled: %v", err)
	} else {
		http.Handle("/api/v1/cfssl/sign", signHandler)
	}

	log.Info("Setting up bundler endpoint")
	bundleHandler, err := api.NewBundleHandler(Config.caBundleFile, Config.intBundleFile)
	if err != nil {
		log.Warningf("endpoint '/api/v1/cfssl/bundle' is disabled: %v", err)
	} else {
		http.Handle("/api/v1/cfssl/bundle", bundleHandler)
	}

	log.Info("Setting up CSR endpoint")
	generatorHandler, err := api.NewGeneratorHandler(api.CSRValidate)
	if err != nil {
		log.Errorf("Failed to set up CSR endpoint: %v", err)
		return err
	}
	http.Handle("/api/v1/cfssl/newkey", generatorHandler)

	log.Info("Setting up new cert endpoint")
	newCertGenerator, err := api.NewCertGeneratorHandler(api.CSRValidate,
		Config.caFile, Config.caKeyFile)
	if err != nil {
		log.Errorf("endpoint '/api/v1/cfssl/newcert' is disabled")
	} else {
		http.Handle("/api/v1/cfssl/newcert", newCertGenerator)
	}

	log.Info("Setting up initial CA endpoint")
	http.Handle("/api/v1/cfssl/init_ca", api.NewInitCAHandler())

	if Config.remote != "" {
		log.Info("Remote CFSSL endpoint given, setting up remote certificate generator")
		if rcg, err := api.NewRemoteCertGenerator(api.CSRValidate, Config.remote); err != nil {
			log.Errorf("Failed to set up remote certificate generator: %v", err)
			return err
		} else {
			http.Handle("/api/v1/cfssl/remotecert", rcg)
		}
	}

	log.Info("Handler set up complete.")
	return nil
}
Пример #11
0
// HandleError is the centralised error handling and reporting.
func HandleError(w http.ResponseWriter, err error) (code int) {
	if err == nil {
		return http.StatusOK
	}
	msg := err.Error()
	httpCode := http.StatusInternalServerError

	// If it is recognized as HttpError emitted from cfssl,
	// we rewrite the status code accordingly. If it is a
	// cfssl error, set the http status to StatusBadRequest
	switch err := err.(type) {
	case *errors.HTTPError:
		httpCode = err.StatusCode
		code = err.StatusCode
	case *errors.Error:
		httpCode = http.StatusBadRequest
		code = err.ErrorCode
		msg = err.Message
	}

	response := NewErrorResponse(msg, code)
	jsonMessage, err := json.Marshal(response)
	if err != nil {
		log.Errorf("Failed to marshal JSON: %v", err)
	} else {
		msg = string(jsonMessage)
	}
	http.Error(w, msg, httpCode)
	return code
}
Пример #12
0
// NewCertGeneratorHandler builds a new handler for generating
// certificates directly from certificate requests; the validator covers
// the certificate request and the CA's key and certificate are used to
// sign the generated request. If remote is not an empty string, the
// handler will send signature requests to the CFSSL instance contained
// in remote.
func NewCertGeneratorHandler(validator Validator, caFile, caKeyFile string, policy *config.Signing) (http.Handler, error) {
	var err error
	log.Info("setting up new generator / signer")
	cg := new(CertGeneratorHandler)

	if policy == nil {
		policy = &config.Signing{
			Default:  config.DefaultConfig(),
			Profiles: nil,
		}
	}

	root := universal.Root{
		Config: map[string]string{
			"ca-file":     caFile,
			"ca-key-file": caKeyFile,
		},
	}
	if cg.signer, err = universal.NewSigner(root, policy); err != nil {
		log.Errorf("setting up signer failed: %v", err)
		return nil, err
	}

	cg.generator = &csr.Generator{Validator: validator}

	return api.HTTPHandler{Handler: cg, Methods: []string{"POST"}}, nil
}
Пример #13
0
// NewFromSigner creates a new root certificate from a crypto.Signer.
func NewFromSigner(req *csr.CertificateRequest, priv crypto.Signer) (cert, csrPEM []byte, err error) {
	policy := CAPolicy()
	if req.CA != nil {
		if req.CA.Expiry != "" {
			policy.Default.ExpiryString = req.CA.Expiry
			policy.Default.Expiry, err = time.ParseDuration(req.CA.Expiry)
			if err != nil {
				return nil, nil, err
			}
		}

		signer.MaxPathLen = req.CA.PathLength
		if req.CA.PathLength != 0 && req.CA.PathLenZero == true {
			log.Infof("ignore invalid 'pathlenzero' value")
		} else {
			signer.MaxPathLenZero = req.CA.PathLenZero
		}
	}

	csrPEM, err = csr.Generate(priv, req)
	if err != nil {
		return nil, nil, err
	}

	s, err := local.NewSigner(priv, nil, signer.DefaultSigAlgo(priv), nil)
	if err != nil {
		log.Errorf("failed to create signer: %v", err)
		return
	}
	s.SetPolicy(policy)

	signReq := signer.SignRequest{Request: string(csrPEM)}
	cert, err = s.Sign(signReq)
	return
}
Пример #14
0
// Generate creates a new CSR from a CertificateRequest structure and
// an existing key. The KeyRequest field is ignored.
func Generate(priv crypto.Signer, req *CertificateRequest) (csr []byte, err error) {
	sigAlgo := helpers.SignerAlgo(priv, crypto.SHA256)
	if sigAlgo == x509.UnknownSignatureAlgorithm {
		return nil, cferr.New(cferr.PrivateKeyError, cferr.Unavailable)
	}

	var tpl = x509.CertificateRequest{
		Subject:            req.Name(),
		SignatureAlgorithm: sigAlgo,
	}

	for i := range req.Hosts {
		if ip := net.ParseIP(req.Hosts[i]); ip != nil {
			tpl.IPAddresses = append(tpl.IPAddresses, ip)
		} else {
			tpl.DNSNames = append(tpl.DNSNames, req.Hosts[i])
		}
	}

	csr, err = x509.CreateCertificateRequest(rand.Reader, &tpl, priv)
	if err != nil {
		log.Errorf("failed to generate a CSR: %v", err)
		err = cferr.Wrap(cferr.CSRError, cferr.BadRequest, err)
		return
	}
	block := pem.Block{
		Type:  "CERTIFICATE REQUEST",
		Bytes: csr,
	}

	log.Info("encoded CSR")
	csr = pem.EncodeToMemory(&block)
	return
}
Пример #15
0
// New creates a new root certificate from the certificate request.
func New(req *csr.CertificateRequest) (cert, csrPEM, key []byte, err error) {
	policy := CAPolicy()
	if req.CA != nil {
		if req.CA.Expiry != "" {
			policy.Default.ExpiryString = req.CA.Expiry
			policy.Default.Expiry, err = time.ParseDuration(req.CA.Expiry)
			if err != nil {
				return
			}
		}

		policy.Default.CAConstraint.MaxPathLen = req.CA.PathLength
		if req.CA.PathLength != 0 && req.CA.PathLenZero == true {
			log.Infof("ignore invalid 'pathlenzero' value")
		} else {
			policy.Default.CAConstraint.MaxPathLenZero = req.CA.PathLenZero
		}
	}

	g := &csr.Generator{Validator: validator}
	csrPEM, key, err = g.ProcessRequest(req)
	if err != nil {
		log.Errorf("failed to process request: %v", err)
		key = nil
		return
	}

	priv, err := helpers.ParsePrivateKeyPEM(key)
	if err != nil {
		log.Errorf("failed to parse private key: %v", err)
		return
	}

	s, err := local.NewSigner(priv, nil, signer.DefaultSigAlgo(priv), policy)
	if err != nil {
		log.Errorf("failed to create signer: %v", err)
		return
	}

	signReq := signer.SignRequest{Hosts: req.Hosts, Request: string(csrPEM)}
	cert, err = s.Sign(signReq)

	return

}
Пример #16
0
// NewSignHandler generates a new SignHandler using the certificate
// authority private key and certficate to sign certificates.
func NewSignHandler(caFile, cakeyFile string) (http.Handler, error) {
	var err error
	s := new(SignHandler)
	// TODO(kyle): add profile loading to API server
	if s.signer, err = signer.NewSigner(caFile, cakeyFile, nil); err != nil {
		log.Errorf("setting up signer failed: %v", err)
		return nil, err
	}
	return HttpHandler{s, "POST"}, nil
}
Пример #17
0
// Close marks conn as closed and closed the inner net.Conn.
func (c *Conn) Close() {
	c.Lock()
	defer c.Unlock()
	c.users--
	if c.users == 0 {
		if err := c.Conn.Close(); err != nil {
			log.Errorf("Unable to close connection: %v", err)
		}
	}
}
Пример #18
0
// NewBundlerFromPEM creates a new Bundler from PEM-encoded root certificates and
// intermediate certificates.
// If caBundlePEM is nil, the resulting Bundler can only do "Force" bundle.
func NewBundlerFromPEM(caBundlePEM, intBundlePEM []byte) (*Bundler, error) {
	log.Debug("parsing root certificates from PEM")
	roots, err := helpers.ParseCertificatesPEM(caBundlePEM)
	if err != nil {
		log.Errorf("failed to parse root bundle: %v", err)
		return nil, errors.New(errors.RootError, errors.ParseFailed)
	}

	log.Debug("parse intermediate certificates from PEM")
	intermediates, err := helpers.ParseCertificatesPEM(intBundlePEM)
	if err != nil {
		log.Errorf("failed to parse intermediate bundle: %v", err)
		return nil, errors.New(errors.IntermediatesError, errors.ParseFailed)
	}

	b := &Bundler{
		KnownIssuers:     map[string]bool{},
		IntermediatePool: x509.NewCertPool(),
	}

	log.Debug("building certificate pools")

	// RootPool will be nil if caBundlePEM is nil, also
	// that translates to caBundleFile is "".
	// Systems root store will be used.
	if caBundlePEM != nil {
		b.RootPool = x509.NewCertPool()
	}

	for _, c := range roots {
		b.RootPool.AddCert(c)
		b.KnownIssuers[string(c.Signature)] = true
	}

	for _, c := range intermediates {
		b.IntermediatePool.AddCert(c)
		b.KnownIssuers[string(c.Signature)] = true
	}

	log.Debug("bundler set up")
	return b, nil
}
Пример #19
0
func NewRemoteCertGenerator(validator Validator, remote string) (http.Handler, error) {
	log.Info("setting up a new remote certificate generator")
	cg := new(RemoteCertGeneratorHandler)
	if cg.remote = client.NewServer(remote); cg.remote == nil {
		log.Errorf("invalid address for remote server")
		return nil, errors.New(errors.DialError, errors.Unknown, nil)
	}

	cg.generator = &csr.Generator{validator}
	return HttpHandler{cg, "POST"}, nil
}
Пример #20
0
// New creates a new root certificate from the certificate request.
func New(req *csr.CertificateRequest) (cert, csrPEM, key []byte, err error) {
	if req.CA != nil {
		if req.CA.Expiry != "" {
			CAPolicy.Default.ExpiryString = req.CA.Expiry
			CAPolicy.Default.Expiry, err = time.ParseDuration(req.CA.Expiry)
		}

		if req.CA.PathLength != 0 {
			signer.MaxPathLen = req.CA.PathLength
		}
	}

	g := &csr.Generator{Validator: validator}
	csrPEM, key, err = g.ProcessRequest(req)
	if err != nil {
		log.Errorf("failed to process request: %v", err)
		key = nil
		return
	}

	priv, err := helpers.ParsePrivateKeyPEM(key)
	if err != nil {
		log.Errorf("failed to parse private key: %v", err)
		return
	}

	s, err := local.NewSigner(priv, nil, signer.DefaultSigAlgo(priv), nil)
	if err != nil {
		log.Errorf("failed to create signer: %v", err)
		return
	}
	s.SetPolicy(CAPolicy)

	signReq := signer.SignRequest{Hosts: req.Hosts, Request: string(csrPEM)}
	cert, err = s.Sign(signReq)

	return

}
Пример #21
0
// New creates a new root certificate from the certificate request.
func New(req *csr.CertificateRequest) (cert, key []byte, err error) {
	log.Infof("creating root certificate from CSR")
	g := &csr.Generator{validator}
	csr, key, err := g.ProcessRequest(req)
	if err != nil {
		log.Errorf("failed to process request: %v", err)
		key = nil
		return
	}

	priv, err := helpers.ParsePrivateKeyPEM(key)
	if err != nil {
		log.Errorf("failed to parse private key: %v", err)
		return
	}

	s := &signer.Signer{
		Priv:   priv,
		Policy: CAPolicy,
	}

	cert, err = s.Sign("", csr, "")
	return
}
Пример #22
0
// NewHandler generates a new Handler using the certificate
// authority private key and certficate to sign certificates. If remote
// is not an empty string, the handler will send signature requests to
// the CFSSL instance contained in remote by default.
func NewHandler(caFile, caKeyFile string, policy *config.Signing) (http.Handler, error) {
	root := universal.Root{
		Config: map[string]string{
			"cert-file": caFile,
			"key-file":  caKeyFile,
		},
	}
	s, err := universal.NewSigner(root, policy)
	if err != nil {
		log.Errorf("setting up signer failed: %v", err)
		return nil, err
	}

	return NewHandlerFromSigner(s)
}
Пример #23
0
// post connects to the remote server and returns a Response struct
func (srv *server) post(url string, jsonData []byte) (*api.Response, error) {
	var resp *http.Response
	var err error
	client := &http.Client{}
	if srv.TLSConfig != nil {
		client.Transport = srv.createTLSTransport()
	}
	req, err := http.NewRequest("POST", url, bytes.NewReader(jsonData))
	if err != nil {
		err = fmt.Errorf("failed POST to %s: %v", url, err)
		return nil, errors.Wrap(errors.APIClientError, errors.ClientHTTPError, err)
	}
	req.Header.Set("content-type", "application/json")
	if srv.reqModifier != nil {
		srv.reqModifier(req, jsonData)
	}
	resp, err = client.Do(req)
	if err != nil {
		err = fmt.Errorf("failed POST to %s: %v", url, err)
		return nil, errors.Wrap(errors.APIClientError, errors.ClientHTTPError, err)
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, errors.Wrap(errors.APIClientError, errors.IOError, err)
	}
	resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		log.Errorf("http error with %s", url)
		return nil, errors.Wrap(errors.APIClientError, errors.ClientHTTPError, stderr.New(string(body)))
	}

	var response api.Response
	err = json.Unmarshal(body, &response)
	if err != nil {
		log.Debug("Unable to parse response body:", string(body))
		return nil, errors.Wrap(errors.APIClientError, errors.JSONError, err)
	}

	if !response.Success || response.Result == nil {
		if len(response.Errors) > 0 {
			return nil, errors.Wrap(errors.APIClientError, errors.ServerRequestFailed, stderr.New(response.Errors[0].Message))
		}
		return nil, errors.New(errors.APIClientError, errors.ServerRequestFailed)
	}

	return &response, nil
}
Пример #24
0
func (b *Bundler) verifyChain(chain []*fetchedIntermediate) bool {
	// This process will verify if the root of the (partial) chain is in our root pool,
	// and will fail otherwise.
	log.Debugf("verifying chain")
	for vchain := chain[:]; len(vchain) > 0; vchain = vchain[1:] {
		cert := vchain[0]
		// If this is a certificate in one of the pools, skip it.
		if b.KnownIssuers[string(cert.Cert.Signature)] {
			log.Debugf("certificate is known")
			continue
		}

		_, err := cert.Cert.Verify(b.VerifyOptions())
		if err != nil {
			log.Debugf("certificate failed verification: %v", err)
			return false
		} else if len(chain) == len(vchain) && isChainRootNode(cert.Cert) {
			// The first certificate in the chain is a root; it shouldn't be stored.
			log.Debug("looking at root certificate, will not store")
			continue
		}

		// leaf cert has an empty name, don't store leaf cert.
		if cert.Name == "" {
			continue
		}

		log.Debug("add certificate to intermediate pool:", cert.Name)
		b.IntermediatePool.AddCert(cert.Cert)
		b.KnownIssuers[string(cert.Cert.Signature)] = true

		if IntermediateStash != "" {
			fileName := filepath.Join(IntermediateStash, cert.Name)

			var block = pem.Block{Type: "CERTIFICATE", Bytes: cert.Cert.Raw}

			log.Debugf("write intermediate to stash directory: %s", fileName)
			// If the write fails, verification should not fail.
			err = ioutil.WriteFile(fileName, pem.EncodeToMemory(&block), 0644)
			if err != nil {
				log.Errorf("failed to write new intermediate: %v", err)
			} else {
				log.Info("stashed new intermediate ", cert.Name)
			}
		}
	}
	return true
}
Пример #25
0
func main() {
	var addr, conf string
	flag.StringVar(&addr, "a", "127.0.0.1:9876", "`address` of server")
	flag.StringVar(&conf, "f", "server.json", "config `file` to use")
	flag.Parse()

	var id = new(core.Identity)
	data, err := ioutil.ReadFile(conf)
	if err != nil {
		exlib.Err(1, err, "reading config file")
	}

	err = json.Unmarshal(data, id)
	if err != nil {
		exlib.Err(1, err, "parsing config file")
	}

	tr, err := transport.New(exlib.Before, id)
	if err != nil {
		exlib.Err(1, err, "creating transport")
	}

	l, err := transport.Listen(addr, tr)
	if err != nil {
		exlib.Err(1, err, "setting up listener")
	}

	var errChan = make(chan error, 0)
	go func(ec <-chan error) {
		for {
			err, ok := <-ec
			if !ok {
				log.Warning("error channel closed, future errors will not be reported")
				break
			}
			log.Errorf("auto update error: %v", err)
		}
	}(errChan)

	log.Info("setting up auto-update")
	go l.AutoUpdate(nil, errChan)

	log.Info("listening on ", addr)
	exlib.Warn(serve(l), "serving listener")
}
Пример #26
0
func dumpMetrics(w http.ResponseWriter, req *http.Request) {
	log.Info("whitelisted requested for metrics endpoint")
	var statsOut = struct {
		Metrics metrics.Registry `json:"metrics"`
		Signers []string         `json:"signers"`
	}{stats.Registry, make([]string, 0, len(signers))}

	for signer := range signers {
		statsOut.Signers = append(statsOut.Signers, signer)
	}

	out, err := json.Marshal(statsOut)
	if err != nil {
		log.Errorf("failed to dump metrics: %v", err)
	}

	w.Write(out)
}
Пример #27
0
// ParseRequest takes a certificate request and generates a key and
// CSR from it. It does no validation -- caveat emptor. It will,
// however, fail if the key request is not valid (i.e., an unsupported
// curve or RSA key size). The lack of validation was specifically
// chosen to allow the end user to define a policy and validate the
// request appropriately before calling this function.
func ParseRequest(req *CertificateRequest) (csr, key []byte, err error) {
	log.Info("received CSR")
	if req.KeyRequest == nil {
		req.KeyRequest = NewBasicKeyRequest()
	}

	log.Infof("generating key: %s-%d", req.KeyRequest.Algo(), req.KeyRequest.Size())
	priv, err := req.KeyRequest.Generate()
	if err != nil {
		err = cferr.Wrap(cferr.PrivateKeyError, cferr.GenerationFailed, err)
		return
	}

	switch priv := priv.(type) {
	case *rsa.PrivateKey:
		key = x509.MarshalPKCS1PrivateKey(priv)
		block := pem.Block{
			Type:  "RSA PRIVATE KEY",
			Bytes: key,
		}
		key = pem.EncodeToMemory(&block)
	case *ecdsa.PrivateKey:
		key, err = x509.MarshalECPrivateKey(priv)
		if err != nil {
			err = cferr.Wrap(cferr.PrivateKeyError, cferr.Unknown, err)
			return
		}
		block := pem.Block{
			Type:  "EC PRIVATE KEY",
			Bytes: key,
		}
		key = pem.EncodeToMemory(&block)
	default:
		panic("Generate should have failed to produce a valid key.")
	}

	csr, err = Generate(priv.(crypto.Signer), req)
	if err != nil {
		log.Errorf("failed to generate a CSR: %v", err)
		err = cferr.Wrap(cferr.CSRError, cferr.BadRequest, err)
	}
	return
}
Пример #28
0
func main() {
	var s *server.Server
	if initToken != "" {
		s = initializeServer()
	} else {
		s, err := server.NewServerFromFile(certFile, keyFile, caFile,
			net.JoinHostPort("", port), net.JoinHostPort("", metricsPort))
		if err != nil {
			log.Warningf("Could not create server. Run with `gokeyless -init-token=XXX` to get %s and %s", keyFile, certFile)
			log.Fatal(err)
		}

		if err := s.LoadKeysFromDir(keyDir, LoadKey); err != nil {
			log.Fatal(err)
		}

		// Start server in background, then listen for SIGHUPs to reload keys.
		go func() {
			log.Fatal(s.ListenAndServe())
		}()
	}

	if pidFile != "" {
		if f, err := os.Create(pidFile); err != nil {
			log.Errorf("error creating pid file: %v", err)
		} else {
			fmt.Fprintf(f, "%d", os.Getpid())
			f.Close()
		}
	}

	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGHUP)
	for {
		select {
		case <-c:
			log.Info("Received SIGHUP, reloading keys...")
			if err := s.LoadKeysFromDir(keyDir, LoadKey); err != nil {
				log.Fatal(err)
			}
		}
	}
}
Пример #29
0
// post connects to the remote server and returns a Response struct
func (srv *server) post(url string, jsonData []byte) (*api.Response, error) {
	buf := bytes.NewBuffer(jsonData)
	var resp *http.Response
	var err error
	if srv.TLSConfig != nil {
		transport := srv.createTransport()
		client := &http.Client{Transport: transport}
		resp, err = client.Post(url, "application/json", buf)
	} else {
		resp, err = http.Post(url, "application/json", buf)
	}
	if err != nil {
		err = fmt.Errorf("failed POST to %s: %v", url, err)
		return nil, errors.Wrap(errors.APIClientError, errors.ClientHTTPError, err)
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, errors.Wrap(errors.APIClientError, errors.IOError, err)
	}
	resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		log.Errorf("http error with %s", url)
		return nil, errors.Wrap(errors.APIClientError, errors.ClientHTTPError, stderr.New(string(body)))
	}

	var response api.Response
	err = json.Unmarshal(body, &response)
	if err != nil {
		log.Debug("Unable to parse response body:", string(body))
		return nil, errors.Wrap(errors.APIClientError, errors.JSONError, err)
	}

	if !response.Success || response.Result == nil {
		if len(response.Errors) > 0 {
			return nil, errors.Wrap(errors.APIClientError, errors.ServerRequestFailed, stderr.New(response.Errors[0].Message))
		}
		return nil, errors.New(errors.APIClientError, errors.ServerRequestFailed)
	}

	return &response, nil
}
Пример #30
0
func fail(w http.ResponseWriter, req *http.Request, status, code int, msg, ad string) {
	incErrors()

	if ad != "" {
		ad = " (" + ad + ")"
	}
	log.Errorf("[HTTP %d] %d - %s%s", status, code, msg, ad)

	dumpReq, err := httputil.DumpRequest(req, true)
	if err != nil {
		fmt.Printf("%v#v\n", req)
	} else {
		fmt.Printf("%s\n", dumpReq)
	}

	res := api.NewErrorResponse(msg, code)
	w.WriteHeader(status)
	jenc := json.NewEncoder(w)
	jenc.Encode(res)
}