Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
dopey committed May 25, 2021
1 parent 423942d commit 1726076
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 297 deletions.
9 changes: 0 additions & 9 deletions authority/admin/collection.go
Expand Up @@ -178,12 +178,3 @@ func loadAdmin(m *sync.Map, key string) (*linkedca.Admin, bool) {
}
return adm, true
}

/*
// provisionerSum returns the SHA1 of the provisioners ID. From this we will
// create the unique and sorted id.
func provisionerSum(p Interface) []byte {
sum := sha1.Sum([]byte(p.GetID()))
return sum[:]
}
*/
4 changes: 2 additions & 2 deletions authority/config/config.go
Expand Up @@ -8,11 +8,11 @@ import (
"time"

"github.com/pkg/errors"
"github.com/smallstep/certificates/authority/admin"
"github.com/smallstep/certificates/authority/provisioner"
cas "github.com/smallstep/certificates/cas/apiv1"
"github.com/smallstep/certificates/db"
kms "github.com/smallstep/certificates/kms/apiv1"
"github.com/smallstep/certificates/linkedca"
"github.com/smallstep/certificates/templates"
)

Expand Down Expand Up @@ -96,7 +96,7 @@ type AuthConfig struct {
*cas.Options
AuthorityID string `json:"authorityID,omitempty"`
Provisioners provisioner.List `json:"provisioners"`
Admins []*admin.Admin `json:"-"`
Admins []*linkedca.Admin `json:"-"`
Template *ASN1DN `json:"template,omitempty"`
Claims *provisioner.Claims `json:"claims,omitempty"`
DisableIssuedAtCheck bool `json:"disableIssuedAtCheck,omitempty"`
Expand Down
42 changes: 8 additions & 34 deletions authority/mgmt/config.go
Expand Up @@ -2,6 +2,7 @@ package mgmt

import (
"github.com/smallstep/certificates/authority/config"
"github.com/smallstep/certificates/linkedca"
)

const (
Expand All @@ -11,49 +12,22 @@ const (
DefaultAuthorityID = "00000000-0000-0000-0000-000000000000"
)

// Claims encapsulates all x509 and ssh claims applied to the authority
// configuration. E.g. maxTLSCertDuration, defaultSSHCertDuration, etc.
type Claims struct {
X509 *X509Claims `json:"x509Claims"`
SSH *SSHClaims `json:"sshClaims"`
DisableRenewal bool `json:"disableRenewal"`
}

// X509Claims are the x509 claims applied to the authority.
type X509Claims struct {
Durations *Durations `json:"durations"`
}

// SSHClaims are the ssh claims applied to the authority.
type SSHClaims struct {
Enabled bool `json:"enabled"`
UserDurations *Durations `json:"userDurations"`
HostDurations *Durations `json:"hostDurations"`
}

// Durations represents min, max, default, duration.
type Durations struct {
Min string `json:"min"`
Max string `json:"max"`
Default string `json:"default"`
}

func NewDefaultClaims() *Claims {
return &Claims{
X509: &X509Claims{
Durations: &Durations{
func NewDefaultClaims() *linkedca.Claims {
return &linkedca.Claims{
X509: &linkedca.X509Claims{
Durations: &linkedca.Durations{
Min: config.GlobalProvisionerClaims.MinTLSDur.String(),
Max: config.GlobalProvisionerClaims.MaxTLSDur.String(),
Default: config.GlobalProvisionerClaims.DefaultTLSDur.String(),
},
},
SSH: &SSHClaims{
UserDurations: &Durations{
Ssh: &linkedca.SSHClaims{
UserDurations: &linkedca.Durations{
Min: config.GlobalProvisionerClaims.MinUserSSHDur.String(),
Max: config.GlobalProvisionerClaims.MaxUserSSHDur.String(),
Default: config.GlobalProvisionerClaims.DefaultUserSSHDur.String(),
},
HostDurations: &Durations{
HostDurations: &linkedca.Durations{
Min: config.GlobalProvisionerClaims.MinHostSSHDur.String(),
Max: config.GlobalProvisionerClaims.MaxHostSSHDur.String(),
Default: config.GlobalProvisionerClaims.DefaultHostSSHDur.String(),
Expand Down
20 changes: 20 additions & 0 deletions authority/mgmt/db.go
Expand Up @@ -17,11 +17,13 @@ type DB interface {
GetProvisioner(ctx context.Context, id string) (*linkedca.Provisioner, error)
GetProvisioners(ctx context.Context) ([]*linkedca.Provisioner, error)
UpdateProvisioner(ctx context.Context, prov *linkedca.Provisioner) error
DeleteProvisioner(ctx context.Context, id string) error

CreateAdmin(ctx context.Context, admin *linkedca.Admin) error
GetAdmin(ctx context.Context, id string) (*linkedca.Admin, error)
GetAdmins(ctx context.Context) ([]*linkedca.Admin, error)
UpdateAdmin(ctx context.Context, admin *linkedca.Admin) error
DeleteAdmin(ctx context.Context, id string) error
}

// MockDB is an implementation of the DB interface that should only be used as
Expand All @@ -31,11 +33,13 @@ type MockDB struct {
MockGetProvisioner func(ctx context.Context, id string) (*linkedca.Provisioner, error)
MockGetProvisioners func(ctx context.Context) ([]*linkedca.Provisioner, error)
MockUpdateProvisioner func(ctx context.Context, prov *linkedca.Provisioner) error
MockDeleteProvisioner func(ctx context.Context, id string) error

MockCreateAdmin func(ctx context.Context, adm *linkedca.Admin) error
MockGetAdmin func(ctx context.Context, id string) (*linkedca.Admin, error)
MockGetAdmins func(ctx context.Context) ([]*linkedca.Admin, error)
MockUpdateAdmin func(ctx context.Context, adm *linkedca.Admin) error
MockDeleteAdmin func(ctx context.Context, id string) error

MockError error
MockRet1 interface{}
Expand Down Expand Up @@ -79,6 +83,14 @@ func (m *MockDB) UpdateProvisioner(ctx context.Context, prov *linkedca.Provision
return m.MockError
}

// DeleteProvisioner mock
func (m *MockDB) DeleteProvisioner(ctx context.Context, id string) error {
if m.MockDeleteProvisioner != nil {
return m.MockDeleteProvisioner(ctx, id)
}
return m.MockError
}

// CreateAdmin mock
func (m *MockDB) CreateAdmin(ctx context.Context, admin *linkedca.Admin) error {
if m.MockCreateAdmin != nil {
Expand Down Expand Up @@ -114,3 +126,11 @@ func (m *MockDB) UpdateAdmin(ctx context.Context, adm *linkedca.Admin) error {
}
return m.MockError
}

// DeleteAdmin mock
func (m *MockDB) DeleteAdmin(ctx context.Context, id string) error {
if m.MockDeleteAdmin != nil {
return m.MockDeleteAdmin(ctx, id)
}
return m.MockError
}
91 changes: 45 additions & 46 deletions authority/mgmt/db/nosql/admin.go
Expand Up @@ -6,21 +6,20 @@ import (
"time"

"github.com/pkg/errors"
"github.com/smallstep/certificates/authority/admin"
"github.com/smallstep/certificates/authority/mgmt"
"github.com/smallstep/certificates/authority/status"
"github.com/smallstep/certificates/linkedca"
"github.com/smallstep/nosql"
)

// dbAdmin is the database representation of the Admin type.
type dbAdmin struct {
ID string `json:"id"`
AuthorityID string `json:"authorityID"`
ProvisionerID string `json:"provisionerID"`
Subject string `json:"subject"`
Type admin.Type `json:"type"`
CreatedAt time.Time `json:"createdAt"`
DeletedAt time.Time `json:"deletedAt"`
ID string `json:"id"`
AuthorityID string `json:"authorityID"`
ProvisionerID string `json:"provisionerID"`
Subject string `json:"subject"`
Type linkedca.Admin_Type `json:"type"`
CreatedAt time.Time `json:"createdAt"`
DeletedAt time.Time `json:"deletedAt"`
}

func (dbp *dbAdmin) clone() *dbAdmin {
Expand Down Expand Up @@ -59,30 +58,28 @@ func unmarshalDBAdmin(data []byte, id string) (*dbAdmin, error) {
if err := json.Unmarshal(data, dba); err != nil {
return nil, errors.Wrapf(err, "error unmarshaling admin %s into dbAdmin", id)
}
if !dba.DeletedAt.IsZero() {
return nil, mgmt.NewError(mgmt.ErrorDeletedType, "admin %s is deleted", id)
}
return dba, nil
}

func unmarshalAdmin(data []byte, id string) (*mgmt.Admin, error) {
var dba = new(dbAdmin)
if err := json.Unmarshal(data, dba); err != nil {
return nil, errors.Wrapf(err, "error unmarshaling admin %s into dbAdmin", id)
func unmarshalAdmin(data []byte, id string) (*linkedca.Admin, error) {
dba, err := unmarshalDBAdmin(data, id)
if err != nil {
return nil, err
}
adm := &mgmt.Admin{
ID: dba.ID,
AuthorityID: dba.AuthorityID,
ProvisionerID: dba.ProvisionerID,
return &linkedca.Admin{
Id: dba.ID,
AuthorityId: dba.AuthorityID,
ProvisionerId: dba.ProvisionerID,
Subject: dba.Subject,
Type: dba.Type,
Status: status.Active,
}
if !dba.DeletedAt.IsZero() {
adm.Status = status.Deleted
}
return adm, nil
}, nil
}

// GetAdmin retrieves and unmarshals a admin from the database.
func (db *DB) GetAdmin(ctx context.Context, id string) (*mgmt.Admin, error) {
func (db *DB) GetAdmin(ctx context.Context, id string) (*linkedca.Admin, error) {
data, err := db.getDBAdminBytes(ctx, id)
if err != nil {
return nil, err
Expand All @@ -91,12 +88,9 @@ func (db *DB) GetAdmin(ctx context.Context, id string) (*mgmt.Admin, error) {
if err != nil {
return nil, err
}
if adm.Status == status.Deleted {
return nil, mgmt.NewError(mgmt.ErrorDeletedType, "admin %s is deleted", adm.ID)
}
if adm.AuthorityID != db.authorityID {
if adm.AuthorityId != db.authorityID {
return nil, mgmt.NewError(mgmt.ErrorAuthorityMismatchType,
"admin %s is not owned by authority %s", adm.ID, db.authorityID)
"admin %s is not owned by authority %s", adm.Id, db.authorityID)
}

return adm, nil
Expand All @@ -105,21 +99,18 @@ func (db *DB) GetAdmin(ctx context.Context, id string) (*mgmt.Admin, error) {
// GetAdmins retrieves and unmarshals all active (not deleted) admins
// from the database.
// TODO should we be paginating?
func (db *DB) GetAdmins(ctx context.Context) ([]*mgmt.Admin, error) {
func (db *DB) GetAdmins(ctx context.Context) ([]*linkedca.Admin, error) {
dbEntries, err := db.db.List(authorityAdminsTable)
if err != nil {
return nil, errors.Wrap(err, "error loading admins")
}
var admins = []*mgmt.Admin{}
var admins = []*linkedca.Admin{}
for _, entry := range dbEntries {
adm, err := unmarshalAdmin(entry.Value, string(entry.Key))
if err != nil {
return nil, err
}
if adm.Status == status.Deleted {
continue
}
if adm.AuthorityID != db.authorityID {
if adm.AuthorityId != db.authorityID {
continue
}
admins = append(admins, adm)
Expand All @@ -128,18 +119,18 @@ func (db *DB) GetAdmins(ctx context.Context) ([]*mgmt.Admin, error) {
}

// CreateAdmin stores a new admin to the database.
func (db *DB) CreateAdmin(ctx context.Context, adm *mgmt.Admin) error {
func (db *DB) CreateAdmin(ctx context.Context, adm *linkedca.Admin) error {
var err error
adm.ID, err = randID()
adm.Id, err = randID()
if err != nil {
return mgmt.WrapErrorISE(err, "error generating random id for admin")
}
adm.AuthorityID = db.authorityID
adm.AuthorityId = db.authorityID

dba := &dbAdmin{
ID: adm.ID,
ID: adm.Id,
AuthorityID: db.authorityID,
ProvisionerID: adm.ProvisionerID,
ProvisionerID: adm.ProvisionerId,
Subject: adm.Subject,
Type: adm.Type,
CreatedAt: clock.Now(),
Expand All @@ -149,19 +140,27 @@ func (db *DB) CreateAdmin(ctx context.Context, adm *mgmt.Admin) error {
}

// UpdateAdmin saves an updated admin to the database.
func (db *DB) UpdateAdmin(ctx context.Context, adm *mgmt.Admin) error {
old, err := db.getDBAdmin(ctx, adm.ID)
func (db *DB) UpdateAdmin(ctx context.Context, adm *linkedca.Admin) error {
old, err := db.getDBAdmin(ctx, adm.Id)
if err != nil {
return err
}

nu := old.clone()
nu.Type = adm.Type

return db.save(ctx, old.ID, nu, old, "admin", authorityAdminsTable)
}

// If the admin was active but is now deleted ...
if old.DeletedAt.IsZero() && adm.Status == status.Deleted {
nu.DeletedAt = clock.Now()
// DeleteAdmin saves an updated admin to the database.
func (db *DB) DeleteAdmin(ctx context.Context, id string) error {
old, err := db.getDBAdmin(ctx, id)
if err != nil {
return err
}
nu.Type = adm.Type

nu := old.clone()
nu.DeletedAt = clock.Now()

return db.save(ctx, old.ID, nu, old, "admin", authorityAdminsTable)
}

0 comments on commit 1726076

Please sign in to comment.