Example #1
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 errutil.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
	}

	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
}
Example #2
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 #3
0
func (b *backend) pathConnectionWrite(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
	hosts := data.Get("hosts").(string)
	username := data.Get("username").(string)
	password := data.Get("password").(string)

	switch {
	case len(hosts) == 0:
		return logical.ErrorResponse("Hosts cannot be empty"), nil
	case len(username) == 0:
		return logical.ErrorResponse("Username cannot be empty"), nil
	case len(password) == 0:
		return logical.ErrorResponse("Password cannot be empty"), nil
	}

	config := &sessionConfig{
		Hosts:           hosts,
		Username:        username,
		Password:        password,
		TLS:             data.Get("tls").(bool),
		InsecureTLS:     data.Get("insecure_tls").(bool),
		ProtocolVersion: data.Get("protocol_version").(int),
		ConnectTimeout:  data.Get("connect_timeout").(int),
	}

	config.TLSMinVersion = data.Get("tls_min_version").(string)
	if config.TLSMinVersion == "" {
		return logical.ErrorResponse("failed to get 'tls_min_version' value"), nil
	}

	var ok bool
	_, ok = tlsutil.TLSLookup[config.TLSMinVersion]
	if !ok {
		return logical.ErrorResponse("invalid 'tls_min_version'"), nil
	}

	if config.InsecureTLS {
		config.TLS = true
	}

	pemBundle := data.Get("pem_bundle").(string)
	pemJSON := data.Get("pem_json").(string)

	var certBundle *certutil.CertBundle
	var parsedCertBundle *certutil.ParsedCertBundle
	var err error

	switch {
	case len(pemJSON) != 0:
		parsedCertBundle, err = certutil.ParsePKIJSON([]byte(pemJSON))
		if err != nil {
			return logical.ErrorResponse(fmt.Sprintf("Could not parse given JSON; it must be in the format of the output of the PKI backend certificate issuing command: %s", err)), nil
		}
		certBundle, err = parsedCertBundle.ToCertBundle()
		if err != nil {
			return logical.ErrorResponse(fmt.Sprintf("Error marshaling PEM information: %s", err)), nil
		}
		config.Certificate = certBundle.Certificate
		config.PrivateKey = certBundle.PrivateKey
		config.IssuingCA = certBundle.IssuingCA
		config.TLS = true

	case len(pemBundle) != 0:
		parsedCertBundle, err = certutil.ParsePEMBundle(pemBundle)
		if err != nil {
			return logical.ErrorResponse(fmt.Sprintf("Error parsing the given PEM information: %s", err)), nil
		}
		certBundle, err = parsedCertBundle.ToCertBundle()
		if err != nil {
			return logical.ErrorResponse(fmt.Sprintf("Error marshaling PEM information: %s", err)), nil
		}
		config.Certificate = certBundle.Certificate
		config.PrivateKey = certBundle.PrivateKey
		config.IssuingCA = certBundle.IssuingCA
		config.TLS = true
	}

	session, err := createSession(config, req.Storage)
	if err != nil {
		return logical.ErrorResponse(err.Error()), nil
	}

	// Store it
	entry, err := logical.StorageEntryJSON("config/connection", config)
	if err != nil {
		return nil, err
	}
	if err := req.Storage.Put(entry); err != nil {
		return nil, err
	}

	// Reset the DB connection
	b.ResetDB(session)

	return nil, nil
}
Example #4
0
func (b *backend) pathCAWrite(
	req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
	pemBundle := d.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
		}
	}

	// Handle the case of a self-signed certificate
	if parsedBundle.Certificate == nil && parsedBundle.IssuingCA != nil {
		parsedBundle.Certificate = parsedBundle.IssuingCA
		parsedBundle.CertificateBytes = parsedBundle.IssuingCABytes
	}

	// TODO?: CRLs can only be generated with RSA keys right now, in the
	// Go standard library. The plubming is here to support non-RSA keys
	// if the library gets support

	if parsedBundle.PrivateKeyType != certutil.RSAPrivateKey {
		return logical.ErrorResponse("Currently, only RSA keys are supported for the CA certificate"), 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 blank CRL
	entry.Key = "ca"
	entry.Value = parsedBundle.CertificateBytes
	err = req.Storage.Put(entry)
	if err != nil {
		return nil, err
	}

	entry.Key = "crl"
	entry.Value = []byte{}
	err = req.Storage.Put(entry)
	if err != nil {
		return nil, err
	}

	return nil, nil
}
Example #5
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
}