forked from TrueCloudLab/certificates
NoopDB -> SimpleDB
This commit is contained in:
parent
b73fe8c157
commit
81db527f12
9 changed files with 112 additions and 99 deletions
|
@ -22,7 +22,6 @@ type Authority struct {
|
|||
intermediateIdentity *x509util.Identity
|
||||
validateOnce bool
|
||||
certificates *sync.Map
|
||||
ottMap *sync.Map
|
||||
startTime time.Time
|
||||
provisioners *provisioner.Collection
|
||||
db db.AuthDB
|
||||
|
@ -40,7 +39,6 @@ func New(config *Config) (*Authority, error) {
|
|||
var a = &Authority{
|
||||
config: config,
|
||||
certificates: new(sync.Map),
|
||||
ottMap: new(sync.Map),
|
||||
provisioners: provisioner.NewCollection(config.getAudiences()),
|
||||
}
|
||||
if err := a.init(); err != nil {
|
||||
|
@ -58,8 +56,8 @@ func (a *Authority) init() error {
|
|||
|
||||
var err error
|
||||
|
||||
// Initialize step-ca Database if defined in configuration.
|
||||
// If a.config.DB is nil then a noopDB will be returned.
|
||||
// Initialize step-ca Database.
|
||||
// If a.config.DB is nil then a simple, barebones in memory DB will be used.
|
||||
if a.db, err = db.New(a.config.DB); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -4,19 +4,12 @@ import (
|
|||
"crypto/x509"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/smallstep/certificates/authority/provisioner"
|
||||
"github.com/smallstep/certificates/db"
|
||||
"github.com/smallstep/cli/jose"
|
||||
)
|
||||
|
||||
type idUsed struct {
|
||||
UsedAt int64 `json:"ua,omitempty"`
|
||||
Subject string `json:"sub,omitempty"`
|
||||
}
|
||||
|
||||
// Claims extends jose.Claims with step attributes.
|
||||
type Claims struct {
|
||||
jose.Claims
|
||||
|
@ -73,23 +66,13 @@ func (a *Authority) authorizeToken(ott string) (provisioner.Interface, error) {
|
|||
reuseKey = claims.Nonce
|
||||
}
|
||||
if reuseKey != "" {
|
||||
switch a.db.(type) {
|
||||
case *db.NoopDB:
|
||||
if _, ok := a.ottMap.LoadOrStore(reuseKey, &idUsed{
|
||||
UsedAt: time.Now().Unix(),
|
||||
Subject: claims.Subject,
|
||||
}); ok {
|
||||
return nil, &apiError{errors.Errorf("authorizeToken: token already used"), http.StatusUnauthorized, errContext}
|
||||
}
|
||||
default:
|
||||
ok, err := a.db.UseToken(reuseKey, ott)
|
||||
if err != nil {
|
||||
return nil, &apiError{errors.Wrap(err, "authorizeToken: failed when checking if token already used"),
|
||||
http.StatusInternalServerError, errContext}
|
||||
}
|
||||
if !ok {
|
||||
return nil, &apiError{errors.Errorf("authorizeToken: token already used"), http.StatusUnauthorized, errContext}
|
||||
}
|
||||
ok, err := a.db.UseToken(reuseKey, ott)
|
||||
if err != nil {
|
||||
return nil, &apiError{errors.Wrap(err, "authorizeToken: failed when checking if token already used"),
|
||||
http.StatusInternalServerError, errContext}
|
||||
}
|
||||
if !ok {
|
||||
return nil, &apiError{errors.Errorf("authorizeToken: token already used"), http.StatusUnauthorized, errContext}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ func TestAuthority_authorizeToken(t *testing.T) {
|
|||
http.StatusUnauthorized, context{"ott": raw}},
|
||||
}
|
||||
},
|
||||
"ok/noopdb": func(t *testing.T) *authorizeTest {
|
||||
"ok/simpledb": func(t *testing.T) *authorizeTest {
|
||||
cl := jwt.Claims{
|
||||
Subject: "test.smallstep.com",
|
||||
Issuer: validIssuer,
|
||||
|
@ -133,9 +133,8 @@ func TestAuthority_authorizeToken(t *testing.T) {
|
|||
ott: raw,
|
||||
}
|
||||
},
|
||||
"fail/noopdb/token-already-used": func(t *testing.T) *authorizeTest {
|
||||
"fail/simpledb/token-already-used": func(t *testing.T) *authorizeTest {
|
||||
_a := testAuthority(t)
|
||||
|
||||
cl := jwt.Claims{
|
||||
Subject: "test.smallstep.com",
|
||||
Issuer: validIssuer,
|
||||
|
|
|
@ -592,7 +592,6 @@ func TestRevoke(t *testing.T) {
|
|||
tests := map[string]func() test{
|
||||
"error/token/authorizeRevoke error": func() test {
|
||||
a := testAuthority(t)
|
||||
a.db = new(db.NoopDB)
|
||||
ctx := getCtx()
|
||||
ctx["ott"] = "foo"
|
||||
return test{
|
||||
|
@ -609,8 +608,6 @@ func TestRevoke(t *testing.T) {
|
|||
},
|
||||
"error/nil-db": func() test {
|
||||
a := testAuthority(t)
|
||||
a.db = new(db.NoopDB)
|
||||
|
||||
cl := jwt.Claims{
|
||||
Subject: "sn",
|
||||
Issuer: validIssuer,
|
||||
|
|
2
db/db.go
2
db/db.go
|
@ -45,7 +45,7 @@ type DB struct {
|
|||
// New returns a new database client that implements the AuthDB interface.
|
||||
func New(c *Config) (AuthDB, error) {
|
||||
if c == nil {
|
||||
return new(NoopDB), nil
|
||||
return newSimpleDB(c)
|
||||
}
|
||||
|
||||
db, err := nosql.New(c.Type, c.DataSource, nosql.WithDatabase(c.Database),
|
||||
|
|
43
db/noop.go
43
db/noop.go
|
@ -1,43 +0,0 @@
|
|||
package db
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// ErrNotImplemented is an error returned when an operation is Not Implemented.
|
||||
var ErrNotImplemented = errors.Errorf("not implemented")
|
||||
|
||||
// NoopDB implements the DB interface with Noops
|
||||
type NoopDB int
|
||||
|
||||
// Init noop
|
||||
func (n *NoopDB) Init(c *Config) (AuthDB, error) {
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// IsRevoked noop
|
||||
func (n *NoopDB) IsRevoked(sn string) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Revoke returns a "NotImplemented" error.
|
||||
func (n *NoopDB) Revoke(rci *RevokedCertificateInfo) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
// StoreCertificate returns a "NotImplemented" error.
|
||||
func (n *NoopDB) StoreCertificate(crt *x509.Certificate) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
// UseToken returns a "NotImplemented" error.
|
||||
func (n *NoopDB) UseToken(id, tok string) (bool, error) {
|
||||
return false, ErrNotImplemented
|
||||
}
|
||||
|
||||
// Shutdown returns nil
|
||||
func (n *NoopDB) Shutdown() error {
|
||||
return nil
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
package db
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/smallstep/assert"
|
||||
)
|
||||
|
||||
func Test_noop(t *testing.T) {
|
||||
db := new(NoopDB)
|
||||
|
||||
_db, err := db.Init(&Config{})
|
||||
assert.FatalError(t, err)
|
||||
assert.Equals(t, db, _db)
|
||||
|
||||
isRevoked, err := db.IsRevoked("foo")
|
||||
assert.False(t, isRevoked)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equals(t, db.Revoke(&RevokedCertificateInfo{}), ErrNotImplemented)
|
||||
}
|
63
db/simple.go
Normal file
63
db/simple.go
Normal file
|
@ -0,0 +1,63 @@
|
|||
package db
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// ErrNotImplemented is an error returned when an operation is Not Implemented.
|
||||
var ErrNotImplemented = errors.Errorf("not implemented")
|
||||
|
||||
// SimpleDB is a barebones implementation of the DB interface. It is NOT an
|
||||
// in memory implementation of the DB, but rather the bare minimum of
|
||||
// functionality that the CA requires to operate securely.
|
||||
type SimpleDB struct {
|
||||
usedTokens *sync.Map
|
||||
}
|
||||
|
||||
func newSimpleDB(c *Config) (AuthDB, error) {
|
||||
db := &SimpleDB{}
|
||||
db.usedTokens = new(sync.Map)
|
||||
return db, nil
|
||||
}
|
||||
|
||||
// IsRevoked noop
|
||||
func (s *SimpleDB) IsRevoked(sn string) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Revoke returns a "NotImplemented" error.
|
||||
func (s *SimpleDB) Revoke(rci *RevokedCertificateInfo) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
// StoreCertificate returns a "NotImplemented" error.
|
||||
func (s *SimpleDB) StoreCertificate(crt *x509.Certificate) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
type usedToken struct {
|
||||
UsedAt int64 `json:"ua,omitempty"`
|
||||
Token string `json:"tok,omitempty"`
|
||||
}
|
||||
|
||||
// UseToken returns a "NotImplemented" error.
|
||||
func (s *SimpleDB) UseToken(id, tok string) (bool, error) {
|
||||
if _, ok := s.usedTokens.LoadOrStore(id, &usedToken{
|
||||
UsedAt: time.Now().Unix(),
|
||||
Token: tok,
|
||||
}); ok {
|
||||
// Token already exists in DB.
|
||||
return false, nil
|
||||
}
|
||||
// Successfully stored token.
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// Shutdown returns nil
|
||||
func (s *SimpleDB) Shutdown() error {
|
||||
return nil
|
||||
}
|
37
db/simple_test.go
Normal file
37
db/simple_test.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
package db
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/smallstep/assert"
|
||||
)
|
||||
|
||||
func TestSimpleDB(t *testing.T) {
|
||||
db, err := newSimpleDB(nil)
|
||||
assert.FatalError(t, err)
|
||||
|
||||
// Revoke
|
||||
assert.Equals(t, ErrNotImplemented, db.Revoke(nil))
|
||||
|
||||
// IsRevoked -- verify noop
|
||||
isRevoked, err := db.IsRevoked("foo")
|
||||
assert.False(t, isRevoked)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// StoreCertificate
|
||||
assert.Equals(t, ErrNotImplemented, db.StoreCertificate(nil))
|
||||
|
||||
// UseToken
|
||||
ok, err := db.UseToken("foo", "bar")
|
||||
assert.True(t, ok)
|
||||
assert.Nil(t, err)
|
||||
ok, err = db.UseToken("foo", "cat")
|
||||
assert.False(t, ok)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// Shutdown -- verify noop
|
||||
assert.FatalError(t, db.Shutdown())
|
||||
ok, err = db.UseToken("foo", "cat")
|
||||
assert.False(t, ok)
|
||||
assert.Nil(t, err)
|
||||
}
|
Loading…
Reference in a new issue