diff --git a/builtin/credential/cert/backend.go b/builtin/credential/cert/backend.go index 89625fbb4..a8bc2538b 100644 --- a/builtin/credential/cert/backend.go +++ b/builtin/credential/cert/backend.go @@ -40,6 +40,7 @@ func Backend() *backend { pathLogin(&b), pathListCerts(&b), pathCerts(&b), + pathListCRLs(&b), pathCRLs(&b), }, AuthRenew: b.pathLoginRenew, diff --git a/builtin/credential/cert/backend_test.go b/builtin/credential/cert/backend_test.go index 4365df477..ad350d90a 100644 --- a/builtin/credential/cert/backend_test.go +++ b/builtin/credential/cert/backend_test.go @@ -925,6 +925,21 @@ func TestBackend_RegisteredNonCA_CRL(t *testing.T) { t.Fatalf("err:%v resp:%#v", err, resp) } + // Ensure the CRL shows up on a list. + listReq := &logical.Request{ + Operation: logical.ListOperation, + Storage: storage, + Path: "crls", + Data: map[string]interface{}{}, + } + resp, err = b.HandleRequest(context.Background(), listReq) + if err != nil || (resp != nil && resp.IsError()) { + t.Fatalf("err:%v resp:%#v", err, resp) + } + if len(resp.Data) != 1 || len(resp.Data["keys"].([]string)) != 1 || resp.Data["keys"].([]string)[0] != "issuedcrl" { + t.Fatalf("bad listing: resp:%v", resp) + } + // Attempt login with the same connection state but with the CRL registered resp, err = b.HandleRequest(context.Background(), loginReq) if err != nil { diff --git a/builtin/credential/cert/path_crls.go b/builtin/credential/cert/path_crls.go index fc87671d8..787c5572d 100644 --- a/builtin/credential/cert/path_crls.go +++ b/builtin/credential/cert/path_crls.go @@ -16,6 +16,28 @@ import ( "github.com/hashicorp/vault/sdk/logical" ) +func pathListCRLs(b *backend) *framework.Path { + return &framework.Path{ + Pattern: "crls/?$", + Operations: map[logical.Operation]framework.OperationHandler{ + logical.ListOperation: &framework.PathOperation{ + Callback: b.pathCRLsList, + }, + }, + HelpSynopsis: pathCRLsHelpSyn, + HelpDescription: pathCRLsHelpDesc, + } +} + +func (b *backend) pathCRLsList(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) { + entries, err := req.Storage.List(ctx, "crls/") + if err != nil { + return nil, fmt.Errorf("failed to list CRLs: %w", err) + } + + return logical.ListResponse(entries), nil +} + func pathCRLs(b *backend) *framework.Path { return &framework.Path{ Pattern: "crls/" + framework.GenericNameRegex("name"), @@ -288,7 +310,7 @@ Manage Certificate Revocation Lists checked during authentication. ` const pathCRLsHelpDesc = ` -This endpoint allows you to create, read, update, and delete the Certificate +This endpoint allows you to list, create, read, update, and delete the Certificate Revocation Lists checked during authentication, and/or CRL Distribution Point URLs. diff --git a/changelog/18043.txt b/changelog/18043.txt new file mode 100644 index 000000000..564574c7f --- /dev/null +++ b/changelog/18043.txt @@ -0,0 +1,3 @@ +```release-note:improvement +auth/cert: Support listing provisioned CRLs within the mount. +``` diff --git a/website/content/api-docs/auth/cert.mdx b/website/content/api-docs/auth/cert.mdx index 0aee9430f..5b4abff6b 100644 --- a/website/content/api-docs/auth/cert.mdx +++ b/website/content/api-docs/auth/cert.mdx @@ -187,6 +187,40 @@ $ curl \ https://127.0.0.1:8200/v1/auth/cert/certs/cert1 ``` +## List CRLs + +Lists configured certificate revocation lists. + +| Method | Path | +| :----- | :---------------- | +| `LIST` | `/auth/cert/crls` | + +### Sample Request + +```shell-session +$ curl \ + --header "X-Vault-Token: ..." \ + --request LIST \ + --cacert vault-ca.pem \ + https://127.0.0.1:8200/v1/auth/cert/crls +``` + +### Sample Response + +```json +{ + "auth": null, + "warnings": null, + "wrap_info": null, + "data": { + "keys": ["crl1", "crl2"] + }, + "lease_duration": 0, + "renewable": false, + "lease_id": "" +} +``` + ## Create CRL Sets a named CRL.