Example #1
0
func (b *backend) pathSetSignedIntermediate(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
	cert := data.Get("certificate").(string)

	if cert == "" {
		return logical.ErrorResponse("no certificate provided in the \"certficate\" parameter"), nil
	}

	inputBundle, err := certutil.ParsePEMBundle(cert)
	if err != nil {
		switch err.(type) {
		case certutil.InternalError:
			return nil, err
		default:
			return logical.ErrorResponse(err.Error()), nil
		}
	}

	// If only one certificate is provided and it's a CA
	// the parsing will assign it to the IssuingCA, so move it over
	if inputBundle.Certificate == nil && inputBundle.IssuingCA != nil {
		inputBundle.Certificate = inputBundle.IssuingCA
		inputBundle.IssuingCA = nil
		inputBundle.CertificateBytes = inputBundle.IssuingCABytes
		inputBundle.IssuingCABytes = nil
	}

	if inputBundle.Certificate == nil {
		return logical.ErrorResponse("supplied certificate could not be successfully parsed"), nil
	}

	cb := &certutil.CertBundle{}
	entry, err := req.Storage.Get("config/ca_bundle")
	if err != nil {
		return nil, err
	}
	if entry == nil {
		return logical.ErrorResponse("could not find any existing entry with a private key"), nil
	}

	err = entry.DecodeJSON(cb)
	if err != nil {
		return nil, err
	}

	if len(cb.PrivateKey) == 0 || cb.PrivateKeyType == "" {
		return logical.ErrorResponse("could not find an existing private key"), nil
	}

	parsedCB, err := cb.ToParsedCertBundle()
	if err != nil {
		return nil, err
	}
	if parsedCB.PrivateKey == nil {
		return nil, fmt.Errorf("saved key could not be parsed successfully")
	}

	equal, err := certutil.ComparePublicKeys(parsedCB.PrivateKey.Public(), inputBundle.Certificate.PublicKey)
	if err != nil {
		return logical.ErrorResponse(fmt.Sprintf(
			"error matching public keys: %v", err)), nil
	}
	if !equal {
		return logical.ErrorResponse("key in certificate does not match stored key"), nil
	}

	inputBundle.PrivateKey = parsedCB.PrivateKey
	inputBundle.PrivateKeyType = parsedCB.PrivateKeyType
	inputBundle.PrivateKeyBytes = parsedCB.PrivateKeyBytes

	if !inputBundle.Certificate.IsCA {
		return logical.ErrorResponse("the given certificate is not marked for CA use and cannot be used with this backend"), nil
	}

	cb, err = inputBundle.ToCertBundle()
	if err != nil {
		return nil, fmt.Errorf("error converting raw values into cert bundle: %s", err)
	}

	entry, err = logical.StorageEntryJSON("config/ca_bundle", cb)
	if err != nil {
		return nil, err
	}
	err = req.Storage.Put(entry)
	if err != nil {
		return nil, err
	}

	entry.Key = "certs/" + cb.SerialNumber
	entry.Value = inputBundle.CertificateBytes
	err = req.Storage.Put(entry)
	if err != nil {
		return nil, err
	}

	// For ease of later use, also store just the certificate at a known
	// location
	entry.Key = "ca"
	entry.Value = inputBundle.CertificateBytes
	err = req.Storage.Put(entry)
	if err != nil {
		return nil, err
	}

	// Build a fresh CRL
	err = buildCRL(b, req)

	return nil, err
}
Example #2
0
func (b *backend) pathCAWrite(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
	pemBundle := data.Get("pem_bundle").(string)

	parsedBundle, err := certutil.ParsePEMBundle(pemBundle)
	if err != nil {
		switch err.(type) {
		case certutil.InternalError:
			return nil, err
		default:
			return logical.ErrorResponse(err.Error()), nil
		}
	}

	if parsedBundle.PrivateKey == nil ||
		parsedBundle.PrivateKeyType == certutil.UnknownPrivateKey {
		return logical.ErrorResponse("private key not found in the PEM bundle"), nil
	}

	// Handle the case of a self-signed certificate; the parsing function will
	// see the CA and put it into the issuer
	if parsedBundle.Certificate == nil &&
		parsedBundle.IssuingCA != nil {
		equal, err := certutil.ComparePublicKeys(parsedBundle.IssuingCA.PublicKey, parsedBundle.PrivateKey.Public())
		if err != nil {
			return logical.ErrorResponse(fmt.Sprintf(
				"got only a CA and private key but could not verify the public keys match: %v", err)), nil
		}
		if !equal {
			return logical.ErrorResponse(
				"got only a CA and private key but keys do not match"), nil
		}
		parsedBundle.Certificate = parsedBundle.IssuingCA
		parsedBundle.CertificateBytes = parsedBundle.IssuingCABytes
	}

	if parsedBundle.Certificate == nil {
		return logical.ErrorResponse("no certificate found in the PEM bundle"), nil
	}

	if !parsedBundle.Certificate.IsCA {
		return logical.ErrorResponse("the given certificate is not marked for CA use and cannot be used with this backend"), nil
	}

	cb, err := parsedBundle.ToCertBundle()
	if err != nil {
		return nil, fmt.Errorf("error converting raw values into cert bundle: %s", err)
	}

	entry, err := logical.StorageEntryJSON("config/ca_bundle", cb)
	if err != nil {
		return nil, err
	}
	err = req.Storage.Put(entry)
	if err != nil {
		return nil, err
	}

	// For ease of later use, also store just the certificate at a known
	// location, plus a fresh CRL
	entry.Key = "ca"
	entry.Value = parsedBundle.CertificateBytes
	err = req.Storage.Put(entry)
	if err != nil {
		return nil, err
	}

	err = buildCRL(b, req)

	return nil, err
}