mirror of
https://github.com/hashicorp/vault.git
synced 2025-11-29 06:31:10 +01:00
Add sign method (untested)
This commit is contained in:
parent
667d5cafd3
commit
62049cd059
@ -43,6 +43,7 @@ func Backend() *framework.Backend {
|
|||||||
pathSetCA(&b),
|
pathSetCA(&b),
|
||||||
pathConfigCA(&b),
|
pathConfigCA(&b),
|
||||||
pathConfigCRL(&b),
|
pathConfigCRL(&b),
|
||||||
|
pathSign(&b),
|
||||||
pathIssue(&b),
|
pathIssue(&b),
|
||||||
pathRotateCRL(&b),
|
pathRotateCRL(&b),
|
||||||
pathFetchCA(&b),
|
pathFetchCA(&b),
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import (
|
|||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"crypto/x509/pkix"
|
"crypto/x509/pkix"
|
||||||
|
"encoding/pem"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"net"
|
"net"
|
||||||
@ -215,7 +216,6 @@ func generateCSR(b *backend,
|
|||||||
func signCert(b *backend,
|
func signCert(b *backend,
|
||||||
role *roleEntry,
|
role *roleEntry,
|
||||||
signingBundle *certutil.ParsedCertBundle,
|
signingBundle *certutil.ParsedCertBundle,
|
||||||
csr *x509.CertificateRequest,
|
|
||||||
isCA bool,
|
isCA bool,
|
||||||
req *logical.Request,
|
req *logical.Request,
|
||||||
data *framework.FieldData) (*certutil.ParsedCertBundle, error) {
|
data *framework.FieldData) (*certutil.ParsedCertBundle, error) {
|
||||||
@ -225,6 +225,22 @@ func signCert(b *backend,
|
|||||||
return nil, certutil.UserError{Err: "The common_name field is required"}
|
return nil, certutil.UserError{Err: "The common_name field is required"}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
csrString := req.Data["csr"].(string)
|
||||||
|
if csrString == "" {
|
||||||
|
return nil, certutil.UserError{Err: fmt.Sprintf(
|
||||||
|
"\"csr\" is empty")}
|
||||||
|
}
|
||||||
|
|
||||||
|
pemBytes := []byte(csrString)
|
||||||
|
pemBlock, pemBytes := pem.Decode(pemBytes)
|
||||||
|
if pemBlock == nil {
|
||||||
|
return nil, certutil.UserError{Err: "csr contains no data"}
|
||||||
|
}
|
||||||
|
csr, err := x509.ParseCertificateRequest(pemBlock.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, certutil.UserError{Err: "certificate request could not be parsed"}
|
||||||
|
}
|
||||||
|
|
||||||
creationBundle, err := generateCreationBundle(b, role, signingBundle, isCA, req, data)
|
creationBundle, err := generateCreationBundle(b, role, signingBundle, isCA, req, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
package pki
|
package pki
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/x509"
|
|
||||||
"encoding/pem"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
@ -413,22 +411,6 @@ func (b *backend) pathCASignWrite(
|
|||||||
pkiAddress = pkiAddress[:len(pkiAddress)-1]
|
pkiAddress = pkiAddress[:len(pkiAddress)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
csrString := req.Data["csr"].(string)
|
|
||||||
if csrString == "" {
|
|
||||||
return logical.ErrorResponse(fmt.Sprintf(
|
|
||||||
"\"csr\" is empty")), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
pemBytes := []byte(csrString)
|
|
||||||
pemBlock, pemBytes := pem.Decode(pemBytes)
|
|
||||||
if pemBlock == nil {
|
|
||||||
return nil, certutil.UserError{Err: "csr contains no data"}
|
|
||||||
}
|
|
||||||
csr, err := x509.ParseCertificateRequest(pemBlock.Bytes)
|
|
||||||
if err != nil {
|
|
||||||
return nil, certutil.UserError{Err: "certificate request could not be parsed"}
|
|
||||||
}
|
|
||||||
|
|
||||||
req.Data["pki_address"] = pkiAddress
|
req.Data["pki_address"] = pkiAddress
|
||||||
|
|
||||||
role := &roleEntry{
|
role := &roleEntry{
|
||||||
@ -464,7 +446,7 @@ func (b *backend) pathCASignWrite(
|
|||||||
"Error fetching CA certificate: %s", caErr)}
|
"Error fetching CA certificate: %s", caErr)}
|
||||||
}
|
}
|
||||||
|
|
||||||
parsedBundle, err := signCert(b, role, signingBundle, csr, true, req, data)
|
parsedBundle, err := signCert(b, role, signingBundle, true, req, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch err.(type) {
|
switch err.(type) {
|
||||||
case certutil.UserError:
|
case certutil.UserError:
|
||||||
|
|||||||
@ -44,10 +44,6 @@ the role default, backend default, or system
|
|||||||
default TTL is used, in that order. Cannot
|
default TTL is used, in that order. Cannot
|
||||||
be later than the role max TTL.`,
|
be later than the role max TTL.`,
|
||||||
},
|
},
|
||||||
"csr": &framework.FieldSchema{
|
|
||||||
Type: framework.TypeString,
|
|
||||||
Description: `PEM-format CSR to be signed.`,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func pathIssue(b *backend) *framework.Path {
|
func pathIssue(b *backend) *framework.Path {
|
||||||
@ -65,7 +61,7 @@ func pathIssue(b *backend) *framework.Path {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func pathSign(b *backend) *framework.Path {
|
func pathSign(b *backend) *framework.Path {
|
||||||
return &framework.Path{
|
ret := &framework.Path{
|
||||||
Pattern: "sign/" + framework.GenericNameRegex("role"),
|
Pattern: "sign/" + framework.GenericNameRegex("role"),
|
||||||
Fields: issueAndSignSchema,
|
Fields: issueAndSignSchema,
|
||||||
|
|
||||||
@ -76,6 +72,13 @@ func pathSign(b *backend) *framework.Path {
|
|||||||
HelpSynopsis: pathIssueCertHelpSyn,
|
HelpSynopsis: pathIssueCertHelpSyn,
|
||||||
HelpDescription: pathIssueCertHelpDesc,
|
HelpDescription: pathIssueCertHelpDesc,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret.Fields["csr"] = &framework.FieldSchema{
|
||||||
|
Type: framework.TypeString,
|
||||||
|
Description: `PEM-format CSR to be signed.`,
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *backend) pathIssueCert(
|
func (b *backend) pathIssueCert(
|
||||||
@ -136,6 +139,64 @@ func (b *backend) pathIssueCert(
|
|||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *backend) pathSignCSR(
|
||||||
|
req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
||||||
|
roleName := data.Get("role").(string)
|
||||||
|
|
||||||
|
// Get the role
|
||||||
|
role, err := b.getRole(req.Storage, roleName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if role == nil {
|
||||||
|
return logical.ErrorResponse(fmt.Sprintf("Unknown role: %s", roleName)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var caErr error
|
||||||
|
signingBundle, caErr := fetchCAInfo(req)
|
||||||
|
switch caErr.(type) {
|
||||||
|
case certutil.UserError:
|
||||||
|
return nil, certutil.UserError{Err: fmt.Sprintf(
|
||||||
|
"Could not fetch the CA certificate (was one set?): %s", caErr)}
|
||||||
|
case certutil.InternalError:
|
||||||
|
return nil, certutil.InternalError{Err: fmt.Sprintf(
|
||||||
|
"Error fetching CA certificate: %s", caErr)}
|
||||||
|
}
|
||||||
|
|
||||||
|
parsedBundle, err := signCert(b, role, signingBundle, false, req, data)
|
||||||
|
if err != nil {
|
||||||
|
switch err.(type) {
|
||||||
|
case certutil.UserError:
|
||||||
|
return logical.ErrorResponse(err.Error()), nil
|
||||||
|
case certutil.InternalError:
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cb, err := parsedBundle.ToCertBundle()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Error converting raw cert bundle to cert bundle: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := b.Secret(SecretCertsType).Response(
|
||||||
|
structs.New(cb).Map(),
|
||||||
|
map[string]interface{}{
|
||||||
|
"serial_number": cb.SerialNumber,
|
||||||
|
})
|
||||||
|
|
||||||
|
resp.Secret.TTL = parsedBundle.Certificate.NotAfter.Sub(time.Now())
|
||||||
|
|
||||||
|
err = req.Storage.Put(&logical.StorageEntry{
|
||||||
|
Key: "certs/" + cb.SerialNumber,
|
||||||
|
Value: parsedBundle.CertificateBytes,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Unable to store certificate locally")
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
const pathIssueCertHelpSyn = `
|
const pathIssueCertHelpSyn = `
|
||||||
Request certificates using a certain role with the provided common name.
|
Request certificates using a certain role with the provided common name.
|
||||||
`
|
`
|
||||||
Loading…
x
Reference in New Issue
Block a user