Similar to "/pki/ca(/pem)" routes to retrieve certificates in raw or pem formats, this adds "pki/cert/{serial}/raw(/pem)" routes for any certificate.
This commit is contained in:
parent
e611842ce0
commit
ed457aeae7
|
@ -71,6 +71,7 @@ func Backend(conf *logical.BackendConfig) *backend {
|
|||
pathFetchCAChain(&b),
|
||||
pathFetchCRL(&b),
|
||||
pathFetchCRLViaCertPath(&b),
|
||||
pathFetchValidRaw(&b),
|
||||
pathFetchValid(&b),
|
||||
pathFetchListCerts(&b),
|
||||
pathRevoke(&b),
|
||||
|
|
|
@ -1705,6 +1705,74 @@ func generateRoleSteps(t *testing.T, useCSRs bool) []logicaltest.TestStep {
|
|||
return ret
|
||||
}
|
||||
|
||||
func TestBackend_PathFetchValidRaw(t *testing.T) {
|
||||
// create the backend
|
||||
config := logical.TestBackendConfig()
|
||||
storage := &logical.InmemStorage{}
|
||||
config.StorageView = storage
|
||||
|
||||
b := Backend(config)
|
||||
err := b.Setup(context.Background(), config)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
expectedSerial := "17:67:16:b0:b9:45:58:c0:3a:29:e3:cb:d6:98:33:7a:a6:3b:66:c1"
|
||||
expectedCert := []byte("test certificate")
|
||||
entry := &logical.StorageEntry{
|
||||
Key: fmt.Sprintf("certs/%s", normalizeSerial(expectedSerial)),
|
||||
Value: expectedCert,
|
||||
}
|
||||
err = storage.Put(context.Background(), entry)
|
||||
|
||||
// get der cert
|
||||
resp, err := b.HandleRequest(context.Background(), &logical.Request{
|
||||
Operation: logical.ReadOperation,
|
||||
Path: fmt.Sprintf("cert/%s/raw", expectedSerial),
|
||||
Storage: storage,
|
||||
})
|
||||
if resp != nil && resp.IsError() {
|
||||
t.Fatalf("failed to get raw cert, %#v", resp)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// check the raw cert matches the response body
|
||||
if bytes.Compare(resp.Data[logical.HTTPRawBody].([]byte), expectedCert) != 0 {
|
||||
t.Fatalf("failed to get raw cert")
|
||||
}
|
||||
if resp.Data[logical.HTTPContentType] != "application/pkix-cert" {
|
||||
t.Fatalf("failed to get raw cert content-type")
|
||||
}
|
||||
|
||||
// get pem
|
||||
resp, err = b.HandleRequest(context.Background(), &logical.Request{
|
||||
Operation: logical.ReadOperation,
|
||||
Path: fmt.Sprintf("cert/%s/raw/pem", expectedSerial),
|
||||
Storage: storage,
|
||||
})
|
||||
if resp != nil && resp.IsError() {
|
||||
t.Fatalf("failed to get raw, %#v", resp)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
pemBlock := &pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: expectedCert,
|
||||
}
|
||||
pemCert := []byte(strings.TrimSpace(string(pem.EncodeToMemory(pemBlock))))
|
||||
// check the pem cert matches the response body
|
||||
if bytes.Compare(resp.Data[logical.HTTPRawBody].([]byte), pemCert) != 0 {
|
||||
t.Fatalf("failed to get pem cert")
|
||||
}
|
||||
if resp.Data[logical.HTTPContentType] != "application/pkix-cert" {
|
||||
t.Fatalf("failed to get raw cert content-type")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBackend_PathFetchCertList(t *testing.T) {
|
||||
// create the backend
|
||||
config := logical.TestBackendConfig()
|
||||
|
@ -3039,7 +3107,7 @@ func TestBackend_AllowedURISANsTemplate(t *testing.T) {
|
|||
|
||||
// Write test policy for userpass auth method.
|
||||
err := client.Sys().PutPolicy("test", `
|
||||
path "pki/*" {
|
||||
path "pki/*" {
|
||||
capabilities = ["update"]
|
||||
}`)
|
||||
if err != nil {
|
||||
|
|
|
@ -53,6 +53,27 @@ func pathFetchCRL(b *backend) *framework.Path {
|
|||
}
|
||||
}
|
||||
|
||||
// Returns any valid (non-revoked) cert in raw format.
|
||||
func pathFetchValidRaw(b *backend) *framework.Path {
|
||||
return &framework.Path{
|
||||
Pattern: `cert/(?P<serial>[0-9A-Fa-f-:]+)/raw(/pem)?`,
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"serial": {
|
||||
Type: framework.TypeString,
|
||||
Description: `Certificate serial number, in colon- or
|
||||
hyphen-separated octal`,
|
||||
},
|
||||
},
|
||||
|
||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||
logical.ReadOperation: b.pathFetchRead,
|
||||
},
|
||||
|
||||
HelpSynopsis: pathFetchHelpSyn,
|
||||
HelpDescription: pathFetchHelpDesc,
|
||||
}
|
||||
}
|
||||
|
||||
// Returns any valid (non-revoked) cert. Since "ca" fits the pattern, this path
|
||||
// also handles returning the CA cert in a non-raw format.
|
||||
func pathFetchValid(b *backend) *framework.Path {
|
||||
|
@ -150,6 +171,12 @@ func (b *backend) pathFetchRead(ctx context.Context, req *logical.Request, data
|
|||
case req.Path == "cert/crl":
|
||||
serial = "crl"
|
||||
pemType = "X509 CRL"
|
||||
case strings.HasSuffix(req.Path, "/pem") || strings.HasSuffix(req.Path, "/raw"):
|
||||
serial = data.Get("serial").(string)
|
||||
contentType = "application/pkix-cert"
|
||||
if strings.HasSuffix(req.Path, "/pem") {
|
||||
pemType = "CERTIFICATE"
|
||||
}
|
||||
default:
|
||||
serial = data.Get("serial").(string)
|
||||
pemType = "CERTIFICATE"
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
```release-note:improvement
|
||||
secrets/pki: Add ability to fetch individual certificate as DER or PEM
|
||||
```
|
|
@ -19,6 +19,7 @@ update your API calls accordingly.
|
|||
- [Read CA Certificate](#read-ca-certificate)
|
||||
- [Read CA Certificate Chain](#read-ca-certificate-chain)
|
||||
- [Read Certificate](#read-certificate)
|
||||
- [Read Raw Certificate](#read-raw-certificate)
|
||||
- [List Certificates](#list-certificates)
|
||||
- [Submit CA Information](#submit-ca-information)
|
||||
- [Read CRL Configuration](#read-crl-configuration)
|
||||
|
@ -132,6 +133,37 @@ $ curl \
|
|||
}
|
||||
```
|
||||
|
||||
## Read Raw Certificate
|
||||
|
||||
This endpoint retrieves one of a selection of certificates _in raw DER-encoded
|
||||
form_. This is a bare endpoint that does not return a standard Vault data
|
||||
structure and cannot be read by the Vault CLI; use `/pki/cert/:serial` for that. If
|
||||
`/pem` is added to the endpoint, the selected certificate is returned in PEM format.
|
||||
|
||||
This is an unauthenticated endpoint.
|
||||
|
||||
| Method | Path |
|
||||
| :----- | :---------------------------- |
|
||||
| `GET` | `/pki/cert/:serial/raw(/pem)` |
|
||||
|
||||
### Parameters
|
||||
|
||||
- `serial` `(string: <required>)` – Specifies the serial number of the
|
||||
certificate to select, in hyphen-separated or colon-separated octal.
|
||||
|
||||
### Sample Request
|
||||
|
||||
```shell-session
|
||||
$ curl \
|
||||
http://127.0.0.1:8200/v1/pki/cert/39:dd:2e.../raw
|
||||
```
|
||||
|
||||
### Sample Response
|
||||
|
||||
```text
|
||||
<binary DER-encoded certificate>
|
||||
```
|
||||
|
||||
## List Certificates
|
||||
|
||||
This endpoint returns a list of the current certificates by serial number only.
|
||||
|
|
Loading…
Reference in New Issue