2021-05-03 19:48:20 +00:00
|
|
|
package nosql
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"encoding/json"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/smallstep/assert"
|
|
|
|
"github.com/smallstep/certificates/authority/admin"
|
|
|
|
"github.com/smallstep/certificates/db"
|
|
|
|
"github.com/smallstep/nosql"
|
|
|
|
"github.com/smallstep/nosql/database"
|
|
|
|
"go.step.sm/linkedca"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestDB_getDBProvisionerBytes(t *testing.T) {
|
|
|
|
provID := "provID"
|
|
|
|
type test struct {
|
|
|
|
db nosql.DB
|
|
|
|
err error
|
|
|
|
adminErr *admin.Error
|
|
|
|
}
|
|
|
|
var tests = map[string]func(t *testing.T) test{
|
|
|
|
"fail/not-found": func(t *testing.T) test {
|
|
|
|
return test{
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, string(key), provID)
|
|
|
|
|
2021-10-08 18:59:57 +00:00
|
|
|
return nil, database.ErrNotFound
|
2021-05-03 19:48:20 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
adminErr: admin.NewError(admin.ErrorNotFoundType, "provisioner provID not found"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"fail/db.Get-error": func(t *testing.T) test {
|
|
|
|
return test{
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, string(key), provID)
|
|
|
|
|
|
|
|
return nil, errors.New("force")
|
|
|
|
},
|
|
|
|
},
|
|
|
|
err: errors.New("error loading provisioner provID: force"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"ok": func(t *testing.T) test {
|
|
|
|
return test{
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, string(key), provID)
|
|
|
|
|
|
|
|
return []byte("foo"), nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for name, run := range tests {
|
|
|
|
tc := run(t)
|
|
|
|
t.Run(name, func(t *testing.T) {
|
2021-10-08 18:59:57 +00:00
|
|
|
d := DB{db: tc.db}
|
|
|
|
if b, err := d.getDBProvisionerBytes(context.Background(), provID); err != nil {
|
2021-05-03 19:48:20 +00:00
|
|
|
switch k := err.(type) {
|
|
|
|
case *admin.Error:
|
|
|
|
if assert.NotNil(t, tc.adminErr) {
|
|
|
|
assert.Equals(t, k.Type, tc.adminErr.Type)
|
|
|
|
assert.Equals(t, k.Detail, tc.adminErr.Detail)
|
|
|
|
assert.Equals(t, k.Status, tc.adminErr.Status)
|
|
|
|
assert.Equals(t, k.Err.Error(), tc.adminErr.Err.Error())
|
|
|
|
assert.Equals(t, k.Detail, tc.adminErr.Detail)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
if assert.NotNil(t, tc.err) {
|
|
|
|
assert.HasPrefix(t, err.Error(), tc.err.Error())
|
|
|
|
}
|
|
|
|
}
|
2021-10-08 18:59:57 +00:00
|
|
|
} else if assert.Nil(t, tc.err) && assert.Nil(t, tc.adminErr) {
|
|
|
|
assert.Equals(t, string(b), "foo")
|
2021-05-03 19:48:20 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDB_getDBProvisioner(t *testing.T) {
|
|
|
|
provID := "provID"
|
|
|
|
type test struct {
|
|
|
|
db nosql.DB
|
|
|
|
err error
|
|
|
|
adminErr *admin.Error
|
|
|
|
dbp *dbProvisioner
|
|
|
|
}
|
|
|
|
var tests = map[string]func(t *testing.T) test{
|
|
|
|
"fail/not-found": func(t *testing.T) test {
|
|
|
|
return test{
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, string(key), provID)
|
|
|
|
|
2021-10-08 18:59:57 +00:00
|
|
|
return nil, database.ErrNotFound
|
2021-05-03 19:48:20 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
adminErr: admin.NewError(admin.ErrorNotFoundType, "provisioner provID not found"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"fail/db.Get-error": func(t *testing.T) test {
|
|
|
|
return test{
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, string(key), provID)
|
|
|
|
|
|
|
|
return nil, errors.New("force")
|
|
|
|
},
|
|
|
|
},
|
|
|
|
err: errors.New("error loading provisioner provID: force"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"fail/unmarshal-error": func(t *testing.T) test {
|
|
|
|
return test{
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, string(key), provID)
|
|
|
|
|
|
|
|
return []byte("foo"), nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
err: errors.New("error unmarshaling provisioner provID into dbProvisioner"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"fail/deleted": func(t *testing.T) test {
|
|
|
|
now := clock.Now()
|
|
|
|
dbp := &dbProvisioner{
|
|
|
|
ID: provID,
|
|
|
|
AuthorityID: admin.DefaultAuthorityID,
|
|
|
|
Type: linkedca.Provisioner_JWK,
|
|
|
|
Name: "provName",
|
|
|
|
CreatedAt: now,
|
|
|
|
DeletedAt: now,
|
|
|
|
}
|
|
|
|
b, err := json.Marshal(dbp)
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
return test{
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, string(key), provID)
|
|
|
|
|
|
|
|
return b, nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
adminErr: admin.NewError(admin.ErrorDeletedType, "provisioner provID is deleted"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"ok": func(t *testing.T) test {
|
|
|
|
now := clock.Now()
|
|
|
|
dbp := &dbProvisioner{
|
|
|
|
ID: provID,
|
|
|
|
AuthorityID: admin.DefaultAuthorityID,
|
|
|
|
Type: linkedca.Provisioner_JWK,
|
|
|
|
Name: "provName",
|
|
|
|
CreatedAt: now,
|
|
|
|
}
|
|
|
|
b, err := json.Marshal(dbp)
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
return test{
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, string(key), provID)
|
|
|
|
|
|
|
|
return b, nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
dbp: dbp,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for name, run := range tests {
|
|
|
|
tc := run(t)
|
|
|
|
t.Run(name, func(t *testing.T) {
|
2021-10-08 18:59:57 +00:00
|
|
|
d := DB{db: tc.db, authorityID: admin.DefaultAuthorityID}
|
|
|
|
if dbp, err := d.getDBProvisioner(context.Background(), provID); err != nil {
|
2021-05-03 19:48:20 +00:00
|
|
|
switch k := err.(type) {
|
|
|
|
case *admin.Error:
|
|
|
|
if assert.NotNil(t, tc.adminErr) {
|
|
|
|
assert.Equals(t, k.Type, tc.adminErr.Type)
|
|
|
|
assert.Equals(t, k.Detail, tc.adminErr.Detail)
|
|
|
|
assert.Equals(t, k.Status, tc.adminErr.Status)
|
|
|
|
assert.Equals(t, k.Err.Error(), tc.adminErr.Err.Error())
|
|
|
|
assert.Equals(t, k.Detail, tc.adminErr.Detail)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
if assert.NotNil(t, tc.err) {
|
|
|
|
assert.HasPrefix(t, err.Error(), tc.err.Error())
|
|
|
|
}
|
|
|
|
}
|
2021-10-08 18:59:57 +00:00
|
|
|
} else if assert.Nil(t, tc.err) && assert.Nil(t, tc.adminErr) {
|
|
|
|
assert.Equals(t, dbp.ID, provID)
|
|
|
|
assert.Equals(t, dbp.AuthorityID, tc.dbp.AuthorityID)
|
|
|
|
assert.Equals(t, dbp.Type, tc.dbp.Type)
|
|
|
|
assert.Equals(t, dbp.Name, tc.dbp.Name)
|
|
|
|
assert.Equals(t, dbp.CreatedAt, tc.dbp.CreatedAt)
|
|
|
|
assert.Fatal(t, dbp.DeletedAt.IsZero())
|
2021-05-03 19:48:20 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDB_unmarshalDBProvisioner(t *testing.T) {
|
|
|
|
provID := "provID"
|
|
|
|
type test struct {
|
|
|
|
in []byte
|
|
|
|
err error
|
|
|
|
adminErr *admin.Error
|
|
|
|
dbp *dbProvisioner
|
|
|
|
}
|
|
|
|
var tests = map[string]func(t *testing.T) test{
|
|
|
|
"fail/unmarshal-error": func(t *testing.T) test {
|
|
|
|
return test{
|
|
|
|
in: []byte("foo"),
|
|
|
|
err: errors.New("error unmarshaling provisioner provID into dbProvisioner"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"fail/deleted-error": func(t *testing.T) test {
|
|
|
|
dbp := &dbProvisioner{
|
|
|
|
DeletedAt: clock.Now(),
|
|
|
|
}
|
|
|
|
data, err := json.Marshal(dbp)
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
return test{
|
|
|
|
in: data,
|
|
|
|
adminErr: admin.NewError(admin.ErrorDeletedType, "provisioner %s is deleted", provID),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"fail/authority-mismatch-error": func(t *testing.T) test {
|
|
|
|
dbp := &dbProvisioner{
|
|
|
|
ID: provID,
|
|
|
|
AuthorityID: "foo",
|
|
|
|
}
|
|
|
|
data, err := json.Marshal(dbp)
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
return test{
|
|
|
|
in: data,
|
|
|
|
adminErr: admin.NewError(admin.ErrorAuthorityMismatchType,
|
|
|
|
"provisioner %s is not owned by authority %s", provID, admin.DefaultAuthorityID),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"ok": func(t *testing.T) test {
|
|
|
|
dbp := &dbProvisioner{
|
|
|
|
ID: provID,
|
|
|
|
AuthorityID: admin.DefaultAuthorityID,
|
|
|
|
Type: linkedca.Provisioner_JWK,
|
|
|
|
Name: "provName",
|
|
|
|
CreatedAt: clock.Now(),
|
|
|
|
}
|
|
|
|
data, err := json.Marshal(dbp)
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
return test{
|
|
|
|
in: data,
|
|
|
|
dbp: dbp,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for name, run := range tests {
|
|
|
|
tc := run(t)
|
|
|
|
t.Run(name, func(t *testing.T) {
|
2021-10-08 18:59:57 +00:00
|
|
|
d := DB{authorityID: admin.DefaultAuthorityID}
|
|
|
|
if dbp, err := d.unmarshalDBProvisioner(tc.in, provID); err != nil {
|
2021-05-03 19:48:20 +00:00
|
|
|
switch k := err.(type) {
|
|
|
|
case *admin.Error:
|
|
|
|
if assert.NotNil(t, tc.adminErr) {
|
|
|
|
assert.Equals(t, k.Type, tc.adminErr.Type)
|
|
|
|
assert.Equals(t, k.Detail, tc.adminErr.Detail)
|
|
|
|
assert.Equals(t, k.Status, tc.adminErr.Status)
|
|
|
|
assert.Equals(t, k.Err.Error(), tc.adminErr.Err.Error())
|
|
|
|
assert.Equals(t, k.Detail, tc.adminErr.Detail)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
if assert.NotNil(t, tc.err) {
|
|
|
|
assert.HasPrefix(t, err.Error(), tc.err.Error())
|
|
|
|
}
|
|
|
|
}
|
2021-10-08 18:59:57 +00:00
|
|
|
} else if assert.Nil(t, tc.err) && assert.Nil(t, tc.adminErr) {
|
|
|
|
assert.Equals(t, dbp.ID, provID)
|
|
|
|
assert.Equals(t, dbp.AuthorityID, tc.dbp.AuthorityID)
|
|
|
|
assert.Equals(t, dbp.Type, tc.dbp.Type)
|
|
|
|
assert.Equals(t, dbp.Name, tc.dbp.Name)
|
|
|
|
assert.Equals(t, dbp.Details, tc.dbp.Details)
|
|
|
|
assert.Equals(t, dbp.Claims, tc.dbp.Claims)
|
|
|
|
assert.Equals(t, dbp.X509Template, tc.dbp.X509Template)
|
|
|
|
assert.Equals(t, dbp.SSHTemplate, tc.dbp.SSHTemplate)
|
|
|
|
assert.Equals(t, dbp.CreatedAt, tc.dbp.CreatedAt)
|
|
|
|
assert.Fatal(t, dbp.DeletedAt.IsZero())
|
2021-05-03 19:48:20 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func defaultDBP(t *testing.T) *dbProvisioner {
|
|
|
|
details := &linkedca.ProvisionerDetails_ACME{
|
|
|
|
ACME: &linkedca.ACMEProvisioner{
|
|
|
|
ForceCn: true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
detailBytes, err := json.Marshal(details)
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
|
|
|
|
return &dbProvisioner{
|
|
|
|
ID: "provID",
|
|
|
|
AuthorityID: admin.DefaultAuthorityID,
|
|
|
|
Type: linkedca.Provisioner_ACME,
|
|
|
|
Name: "provName",
|
|
|
|
Details: detailBytes,
|
|
|
|
Claims: &linkedca.Claims{
|
|
|
|
DisableRenewal: true,
|
|
|
|
X509: &linkedca.X509Claims{
|
|
|
|
Enabled: true,
|
|
|
|
Durations: &linkedca.Durations{
|
|
|
|
Min: "5m",
|
|
|
|
Max: "12h",
|
|
|
|
Default: "6h",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Ssh: &linkedca.SSHClaims{
|
|
|
|
Enabled: true,
|
|
|
|
UserDurations: &linkedca.Durations{
|
|
|
|
Min: "5m",
|
|
|
|
Max: "12h",
|
|
|
|
Default: "6h",
|
|
|
|
},
|
|
|
|
HostDurations: &linkedca.Durations{
|
|
|
|
Min: "5m",
|
|
|
|
Max: "12h",
|
|
|
|
Default: "6h",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
X509Template: &linkedca.Template{
|
|
|
|
Template: []byte("foo"),
|
|
|
|
Data: []byte("bar"),
|
|
|
|
},
|
|
|
|
SSHTemplate: &linkedca.Template{
|
|
|
|
Template: []byte("baz"),
|
|
|
|
Data: []byte("zap"),
|
|
|
|
},
|
|
|
|
CreatedAt: clock.Now(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDB_unmarshalProvisioner(t *testing.T) {
|
|
|
|
provID := "provID"
|
|
|
|
type test struct {
|
|
|
|
in []byte
|
|
|
|
err error
|
|
|
|
adminErr *admin.Error
|
|
|
|
dbp *dbProvisioner
|
|
|
|
}
|
|
|
|
var tests = map[string]func(t *testing.T) test{
|
|
|
|
"fail/unmarshal-error": func(t *testing.T) test {
|
|
|
|
return test{
|
|
|
|
in: []byte("foo"),
|
|
|
|
err: errors.New("error unmarshaling provisioner provID into dbProvisioner"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"fail/deleted-error": func(t *testing.T) test {
|
|
|
|
dbp := &dbProvisioner{
|
|
|
|
DeletedAt: time.Now(),
|
|
|
|
}
|
|
|
|
data, err := json.Marshal(dbp)
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
return test{
|
|
|
|
in: data,
|
|
|
|
adminErr: admin.NewError(admin.ErrorDeletedType, "provisioner provID is deleted"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"ok": func(t *testing.T) test {
|
|
|
|
dbp := defaultDBP(t)
|
|
|
|
data, err := json.Marshal(dbp)
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
return test{
|
|
|
|
in: data,
|
|
|
|
dbp: dbp,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for name, run := range tests {
|
|
|
|
tc := run(t)
|
|
|
|
t.Run(name, func(t *testing.T) {
|
2021-10-08 18:59:57 +00:00
|
|
|
d := DB{authorityID: admin.DefaultAuthorityID}
|
|
|
|
if prov, err := d.unmarshalProvisioner(tc.in, provID); err != nil {
|
2021-05-03 19:48:20 +00:00
|
|
|
switch k := err.(type) {
|
|
|
|
case *admin.Error:
|
|
|
|
if assert.NotNil(t, tc.adminErr) {
|
|
|
|
assert.Equals(t, k.Type, tc.adminErr.Type)
|
|
|
|
assert.Equals(t, k.Detail, tc.adminErr.Detail)
|
|
|
|
assert.Equals(t, k.Status, tc.adminErr.Status)
|
|
|
|
assert.Equals(t, k.Err.Error(), tc.adminErr.Err.Error())
|
|
|
|
assert.Equals(t, k.Detail, tc.adminErr.Detail)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
if assert.NotNil(t, tc.err) {
|
|
|
|
assert.HasPrefix(t, err.Error(), tc.err.Error())
|
|
|
|
}
|
|
|
|
}
|
2021-10-08 18:59:57 +00:00
|
|
|
} else if assert.Nil(t, tc.err) && assert.Nil(t, tc.adminErr) {
|
|
|
|
assert.Equals(t, prov.Id, provID)
|
|
|
|
assert.Equals(t, prov.AuthorityId, tc.dbp.AuthorityID)
|
|
|
|
assert.Equals(t, prov.Type, tc.dbp.Type)
|
|
|
|
assert.Equals(t, prov.Name, tc.dbp.Name)
|
|
|
|
assert.Equals(t, prov.Claims, tc.dbp.Claims)
|
|
|
|
assert.Equals(t, prov.X509Template, tc.dbp.X509Template)
|
|
|
|
assert.Equals(t, prov.SshTemplate, tc.dbp.SSHTemplate)
|
|
|
|
|
|
|
|
retDetailsBytes, err := json.Marshal(prov.Details.GetData())
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
assert.Equals(t, retDetailsBytes, tc.dbp.Details)
|
2021-05-03 19:48:20 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDB_GetProvisioner(t *testing.T) {
|
|
|
|
provID := "provID"
|
|
|
|
type test struct {
|
|
|
|
db nosql.DB
|
|
|
|
err error
|
|
|
|
adminErr *admin.Error
|
|
|
|
dbp *dbProvisioner
|
|
|
|
}
|
|
|
|
var tests = map[string]func(t *testing.T) test{
|
|
|
|
"fail/not-found": func(t *testing.T) test {
|
|
|
|
return test{
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, string(key), provID)
|
|
|
|
|
2021-10-08 18:59:57 +00:00
|
|
|
return nil, database.ErrNotFound
|
2021-05-03 19:48:20 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
adminErr: admin.NewError(admin.ErrorNotFoundType, "provisioner provID not found"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"fail/db.Get-error": func(t *testing.T) test {
|
|
|
|
return test{
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, string(key), provID)
|
|
|
|
|
|
|
|
return nil, errors.New("force")
|
|
|
|
},
|
|
|
|
},
|
|
|
|
err: errors.New("error loading provisioner provID: force"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"fail/unmarshal-error": func(t *testing.T) test {
|
|
|
|
return test{
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, string(key), provID)
|
|
|
|
|
|
|
|
return []byte("foo"), nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
err: errors.New("error unmarshaling provisioner provID into dbProvisioner"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"fail/deleted": func(t *testing.T) test {
|
|
|
|
dbp := defaultDBP(t)
|
|
|
|
dbp.DeletedAt = clock.Now()
|
|
|
|
b, err := json.Marshal(dbp)
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
return test{
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, string(key), provID)
|
|
|
|
|
|
|
|
return b, nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
dbp: dbp,
|
|
|
|
adminErr: admin.NewError(admin.ErrorDeletedType, "provisioner provID is deleted"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"fail/authorityID-mismatch": func(t *testing.T) test {
|
|
|
|
dbp := defaultDBP(t)
|
|
|
|
dbp.AuthorityID = "foo"
|
|
|
|
b, err := json.Marshal(dbp)
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
return test{
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, string(key), provID)
|
|
|
|
|
|
|
|
return b, nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
dbp: dbp,
|
|
|
|
adminErr: admin.NewError(admin.ErrorAuthorityMismatchType,
|
|
|
|
"provisioner %s is not owned by authority %s", dbp.ID, admin.DefaultAuthorityID),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"ok": func(t *testing.T) test {
|
|
|
|
dbp := defaultDBP(t)
|
|
|
|
b, err := json.Marshal(dbp)
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
return test{
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, string(key), provID)
|
|
|
|
|
|
|
|
return b, nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
dbp: dbp,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for name, run := range tests {
|
|
|
|
tc := run(t)
|
|
|
|
t.Run(name, func(t *testing.T) {
|
2021-10-08 18:59:57 +00:00
|
|
|
d := DB{db: tc.db, authorityID: admin.DefaultAuthorityID}
|
|
|
|
if prov, err := d.GetProvisioner(context.Background(), provID); err != nil {
|
2021-05-03 19:48:20 +00:00
|
|
|
switch k := err.(type) {
|
|
|
|
case *admin.Error:
|
|
|
|
if assert.NotNil(t, tc.adminErr) {
|
|
|
|
assert.Equals(t, k.Type, tc.adminErr.Type)
|
|
|
|
assert.Equals(t, k.Detail, tc.adminErr.Detail)
|
|
|
|
assert.Equals(t, k.Status, tc.adminErr.Status)
|
|
|
|
assert.Equals(t, k.Err.Error(), tc.adminErr.Err.Error())
|
|
|
|
assert.Equals(t, k.Detail, tc.adminErr.Detail)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
if assert.NotNil(t, tc.err) {
|
|
|
|
assert.HasPrefix(t, err.Error(), tc.err.Error())
|
|
|
|
}
|
|
|
|
}
|
2021-10-08 18:59:57 +00:00
|
|
|
} else if assert.Nil(t, tc.err) && assert.Nil(t, tc.adminErr) {
|
|
|
|
assert.Equals(t, prov.Id, provID)
|
|
|
|
assert.Equals(t, prov.AuthorityId, tc.dbp.AuthorityID)
|
|
|
|
assert.Equals(t, prov.Type, tc.dbp.Type)
|
|
|
|
assert.Equals(t, prov.Name, tc.dbp.Name)
|
|
|
|
assert.Equals(t, prov.Claims, tc.dbp.Claims)
|
|
|
|
assert.Equals(t, prov.X509Template, tc.dbp.X509Template)
|
|
|
|
assert.Equals(t, prov.SshTemplate, tc.dbp.SSHTemplate)
|
|
|
|
|
|
|
|
retDetailsBytes, err := json.Marshal(prov.Details.GetData())
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
assert.Equals(t, retDetailsBytes, tc.dbp.Details)
|
2021-05-03 19:48:20 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDB_DeleteProvisioner(t *testing.T) {
|
|
|
|
provID := "provID"
|
|
|
|
type test struct {
|
|
|
|
db nosql.DB
|
|
|
|
err error
|
|
|
|
adminErr *admin.Error
|
|
|
|
}
|
|
|
|
var tests = map[string]func(t *testing.T) test{
|
|
|
|
"fail/not-found": func(t *testing.T) test {
|
|
|
|
return test{
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, string(key), provID)
|
|
|
|
|
2021-10-08 18:59:57 +00:00
|
|
|
return nil, database.ErrNotFound
|
2021-05-03 19:48:20 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
adminErr: admin.NewError(admin.ErrorNotFoundType, "provisioner provID not found"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"fail/db.Get-error": func(t *testing.T) test {
|
|
|
|
return test{
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, string(key), provID)
|
|
|
|
|
|
|
|
return nil, errors.New("force")
|
|
|
|
},
|
|
|
|
},
|
|
|
|
err: errors.New("error loading provisioner provID: force"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"fail/save-error": func(t *testing.T) test {
|
|
|
|
dbp := defaultDBP(t)
|
|
|
|
data, err := json.Marshal(dbp)
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
return test{
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, string(key), provID)
|
|
|
|
|
|
|
|
return data, nil
|
|
|
|
},
|
|
|
|
MCmpAndSwap: func(bucket, key, old, nu []byte) ([]byte, bool, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, string(key), provID)
|
|
|
|
assert.Equals(t, string(old), string(data))
|
|
|
|
|
|
|
|
var _dbp = new(dbProvisioner)
|
|
|
|
assert.FatalError(t, json.Unmarshal(nu, _dbp))
|
|
|
|
|
|
|
|
assert.Equals(t, _dbp.ID, provID)
|
|
|
|
assert.Equals(t, _dbp.AuthorityID, dbp.AuthorityID)
|
|
|
|
assert.Equals(t, _dbp.Type, dbp.Type)
|
|
|
|
assert.Equals(t, _dbp.Name, dbp.Name)
|
|
|
|
assert.Equals(t, _dbp.Claims, dbp.Claims)
|
|
|
|
assert.Equals(t, _dbp.X509Template, dbp.X509Template)
|
|
|
|
assert.Equals(t, _dbp.SSHTemplate, dbp.SSHTemplate)
|
|
|
|
assert.Equals(t, _dbp.CreatedAt, dbp.CreatedAt)
|
|
|
|
assert.Equals(t, _dbp.Details, dbp.Details)
|
|
|
|
|
|
|
|
assert.True(t, _dbp.DeletedAt.Before(time.Now()))
|
|
|
|
assert.True(t, _dbp.DeletedAt.After(time.Now().Add(-time.Minute)))
|
|
|
|
|
|
|
|
return nil, false, errors.New("force")
|
|
|
|
},
|
|
|
|
},
|
|
|
|
err: errors.New("error saving authority provisioner: force"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"ok": func(t *testing.T) test {
|
|
|
|
dbp := defaultDBP(t)
|
|
|
|
data, err := json.Marshal(dbp)
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
return test{
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, string(key), provID)
|
|
|
|
|
|
|
|
return data, nil
|
|
|
|
},
|
|
|
|
MCmpAndSwap: func(bucket, key, old, nu []byte) ([]byte, bool, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, string(key), provID)
|
|
|
|
assert.Equals(t, string(old), string(data))
|
|
|
|
|
|
|
|
var _dbp = new(dbProvisioner)
|
|
|
|
assert.FatalError(t, json.Unmarshal(nu, _dbp))
|
|
|
|
|
|
|
|
assert.Equals(t, _dbp.ID, provID)
|
|
|
|
assert.Equals(t, _dbp.AuthorityID, dbp.AuthorityID)
|
|
|
|
assert.Equals(t, _dbp.Type, dbp.Type)
|
|
|
|
assert.Equals(t, _dbp.Name, dbp.Name)
|
|
|
|
assert.Equals(t, _dbp.Claims, dbp.Claims)
|
|
|
|
assert.Equals(t, _dbp.X509Template, dbp.X509Template)
|
|
|
|
assert.Equals(t, _dbp.SSHTemplate, dbp.SSHTemplate)
|
|
|
|
assert.Equals(t, _dbp.CreatedAt, dbp.CreatedAt)
|
|
|
|
assert.Equals(t, _dbp.Details, dbp.Details)
|
|
|
|
|
|
|
|
assert.True(t, _dbp.DeletedAt.Before(time.Now()))
|
|
|
|
assert.True(t, _dbp.DeletedAt.After(time.Now().Add(-time.Minute)))
|
|
|
|
|
|
|
|
return nu, true, nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for name, run := range tests {
|
|
|
|
tc := run(t)
|
|
|
|
t.Run(name, func(t *testing.T) {
|
2021-10-08 18:59:57 +00:00
|
|
|
d := DB{db: tc.db, authorityID: admin.DefaultAuthorityID}
|
|
|
|
if err := d.DeleteProvisioner(context.Background(), provID); err != nil {
|
2021-05-03 19:48:20 +00:00
|
|
|
switch k := err.(type) {
|
|
|
|
case *admin.Error:
|
|
|
|
if assert.NotNil(t, tc.adminErr) {
|
|
|
|
assert.Equals(t, k.Type, tc.adminErr.Type)
|
|
|
|
assert.Equals(t, k.Detail, tc.adminErr.Detail)
|
|
|
|
assert.Equals(t, k.Status, tc.adminErr.Status)
|
|
|
|
assert.Equals(t, k.Err.Error(), tc.adminErr.Err.Error())
|
|
|
|
assert.Equals(t, k.Detail, tc.adminErr.Detail)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
if assert.NotNil(t, tc.err) {
|
|
|
|
assert.HasPrefix(t, err.Error(), tc.err.Error())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDB_GetProvisioners(t *testing.T) {
|
|
|
|
fooProv := defaultDBP(t)
|
|
|
|
fooProv.Name = "foo"
|
|
|
|
foob, err := json.Marshal(fooProv)
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
|
|
|
|
barProv := defaultDBP(t)
|
|
|
|
barProv.Name = "bar"
|
|
|
|
barProv.DeletedAt = clock.Now()
|
|
|
|
barb, err := json.Marshal(barProv)
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
|
|
|
|
bazProv := defaultDBP(t)
|
|
|
|
bazProv.Name = "baz"
|
|
|
|
bazProv.AuthorityID = "baz"
|
|
|
|
bazb, err := json.Marshal(bazProv)
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
|
|
|
|
zapProv := defaultDBP(t)
|
|
|
|
zapProv.Name = "zap"
|
|
|
|
zapb, err := json.Marshal(zapProv)
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
|
|
|
|
type test struct {
|
|
|
|
db nosql.DB
|
|
|
|
err error
|
|
|
|
adminErr *admin.Error
|
|
|
|
verify func(*testing.T, []*linkedca.Provisioner)
|
|
|
|
}
|
|
|
|
var tests = map[string]func(t *testing.T) test{
|
|
|
|
"fail/db.List-error": func(t *testing.T) test {
|
|
|
|
return test{
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MList: func(bucket []byte) ([]*database.Entry, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
|
|
|
|
return nil, errors.New("force")
|
|
|
|
},
|
|
|
|
},
|
|
|
|
err: errors.New("error loading provisioners"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"fail/unmarshal-error": func(t *testing.T) test {
|
|
|
|
ret := []*database.Entry{
|
|
|
|
{Bucket: provisionersTable, Key: []byte("foo"), Value: foob},
|
|
|
|
{Bucket: provisionersTable, Key: []byte("bar"), Value: barb},
|
|
|
|
{Bucket: provisionersTable, Key: []byte("zap"), Value: []byte("zap")},
|
|
|
|
}
|
|
|
|
return test{
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MList: func(bucket []byte) ([]*database.Entry, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
|
|
|
|
return ret, nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
err: errors.New("error unmarshaling provisioner zap into dbProvisioner"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"ok/none": func(t *testing.T) test {
|
|
|
|
ret := []*database.Entry{}
|
|
|
|
return test{
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MList: func(bucket []byte) ([]*database.Entry, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
|
|
|
|
return ret, nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
verify: func(t *testing.T, provs []*linkedca.Provisioner) {
|
|
|
|
assert.Equals(t, len(provs), 0)
|
|
|
|
},
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"ok/only-invalid": func(t *testing.T) test {
|
|
|
|
ret := []*database.Entry{
|
|
|
|
{Bucket: provisionersTable, Key: []byte("bar"), Value: barb},
|
|
|
|
{Bucket: provisionersTable, Key: []byte("baz"), Value: bazb},
|
|
|
|
}
|
|
|
|
return test{
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MList: func(bucket []byte) ([]*database.Entry, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
|
|
|
|
return ret, nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
verify: func(t *testing.T, provs []*linkedca.Provisioner) {
|
|
|
|
assert.Equals(t, len(provs), 0)
|
|
|
|
},
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"ok": func(t *testing.T) test {
|
|
|
|
ret := []*database.Entry{
|
|
|
|
{Bucket: provisionersTable, Key: []byte("foo"), Value: foob},
|
|
|
|
{Bucket: provisionersTable, Key: []byte("bar"), Value: barb},
|
|
|
|
{Bucket: provisionersTable, Key: []byte("baz"), Value: bazb},
|
|
|
|
{Bucket: provisionersTable, Key: []byte("zap"), Value: zapb},
|
|
|
|
}
|
|
|
|
return test{
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MList: func(bucket []byte) ([]*database.Entry, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
|
|
|
|
return ret, nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
verify: func(t *testing.T, provs []*linkedca.Provisioner) {
|
|
|
|
assert.Equals(t, len(provs), 2)
|
|
|
|
|
|
|
|
assert.Equals(t, provs[0].Id, fooProv.ID)
|
|
|
|
assert.Equals(t, provs[0].AuthorityId, fooProv.AuthorityID)
|
|
|
|
assert.Equals(t, provs[0].Type, fooProv.Type)
|
|
|
|
assert.Equals(t, provs[0].Name, fooProv.Name)
|
|
|
|
assert.Equals(t, provs[0].Claims, fooProv.Claims)
|
|
|
|
assert.Equals(t, provs[0].X509Template, fooProv.X509Template)
|
|
|
|
assert.Equals(t, provs[0].SshTemplate, fooProv.SSHTemplate)
|
|
|
|
|
|
|
|
retDetailsBytes, err := json.Marshal(provs[0].Details.GetData())
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
assert.Equals(t, retDetailsBytes, fooProv.Details)
|
|
|
|
|
|
|
|
assert.Equals(t, provs[1].Id, zapProv.ID)
|
|
|
|
assert.Equals(t, provs[1].AuthorityId, zapProv.AuthorityID)
|
|
|
|
assert.Equals(t, provs[1].Type, zapProv.Type)
|
|
|
|
assert.Equals(t, provs[1].Name, zapProv.Name)
|
|
|
|
assert.Equals(t, provs[1].Claims, zapProv.Claims)
|
|
|
|
assert.Equals(t, provs[1].X509Template, zapProv.X509Template)
|
|
|
|
assert.Equals(t, provs[1].SshTemplate, zapProv.SSHTemplate)
|
|
|
|
|
|
|
|
retDetailsBytes, err = json.Marshal(provs[1].Details.GetData())
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
assert.Equals(t, retDetailsBytes, zapProv.Details)
|
|
|
|
},
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for name, run := range tests {
|
|
|
|
tc := run(t)
|
|
|
|
t.Run(name, func(t *testing.T) {
|
2021-10-08 18:59:57 +00:00
|
|
|
d := DB{db: tc.db, authorityID: admin.DefaultAuthorityID}
|
|
|
|
if provs, err := d.GetProvisioners(context.Background()); err != nil {
|
2021-05-03 19:48:20 +00:00
|
|
|
switch k := err.(type) {
|
|
|
|
case *admin.Error:
|
|
|
|
if assert.NotNil(t, tc.adminErr) {
|
|
|
|
assert.Equals(t, k.Type, tc.adminErr.Type)
|
|
|
|
assert.Equals(t, k.Detail, tc.adminErr.Detail)
|
|
|
|
assert.Equals(t, k.Status, tc.adminErr.Status)
|
|
|
|
assert.Equals(t, k.Err.Error(), tc.adminErr.Err.Error())
|
|
|
|
assert.Equals(t, k.Detail, tc.adminErr.Detail)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
if assert.NotNil(t, tc.err) {
|
|
|
|
assert.HasPrefix(t, err.Error(), tc.err.Error())
|
|
|
|
}
|
|
|
|
}
|
2021-10-08 18:59:57 +00:00
|
|
|
} else if assert.Nil(t, tc.err) && assert.Nil(t, tc.adminErr) {
|
|
|
|
tc.verify(t, provs)
|
2021-05-03 19:48:20 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDB_CreateProvisioner(t *testing.T) {
|
|
|
|
type test struct {
|
|
|
|
db nosql.DB
|
|
|
|
err error
|
|
|
|
adminErr *admin.Error
|
|
|
|
prov *linkedca.Provisioner
|
|
|
|
}
|
|
|
|
var tests = map[string]func(t *testing.T) test{
|
|
|
|
"fail/save-error": func(t *testing.T) test {
|
|
|
|
dbp := defaultDBP(t)
|
|
|
|
prov, err := dbp.convert2linkedca()
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
|
|
|
|
return test{
|
|
|
|
prov: prov,
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MCmpAndSwap: func(bucket, key, old, nu []byte) ([]byte, bool, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, old, nil)
|
|
|
|
|
|
|
|
var _dbp = new(dbProvisioner)
|
|
|
|
assert.FatalError(t, json.Unmarshal(nu, _dbp))
|
|
|
|
|
|
|
|
assert.True(t, len(_dbp.ID) > 0 && _dbp.ID == string(key))
|
|
|
|
assert.Equals(t, _dbp.AuthorityID, prov.AuthorityId)
|
|
|
|
assert.Equals(t, _dbp.Type, prov.Type)
|
|
|
|
assert.Equals(t, _dbp.Name, prov.Name)
|
|
|
|
assert.Equals(t, _dbp.Claims, prov.Claims)
|
|
|
|
assert.Equals(t, _dbp.X509Template, prov.X509Template)
|
|
|
|
assert.Equals(t, _dbp.SSHTemplate, prov.SshTemplate)
|
|
|
|
|
|
|
|
retDetailsBytes, err := json.Marshal(prov.Details.GetData())
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
assert.Equals(t, retDetailsBytes, _dbp.Details)
|
|
|
|
|
|
|
|
assert.True(t, _dbp.DeletedAt.IsZero())
|
|
|
|
assert.True(t, _dbp.CreatedAt.Before(time.Now()))
|
|
|
|
assert.True(t, _dbp.CreatedAt.After(time.Now().Add(-time.Minute)))
|
|
|
|
|
|
|
|
return nil, false, errors.New("force")
|
|
|
|
},
|
|
|
|
},
|
|
|
|
adminErr: admin.NewErrorISE("error creating provisioner provName: error saving authority provisioner: force"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"ok": func(t *testing.T) test {
|
|
|
|
dbp := defaultDBP(t)
|
|
|
|
prov, err := dbp.convert2linkedca()
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
|
|
|
|
return test{
|
|
|
|
prov: prov,
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MCmpAndSwap: func(bucket, key, old, nu []byte) ([]byte, bool, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, old, nil)
|
|
|
|
|
|
|
|
var _dbp = new(dbProvisioner)
|
|
|
|
assert.FatalError(t, json.Unmarshal(nu, _dbp))
|
|
|
|
|
|
|
|
assert.True(t, len(_dbp.ID) > 0 && _dbp.ID == string(key))
|
|
|
|
assert.Equals(t, _dbp.AuthorityID, prov.AuthorityId)
|
|
|
|
assert.Equals(t, _dbp.Type, prov.Type)
|
|
|
|
assert.Equals(t, _dbp.Name, prov.Name)
|
|
|
|
assert.Equals(t, _dbp.Claims, prov.Claims)
|
|
|
|
assert.Equals(t, _dbp.X509Template, prov.X509Template)
|
|
|
|
assert.Equals(t, _dbp.SSHTemplate, prov.SshTemplate)
|
|
|
|
|
|
|
|
retDetailsBytes, err := json.Marshal(prov.Details.GetData())
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
assert.Equals(t, retDetailsBytes, _dbp.Details)
|
|
|
|
|
|
|
|
assert.True(t, _dbp.DeletedAt.IsZero())
|
|
|
|
assert.True(t, _dbp.CreatedAt.Before(time.Now()))
|
|
|
|
assert.True(t, _dbp.CreatedAt.After(time.Now().Add(-time.Minute)))
|
|
|
|
|
|
|
|
return nu, true, nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for name, run := range tests {
|
|
|
|
tc := run(t)
|
|
|
|
t.Run(name, func(t *testing.T) {
|
2021-10-08 18:59:57 +00:00
|
|
|
d := DB{db: tc.db, authorityID: admin.DefaultAuthorityID}
|
|
|
|
if err := d.CreateProvisioner(context.Background(), tc.prov); err != nil {
|
2021-05-03 19:48:20 +00:00
|
|
|
switch k := err.(type) {
|
|
|
|
case *admin.Error:
|
|
|
|
if assert.NotNil(t, tc.adminErr) {
|
|
|
|
assert.Equals(t, k.Type, tc.adminErr.Type)
|
|
|
|
assert.Equals(t, k.Detail, tc.adminErr.Detail)
|
|
|
|
assert.Equals(t, k.Status, tc.adminErr.Status)
|
|
|
|
assert.Equals(t, k.Err.Error(), tc.adminErr.Err.Error())
|
|
|
|
assert.Equals(t, k.Detail, tc.adminErr.Detail)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
if assert.NotNil(t, tc.err) {
|
|
|
|
assert.HasPrefix(t, err.Error(), tc.err.Error())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDB_UpdateProvisioner(t *testing.T) {
|
|
|
|
provID := "provID"
|
|
|
|
type test struct {
|
|
|
|
db nosql.DB
|
|
|
|
err error
|
|
|
|
adminErr *admin.Error
|
|
|
|
prov *linkedca.Provisioner
|
|
|
|
}
|
|
|
|
var tests = map[string]func(t *testing.T) test{
|
|
|
|
"fail/not-found": func(t *testing.T) test {
|
|
|
|
return test{
|
|
|
|
prov: &linkedca.Provisioner{Id: provID},
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, string(key), provID)
|
|
|
|
|
2021-10-08 18:59:57 +00:00
|
|
|
return nil, database.ErrNotFound
|
2021-05-03 19:48:20 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
adminErr: admin.NewError(admin.ErrorNotFoundType, "provisioner provID not found"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"fail/db.Get-error": func(t *testing.T) test {
|
|
|
|
return test{
|
|
|
|
prov: &linkedca.Provisioner{Id: provID},
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, string(key), provID)
|
|
|
|
|
|
|
|
return nil, errors.New("force")
|
|
|
|
},
|
|
|
|
},
|
|
|
|
err: errors.New("error loading provisioner provID: force"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"fail/update-deleted": func(t *testing.T) test {
|
|
|
|
dbp := defaultDBP(t)
|
|
|
|
dbp.DeletedAt = clock.Now()
|
|
|
|
data, err := json.Marshal(dbp)
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
return test{
|
|
|
|
prov: &linkedca.Provisioner{Id: provID},
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, string(key), provID)
|
|
|
|
|
|
|
|
return data, nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
adminErr: admin.NewError(admin.ErrorDeletedType, "provisioner %s is deleted", provID),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"fail/update-type-error": func(t *testing.T) test {
|
|
|
|
dbp := defaultDBP(t)
|
|
|
|
|
|
|
|
upd, err := dbp.convert2linkedca()
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
upd.Type = linkedca.Provisioner_JWK
|
|
|
|
|
|
|
|
data, err := json.Marshal(dbp)
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
return test{
|
|
|
|
prov: upd,
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, string(key), provID)
|
|
|
|
|
|
|
|
return data, nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
adminErr: admin.NewError(admin.ErrorBadRequestType, "cannot update provisioner type"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"fail/save-error": func(t *testing.T) test {
|
|
|
|
dbp := defaultDBP(t)
|
|
|
|
|
|
|
|
prov, err := dbp.convert2linkedca()
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
|
|
|
|
data, err := json.Marshal(dbp)
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
return test{
|
|
|
|
prov: prov,
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, string(key), provID)
|
|
|
|
|
|
|
|
return data, nil
|
|
|
|
},
|
|
|
|
MCmpAndSwap: func(bucket, key, old, nu []byte) ([]byte, bool, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, string(key), provID)
|
|
|
|
assert.Equals(t, string(old), string(data))
|
|
|
|
|
|
|
|
var _dbp = new(dbProvisioner)
|
|
|
|
assert.FatalError(t, json.Unmarshal(nu, _dbp))
|
|
|
|
|
|
|
|
assert.True(t, len(_dbp.ID) > 0 && _dbp.ID == string(key))
|
|
|
|
assert.Equals(t, _dbp.AuthorityID, prov.AuthorityId)
|
|
|
|
assert.Equals(t, _dbp.Type, prov.Type)
|
|
|
|
assert.Equals(t, _dbp.Name, prov.Name)
|
|
|
|
assert.Equals(t, _dbp.Claims, prov.Claims)
|
|
|
|
assert.Equals(t, _dbp.X509Template, prov.X509Template)
|
|
|
|
assert.Equals(t, _dbp.SSHTemplate, prov.SshTemplate)
|
|
|
|
|
|
|
|
retDetailsBytes, err := json.Marshal(prov.Details.GetData())
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
assert.Equals(t, retDetailsBytes, _dbp.Details)
|
|
|
|
|
|
|
|
assert.True(t, _dbp.DeletedAt.IsZero())
|
|
|
|
assert.True(t, _dbp.CreatedAt.Before(time.Now()))
|
|
|
|
assert.True(t, _dbp.CreatedAt.After(time.Now().Add(-time.Minute)))
|
|
|
|
|
|
|
|
return nil, false, errors.New("force")
|
|
|
|
},
|
|
|
|
},
|
|
|
|
err: errors.New("error saving authority provisioner: force"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"ok": func(t *testing.T) test {
|
|
|
|
dbp := defaultDBP(t)
|
|
|
|
|
|
|
|
prov, err := dbp.convert2linkedca()
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
|
|
|
|
prov.Name = "new-name"
|
|
|
|
prov.Claims = &linkedca.Claims{
|
|
|
|
DisableRenewal: true,
|
|
|
|
X509: &linkedca.X509Claims{
|
|
|
|
Enabled: true,
|
|
|
|
Durations: &linkedca.Durations{
|
|
|
|
Min: "10m",
|
|
|
|
Max: "8h",
|
|
|
|
Default: "4h",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Ssh: &linkedca.SSHClaims{
|
|
|
|
Enabled: true,
|
|
|
|
UserDurations: &linkedca.Durations{
|
|
|
|
Min: "7m",
|
|
|
|
Max: "11h",
|
|
|
|
Default: "5h",
|
|
|
|
},
|
|
|
|
HostDurations: &linkedca.Durations{
|
|
|
|
Min: "4m",
|
|
|
|
Max: "24h",
|
|
|
|
Default: "24h",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
prov.X509Template = &linkedca.Template{
|
|
|
|
Template: []byte("x"),
|
|
|
|
Data: []byte("y"),
|
|
|
|
}
|
|
|
|
prov.SshTemplate = &linkedca.Template{
|
|
|
|
Template: []byte("z"),
|
|
|
|
Data: []byte("w"),
|
|
|
|
}
|
|
|
|
prov.Details = &linkedca.ProvisionerDetails{
|
|
|
|
Data: &linkedca.ProvisionerDetails_ACME{
|
|
|
|
ACME: &linkedca.ACMEProvisioner{
|
|
|
|
ForceCn: false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
data, err := json.Marshal(dbp)
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
return test{
|
|
|
|
prov: prov,
|
|
|
|
db: &db.MockNoSQLDB{
|
|
|
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, string(key), provID)
|
|
|
|
|
|
|
|
return data, nil
|
|
|
|
},
|
|
|
|
MCmpAndSwap: func(bucket, key, old, nu []byte) ([]byte, bool, error) {
|
|
|
|
assert.Equals(t, bucket, provisionersTable)
|
|
|
|
assert.Equals(t, string(key), provID)
|
|
|
|
assert.Equals(t, string(old), string(data))
|
|
|
|
|
|
|
|
var _dbp = new(dbProvisioner)
|
|
|
|
assert.FatalError(t, json.Unmarshal(nu, _dbp))
|
|
|
|
|
|
|
|
assert.True(t, len(_dbp.ID) > 0 && _dbp.ID == string(key))
|
|
|
|
assert.Equals(t, _dbp.AuthorityID, prov.AuthorityId)
|
|
|
|
assert.Equals(t, _dbp.Type, prov.Type)
|
|
|
|
assert.Equals(t, _dbp.Name, prov.Name)
|
|
|
|
assert.Equals(t, _dbp.Claims, prov.Claims)
|
|
|
|
assert.Equals(t, _dbp.X509Template, prov.X509Template)
|
|
|
|
assert.Equals(t, _dbp.SSHTemplate, prov.SshTemplate)
|
|
|
|
|
|
|
|
retDetailsBytes, err := json.Marshal(prov.Details.GetData())
|
|
|
|
assert.FatalError(t, err)
|
|
|
|
assert.Equals(t, retDetailsBytes, _dbp.Details)
|
|
|
|
|
|
|
|
assert.True(t, _dbp.DeletedAt.IsZero())
|
|
|
|
assert.True(t, _dbp.CreatedAt.Before(time.Now()))
|
|
|
|
assert.True(t, _dbp.CreatedAt.After(time.Now().Add(-time.Minute)))
|
|
|
|
|
|
|
|
return nu, true, nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for name, run := range tests {
|
|
|
|
tc := run(t)
|
|
|
|
t.Run(name, func(t *testing.T) {
|
2021-10-08 18:59:57 +00:00
|
|
|
d := DB{db: tc.db, authorityID: admin.DefaultAuthorityID}
|
|
|
|
if err := d.UpdateProvisioner(context.Background(), tc.prov); err != nil {
|
2021-05-03 19:48:20 +00:00
|
|
|
switch k := err.(type) {
|
|
|
|
case *admin.Error:
|
|
|
|
if assert.NotNil(t, tc.adminErr) {
|
|
|
|
assert.Equals(t, k.Type, tc.adminErr.Type)
|
|
|
|
assert.Equals(t, k.Detail, tc.adminErr.Detail)
|
|
|
|
assert.Equals(t, k.Status, tc.adminErr.Status)
|
|
|
|
assert.Equals(t, k.Err.Error(), tc.adminErr.Err.Error())
|
|
|
|
assert.Equals(t, k.Detail, tc.adminErr.Detail)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
if assert.NotNil(t, tc.err) {
|
|
|
|
assert.HasPrefix(t, err.Error(), tc.err.Error())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|