Merge branch 'main' of github.com:hashicorp/vault

This commit is contained in:
Mark Collao
2022-09-20 16:33:25 -05:00
5 changed files with 247 additions and 0 deletions

View File

@@ -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

View File

@@ -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 := ""

View File

@@ -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)

View File

@@ -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.

View File

@@ -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)