exposing authority configuration for provisioner cli commands

This commit is contained in:
max furman 2022-04-25 10:23:07 -07:00
parent 3424442c50
commit b91affdd34
6 changed files with 115 additions and 48 deletions

View file

@ -71,6 +71,52 @@ type DB interface {
DeleteAdmin(ctx context.Context, id string) error
}
type NoDB struct{}
func NewNoDB() *NoDB {
return &NoDB{}
}
func (n *NoDB) CreateProvisioner(ctx context.Context, prov *linkedca.Provisioner) error {
return nil
}
func (n *NoDB) GetProvisioner(ctx context.Context, id string) (*linkedca.Provisioner, error) {
return nil, nil
}
func (n *NoDB) GetProvisioners(ctx context.Context) ([]*linkedca.Provisioner, error) {
return nil, nil
}
func (n *NoDB) UpdateProvisioner(ctx context.Context, prov *linkedca.Provisioner) error {
return nil
}
func (n *NoDB) DeleteProvisioner(ctx context.Context, id string) error {
return nil
}
func (n *NoDB) CreateAdmin(ctx context.Context, admin *linkedca.Admin) error {
return nil
}
func (n *NoDB) GetAdmin(ctx context.Context, id string) (*linkedca.Admin, error) {
return nil, nil
}
func (n *NoDB) GetAdmins(ctx context.Context) ([]*linkedca.Admin, error) {
return nil, nil
}
func (n *NoDB) UpdateAdmin(ctx context.Context, prov *linkedca.Admin) error {
return nil
}
func (n *NoDB) DeleteAdmin(ctx context.Context, id string) error {
return nil
}
// MockDB is an implementation of the DB interface that should only be used as
// a mock in tests.
type MockDB struct {

View file

@ -49,7 +49,7 @@ func (a *Authority) StoreAdmin(ctx context.Context, adm *linkedca.Admin, prov pr
return admin.WrapErrorISE(err, "error creating admin")
}
if err := a.admins.Store(adm, prov); err != nil {
if err := a.reloadAdminResources(ctx); err != nil {
if err := a.ReloadAdminResources(ctx); err != nil {
return admin.WrapErrorISE(err, "error reloading admin resources on failed admin store")
}
return admin.WrapErrorISE(err, "error storing admin in authority cache")
@ -66,7 +66,7 @@ func (a *Authority) UpdateAdmin(ctx context.Context, id string, nu *linkedca.Adm
return nil, admin.WrapErrorISE(err, "error updating cached admin %s", id)
}
if err := a.adminDB.UpdateAdmin(ctx, adm); err != nil {
if err := a.reloadAdminResources(ctx); err != nil {
if err := a.ReloadAdminResources(ctx); err != nil {
return nil, admin.WrapErrorISE(err, "error reloading admin resources on failed admin update")
}
return nil, admin.WrapErrorISE(err, "error updating admin %s", id)
@ -88,7 +88,7 @@ func (a *Authority) removeAdmin(ctx context.Context, id string) error {
return admin.WrapErrorISE(err, "error removing admin %s from authority cache", id)
}
if err := a.adminDB.DeleteAdmin(ctx, id); err != nil {
if err := a.reloadAdminResources(ctx); err != nil {
if err := a.ReloadAdminResources(ctx); err != nil {
return admin.WrapErrorISE(err, "error reloading admin resources on failed admin remove")
}
return admin.WrapErrorISE(err, "error deleting admin %s", id)

View file

@ -115,6 +115,20 @@ func New(cfg *config.Config, opts ...Option) (*Authority, error) {
return a, nil
}
// FromOptions creates an Authority exclusively using the passed in options
// and does not intialize the Authority.
func FromOptions(opts ...Option) (*Authority, error) {
var a = new(Authority)
// Apply options.
for _, fn := range opts {
if err := fn(a); err != nil {
return nil, err
}
}
return a, nil
}
// NewEmbedded initializes an authority that can be embedded in a different
// project without the limitations of the config.
func NewEmbedded(opts ...Option) (*Authority, error) {
@ -153,8 +167,8 @@ func NewEmbedded(opts ...Option) (*Authority, error) {
return a, nil
}
// reloadAdminResources reloads admins and provisioners from the DB.
func (a *Authority) reloadAdminResources(ctx context.Context) error {
// ReloadAdminResources reloads admins and provisioners from the DB.
func (a *Authority) ReloadAdminResources(ctx context.Context) error {
var (
provList provisioner.List
adminList []*linkedca.Admin
@ -551,7 +565,7 @@ func (a *Authority) init() error {
}
// Load Provisioners and Admins
if err := a.reloadAdminResources(context.Background()); err != nil {
if err := a.ReloadAdminResources(context.Background()); err != nil {
return err
}
@ -587,6 +601,12 @@ func (a *Authority) GetAdminDatabase() admin.DB {
return a.adminDB
}
// GetConfig returns the config.
func (a *Authority) GetConfig() *config.Config {
return a.config
}
// GetInfo returns information about the authority.
func (a *Authority) GetInfo() Info {
ai := Info{
StartTime: a.startTime,

View file

@ -145,7 +145,7 @@ func (a *Authority) generateProvisionerConfig(ctx context.Context) (provisioner.
}
// StoreProvisioner stores an provisioner.Interface to the authority.
// StoreProvisioner stores a provisioner to the authority.
func (a *Authority) StoreProvisioner(ctx context.Context, prov *linkedca.Provisioner) error {
a.adminMutex.Lock()
defer a.adminMutex.Unlock()
@ -191,7 +191,7 @@ func (a *Authority) StoreProvisioner(ctx context.Context, prov *linkedca.Provisi
}
if err := a.provisioners.Store(certProv); err != nil {
if err := a.reloadAdminResources(ctx); err != nil {
if err := a.ReloadAdminResources(ctx); err != nil {
return admin.WrapErrorISE(err, "error reloading admin resources on failed provisioner store")
}
return admin.WrapErrorISE(err, "error storing provisioner in authority cache")
@ -223,7 +223,7 @@ func (a *Authority) UpdateProvisioner(ctx context.Context, nu *linkedca.Provisio
return admin.WrapErrorISE(err, "error updating provisioner '%s' in authority cache", nu.Name)
}
if err := a.adminDB.UpdateProvisioner(ctx, nu); err != nil {
if err := a.reloadAdminResources(ctx); err != nil {
if err := a.ReloadAdminResources(ctx); err != nil {
return admin.WrapErrorISE(err, "error reloading admin resources on failed provisioner update")
}
return admin.WrapErrorISE(err, "error updating provisioner '%s'", nu.Name)
@ -267,7 +267,7 @@ func (a *Authority) RemoveProvisioner(ctx context.Context, id string) error {
}
// Remove provisioner from database.
if err := a.adminDB.DeleteProvisioner(ctx, provID); err != nil {
if err := a.reloadAdminResources(ctx); err != nil {
if err := a.ReloadAdminResources(ctx); err != nil {
return admin.WrapErrorISE(err, "error reloading admin resources on failed provisioner remove")
}
return admin.WrapErrorISE(err, "error deleting provisioner %s", provName)

View file

@ -363,19 +363,19 @@ retry:
// GetProvisioner performs the GET /admin/provisioners/{name} request to the CA.
func (c *AdminClient) GetProvisioner(opts ...ProvisionerOption) (*linkedca.Provisioner, error) {
var retried bool
o := new(provisionerOptions)
if err := o.apply(opts); err != nil {
o := new(ProvisionerOptions)
if err := o.Apply(opts); err != nil {
return nil, err
}
var u *url.URL
switch {
case len(o.id) > 0:
case len(o.ID) > 0:
u = c.endpoint.ResolveReference(&url.URL{
Path: "/admin/provisioners/id",
RawQuery: o.rawQuery(),
})
case len(o.name) > 0:
u = c.endpoint.ResolveReference(&url.URL{Path: path.Join(adminURLPrefix, "provisioners", o.name)})
case len(o.Name) > 0:
u = c.endpoint.ResolveReference(&url.URL{Path: path.Join(adminURLPrefix, "provisioners", o.Name)})
default:
return nil, errors.New("must set either name or id in method options")
}
@ -410,8 +410,8 @@ retry:
// GetProvisionersPaginate performs the GET /admin/provisioners request to the CA.
func (c *AdminClient) GetProvisionersPaginate(opts ...ProvisionerOption) (*adminAPI.GetProvisionersResponse, error) {
var retried bool
o := new(provisionerOptions)
if err := o.apply(opts); err != nil {
o := new(ProvisionerOptions)
if err := o.Apply(opts); err != nil {
return nil, err
}
u := c.endpoint.ResolveReference(&url.URL{
@ -472,19 +472,19 @@ func (c *AdminClient) RemoveProvisioner(opts ...ProvisionerOption) error {
retried bool
)
o := new(provisionerOptions)
if err := o.apply(opts); err != nil {
o := new(ProvisionerOptions)
if err := o.Apply(opts); err != nil {
return err
}
switch {
case len(o.id) > 0:
case len(o.ID) > 0:
u = c.endpoint.ResolveReference(&url.URL{
Path: path.Join(adminURLPrefix, "provisioners/id"),
RawQuery: o.rawQuery(),
})
case len(o.name) > 0:
u = c.endpoint.ResolveReference(&url.URL{Path: path.Join(adminURLPrefix, "provisioners", o.name)})
case len(o.Name) > 0:
u = c.endpoint.ResolveReference(&url.URL{Path: path.Join(adminURLPrefix, "provisioners", o.Name)})
default:
return errors.New("must set either name or id in method options")
}

View file

@ -425,16 +425,17 @@ func parseEndpoint(endpoint string) (*url.URL, error) {
}
// ProvisionerOption is the type of options passed to the Provisioner method.
type ProvisionerOption func(o *provisionerOptions) error
type ProvisionerOption func(o *ProvisionerOptions) error
type provisionerOptions struct {
cursor string
limit int
id string
name string
// ProvisionerOptions stores options for the provisioner CRUD API.
type ProvisionerOptions struct {
Cursor string
Limit int
ID string
Name string
}
func (o *provisionerOptions) apply(opts []ProvisionerOption) (err error) {
func (o *ProvisionerOptions) Apply(opts []ProvisionerOption) (err error) {
for _, fn := range opts {
if err = fn(o); err != nil {
return
@ -443,51 +444,51 @@ func (o *provisionerOptions) apply(opts []ProvisionerOption) (err error) {
return
}
func (o *provisionerOptions) rawQuery() string {
func (o *ProvisionerOptions) rawQuery() string {
v := url.Values{}
if len(o.cursor) > 0 {
v.Set("cursor", o.cursor)
if len(o.Cursor) > 0 {
v.Set("cursor", o.Cursor)
}
if o.limit > 0 {
v.Set("limit", strconv.Itoa(o.limit))
if o.Limit > 0 {
v.Set("limit", strconv.Itoa(o.Limit))
}
if len(o.id) > 0 {
v.Set("id", o.id)
if len(o.ID) > 0 {
v.Set("id", o.ID)
}
if len(o.name) > 0 {
v.Set("name", o.name)
if len(o.Name) > 0 {
v.Set("name", o.Name)
}
return v.Encode()
}
// WithProvisionerCursor will request the provisioners starting with the given cursor.
func WithProvisionerCursor(cursor string) ProvisionerOption {
return func(o *provisionerOptions) error {
o.cursor = cursor
return func(o *ProvisionerOptions) error {
o.Cursor = cursor
return nil
}
}
// WithProvisionerLimit will request the given number of provisioners.
func WithProvisionerLimit(limit int) ProvisionerOption {
return func(o *provisionerOptions) error {
o.limit = limit
return func(o *ProvisionerOptions) error {
o.Limit = limit
return nil
}
}
// WithProvisionerID will request the given provisioner.
func WithProvisionerID(id string) ProvisionerOption {
return func(o *provisionerOptions) error {
o.id = id
return func(o *ProvisionerOptions) error {
o.ID = id
return nil
}
}
// WithProvisionerName will request the given provisioner.
func WithProvisionerName(name string) ProvisionerOption {
return func(o *provisionerOptions) error {
o.name = name
return func(o *ProvisionerOptions) error {
o.Name = name
return nil
}
}
@ -810,8 +811,8 @@ retry:
// paginate the provisioners.
func (c *Client) Provisioners(opts ...ProvisionerOption) (*api.ProvisionersResponse, error) {
var retried bool
o := new(provisionerOptions)
if err := o.apply(opts); err != nil {
o := new(ProvisionerOptions)
if err := o.Apply(opts); err != nil {
return nil, err
}
u := c.endpoint.ResolveReference(&url.URL{