package admin import ( "context" "encoding/json" "fmt" "github.com/pkg/errors" "go.step.sm/linkedca" "github.com/smallstep/certificates/authority/admin/eak" ) const ( // DefaultAuthorityID is the default AuthorityID. This will be the ID // of the first Authority created, as well as the default AuthorityID // if one is not specified in the configuration. DefaultAuthorityID = "00000000-0000-0000-0000-000000000000" ) // ErrNotFound is an error that should be used by the authority.DB interface to // indicate that an entity does not exist. var ErrNotFound = errors.New("not found") // UnmarshalProvisionerDetails unmarshals details type to the specific provisioner details. func UnmarshalProvisionerDetails(typ linkedca.Provisioner_Type, data []byte) (*linkedca.ProvisionerDetails, error) { var v linkedca.ProvisionerDetails switch typ { case linkedca.Provisioner_JWK: v.Data = new(linkedca.ProvisionerDetails_JWK) case linkedca.Provisioner_OIDC: v.Data = new(linkedca.ProvisionerDetails_OIDC) case linkedca.Provisioner_GCP: v.Data = new(linkedca.ProvisionerDetails_GCP) case linkedca.Provisioner_AWS: v.Data = new(linkedca.ProvisionerDetails_AWS) case linkedca.Provisioner_AZURE: v.Data = new(linkedca.ProvisionerDetails_Azure) case linkedca.Provisioner_ACME: v.Data = new(linkedca.ProvisionerDetails_ACME) case linkedca.Provisioner_X5C: v.Data = new(linkedca.ProvisionerDetails_X5C) case linkedca.Provisioner_K8SSA: v.Data = new(linkedca.ProvisionerDetails_K8SSA) case linkedca.Provisioner_SSHPOP: v.Data = new(linkedca.ProvisionerDetails_SSHPOP) case linkedca.Provisioner_SCEP: v.Data = new(linkedca.ProvisionerDetails_SCEP) default: return nil, fmt.Errorf("unsupported provisioner type %s", typ) } if err := json.Unmarshal(data, v.Data); err != nil { return nil, err } return &linkedca.ProvisionerDetails{Data: v.Data}, nil } // DB is the DB interface expected by the step-ca ACME API. type DB interface { CreateProvisioner(ctx context.Context, prov *linkedca.Provisioner) error 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 CreateExternalAccountKey(ctx context.Context, name string) (*eak.ExternalAccountKey, error) } // MockDB is an implementation of the DB interface that should only be used as // a mock in tests. type MockDB struct { MockCreateProvisioner func(ctx context.Context, prov *linkedca.Provisioner) error 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 MockCreateExternalAccountKey func(ctx context.Context, name string) (*eak.ExternalAccountKey, error) MockError error MockRet1 interface{} } // CreateProvisioner mock. func (m *MockDB) CreateProvisioner(ctx context.Context, prov *linkedca.Provisioner) error { if m.MockCreateProvisioner != nil { return m.MockCreateProvisioner(ctx, prov) } else if m.MockError != nil { return m.MockError } return m.MockError } // GetProvisioner mock. func (m *MockDB) GetProvisioner(ctx context.Context, id string) (*linkedca.Provisioner, error) { if m.MockGetProvisioner != nil { return m.MockGetProvisioner(ctx, id) } else if m.MockError != nil { return nil, m.MockError } return m.MockRet1.(*linkedca.Provisioner), m.MockError } // GetProvisioners mock func (m *MockDB) GetProvisioners(ctx context.Context) ([]*linkedca.Provisioner, error) { if m.MockGetProvisioners != nil { return m.MockGetProvisioners(ctx) } else if m.MockError != nil { return nil, m.MockError } return m.MockRet1.([]*linkedca.Provisioner), m.MockError } // UpdateProvisioner mock func (m *MockDB) UpdateProvisioner(ctx context.Context, prov *linkedca.Provisioner) error { if m.MockUpdateProvisioner != nil { return m.MockUpdateProvisioner(ctx, prov) } 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 { return m.MockCreateAdmin(ctx, admin) } return m.MockError } // GetAdmin mock. func (m *MockDB) GetAdmin(ctx context.Context, id string) (*linkedca.Admin, error) { if m.MockGetAdmin != nil { return m.MockGetAdmin(ctx, id) } else if m.MockError != nil { return nil, m.MockError } return m.MockRet1.(*linkedca.Admin), m.MockError } // GetAdmins mock func (m *MockDB) GetAdmins(ctx context.Context) ([]*linkedca.Admin, error) { if m.MockGetAdmins != nil { return m.MockGetAdmins(ctx) } else if m.MockError != nil { return nil, m.MockError } return m.MockRet1.([]*linkedca.Admin), m.MockError } // UpdateAdmin mock func (m *MockDB) UpdateAdmin(ctx context.Context, adm *linkedca.Admin) error { if m.MockUpdateAdmin != nil { return m.MockUpdateAdmin(ctx, adm) } 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 } func (m *MockDB) CreateExternalAccountKey(ctx context.Context, name string) (*eak.ExternalAccountKey, error) { if m.MockCreateExternalAccountKey != nil { return m.MockCreateExternalAccountKey(ctx, name) } return m.MockRet1.(*eak.ExternalAccountKey), m.MockError }