Merge branch 'master' into ui-toolbar
This commit is contained in:
commit
81c3cbdbfa
|
@ -12,7 +12,16 @@ import (
|
|||
squarejwt "gopkg.in/square/go-jose.v2/jwt"
|
||||
|
||||
"github.com/hashicorp/errwrap"
|
||||
"github.com/hashicorp/vault/sdk/helper/pluginutil"
|
||||
)
|
||||
|
||||
var (
|
||||
// PluginMetadataModeEnv is an ENV name used to disable TLS communication
|
||||
// to bootstrap mounting plugins.
|
||||
PluginMetadataModeEnv = "VAULT_PLUGIN_METADATA_MODE"
|
||||
|
||||
// PluginUnwrapTokenEnv is the ENV name used to pass unwrap tokens to the
|
||||
// plugin.
|
||||
PluginUnwrapTokenEnv = "VAULT_UNWRAP_TOKEN"
|
||||
)
|
||||
|
||||
// PluginAPIClientMeta is a helper that plugins can use to configure TLS connections
|
||||
|
@ -61,12 +70,12 @@ func (f *PluginAPIClientMeta) GetTLSConfig() *TLSConfig {
|
|||
// VaultPluginTLSProvider is run inside a plugin and retrieves the response
|
||||
// wrapped TLS certificate from vault. It returns a configured TLS Config.
|
||||
func VaultPluginTLSProvider(apiTLSConfig *TLSConfig) func() (*tls.Config, error) {
|
||||
if os.Getenv(pluginutil.PluginMetadataModeEnv) == "true" {
|
||||
if os.Getenv(PluginMetadataModeEnv) == "true" {
|
||||
return nil
|
||||
}
|
||||
|
||||
return func() (*tls.Config, error) {
|
||||
unwrapToken := os.Getenv(pluginutil.PluginUnwrapTokenEnv)
|
||||
unwrapToken := os.Getenv(PluginUnwrapTokenEnv)
|
||||
|
||||
parsedJWT, err := squarejwt.ParseSigned(unwrapToken)
|
||||
if err != nil {
|
||||
|
|
|
@ -432,7 +432,7 @@ func checkCertsAndPrivateKey(keyType string, key crypto.Signer, usage x509.KeyUs
|
|||
}
|
||||
|
||||
func generateURLSteps(t *testing.T, caCert, caKey string, intdata, reqdata map[string]interface{}) []logicaltest.TestStep {
|
||||
expected := urlEntries{
|
||||
expected := certutil.URLEntries{
|
||||
IssuingCertificates: []string{
|
||||
"http://example.com/ca1",
|
||||
"http://example.com/ca2",
|
||||
|
@ -499,7 +499,7 @@ func generateURLSteps(t *testing.T, caCert, caKey string, intdata, reqdata map[s
|
|||
if resp.Data == nil {
|
||||
return fmt.Errorf("no data returned")
|
||||
}
|
||||
var entries urlEntries
|
||||
var entries certutil.URLEntries
|
||||
err := mapstructure.Decode(resp.Data, &entries)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/hashicorp/vault/sdk/framework"
|
||||
"github.com/hashicorp/vault/sdk/helper/certutil"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
)
|
||||
|
||||
|
@ -53,7 +54,9 @@ func (b *backend) getGenerationParams(
|
|||
return
|
||||
}
|
||||
|
||||
errorResp = validateKeyTypeLength(role.KeyType, role.KeyBits)
|
||||
if err := certutil.ValidateKeyTypeLength(role.KeyType, role.KeyBits); err != nil {
|
||||
errorResp = logical.ErrorResponse(err.Error())
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -139,20 +139,20 @@ func TestPki_MultipleOUs(t *testing.T) {
|
|||
"ttl": 3600,
|
||||
},
|
||||
}
|
||||
input := &dataBundle{
|
||||
input := &inputBundle{
|
||||
apiData: apiData,
|
||||
role: &roleEntry{
|
||||
MaxTTL: 3600,
|
||||
OU: []string{"Z", "E", "V"},
|
||||
},
|
||||
}
|
||||
err := generateCreationBundle(&b, input)
|
||||
cb, err := generateCreationBundle(&b, input, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Error: %v", err)
|
||||
}
|
||||
|
||||
expected := []string{"Z", "E", "V"}
|
||||
actual := input.params.Subject.OrganizationalUnit
|
||||
actual := cb.Params.Subject.OrganizationalUnit
|
||||
|
||||
if !reflect.DeepEqual(expected, actual) {
|
||||
t.Fatalf("Expected %v, got %v", expected, actual)
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/asaskevich/govalidator"
|
||||
"github.com/fatih/structs"
|
||||
"github.com/hashicorp/vault/sdk/framework"
|
||||
"github.com/hashicorp/vault/sdk/helper/certutil"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
)
|
||||
|
||||
|
@ -53,7 +54,7 @@ func validateURLs(urls []string) string {
|
|||
return ""
|
||||
}
|
||||
|
||||
func getURLs(ctx context.Context, req *logical.Request) (*urlEntries, error) {
|
||||
func getURLs(ctx context.Context, req *logical.Request) (*certutil.URLEntries, error) {
|
||||
entry, err := req.Storage.Get(ctx, "urls")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -62,7 +63,7 @@ func getURLs(ctx context.Context, req *logical.Request) (*urlEntries, error) {
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
var entries urlEntries
|
||||
var entries certutil.URLEntries
|
||||
if err := entry.DecodeJSON(&entries); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -70,7 +71,7 @@ func getURLs(ctx context.Context, req *logical.Request) (*urlEntries, error) {
|
|||
return &entries, nil
|
||||
}
|
||||
|
||||
func writeURLs(ctx context.Context, req *logical.Request, entries *urlEntries) error {
|
||||
func writeURLs(ctx context.Context, req *logical.Request, entries *certutil.URLEntries) error {
|
||||
entry, err := logical.StorageEntryJSON("urls", entries)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -109,7 +110,7 @@ func (b *backend) pathWriteURL(ctx context.Context, req *logical.Request, data *
|
|||
return nil, err
|
||||
}
|
||||
if entries == nil {
|
||||
entries = &urlEntries{
|
||||
entries = &certutil.URLEntries{
|
||||
IssuingCertificates: []string{},
|
||||
CRLDistributionPoints: []string{},
|
||||
OCSPServers: []string{},
|
||||
|
@ -141,12 +142,6 @@ func (b *backend) pathWriteURL(ctx context.Context, req *logical.Request, data *
|
|||
return nil, writeURLs(ctx, req, entries)
|
||||
}
|
||||
|
||||
type urlEntries struct {
|
||||
IssuingCertificates []string `json:"issuing_certificates" structs:"issuing_certificates" mapstructure:"issuing_certificates"`
|
||||
CRLDistributionPoints []string `json:"crl_distribution_points" structs:"crl_distribution_points" mapstructure:"crl_distribution_points"`
|
||||
OCSPServers []string `json:"ocsp_servers" structs:"ocsp_servers" mapstructure:"ocsp_servers"`
|
||||
}
|
||||
|
||||
const pathConfigURLsHelpSyn = `
|
||||
Set the URLs for the issuing CA, CRL distribution points, and OCSP servers.
|
||||
`
|
||||
|
|
|
@ -71,7 +71,7 @@ func (b *backend) pathGenerateIntermediate(ctx context.Context, req *logical.Req
|
|||
}
|
||||
|
||||
var resp *logical.Response
|
||||
input := &dataBundle{
|
||||
input := &inputBundle{
|
||||
role: role,
|
||||
req: req,
|
||||
apiData: data,
|
||||
|
|
|
@ -205,18 +205,17 @@ func (b *backend) pathIssueSignCert(ctx context.Context, req *logical.Request, d
|
|||
"error fetching CA certificate: %s", caErr)}
|
||||
}
|
||||
|
||||
input := &dataBundle{
|
||||
input := &inputBundle{
|
||||
req: req,
|
||||
apiData: data,
|
||||
role: role,
|
||||
signingBundle: signingBundle,
|
||||
}
|
||||
var parsedBundle *certutil.ParsedCertBundle
|
||||
var err error
|
||||
if useCSR {
|
||||
parsedBundle, err = signCert(b, input, false, useCSRValues)
|
||||
parsedBundle, err = signCert(b, input, signingBundle, false, useCSRValues)
|
||||
} else {
|
||||
parsedBundle, err = generateCert(ctx, b, input, false)
|
||||
parsedBundle, err = generateCert(ctx, b, input, signingBundle, false)
|
||||
}
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
"github.com/hashicorp/errwrap"
|
||||
"github.com/hashicorp/vault/sdk/framework"
|
||||
"github.com/hashicorp/vault/sdk/helper/certutil"
|
||||
"github.com/hashicorp/vault/sdk/helper/consts"
|
||||
"github.com/hashicorp/vault/sdk/helper/parseutil"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
|
@ -552,13 +553,13 @@ func (b *backend) pathRoleCreate(ctx context.Context, req *logical.Request, data
|
|||
), nil
|
||||
}
|
||||
|
||||
if errResp := validateKeyTypeLength(entry.KeyType, entry.KeyBits); errResp != nil {
|
||||
return errResp, nil
|
||||
if err := certutil.ValidateKeyTypeLength(entry.KeyType, entry.KeyBits); err != nil {
|
||||
return logical.ErrorResponse(err.Error()), nil
|
||||
}
|
||||
|
||||
if len(entry.ExtKeyUsageOIDs) > 0 {
|
||||
for _, oidstr := range entry.ExtKeyUsageOIDs {
|
||||
_, err := stringToOid(oidstr)
|
||||
_, err := certutil.StringToOid(oidstr)
|
||||
if err != nil {
|
||||
return logical.ErrorResponse(fmt.Sprintf("%q could not be parsed as a valid oid for an extended key usage", oidstr)), nil
|
||||
}
|
||||
|
@ -567,7 +568,7 @@ func (b *backend) pathRoleCreate(ctx context.Context, req *logical.Request, data
|
|||
|
||||
if len(entry.PolicyIdentifiers) > 0 {
|
||||
for _, oidstr := range entry.PolicyIdentifiers {
|
||||
_, err := stringToOid(oidstr)
|
||||
_, err := certutil.StringToOid(oidstr)
|
||||
if err != nil {
|
||||
return logical.ErrorResponse(fmt.Sprintf("%q could not be parsed as a valid oid for a policy identifier", oidstr)), nil
|
||||
}
|
||||
|
@ -614,51 +615,51 @@ func parseKeyUsages(input []string) int {
|
|||
return int(parsedKeyUsages)
|
||||
}
|
||||
|
||||
func parseExtKeyUsages(role *roleEntry) certExtKeyUsage {
|
||||
var parsedKeyUsages certExtKeyUsage
|
||||
func parseExtKeyUsages(role *roleEntry) certutil.CertExtKeyUsage {
|
||||
var parsedKeyUsages certutil.CertExtKeyUsage
|
||||
|
||||
if role.ServerFlag {
|
||||
parsedKeyUsages |= serverAuthExtKeyUsage
|
||||
parsedKeyUsages |= certutil.ServerAuthExtKeyUsage
|
||||
}
|
||||
|
||||
if role.ClientFlag {
|
||||
parsedKeyUsages |= clientAuthExtKeyUsage
|
||||
parsedKeyUsages |= certutil.ClientAuthExtKeyUsage
|
||||
}
|
||||
|
||||
if role.CodeSigningFlag {
|
||||
parsedKeyUsages |= codeSigningExtKeyUsage
|
||||
parsedKeyUsages |= certutil.CodeSigningExtKeyUsage
|
||||
}
|
||||
|
||||
if role.EmailProtectionFlag {
|
||||
parsedKeyUsages |= emailProtectionExtKeyUsage
|
||||
parsedKeyUsages |= certutil.EmailProtectionExtKeyUsage
|
||||
}
|
||||
|
||||
for _, k := range role.ExtKeyUsage {
|
||||
switch strings.ToLower(strings.TrimSpace(k)) {
|
||||
case "any":
|
||||
parsedKeyUsages |= anyExtKeyUsage
|
||||
parsedKeyUsages |= certutil.AnyExtKeyUsage
|
||||
case "serverauth":
|
||||
parsedKeyUsages |= serverAuthExtKeyUsage
|
||||
parsedKeyUsages |= certutil.ServerAuthExtKeyUsage
|
||||
case "clientauth":
|
||||
parsedKeyUsages |= clientAuthExtKeyUsage
|
||||
parsedKeyUsages |= certutil.ClientAuthExtKeyUsage
|
||||
case "codesigning":
|
||||
parsedKeyUsages |= codeSigningExtKeyUsage
|
||||
parsedKeyUsages |= certutil.CodeSigningExtKeyUsage
|
||||
case "emailprotection":
|
||||
parsedKeyUsages |= emailProtectionExtKeyUsage
|
||||
parsedKeyUsages |= certutil.EmailProtectionExtKeyUsage
|
||||
case "ipsecendsystem":
|
||||
parsedKeyUsages |= ipsecEndSystemExtKeyUsage
|
||||
parsedKeyUsages |= certutil.IpsecEndSystemExtKeyUsage
|
||||
case "ipsectunnel":
|
||||
parsedKeyUsages |= ipsecTunnelExtKeyUsage
|
||||
parsedKeyUsages |= certutil.IpsecTunnelExtKeyUsage
|
||||
case "ipsecuser":
|
||||
parsedKeyUsages |= ipsecUserExtKeyUsage
|
||||
parsedKeyUsages |= certutil.IpsecUserExtKeyUsage
|
||||
case "timestamping":
|
||||
parsedKeyUsages |= timeStampingExtKeyUsage
|
||||
parsedKeyUsages |= certutil.TimeStampingExtKeyUsage
|
||||
case "ocspsigning":
|
||||
parsedKeyUsages |= ocspSigningExtKeyUsage
|
||||
parsedKeyUsages |= certutil.OcspSigningExtKeyUsage
|
||||
case "microsoftservergatedcrypto":
|
||||
parsedKeyUsages |= microsoftServerGatedCryptoExtKeyUsage
|
||||
parsedKeyUsages |= certutil.MicrosoftServerGatedCryptoExtKeyUsage
|
||||
case "netscapeservergatedcrypto":
|
||||
parsedKeyUsages |= netscapeServerGatedCryptoExtKeyUsage
|
||||
parsedKeyUsages |= certutil.NetscapeServerGatedCryptoExtKeyUsage
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"encoding/base64"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"github.com/hashicorp/vault/sdk/helper/certutil"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -139,12 +140,12 @@ func (b *backend) pathCAGenerateRoot(ctx context.Context, req *logical.Request,
|
|||
role.MaxPathLength = &maxPathLength
|
||||
}
|
||||
|
||||
input := &dataBundle{
|
||||
input := &inputBundle{
|
||||
req: req,
|
||||
apiData: data,
|
||||
role: role,
|
||||
}
|
||||
parsedBundle, err := generateCert(ctx, b, input, true)
|
||||
parsedBundle, err := generateCert(ctx, b, input, nil, true)
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
case errutil.UserError:
|
||||
|
@ -296,13 +297,12 @@ func (b *backend) pathCASignIntermediate(ctx context.Context, req *logical.Reque
|
|||
role.MaxPathLength = &maxPathLength
|
||||
}
|
||||
|
||||
input := &dataBundle{
|
||||
input := &inputBundle{
|
||||
req: req,
|
||||
apiData: data,
|
||||
signingBundle: signingBundle,
|
||||
role: role,
|
||||
}
|
||||
parsedBundle, err := signCert(b, input, true, useCSRValues)
|
||||
parsedBundle, err := signCert(b, input, signingBundle, true, useCSRValues)
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
case errutil.UserError:
|
||||
|
@ -420,7 +420,7 @@ func (b *backend) pathCASignSelfIssued(ctx context.Context, req *logical.Request
|
|||
return nil, errwrap.Wrapf("error converting raw signing bundle to cert bundle: {{err}}", err)
|
||||
}
|
||||
|
||||
urls := &urlEntries{}
|
||||
urls := &certutil.URLEntries{}
|
||||
if signingBundle.URLs != nil {
|
||||
urls = signingBundle.URLs
|
||||
}
|
||||
|
|
|
@ -168,7 +168,7 @@ func (s *StoragePacker) DeleteItem(_ context.Context, itemID string) error {
|
|||
bucket.Items = append(bucket.Items[:foundIdx], bucket.Items[foundIdx+1:]...)
|
||||
|
||||
// Persist bucket entry only if there is an update
|
||||
err = s.putBucket(&bucket)
|
||||
err = s.PutBucket(&bucket)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -177,7 +177,7 @@ func (s *StoragePacker) DeleteItem(_ context.Context, itemID string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *StoragePacker) putBucket(bucket *Bucket) error {
|
||||
func (s *StoragePacker) PutBucket(bucket *Bucket) error {
|
||||
if bucket == nil {
|
||||
return fmt.Errorf("nil bucket entry")
|
||||
}
|
||||
|
@ -298,7 +298,7 @@ func (s *StoragePacker) PutItem(_ context.Context, item *Item) error {
|
|||
}
|
||||
}
|
||||
|
||||
return s.putBucket(bucket)
|
||||
return s.PutBucket(bucket)
|
||||
}
|
||||
|
||||
// NewStoragePacker creates a new storage packer for a given view
|
||||
|
|
|
@ -9,16 +9,24 @@ import (
|
|||
"crypto/rsa"
|
||||
"crypto/sha1"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"net"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/errwrap"
|
||||
"github.com/hashicorp/vault/sdk/helper/errutil"
|
||||
"github.com/hashicorp/vault/sdk/helper/jsonutil"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"golang.org/x/crypto/cryptobyte"
|
||||
cbasn1 "golang.org/x/crypto/cryptobyte/asn1"
|
||||
)
|
||||
|
||||
// GetHexFormatted returns the byte buffer formatted in hex with
|
||||
|
@ -275,7 +283,7 @@ func ComparePublicKeys(key1Iface, key2Iface crypto.PublicKey) (bool, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// PasrsePublicKeyPEM is used to parse RSA and ECDSA public keys from PEMs
|
||||
// ParsePublicKeyPEM is used to parse RSA and ECDSA public keys from PEMs
|
||||
func ParsePublicKeyPEM(data []byte) (interface{}, error) {
|
||||
block, data := pem.Decode(data)
|
||||
if block != nil {
|
||||
|
@ -299,3 +307,500 @@ func ParsePublicKeyPEM(data []byte) (interface{}, error) {
|
|||
|
||||
return nil, errors.New("data does not contain any valid RSA or ECDSA public keys")
|
||||
}
|
||||
|
||||
// addPolicyIdentifiers adds certificate policies extension
|
||||
//
|
||||
func AddPolicyIdentifiers(data *CreationBundle, certTemplate *x509.Certificate) {
|
||||
for _, oidstr := range data.Params.PolicyIdentifiers {
|
||||
oid, err := StringToOid(oidstr)
|
||||
if err == nil {
|
||||
certTemplate.PolicyIdentifiers = append(certTemplate.PolicyIdentifiers, oid)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// addExtKeyUsageOids adds custom extended key usage OIDs to certificate
|
||||
func AddExtKeyUsageOids(data *CreationBundle, certTemplate *x509.Certificate) {
|
||||
for _, oidstr := range data.Params.ExtKeyUsageOIDs {
|
||||
oid, err := StringToOid(oidstr)
|
||||
if err == nil {
|
||||
certTemplate.UnknownExtKeyUsage = append(certTemplate.UnknownExtKeyUsage, oid)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func HandleOtherCSRSANs(in *x509.CertificateRequest, sans map[string][]string) error {
|
||||
certTemplate := &x509.Certificate{
|
||||
DNSNames: in.DNSNames,
|
||||
IPAddresses: in.IPAddresses,
|
||||
EmailAddresses: in.EmailAddresses,
|
||||
URIs: in.URIs,
|
||||
}
|
||||
if err := HandleOtherSANs(certTemplate, sans); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(certTemplate.ExtraExtensions) > 0 {
|
||||
for _, v := range certTemplate.ExtraExtensions {
|
||||
in.ExtraExtensions = append(in.ExtraExtensions, v)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func HandleOtherSANs(in *x509.Certificate, sans map[string][]string) error {
|
||||
// If other SANs is empty we return which causes normal Go stdlib parsing
|
||||
// of the other SAN types
|
||||
if len(sans) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var rawValues []asn1.RawValue
|
||||
|
||||
// We need to generate an IMPLICIT sequence for compatibility with OpenSSL
|
||||
// -- it's an open question what the default for RFC 5280 actually is, see
|
||||
// https://github.com/openssl/openssl/issues/5091 -- so we have to use
|
||||
// cryptobyte because using the asn1 package's marshaling always produces
|
||||
// an EXPLICIT sequence. Note that asn1 is way too magical according to
|
||||
// agl, and cryptobyte is modeled after the CBB/CBS bits that agl put into
|
||||
// boringssl.
|
||||
for oid, vals := range sans {
|
||||
for _, val := range vals {
|
||||
var b cryptobyte.Builder
|
||||
oidStr, err := StringToOid(oid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b.AddASN1ObjectIdentifier(oidStr)
|
||||
b.AddASN1(cbasn1.Tag(0).ContextSpecific().Constructed(), func(b *cryptobyte.Builder) {
|
||||
b.AddASN1(cbasn1.UTF8String, func(b *cryptobyte.Builder) {
|
||||
b.AddBytes([]byte(val))
|
||||
})
|
||||
})
|
||||
m, err := b.Bytes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rawValues = append(rawValues, asn1.RawValue{Tag: 0, Class: 2, IsCompound: true, Bytes: m})
|
||||
}
|
||||
}
|
||||
|
||||
// If other SANs is empty we return which causes normal Go stdlib parsing
|
||||
// of the other SAN types
|
||||
if len(rawValues) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Append any existing SANs, sans marshalling
|
||||
rawValues = append(rawValues, marshalSANs(in.DNSNames, in.EmailAddresses, in.IPAddresses, in.URIs)...)
|
||||
|
||||
// Marshal and add to ExtraExtensions
|
||||
ext := pkix.Extension{
|
||||
// This is the defined OID for subjectAltName
|
||||
Id: asn1.ObjectIdentifier{2, 5, 29, 17},
|
||||
}
|
||||
var err error
|
||||
ext.Value, err = asn1.Marshal(rawValues)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
in.ExtraExtensions = append(in.ExtraExtensions, ext)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Note: Taken from the Go source code since it's not public, and used in the
|
||||
// modified function below (which also uses these consts upstream)
|
||||
const (
|
||||
nameTypeEmail = 1
|
||||
nameTypeDNS = 2
|
||||
nameTypeURI = 6
|
||||
nameTypeIP = 7
|
||||
)
|
||||
|
||||
// Note: Taken from the Go source code since it's not public, plus changed to not marshal
|
||||
// marshalSANs marshals a list of addresses into a the contents of an X.509
|
||||
// SubjectAlternativeName extension.
|
||||
func marshalSANs(dnsNames, emailAddresses []string, ipAddresses []net.IP, uris []*url.URL) []asn1.RawValue {
|
||||
var rawValues []asn1.RawValue
|
||||
for _, name := range dnsNames {
|
||||
rawValues = append(rawValues, asn1.RawValue{Tag: nameTypeDNS, Class: 2, Bytes: []byte(name)})
|
||||
}
|
||||
for _, email := range emailAddresses {
|
||||
rawValues = append(rawValues, asn1.RawValue{Tag: nameTypeEmail, Class: 2, Bytes: []byte(email)})
|
||||
}
|
||||
for _, rawIP := range ipAddresses {
|
||||
// If possible, we always want to encode IPv4 addresses in 4 bytes.
|
||||
ip := rawIP.To4()
|
||||
if ip == nil {
|
||||
ip = rawIP
|
||||
}
|
||||
rawValues = append(rawValues, asn1.RawValue{Tag: nameTypeIP, Class: 2, Bytes: ip})
|
||||
}
|
||||
for _, uri := range uris {
|
||||
rawValues = append(rawValues, asn1.RawValue{Tag: nameTypeURI, Class: 2, Bytes: []byte(uri.String())})
|
||||
}
|
||||
return rawValues
|
||||
}
|
||||
|
||||
func StringToOid(in string) (asn1.ObjectIdentifier, error) {
|
||||
split := strings.Split(in, ".")
|
||||
ret := make(asn1.ObjectIdentifier, 0, len(split))
|
||||
for _, v := range split {
|
||||
i, err := strconv.Atoi(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret = append(ret, i)
|
||||
}
|
||||
return asn1.ObjectIdentifier(ret), nil
|
||||
}
|
||||
|
||||
func ValidateKeyTypeLength(keyType string, keyBits int) error {
|
||||
switch keyType {
|
||||
case "rsa":
|
||||
switch keyBits {
|
||||
case 2048:
|
||||
case 4096:
|
||||
case 8192:
|
||||
default:
|
||||
return fmt.Errorf("unsupported bit length for RSA key: %d", keyBits)
|
||||
}
|
||||
case "ec":
|
||||
switch keyBits {
|
||||
case 224:
|
||||
case 256:
|
||||
case 384:
|
||||
case 521:
|
||||
default:
|
||||
return fmt.Errorf("unsupported bit length for EC key: %d", keyBits)
|
||||
}
|
||||
case "any":
|
||||
default:
|
||||
return fmt.Errorf("unknown key type %s", keyType)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Performs the heavy lifting of creating a certificate. Returns
|
||||
// a fully-filled-in ParsedCertBundle.
|
||||
func CreateCertificate(data *CreationBundle) (*ParsedCertBundle, error) {
|
||||
var err error
|
||||
result := &ParsedCertBundle{}
|
||||
|
||||
serialNumber, err := GenerateSerialNumber()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := GeneratePrivateKey(data.Params.KeyType,
|
||||
data.Params.KeyBits,
|
||||
result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
subjKeyID, err := GetSubjKeyID(result.PrivateKey)
|
||||
if err != nil {
|
||||
return nil, errutil.InternalError{Err: fmt.Sprintf("error getting subject key ID: %s", err)}
|
||||
}
|
||||
|
||||
certTemplate := &x509.Certificate{
|
||||
SerialNumber: serialNumber,
|
||||
NotBefore: time.Now().Add(-30 * time.Second),
|
||||
NotAfter: data.Params.NotAfter,
|
||||
IsCA: false,
|
||||
SubjectKeyId: subjKeyID,
|
||||
Subject: data.Params.Subject,
|
||||
DNSNames: data.Params.DNSNames,
|
||||
EmailAddresses: data.Params.EmailAddresses,
|
||||
IPAddresses: data.Params.IPAddresses,
|
||||
URIs: data.Params.URIs,
|
||||
}
|
||||
if data.Params.NotBeforeDuration > 0 {
|
||||
certTemplate.NotBefore = time.Now().Add(-1 * data.Params.NotBeforeDuration)
|
||||
}
|
||||
|
||||
if err := HandleOtherSANs(certTemplate, data.Params.OtherSANs); err != nil {
|
||||
return nil, errutil.InternalError{Err: errwrap.Wrapf("error marshaling other SANs: {{err}}", err).Error()}
|
||||
}
|
||||
|
||||
// Add this before calling addKeyUsages
|
||||
if data.SigningBundle == nil {
|
||||
certTemplate.IsCA = true
|
||||
} else if data.Params.BasicConstraintsValidForNonCA {
|
||||
certTemplate.BasicConstraintsValid = true
|
||||
certTemplate.IsCA = false
|
||||
}
|
||||
|
||||
// This will only be filled in from the generation paths
|
||||
if len(data.Params.PermittedDNSDomains) > 0 {
|
||||
certTemplate.PermittedDNSDomains = data.Params.PermittedDNSDomains
|
||||
certTemplate.PermittedDNSDomainsCritical = true
|
||||
}
|
||||
|
||||
AddPolicyIdentifiers(data, certTemplate)
|
||||
|
||||
AddKeyUsages(data, certTemplate)
|
||||
|
||||
AddExtKeyUsageOids(data, certTemplate)
|
||||
|
||||
certTemplate.IssuingCertificateURL = data.Params.URLs.IssuingCertificates
|
||||
certTemplate.CRLDistributionPoints = data.Params.URLs.CRLDistributionPoints
|
||||
certTemplate.OCSPServer = data.Params.URLs.OCSPServers
|
||||
|
||||
var certBytes []byte
|
||||
if data.SigningBundle != nil {
|
||||
switch data.SigningBundle.PrivateKeyType {
|
||||
case RSAPrivateKey:
|
||||
certTemplate.SignatureAlgorithm = x509.SHA256WithRSA
|
||||
case ECPrivateKey:
|
||||
certTemplate.SignatureAlgorithm = x509.ECDSAWithSHA256
|
||||
}
|
||||
|
||||
caCert := data.SigningBundle.Certificate
|
||||
certTemplate.AuthorityKeyId = caCert.SubjectKeyId
|
||||
|
||||
certBytes, err = x509.CreateCertificate(rand.Reader, certTemplate, caCert, result.PrivateKey.Public(), data.SigningBundle.PrivateKey)
|
||||
} else {
|
||||
// Creating a self-signed root
|
||||
if data.Params.MaxPathLength == 0 {
|
||||
certTemplate.MaxPathLen = 0
|
||||
certTemplate.MaxPathLenZero = true
|
||||
} else {
|
||||
certTemplate.MaxPathLen = data.Params.MaxPathLength
|
||||
}
|
||||
|
||||
switch data.Params.KeyType {
|
||||
case "rsa":
|
||||
certTemplate.SignatureAlgorithm = x509.SHA256WithRSA
|
||||
case "ec":
|
||||
certTemplate.SignatureAlgorithm = x509.ECDSAWithSHA256
|
||||
}
|
||||
|
||||
certTemplate.AuthorityKeyId = subjKeyID
|
||||
certTemplate.BasicConstraintsValid = true
|
||||
certBytes, err = x509.CreateCertificate(rand.Reader, certTemplate, certTemplate, result.PrivateKey.Public(), result.PrivateKey)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, errutil.InternalError{Err: fmt.Sprintf("unable to create certificate: %s", err)}
|
||||
}
|
||||
|
||||
result.CertificateBytes = certBytes
|
||||
result.Certificate, err = x509.ParseCertificate(certBytes)
|
||||
if err != nil {
|
||||
return nil, errutil.InternalError{Err: fmt.Sprintf("unable to parse created certificate: %s", err)}
|
||||
}
|
||||
|
||||
if data.SigningBundle != nil {
|
||||
if len(data.SigningBundle.Certificate.AuthorityKeyId) > 0 &&
|
||||
!bytes.Equal(data.SigningBundle.Certificate.AuthorityKeyId, data.SigningBundle.Certificate.SubjectKeyId) {
|
||||
|
||||
result.CAChain = []*CertBlock{
|
||||
&CertBlock{
|
||||
Certificate: data.SigningBundle.Certificate,
|
||||
Bytes: data.SigningBundle.CertificateBytes,
|
||||
},
|
||||
}
|
||||
result.CAChain = append(result.CAChain, data.SigningBundle.CAChain...)
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
var oidExtensionBasicConstraints = []int{2, 5, 29, 19}
|
||||
|
||||
// Creates a CSR. This is currently only meant for use when
|
||||
// generating an intermediate certificate.
|
||||
func CreateCSR(data *CreationBundle, addBasicConstraints bool) (*ParsedCSRBundle, error) {
|
||||
var err error
|
||||
result := &ParsedCSRBundle{}
|
||||
|
||||
if err := GeneratePrivateKey(data.Params.KeyType,
|
||||
data.Params.KeyBits,
|
||||
result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Like many root CAs, other information is ignored
|
||||
csrTemplate := &x509.CertificateRequest{
|
||||
Subject: data.Params.Subject,
|
||||
DNSNames: data.Params.DNSNames,
|
||||
EmailAddresses: data.Params.EmailAddresses,
|
||||
IPAddresses: data.Params.IPAddresses,
|
||||
URIs: data.Params.URIs,
|
||||
}
|
||||
|
||||
if err := HandleOtherCSRSANs(csrTemplate, data.Params.OtherSANs); err != nil {
|
||||
return nil, errutil.InternalError{Err: errwrap.Wrapf("error marshaling other SANs: {{err}}", err).Error()}
|
||||
}
|
||||
|
||||
if addBasicConstraints {
|
||||
type basicConstraints struct {
|
||||
IsCA bool `asn1:"optional"`
|
||||
MaxPathLen int `asn1:"optional,default:-1"`
|
||||
}
|
||||
val, err := asn1.Marshal(basicConstraints{IsCA: true, MaxPathLen: -1})
|
||||
if err != nil {
|
||||
return nil, errutil.InternalError{Err: errwrap.Wrapf("error marshaling basic constraints: {{err}}", err).Error()}
|
||||
}
|
||||
ext := pkix.Extension{
|
||||
Id: oidExtensionBasicConstraints,
|
||||
Value: val,
|
||||
Critical: true,
|
||||
}
|
||||
csrTemplate.ExtraExtensions = append(csrTemplate.ExtraExtensions, ext)
|
||||
}
|
||||
|
||||
switch data.Params.KeyType {
|
||||
case "rsa":
|
||||
csrTemplate.SignatureAlgorithm = x509.SHA256WithRSA
|
||||
case "ec":
|
||||
csrTemplate.SignatureAlgorithm = x509.ECDSAWithSHA256
|
||||
}
|
||||
|
||||
csr, err := x509.CreateCertificateRequest(rand.Reader, csrTemplate, result.PrivateKey)
|
||||
if err != nil {
|
||||
return nil, errutil.InternalError{Err: fmt.Sprintf("unable to create certificate: %s", err)}
|
||||
}
|
||||
|
||||
result.CSRBytes = csr
|
||||
result.CSR, err = x509.ParseCertificateRequest(csr)
|
||||
if err != nil {
|
||||
return nil, errutil.InternalError{Err: fmt.Sprintf("unable to parse created certificate: %v", err)}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// Performs the heavy lifting of generating a certificate from a CSR.
|
||||
// Returns a ParsedCertBundle sans private keys.
|
||||
func SignCertificate(data *CreationBundle) (*ParsedCertBundle, error) {
|
||||
switch {
|
||||
case data == nil:
|
||||
return nil, errutil.UserError{Err: "nil data bundle given to signCertificate"}
|
||||
case data.Params == nil:
|
||||
return nil, errutil.UserError{Err: "nil parameters given to signCertificate"}
|
||||
case data.SigningBundle == nil:
|
||||
return nil, errutil.UserError{Err: "nil signing bundle given to signCertificate"}
|
||||
case data.CSR == nil:
|
||||
return nil, errutil.UserError{Err: "nil csr given to signCertificate"}
|
||||
}
|
||||
|
||||
err := data.CSR.CheckSignature()
|
||||
if err != nil {
|
||||
return nil, errutil.UserError{Err: "request signature invalid"}
|
||||
}
|
||||
|
||||
result := &ParsedCertBundle{}
|
||||
|
||||
serialNumber, err := GenerateSerialNumber()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
marshaledKey, err := x509.MarshalPKIXPublicKey(data.CSR.PublicKey)
|
||||
if err != nil {
|
||||
return nil, errutil.InternalError{Err: fmt.Sprintf("error marshalling public key: %s", err)}
|
||||
}
|
||||
subjKeyID := sha1.Sum(marshaledKey)
|
||||
|
||||
caCert := data.SigningBundle.Certificate
|
||||
|
||||
certTemplate := &x509.Certificate{
|
||||
SerialNumber: serialNumber,
|
||||
Subject: data.Params.Subject,
|
||||
NotBefore: time.Now().Add(-30 * time.Second),
|
||||
NotAfter: data.Params.NotAfter,
|
||||
SubjectKeyId: subjKeyID[:],
|
||||
AuthorityKeyId: caCert.SubjectKeyId,
|
||||
}
|
||||
if data.Params.NotBeforeDuration > 0 {
|
||||
certTemplate.NotBefore = time.Now().Add(-1 * data.Params.NotBeforeDuration)
|
||||
}
|
||||
|
||||
switch data.SigningBundle.PrivateKeyType {
|
||||
case RSAPrivateKey:
|
||||
certTemplate.SignatureAlgorithm = x509.SHA256WithRSA
|
||||
case ECPrivateKey:
|
||||
certTemplate.SignatureAlgorithm = x509.ECDSAWithSHA256
|
||||
}
|
||||
|
||||
if data.Params.UseCSRValues {
|
||||
certTemplate.Subject = data.CSR.Subject
|
||||
certTemplate.Subject.ExtraNames = certTemplate.Subject.Names
|
||||
|
||||
certTemplate.DNSNames = data.CSR.DNSNames
|
||||
certTemplate.EmailAddresses = data.CSR.EmailAddresses
|
||||
certTemplate.IPAddresses = data.CSR.IPAddresses
|
||||
certTemplate.URIs = data.CSR.URIs
|
||||
|
||||
for _, name := range data.CSR.Extensions {
|
||||
if !name.Id.Equal(oidExtensionBasicConstraints) {
|
||||
certTemplate.ExtraExtensions = append(certTemplate.ExtraExtensions, name)
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
certTemplate.DNSNames = data.Params.DNSNames
|
||||
certTemplate.EmailAddresses = data.Params.EmailAddresses
|
||||
certTemplate.IPAddresses = data.Params.IPAddresses
|
||||
certTemplate.URIs = data.Params.URIs
|
||||
}
|
||||
|
||||
if err := HandleOtherSANs(certTemplate, data.Params.OtherSANs); err != nil {
|
||||
return nil, errutil.InternalError{Err: errwrap.Wrapf("error marshaling other SANs: {{err}}", err).Error()}
|
||||
}
|
||||
|
||||
AddPolicyIdentifiers(data, certTemplate)
|
||||
|
||||
AddKeyUsages(data, certTemplate)
|
||||
|
||||
AddExtKeyUsageOids(data, certTemplate)
|
||||
|
||||
var certBytes []byte
|
||||
|
||||
certTemplate.IssuingCertificateURL = data.Params.URLs.IssuingCertificates
|
||||
certTemplate.CRLDistributionPoints = data.Params.URLs.CRLDistributionPoints
|
||||
certTemplate.OCSPServer = data.SigningBundle.URLs.OCSPServers
|
||||
|
||||
if data.Params.IsCA {
|
||||
certTemplate.BasicConstraintsValid = true
|
||||
certTemplate.IsCA = true
|
||||
|
||||
if data.SigningBundle.Certificate.MaxPathLen == 0 &&
|
||||
data.SigningBundle.Certificate.MaxPathLenZero {
|
||||
return nil, errutil.UserError{Err: "signing certificate has a max path length of zero, and cannot issue further CA certificates"}
|
||||
}
|
||||
|
||||
certTemplate.MaxPathLen = data.Params.MaxPathLength
|
||||
if certTemplate.MaxPathLen == 0 {
|
||||
certTemplate.MaxPathLenZero = true
|
||||
}
|
||||
} else if data.Params.BasicConstraintsValidForNonCA {
|
||||
certTemplate.BasicConstraintsValid = true
|
||||
certTemplate.IsCA = false
|
||||
}
|
||||
|
||||
if len(data.Params.PermittedDNSDomains) > 0 {
|
||||
certTemplate.PermittedDNSDomains = data.Params.PermittedDNSDomains
|
||||
certTemplate.PermittedDNSDomainsCritical = true
|
||||
}
|
||||
|
||||
certBytes, err = x509.CreateCertificate(rand.Reader, certTemplate, caCert, data.CSR.PublicKey, data.SigningBundle.PrivateKey)
|
||||
|
||||
if err != nil {
|
||||
return nil, errutil.InternalError{Err: fmt.Sprintf("unable to create certificate: %s", err)}
|
||||
}
|
||||
|
||||
result.CertificateBytes = certBytes
|
||||
result.Certificate, err = x509.ParseCertificate(certBytes)
|
||||
if err != nil {
|
||||
return nil, errutil.InternalError{Err: fmt.Sprintf("unable to parse created certificate: %s", err)}
|
||||
}
|
||||
|
||||
result.CAChain = data.SigningBundle.GetCAChain()
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
|
|
@ -15,10 +15,14 @@ import (
|
|||
"crypto/rsa"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"net"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/errwrap"
|
||||
"github.com/hashicorp/vault/sdk/helper/errutil"
|
||||
|
@ -598,3 +602,158 @@ type IssueData struct {
|
|||
IPSANs string `json:"ip_sans" structs:"ip_sans" mapstructure:"ip_sans"`
|
||||
CSR string `json:"csr" structs:"csr" mapstructure:"csr"`
|
||||
}
|
||||
|
||||
type URLEntries struct {
|
||||
IssuingCertificates []string `json:"issuing_certificates" structs:"issuing_certificates" mapstructure:"issuing_certificates"`
|
||||
CRLDistributionPoints []string `json:"crl_distribution_points" structs:"crl_distribution_points" mapstructure:"crl_distribution_points"`
|
||||
OCSPServers []string `json:"ocsp_servers" structs:"ocsp_servers" mapstructure:"ocsp_servers"`
|
||||
}
|
||||
|
||||
type CAInfoBundle struct {
|
||||
ParsedCertBundle
|
||||
URLs *URLEntries
|
||||
}
|
||||
|
||||
func (b *CAInfoBundle) GetCAChain() []*CertBlock {
|
||||
chain := []*CertBlock{}
|
||||
|
||||
// Include issuing CA in Chain, not including Root Authority
|
||||
if (len(b.Certificate.AuthorityKeyId) > 0 &&
|
||||
!bytes.Equal(b.Certificate.AuthorityKeyId, b.Certificate.SubjectKeyId)) ||
|
||||
(len(b.Certificate.AuthorityKeyId) == 0 &&
|
||||
!bytes.Equal(b.Certificate.RawIssuer, b.Certificate.RawSubject)) {
|
||||
|
||||
chain = append(chain, &CertBlock{
|
||||
Certificate: b.Certificate,
|
||||
Bytes: b.CertificateBytes,
|
||||
})
|
||||
if b.CAChain != nil && len(b.CAChain) > 0 {
|
||||
chain = append(chain, b.CAChain...)
|
||||
}
|
||||
}
|
||||
|
||||
return chain
|
||||
}
|
||||
|
||||
type CertExtKeyUsage int
|
||||
|
||||
const (
|
||||
AnyExtKeyUsage CertExtKeyUsage = 1 << iota
|
||||
ServerAuthExtKeyUsage
|
||||
ClientAuthExtKeyUsage
|
||||
CodeSigningExtKeyUsage
|
||||
EmailProtectionExtKeyUsage
|
||||
IpsecEndSystemExtKeyUsage
|
||||
IpsecTunnelExtKeyUsage
|
||||
IpsecUserExtKeyUsage
|
||||
TimeStampingExtKeyUsage
|
||||
OcspSigningExtKeyUsage
|
||||
MicrosoftServerGatedCryptoExtKeyUsage
|
||||
NetscapeServerGatedCryptoExtKeyUsage
|
||||
MicrosoftCommercialCodeSigningExtKeyUsage
|
||||
MicrosoftKernelCodeSigningExtKeyUsage
|
||||
)
|
||||
|
||||
type CreationParameters struct {
|
||||
Subject pkix.Name
|
||||
DNSNames []string
|
||||
EmailAddresses []string
|
||||
IPAddresses []net.IP
|
||||
URIs []*url.URL
|
||||
OtherSANs map[string][]string
|
||||
IsCA bool
|
||||
KeyType string
|
||||
KeyBits int
|
||||
NotAfter time.Time
|
||||
KeyUsage x509.KeyUsage
|
||||
ExtKeyUsage CertExtKeyUsage
|
||||
ExtKeyUsageOIDs []string
|
||||
PolicyIdentifiers []string
|
||||
BasicConstraintsValidForNonCA bool
|
||||
|
||||
// Only used when signing a CA cert
|
||||
UseCSRValues bool
|
||||
PermittedDNSDomains []string
|
||||
|
||||
// URLs to encode into the certificate
|
||||
URLs *URLEntries
|
||||
|
||||
// The maximum path length to encode
|
||||
MaxPathLength int
|
||||
|
||||
// The duration the certificate will use NotBefore
|
||||
NotBeforeDuration time.Duration
|
||||
}
|
||||
|
||||
type CreationBundle struct {
|
||||
Params *CreationParameters
|
||||
SigningBundle *CAInfoBundle
|
||||
CSR *x509.CertificateRequest
|
||||
}
|
||||
|
||||
// addKeyUsages adds appropriate key usages to the template given the creation
|
||||
// information
|
||||
func AddKeyUsages(data *CreationBundle, certTemplate *x509.Certificate) {
|
||||
if data.Params.IsCA {
|
||||
certTemplate.KeyUsage = x509.KeyUsage(x509.KeyUsageCertSign | x509.KeyUsageCRLSign)
|
||||
return
|
||||
}
|
||||
|
||||
certTemplate.KeyUsage = data.Params.KeyUsage
|
||||
|
||||
if data.Params.ExtKeyUsage&AnyExtKeyUsage != 0 {
|
||||
certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageAny)
|
||||
}
|
||||
|
||||
if data.Params.ExtKeyUsage&ServerAuthExtKeyUsage != 0 {
|
||||
certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageServerAuth)
|
||||
}
|
||||
|
||||
if data.Params.ExtKeyUsage&ClientAuthExtKeyUsage != 0 {
|
||||
certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageClientAuth)
|
||||
}
|
||||
|
||||
if data.Params.ExtKeyUsage&CodeSigningExtKeyUsage != 0 {
|
||||
certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageCodeSigning)
|
||||
}
|
||||
|
||||
if data.Params.ExtKeyUsage&EmailProtectionExtKeyUsage != 0 {
|
||||
certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageEmailProtection)
|
||||
}
|
||||
|
||||
if data.Params.ExtKeyUsage&IpsecEndSystemExtKeyUsage != 0 {
|
||||
certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageIPSECEndSystem)
|
||||
}
|
||||
|
||||
if data.Params.ExtKeyUsage&IpsecTunnelExtKeyUsage != 0 {
|
||||
certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageIPSECTunnel)
|
||||
}
|
||||
|
||||
if data.Params.ExtKeyUsage&IpsecUserExtKeyUsage != 0 {
|
||||
certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageIPSECUser)
|
||||
}
|
||||
|
||||
if data.Params.ExtKeyUsage&TimeStampingExtKeyUsage != 0 {
|
||||
certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageTimeStamping)
|
||||
}
|
||||
|
||||
if data.Params.ExtKeyUsage&OcspSigningExtKeyUsage != 0 {
|
||||
certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageOCSPSigning)
|
||||
}
|
||||
|
||||
if data.Params.ExtKeyUsage&MicrosoftServerGatedCryptoExtKeyUsage != 0 {
|
||||
certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageMicrosoftServerGatedCrypto)
|
||||
}
|
||||
|
||||
if data.Params.ExtKeyUsage&NetscapeServerGatedCryptoExtKeyUsage != 0 {
|
||||
certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageNetscapeServerGatedCrypto)
|
||||
}
|
||||
|
||||
if data.Params.ExtKeyUsage&MicrosoftCommercialCodeSigningExtKeyUsage != 0 {
|
||||
certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageMicrosoftCommercialCodeSigning)
|
||||
}
|
||||
|
||||
if data.Params.ExtKeyUsage&MicrosoftKernelCodeSigningExtKeyUsage != 0 {
|
||||
certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageMicrosoftKernelCodeSigning)
|
||||
}
|
||||
}
|
||||
|
|
15
vendor/github.com/hashicorp/vault/api/plugin_helpers.go
generated
vendored
15
vendor/github.com/hashicorp/vault/api/plugin_helpers.go
generated
vendored
|
@ -12,7 +12,16 @@ import (
|
|||
squarejwt "gopkg.in/square/go-jose.v2/jwt"
|
||||
|
||||
"github.com/hashicorp/errwrap"
|
||||
"github.com/hashicorp/vault/sdk/helper/pluginutil"
|
||||
)
|
||||
|
||||
var (
|
||||
// PluginMetadataModeEnv is an ENV name used to disable TLS communication
|
||||
// to bootstrap mounting plugins.
|
||||
PluginMetadataModeEnv = "VAULT_PLUGIN_METADATA_MODE"
|
||||
|
||||
// PluginUnwrapTokenEnv is the ENV name used to pass unwrap tokens to the
|
||||
// plugin.
|
||||
PluginUnwrapTokenEnv = "VAULT_UNWRAP_TOKEN"
|
||||
)
|
||||
|
||||
// PluginAPIClientMeta is a helper that plugins can use to configure TLS connections
|
||||
|
@ -61,12 +70,12 @@ func (f *PluginAPIClientMeta) GetTLSConfig() *TLSConfig {
|
|||
// VaultPluginTLSProvider is run inside a plugin and retrieves the response
|
||||
// wrapped TLS certificate from vault. It returns a configured TLS Config.
|
||||
func VaultPluginTLSProvider(apiTLSConfig *TLSConfig) func() (*tls.Config, error) {
|
||||
if os.Getenv(pluginutil.PluginMetadataModeEnv) == "true" {
|
||||
if os.Getenv(PluginMetadataModeEnv) == "true" {
|
||||
return nil
|
||||
}
|
||||
|
||||
return func() (*tls.Config, error) {
|
||||
unwrapToken := os.Getenv(pluginutil.PluginUnwrapTokenEnv)
|
||||
unwrapToken := os.Getenv(PluginUnwrapTokenEnv)
|
||||
|
||||
parsedJWT, err := squarejwt.ParseSigned(unwrapToken)
|
||||
if err != nil {
|
||||
|
|
|
@ -100,7 +100,7 @@ The seal can be migrated from Shamir keys to Auto Unseal and vice versa.
|
|||
|
||||
To migrate from Shamir keys to Auto Unseal, take your server cluster offline and update
|
||||
the [seal configuration](/docs/configuration/seal/index.html) with the appropriate seal
|
||||
configuration. When you bring up your server back up, run the unseal process with the
|
||||
configuration. When you bring your server back up, run the unseal process with the
|
||||
`-migrate` flag. All unseal commands must specify the `-migrate` flag. Once the
|
||||
required threshold of unseal keys are entered, the unseal keys will be migrated to
|
||||
recovery keys.
|
||||
|
@ -112,7 +112,7 @@ $ vault operator unseal -migrate
|
|||
To migrate from Auto Unseal to Shamir keys, take your server cluster offline and update
|
||||
the [seal configuration](/docs/configuration/seal/index.html) and add `disabled = "true"`
|
||||
to the seal block. This allows the migration to use this information to decrypt the key
|
||||
but will not unseal Vault. When you bring up your server back up, run the unseal process
|
||||
but will not unseal Vault. When you bring your server back up, run the unseal process
|
||||
with the `-migrate` flag and use the Recovery Keys to perform the migration. All unseal
|
||||
commands must specify the `-migrate` flag. Once the required threshold of recovery keys
|
||||
are entered, the recovery keys will be migrated to be used as unseal keys.
|
||||
|
|
Loading…
Reference in a new issue