mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-26 14:55:01 +00:00
Merge branch 'main' of github.com:hashicorp/vault
This commit is contained in:
@@ -5630,6 +5630,209 @@ func TestBackend_VerifyIssuerUpdateDefaultsMatchCreation(t *testing.T) {
|
||||
"most likely we have a different set of field parameters across create and update of issuers.")
|
||||
}
|
||||
|
||||
func TestBackend_VerifyPSSKeysIssuersFailImport(t *testing.T) {
|
||||
t.Parallel()
|
||||
b, s := createBackendWithStorage(t)
|
||||
|
||||
// PKCS8 parsing fails on this key due to rsaPSS OID
|
||||
rsaOIDKey := `
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEugIBADALBgkqhkiG9w0BAQoEggSmMIIEogIBAAKCAQEAtN0/NPuJHLuyEdBr
|
||||
tUikXoXOV741XZcNvLAIVBIqDA0ege2gXt9A15FGUI4X3u6kT16Fl6MRdtUZ/qNS
|
||||
Vs15nK9A1PI/AVekMgTVFTnoCzs550CKN8iRk9Om+lwHimpyXxKkFW69v8fsXwKE
|
||||
Bsz69jjT7HV9VZQ7fQhmE79brAMuwKP1fUQKdHq5OBKtQ7Cl3Gmipp0izCsVuQIE
|
||||
kBHvT3UUgyaSp2n+FONpOiyuBoYUH5tVEv9sZzBqSsrYBJYF+GvfnFy9AcTdqRe2
|
||||
VX2SjjWjDF84T30OBA798gIFIPwu9R4OjWOlPeh2bo2kGeo3AITjwFZ28m7kS7kc
|
||||
OtvHpwIDAQABAoIBAFQxmjbj0RQbG+3HBBzD0CBgUYnu9ZC3vKFVoMriGci6YrVB
|
||||
FSKU8u5mpkDhpKMWnE6GRdItCvgyg4NSLAZUaIRT4O5ARqwtTDYsobTb2/U+gNnx
|
||||
5WXKbFpQcK6jIK+ClfNEDjYb8yDPxG0GEsfHrBvqoFy25L1t37N4sWwH7HjJyZIe
|
||||
Hbqx4NVDur9qgqaUwkfSeufn4ycHqFtkzKNzCUarDkST9cxE6/1AKfhl09PPuMEa
|
||||
lAY2JLiEplQL5sh9cxG5FObJbutJo5EIhR2OdM0VcPf0MTD9LXKRoGR3SNlG7IlS
|
||||
llJzBjlh4J1ByMX32btKMHzEvlhyrMI90E1SEGECgYEAx1yDQWe4/b1MBqCxA3d0
|
||||
20dDmUHSRQFhkd/Mzkl5dPzRkG42W3ryNbMKdeuL0ZgK9AhfaLCjcj1i+44O7dHb
|
||||
qBTVwfRrer2uoQVCqqJ6z8PGxPJJxTaqh9QuJxkoQ0i43ZNPcjc2M2sWLn+lkkdE
|
||||
MaGMiyrmjIQEC6tmgCtZ1VUCgYEA6D9xoT9VuAnQjDvW2tO5N2U2H/8ZyRd1pC3z
|
||||
H1CzjwShhxsP4YOUaVdw59K95JL4SMxSmpRrhthlW3cRaiT/exBcXLEvz0Qu0OhW
|
||||
a6155ZFjK3UaLDKlwvmtuoAsuAFqX084LO0B1oxvUJESgyPncQ36fv2lZGV7A66z
|
||||
Uo+BKQsCgYB2yGBMMAjA5nDN4iCV+C7gF+3m+pjWFKSVzcqxfoWndptGeuRYTUDT
|
||||
TgIFkHqWPwkHrZVrQxOflYPMbi/m8wr1crSKA5+mWi4aMpAuKvERqYxc/B+IKbIh
|
||||
jAKTuSGMNWAwZP0JCGx65mso+VUleuDe0Wpz4PPM9TuT2GQSKcI0oQKBgHAHcouC
|
||||
npmo+lU65DgoWzaydrpWdpy+2Tt6AsW/Su4ZIMWoMy/oJaXuzQK2cG0ay/NpxArW
|
||||
v0uLhNDrDZZzBF3blYIM4nALhr205UMJqjwntnuXACoDwFvdzoShIXEdFa+l6gYZ
|
||||
yYIxudxWLmTd491wDb5GIgrcvMsY8V1I5dfjAoGAM9g2LtdqgPgK33dCDtZpBm8m
|
||||
y4ri9PqHxnpps9WJ1dO6MW/YbW+a7vbsmNczdJ6XNLEfy2NWho1dw3xe7ztFVDjF
|
||||
cWNUzs1+/6aFsi41UX7EFn3zAFhQUPxT59hXspuWuKbRAWc5fMnxbCfI/Cr8wTLJ
|
||||
E/0kiZ4swUMyI4tYSbM=
|
||||
-----END PRIVATE KEY-----
|
||||
`
|
||||
_, err := CBWrite(b, s, "issuers/import/bundle", map[string]interface{}{
|
||||
"pem_bundle": rsaOIDKey,
|
||||
})
|
||||
require.Error(t, err, "expected error importing PKCS8 rsaPSS OID key")
|
||||
|
||||
_, err = CBWrite(b, s, "keys/import", map[string]interface{}{
|
||||
"key": rsaOIDKey,
|
||||
})
|
||||
require.Error(t, err, "expected error importing PKCS8 rsaPSS OID key")
|
||||
|
||||
// Importing a cert with rsaPSS OID should also fail
|
||||
rsaOIDCert := `
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDfjCCAjGgAwIBAgIBATBCBgkqhkiG9w0BAQowNaAPMA0GCWCGSAFlAwQCAQUA
|
||||
oRwwGgYJKoZIhvcNAQEIMA0GCWCGSAFlAwQCAQUAogQCAgDeMBMxETAPBgNVBAMM
|
||||
CHJvb3Qtb2xkMB4XDTIyMDkxNjE0MDEwM1oXDTIzMDkyNjE0MDEwM1owEzERMA8G
|
||||
A1UEAwwIcm9vdC1vbGQwggEgMAsGCSqGSIb3DQEBCgOCAQ8AMIIBCgKCAQEAtN0/
|
||||
NPuJHLuyEdBrtUikXoXOV741XZcNvLAIVBIqDA0ege2gXt9A15FGUI4X3u6kT16F
|
||||
l6MRdtUZ/qNSVs15nK9A1PI/AVekMgTVFTnoCzs550CKN8iRk9Om+lwHimpyXxKk
|
||||
FW69v8fsXwKEBsz69jjT7HV9VZQ7fQhmE79brAMuwKP1fUQKdHq5OBKtQ7Cl3Gmi
|
||||
pp0izCsVuQIEkBHvT3UUgyaSp2n+FONpOiyuBoYUH5tVEv9sZzBqSsrYBJYF+Gvf
|
||||
nFy9AcTdqRe2VX2SjjWjDF84T30OBA798gIFIPwu9R4OjWOlPeh2bo2kGeo3AITj
|
||||
wFZ28m7kS7kcOtvHpwIDAQABo3UwczAdBgNVHQ4EFgQUVGkTAUJ8inxIVGBlfxf4
|
||||
cDhRSnowHwYDVR0jBBgwFoAUVGkTAUJ8inxIVGBlfxf4cDhRSnowDAYDVR0TBAUw
|
||||
AwEB/zAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwEwQgYJKoZI
|
||||
hvcNAQEKMDWgDzANBglghkgBZQMEAgEFAKEcMBoGCSqGSIb3DQEBCDANBglghkgB
|
||||
ZQMEAgEFAKIEAgIA3gOCAQEAQZ3iQ3NjvS4FYJ5WG41huZI0dkvNFNan+ZYWlYHJ
|
||||
MIQhbFogb/UQB0rlsuldG0+HF1RDXoYNuThfzt5hiBWYEtMBNurezvnOn4DF0hrl
|
||||
Uk3sBVnvTalVXg+UVjqh9hBGB75JYJl6a5Oa2Zrq++4qGNwjd0FqgnoXzqS5UGuB
|
||||
TJL8nlnXPuOIK3VHoXEy7l9GtvEzKcys0xa7g1PYpaJ5D2kpbBJmuQGmU6CDcbP+
|
||||
m0hI4QDfVfHtnBp2VMCvhj0yzowtwF4BFIhv4EXZBU10mzxVj0zyKKft9++X8auH
|
||||
nebuK22ZwzbPe4NhOvAdfNDElkrrtGvTnzkDB7ezPYjelA==
|
||||
-----END CERTIFICATE-----
|
||||
`
|
||||
_, err = CBWrite(b, s, "issuers/import/bundle", map[string]interface{}{
|
||||
"pem_bundle": rsaOIDCert,
|
||||
})
|
||||
require.Error(t, err, "expected error importing PKCS8 rsaPSS OID cert")
|
||||
|
||||
_, err = CBWrite(b, s, "issuers/import/bundle", map[string]interface{}{
|
||||
"pem_bundle": rsaOIDKey + "\n" + rsaOIDCert,
|
||||
})
|
||||
require.Error(t, err, "expected error importing PKCS8 rsaPSS OID key+cert")
|
||||
|
||||
_, err = CBWrite(b, s, "issuers/import/bundle", map[string]interface{}{
|
||||
"pem_bundle": rsaOIDCert + "\n" + rsaOIDKey,
|
||||
})
|
||||
require.Error(t, err, "expected error importing PKCS8 rsaPSS OID cert+key")
|
||||
|
||||
// After all these errors, we should have zero issuers and keys.
|
||||
resp, err := CBList(b, s, "issuers")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, nil, resp.Data["keys"])
|
||||
|
||||
resp, err = CBList(b, s, "keys")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, nil, resp.Data["keys"])
|
||||
|
||||
// If we create a new PSS root, we should be able to issue an intermediate
|
||||
// under it.
|
||||
resp, err = CBWrite(b, s, "root/generate/exported", map[string]interface{}{
|
||||
"use_pss": "true",
|
||||
"common_name": "root x1 - pss",
|
||||
"key_type": "ec",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, resp)
|
||||
require.NotNil(t, resp.Data)
|
||||
require.NotEmpty(t, resp.Data["certificate"])
|
||||
require.NotEmpty(t, resp.Data["private_key"])
|
||||
|
||||
resp, err = CBWrite(b, s, "intermediate/generate/exported", map[string]interface{}{
|
||||
"use_pss": "true",
|
||||
"common_name": "int x1 - pss",
|
||||
"key_type": "ec",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, resp)
|
||||
require.NotNil(t, resp.Data)
|
||||
require.NotEmpty(t, resp.Data["csr"])
|
||||
require.NotEmpty(t, resp.Data["private_key"])
|
||||
|
||||
resp, err = CBWrite(b, s, "issuer/default/sign-intermediate", map[string]interface{}{
|
||||
"use_pss": "true",
|
||||
"common_name": "int x1 - pss",
|
||||
"csr": resp.Data["csr"].(string),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, resp)
|
||||
require.NotNil(t, resp.Data)
|
||||
require.NotEmpty(t, resp.Data["certificate"])
|
||||
|
||||
resp, err = CBWrite(b, s, "issuers/import/bundle", map[string]interface{}{
|
||||
"pem_bundle": resp.Data["certificate"].(string),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Finally, if we were to take an rsaPSS OID'd CSR and use it against this
|
||||
// mount, it will fail.
|
||||
_, err = CBWrite(b, s, "roles/testing", map[string]interface{}{
|
||||
"allow_any_name": true,
|
||||
"ttl": "85s",
|
||||
"key_type": "any",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Issuing a leaf from a CSR with rsaPSS OID should fail...
|
||||
rsaOIDCSR := `-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIICkTCCAUQCAQAwGTEXMBUGA1UEAwwOcmFuY2hlci5teS5vcmcwggEgMAsGCSqG
|
||||
SIb3DQEBCgOCAQ8AMIIBCgKCAQEAtzHuGEUK55lXI08yp9DXoye9yCZbkJZO+Hej
|
||||
1TWGEkbX4hzauRJeNp2+wn8xU5y8ITjWSIXEVDHeezosLCSy0Y2QT7/V45zWPUYY
|
||||
ld0oUnPiwsb9CPFlBRFnX3dO9SS5MONIrNCJGKXmLdF3lgSl8zPT6J/hWM+JBjHO
|
||||
hBzK6L8IYwmcEujrQfnOnOztzgMEBJtWG8rnI8roz1adpczTddDKGymh2QevjhlL
|
||||
X9CLeYSSQZInOMsgaDYl98Hn00K5x0CBp8ADzzXtaPSQ9nsnihN8VvZ/wHw6YbBS
|
||||
BSHa6OD+MrYnw3Sao6/YgBRNT2glIX85uro4ARW9zGB9/748dwIDAQABoAAwQgYJ
|
||||
KoZIhvcNAQEKMDWgDzANBglghkgBZQMEAgEFAKEcMBoGCSqGSIb3DQEBCDANBglg
|
||||
hkgBZQMEAgEFAKIEAgIA3gOCAQEARGAa0HiwzWCpvAdLOVc4/srEyOYFZPLbtv+Y
|
||||
ezZIaUBNaWhOvkunqpa48avmcbGlji7r6fxJ5sT28lHt7ODWcJfn1XPAnqesXErm
|
||||
EBuOIhCv6WiwVyGeTVynuHYkHyw3rIL/zU7N8+zIFV2G2M1UAv5D/eyh/74cr9Of
|
||||
+nvm9jAbkHix8UwOBCFY2LLNl6bXvbIeJEdDOEtA9UmDXs8QGBg4lngyqcE2Z7rz
|
||||
+5N/x4guMk2FqblbFGiCc5fLB0Gp6lFFOqhX9Q8nLJ6HteV42xGJUUtsFpppNCRm
|
||||
82dGIH2PTbXZ0k7iAAwLaPjzOv1v58Wq90o35d4iEsOfJ8v98Q==
|
||||
-----END CERTIFICATE REQUEST-----`
|
||||
|
||||
_, err = CBWrite(b, s, "issuer/default/sign/testing", map[string]interface{}{
|
||||
"common_name": "example.com",
|
||||
"csr": rsaOIDCSR,
|
||||
})
|
||||
require.Error(t, err)
|
||||
|
||||
_, err = CBWrite(b, s, "issuer/default/sign-verbatim", map[string]interface{}{
|
||||
"common_name": "example.com",
|
||||
"use_pss": true,
|
||||
"csr": rsaOIDCSR,
|
||||
})
|
||||
require.Error(t, err)
|
||||
|
||||
_, err = CBWrite(b, s, "issuer/default/sign-intermediate", map[string]interface{}{
|
||||
"common_name": "faulty x1 - pss",
|
||||
"use_pss": true,
|
||||
"csr": rsaOIDCSR,
|
||||
})
|
||||
require.Error(t, err)
|
||||
|
||||
// Vault has a weird API for signing self-signed certificates. Ensure
|
||||
// that doesn't accept rsaPSS OID'd certificates either.
|
||||
_, err = CBWrite(b, s, "issuer/default/sign-self-issued", map[string]interface{}{
|
||||
"use_pss": true,
|
||||
"certificate": rsaOIDCert,
|
||||
})
|
||||
require.Error(t, err)
|
||||
|
||||
// Issuing a regular leaf should succeed.
|
||||
_, err = CBWrite(b, s, "roles/testing", map[string]interface{}{
|
||||
"allow_any_name": true,
|
||||
"ttl": "85s",
|
||||
"key_type": "rsa",
|
||||
"use_pss": "true",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
resp, err = CBWrite(b, s, "issuer/default/issue/testing", map[string]interface{}{
|
||||
"common_name": "example.com",
|
||||
"use_pss": "true",
|
||||
})
|
||||
requireSuccessNonNilResponse(t, resp, err, "failed to issue PSS leaf")
|
||||
}
|
||||
|
||||
var (
|
||||
initTest sync.Once
|
||||
rsaCAKey string
|
||||
|
||||
@@ -765,6 +765,10 @@ func signCert(b *backend,
|
||||
return nil, nil, errutil.UserError{Err: fmt.Sprintf("certificate request could not be parsed: %v", err)}
|
||||
}
|
||||
|
||||
if csr.PublicKeyAlgorithm == x509.UnknownPublicKeyAlgorithm || csr.PublicKey == nil {
|
||||
return nil, nil, errutil.UserError{Err: "Refusing to sign CSR with empty PublicKey. This usually means the SubjectPublicKeyInfo field has an OID not recognized by Go, such as 1.2.840.113549.1.1.10 for rsaPSS."}
|
||||
}
|
||||
|
||||
// This switch validates that the CSR key type matches the role and sets
|
||||
// the value in the actualKeyType/actualKeyBits values.
|
||||
actualKeyType := ""
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
)
|
||||
|
||||
func TestBackend_CRL_EnableDisableRoot(t *testing.T) {
|
||||
t.Parallel()
|
||||
b, s := createBackendWithStorage(t)
|
||||
|
||||
resp, err := CBWrite(b, s, "root/generate/internal", map[string]interface{}{
|
||||
@@ -33,6 +34,7 @@ func TestBackend_CRL_EnableDisableRoot(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBackend_CRLConfigUpdate(t *testing.T) {
|
||||
t.Parallel()
|
||||
b, s := createBackendWithStorage(t)
|
||||
|
||||
// Write a legacy config to storage.
|
||||
@@ -137,6 +139,8 @@ func TestBackend_CRLConfig(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBackend_CRL_AllKeyTypeSigAlgos(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
type testCase struct {
|
||||
KeyType string
|
||||
KeyBits int
|
||||
@@ -192,10 +196,12 @@ func TestBackend_CRL_AllKeyTypeSigAlgos(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBackend_CRL_EnableDisableIntermediateWithRoot(t *testing.T) {
|
||||
t.Parallel()
|
||||
crlEnableDisableIntermediateTestForBackend(t, true)
|
||||
}
|
||||
|
||||
func TestBackend_CRL_EnableDisableIntermediateWithoutRoot(t *testing.T) {
|
||||
t.Parallel()
|
||||
crlEnableDisableIntermediateTestForBackend(t, false)
|
||||
}
|
||||
|
||||
@@ -354,6 +360,7 @@ func crlEnableDisableTestForBackend(t *testing.T, b *backend, s logical.Storage,
|
||||
}
|
||||
|
||||
func TestBackend_Secondary_CRL_Rebuilding(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx := context.Background()
|
||||
b, s := createBackendWithStorage(t)
|
||||
sc := b.makeStorageContext(ctx, s)
|
||||
@@ -378,6 +385,7 @@ func TestBackend_Secondary_CRL_Rebuilding(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCrlRebuilder(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx := context.Background()
|
||||
b, s := createBackendWithStorage(t)
|
||||
sc := b.makeStorageContext(ctx, s)
|
||||
|
||||
@@ -702,6 +702,12 @@ func (sc *storageContext) importIssuer(certValue string, issuerName string) (*is
|
||||
return nil, false, errutil.UserError{Err: "Refusing to import non-CA certificate"}
|
||||
}
|
||||
|
||||
// Ensure this certificate has a parsed public key. Otherwise, we've
|
||||
// likely been given a bad certificate.
|
||||
if issuerCert.PublicKeyAlgorithm == x509.UnknownPublicKeyAlgorithm || issuerCert.PublicKey == nil {
|
||||
return nil, false, errutil.UserError{Err: "Refusing to import CA certificate with empty PublicKey. This usually means the SubjectPublicKeyInfo field has an OID not recognized by Go, such as 1.2.840.113549.1.1.10 for rsaPSS."}
|
||||
}
|
||||
|
||||
// Before we can import a known issuer, we first need to know if the issuer
|
||||
// exists in storage already. This means iterating through all known
|
||||
// issuers and comparing their private value against this value.
|
||||
|
||||
@@ -35,6 +35,7 @@ generating the CA to use with this secrets engine.
|
||||
- [Role-Based Access](#role-based-access)
|
||||
- [Replicated DataSets](#replicated-datasets)
|
||||
- [Cluster Scalability](#cluster-scalability)
|
||||
- [PSS Support](#pss-support)
|
||||
|
||||
## Be Careful with Root CAs
|
||||
|
||||
@@ -564,6 +565,31 @@ set to false. If `generate_lease` is true the lease creation will be forwarded t
|
||||
the active node; if `no_store` is false the entire request will be forwarded to
|
||||
the active node.
|
||||
|
||||
## PSS Support
|
||||
|
||||
Go lacks support for PSS certificates, keys, and CSRs using the `rsaPSS` OID
|
||||
(`1.2.840.113549.1.1.10`). It requires all RSA certificates, keys, and CSRs
|
||||
to use the alternative `rsaEncryption` OID (`1.2.840.113549.1.1.1`).
|
||||
|
||||
When using OpenSSL to generate CAs or CSRs from PKCS8-encoded PSS keys, the
|
||||
resulting CAs and CSRs will have the `rsaPSS` OID. Go and Vault will reject
|
||||
them. Instead, use OpenSSL to generate or convert to a PKCS#1v1.5 private
|
||||
key file and use this to generate the CSR. Vault will, depending on the role
|
||||
and the signing mechanism, still use a PSS signature despite the
|
||||
`rsaEncryption` OID on the request as the SubjectPublicKeyInfo and
|
||||
SignatureAlgorithm fields are orthogonal. When creating an external CA and
|
||||
importing it into Vault, ensure that the `rsaEncryption` OID is present on
|
||||
the SubjectPublicKeyInfo field even if the SignatureAlgorithm is PSS-based.
|
||||
|
||||
These certificates generated by Go (with `rsaEncryption` OID but PSS-based
|
||||
signatures) are otherwise compatible with the fully PSS-based certificates.
|
||||
OpenSSL and NSS support parsing and verifying chains using this type of
|
||||
certificate. Note that some TLS implementations may not support these types
|
||||
of certificates if they do not support `rsa_pss_rsae_*` signature schemes.
|
||||
Additionally, some implementations allow rsaPSS OID certificates to contain
|
||||
restrictions on signature parameters allowed by this certificate, but Go and
|
||||
Vault do not support adding such restrictions.
|
||||
|
||||
## Tutorial
|
||||
|
||||
Refer to the [Build Your Own Certificate Authority (CA)](https://learn.hashicorp.com/vault/secrets-management/sm-pki-engine)
|
||||
|
||||
Reference in New Issue
Block a user