From 8bf935bc2bb30cc160fe716195eda7fce6ab14b2 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Tue, 15 Mar 2016 14:07:40 -0400 Subject: [PATCH] Add list support to certs in cert auth backend. Fixes #1212 --- builtin/credential/cert/backend.go | 1 + builtin/credential/cert/backend_test.go | 51 +++++++++++++++++++---- builtin/credential/cert/path_certs.go | 22 ++++++++++ website/source/docs/auth/cert.html.md | 54 +++++++++++++++++++++---- 4 files changed, 113 insertions(+), 15 deletions(-) diff --git a/builtin/credential/cert/backend.go b/builtin/credential/cert/backend.go index 1ed45cd4b..a07ec3367 100644 --- a/builtin/credential/cert/backend.go +++ b/builtin/credential/cert/backend.go @@ -30,6 +30,7 @@ func Backend() *backend { Paths: append([]*framework.Path{ pathConfig(&b), pathLogin(&b), + pathListCerts(&b), pathCerts(&b), pathCRLs(&b), }), diff --git a/builtin/credential/cert/backend_test.go b/builtin/credential/cert/backend_test.go index 987626152..2421261f7 100644 --- a/builtin/credential/cert/backend_test.go +++ b/builtin/credential/cert/backend_test.go @@ -4,6 +4,7 @@ import ( "crypto/tls" "fmt" "io/ioutil" + "reflect" "testing" "time" @@ -44,14 +45,17 @@ func TestBackend_CertWrites(t *testing.T) { if err != nil { t.Fatalf("err: %v", err) } - logicaltest.Test(t, logicaltest.TestCase{ + + tc := logicaltest.TestCase{ Backend: testFactory(t), Steps: []logicaltest.TestStep{ - testAccStepCert(t, "web", ca1, "foo", false), - testAccStepCert(t, "web", ca2, "foo", false), - testAccStepCert(t, "web", ca3, "foo", true), + testAccStepCert(t, "aaa", ca1, "foo", false), + testAccStepCert(t, "bbb", ca2, "foo", false), + testAccStepCert(t, "ccc", ca3, "foo", true), }, - }) + } + tc.Steps = append(tc.Steps, testAccStepListCerts(t, []string{"aaa", "bbb"})...) + logicaltest.Test(t, tc) } // Test a client trusted by a CA @@ -183,7 +187,7 @@ func testAccStepLogin(t *testing.T, connState tls.ConnectionState) logicaltest.T t.Fatalf("bad lease length: %#v", resp.Auth) } - fn := logicaltest.TestCheckAuth([]string{"foo"}) + fn := logicaltest.TestCheckAuth([]string{"default", "foo"}) return fn(resp) }, } @@ -200,7 +204,7 @@ func testAccStepLoginDefaultLease(t *testing.T, connState tls.ConnectionState) l t.Fatalf("bad lease length: %#v", resp.Auth) } - fn := logicaltest.TestCheckAuth([]string{"foo"}) + fn := logicaltest.TestCheckAuth([]string{"default", "foo"}) return fn(resp) }, } @@ -222,6 +226,39 @@ func testAccStepLoginInvalid(t *testing.T, connState tls.ConnectionState) logica } } +func testAccStepListCerts( + t *testing.T, certs []string) []logicaltest.TestStep { + return []logicaltest.TestStep{ + logicaltest.TestStep{ + Operation: logical.ListOperation, + Path: "certs", + Check: func(resp *logical.Response) error { + if resp == nil { + return fmt.Errorf("nil response") + } + if resp.Data == nil { + return fmt.Errorf("nil data") + } + if resp.Data["keys"] == interface{}(nil) { + return fmt.Errorf("nil keys") + } + keys := resp.Data["keys"].([]string) + if !reflect.DeepEqual(keys, certs) { + return fmt.Errorf("mismatch: keys is %#v, certs is %#v", keys, certs) + } + return nil + }, + }, logicaltest.TestStep{ + Operation: logical.ListOperation, + Path: "certs/", + Check: func(resp *logical.Response) error { + + return nil + }, + }, + } +} + func testAccStepCert( t *testing.T, name string, cert []byte, policies string, expectError bool) logicaltest.TestStep { return logicaltest.TestStep{ diff --git a/builtin/credential/cert/path_certs.go b/builtin/credential/cert/path_certs.go index c94dfdff6..f187ce0f5 100644 --- a/builtin/credential/cert/path_certs.go +++ b/builtin/credential/cert/path_certs.go @@ -10,6 +10,19 @@ import ( "github.com/hashicorp/vault/logical/framework" ) +func pathListCerts(b *backend) *framework.Path { + return &framework.Path{ + Pattern: "certs/?", + + Callbacks: map[logical.Operation]framework.OperationFunc{ + logical.ListOperation: b.pathCertList, + }, + + HelpSynopsis: pathCertHelpSyn, + HelpDescription: pathCertHelpDesc, + } +} + func pathCerts(b *backend) *framework.Path { return &framework.Path{ Pattern: "certs/" + framework.GenericNameRegex("name"), @@ -85,6 +98,15 @@ func (b *backend) pathCertDelete( return nil, nil } +func (b *backend) pathCertList( + req *logical.Request, d *framework.FieldData) (*logical.Response, error) { + certs, err := req.Storage.List("cert/") + if err != nil { + return nil, err + } + return logical.ListResponse(certs), nil +} + func (b *backend) pathCertRead( req *logical.Request, d *framework.FieldData) (*logical.Response, error) { cert, err := b.Cert(req.Storage, strings.ToLower(d.Get("name").(string))) diff --git a/website/source/docs/auth/cert.html.md b/website/source/docs/auth/cert.html.md index d43391ee8..40c947ad5 100644 --- a/website/source/docs/auth/cert.html.md +++ b/website/source/docs/auth/cert.html.md @@ -124,7 +124,7 @@ of the header should be "X-Vault-Token" and the value should be the token.
Description
- Deletes the named role and CA cert from the backend mount. Requires `sudo` access. + Deletes the named role and CA cert from the backend mount.
Method
@@ -149,7 +149,7 @@ of the header should be "X-Vault-Token" and the value should be the token.
Description
- Gets information associated with the named role. Requires `sudo` access. + Gets information associated with the named role.
Method
@@ -185,12 +185,50 @@ of the header should be "X-Vault-Token" and the value should be the token.
+#### LIST + +
+
Description
+
+ Lists configured certificate names. +
+ +
Method
+
GET
+ +
URL
+
`/auth/cert/certs/`
+ +
Parameters
+
+ None +
+ +
Returns
+
+ + ```javascript + { + "lease_id": "", + "renewable": false, + "lease_duration": 0, + "data": { + "keys": ["cert1", "cert2"] + }, + "warnings": null, + "auth": null + } + ``` + +
+
+ #### POST
Description
- Sets a CA cert and associated parameters in a role name. Requires `sudo` access. + Sets a CA cert and associated parameters in a role name.
Method
@@ -243,7 +281,7 @@ of the header should be "X-Vault-Token" and the value should be the token.
Description
- Deletes the named CRL from the backend mount. Requires `sudo` access. + Deletes the named CRL from the backend mount.
Method
@@ -268,9 +306,9 @@ of the header should be "X-Vault-Token" and the value should be the token.
Description
- Gets information associated with the named CRL (currently, the serial numbers contained within). - As the serials can be integers up to an arbitrary size, these are returned as strings. Requires - `sudo` access. + Gets information associated with the named CRL (currently, the serial + numbers contained within). As the serials can be integers up to an + arbitrary size, these are returned as strings.
Method
@@ -311,7 +349,7 @@ of the header should be "X-Vault-Token" and the value should be the token.
Description
- Sets a named CRL. Requires `sudo` access. + Sets a named CRL.
Method