Address first round of feedback from review

This commit is contained in:
Jeff Mitchell 2015-10-30 13:32:51 -04:00
parent 59cc61cc79
commit 154fc24777
5 changed files with 54 additions and 60 deletions

View file

@ -1,19 +1,22 @@
package cert
import (
"sync"
"github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/logical/framework"
)
func Factory(conf *logical.BackendConfig) (logical.Backend, error) {
b, err := Backend().Setup(conf)
b := Backend()
_, err := b.Setup(conf)
if err != nil {
return b, err
}
return b, populateCRLs(conf.StorageView)
return b, b.populateCRLs(conf.StorageView)
}
func Backend() *framework.Backend {
func Backend() *backend {
var b backend
b.Backend = &framework.Backend{
Help: backendHelp,
@ -38,12 +41,18 @@ func Backend() *framework.Backend {
AuthRenew: b.pathLoginRenew,
}
return b.Backend
b.crls = map[string]CRLInfo{}
b.crlUpdateMutex = &sync.RWMutex{}
return &b
}
type backend struct {
*framework.Backend
MapCertId *framework.PathMap
crls map[string]CRLInfo
crlUpdateMutex *sync.RWMutex
}
const backendHelp = `

View file

@ -34,10 +34,6 @@ func TestBackend_basic_CA(t *testing.T) {
if err != nil {
t.Fatalf("err: %v", err)
}
crl, err := ioutil.ReadFile("../../../test/ca/root.crl")
if err != nil {
t.Fatalf("err: %v", err)
}
logicaltest.Test(t, logicaltest.TestCase{
Backend: testFactory(t),
Steps: []logicaltest.TestStep{
@ -48,9 +44,29 @@ func TestBackend_basic_CA(t *testing.T) {
testAccStepLogin(t, connState),
testAccStepCertNoLease(t, "web", ca, "foo"),
testAccStepLoginDefaultLease(t, connState),
},
})
}
// Test CRL behavior
func TestBackend_CRLs(t *testing.T) {
connState := testConnState(t, "../../../test/key/ourdomain.cer",
"../../../test/key/ourdomain.key")
ca, err := ioutil.ReadFile("../../../test/ca/root.cer")
if err != nil {
t.Fatalf("err: %v", err)
}
crl, err := ioutil.ReadFile("../../../test/ca/root.crl")
if err != nil {
t.Fatalf("err: %v", err)
}
logicaltest.Test(t, logicaltest.TestCase{
Backend: testFactory(t),
Steps: []logicaltest.TestStep{
testAccStepCertNoLease(t, "web", ca, "foo"),
testAccStepLoginDefaultLease(t, connState),
testAccStepAddCRL(t, crl, connState),
testAccStepReadCRL(t, connState),
testAccStepReadCRLSerial(t, connState),
testAccStepLoginInvalid(t, connState),
testAccStepDeleteCRL(t, connState),
testAccStepLoginDefaultLease(t, connState),
@ -120,31 +136,6 @@ func testAccStepReadCRL(t *testing.T, connState tls.ConnectionState) logicaltest
}
}
func testAccStepReadCRLSerial(t *testing.T, connState tls.ConnectionState) logicaltest.TestStep {
return logicaltest.TestStep{
Operation: logical.ReadOperation,
Path: "crls/test",
ConnState: &connState,
Data: map[string]interface{}{
"serial": "13",
},
Check: func(resp *logical.Response) error {
serialInfo := map[string]RevokedSerialInfo{}
err := mapstructure.Decode(resp.Data, &serialInfo)
if err != nil {
t.Fatalf("err: %v", err)
}
if len(serialInfo) != 1 {
t.Fatalf("bad: expected info with length 1, got %d", len(serialInfo))
}
if _, ok := serialInfo["test"]; !ok {
t.Fatalf("bad: CRL \"test\" not found in info")
}
return nil
},
}
}
func testAccStepDeleteCRL(t *testing.T, connState tls.ConnectionState) logicaltest.TestStep {
return logicaltest.TestStep{
Operation: logical.DeleteOperation,

View file

@ -5,7 +5,6 @@ import (
"fmt"
"math/big"
"strings"
"sync"
"github.com/fatih/structs"
"github.com/hashicorp/vault/helper/certutil"
@ -42,14 +41,9 @@ using the same name as specified here.`,
}
}
var (
crls = map[string]CRLInfo{}
crlUpdateMutex = &sync.RWMutex{}
)
func populateCRLs(storage logical.Storage) error {
crlUpdateMutex.Lock()
defer crlUpdateMutex.Unlock()
func (b *backend) populateCRLs(storage logical.Storage) error {
b.crlUpdateMutex.Lock()
defer b.crlUpdateMutex.Unlock()
keys, err := storage.List("crls/")
if err != nil {
@ -72,17 +66,17 @@ func populateCRLs(storage logical.Storage) error {
if err != nil {
return fmt.Errorf("error decoding CRL %s: %v", key, err)
}
crls[key] = crlInfo
b.crls[key] = crlInfo
}
return nil
}
func findSerialInCRLs(serial *big.Int) map[string]RevokedSerialInfo {
crlUpdateMutex.RLock()
defer crlUpdateMutex.RUnlock()
func (b *backend) findSerialInCRLs(serial *big.Int) map[string]RevokedSerialInfo {
b.crlUpdateMutex.RLock()
defer b.crlUpdateMutex.RUnlock()
ret := map[string]RevokedSerialInfo{}
for key, crl := range crls {
for key, crl := range b.crls {
if crl.Serials == nil {
continue
}
@ -127,10 +121,10 @@ func (b *backend) pathCRLDelete(
return logical.ErrorResponse(`"name" parameter cannot be empty`), nil
}
crlUpdateMutex.Lock()
defer crlUpdateMutex.Unlock()
b.crlUpdateMutex.Lock()
defer b.crlUpdateMutex.Unlock()
_, ok := crls[name]
_, ok := b.crls[name]
if !ok {
return logical.ErrorResponse(fmt.Sprintf(
"no such CRL %s", name,
@ -144,7 +138,7 @@ func (b *backend) pathCRLDelete(
), nil
}
delete(crls, name)
delete(b.crls, name)
return nil, nil
}
@ -156,12 +150,12 @@ func (b *backend) pathCRLRead(
return logical.ErrorResponse(`"name" parameter must be set`), nil
}
crlUpdateMutex.RLock()
defer crlUpdateMutex.RUnlock()
b.crlUpdateMutex.RLock()
defer b.crlUpdateMutex.RUnlock()
var retData map[string]interface{}
crl, ok := crls[name]
crl, ok := b.crls[name]
if !ok {
return logical.ErrorResponse(fmt.Sprintf(
"no such CRL %s", name,
@ -191,8 +185,8 @@ func (b *backend) pathCRLWrite(
return logical.ErrorResponse("parsed CRL is nil"), nil
}
crlUpdateMutex.Lock()
defer crlUpdateMutex.Unlock()
b.crlUpdateMutex.Lock()
defer b.crlUpdateMutex.Unlock()
crlInfo := CRLInfo{
Serials: map[string]RevokedSerialInfo{},
@ -209,7 +203,7 @@ func (b *backend) pathCRLWrite(
return nil, err
}
crls[name] = crlInfo
b.crls[name] = crlInfo
return nil, nil
}

View file

@ -140,7 +140,7 @@ func (b *backend) checkForValidChain(store logical.Storage, chains [][]*x509.Cer
for _, chain := range chains {
badChain = false
for _, cert := range chain {
badCRLs := findSerialInCRLs(cert.SerialNumber)
badCRLs := b.findSerialInCRLs(cert.SerialNumber)
if len(badCRLs) != 0 {
badChain = true
break

View file

@ -249,7 +249,7 @@ of the header should be "X-Vault-Token" and the value should be the token.
<dd>GET</dd>
<dt>URL</dt>
<dd>`/auth/cert/certs/<name>`</dd>
<dd>`/auth/cert/crls/<name>`</dd>
<dt>Parameters</dt>
<dd>