Address first round of feedback from review
This commit is contained in:
parent
59cc61cc79
commit
154fc24777
|
@ -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 = `
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in a new issue