forked from TrueCloudLab/certificates
dd9850ce4c
Replaces the authority adminDB with a new impmentation that users the linkedca client to retrieve the data. Note that this implementation still hardcodes the endpoint to localhost.
171 lines
4.9 KiB
Go
171 lines
4.9 KiB
Go
package authority
|
|
|
|
import (
|
|
"context"
|
|
"crypto/tls"
|
|
"crypto/x509"
|
|
"io/ioutil"
|
|
"path/filepath"
|
|
|
|
"github.com/pkg/errors"
|
|
"github.com/smallstep/certificates/errs"
|
|
"go.step.sm/cli-utils/config"
|
|
"go.step.sm/linkedca"
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/credentials"
|
|
)
|
|
|
|
type linkedCaClient struct {
|
|
client linkedca.MajordomoClient
|
|
authorityID string
|
|
}
|
|
|
|
func createLinkedCAClient(authorityID, endpoint string) (*linkedCaClient, error) {
|
|
base := filepath.Join(config.StepPath(), "linkedca")
|
|
rootFile := filepath.Join(base, "root_ca.crt")
|
|
certFile := filepath.Join(base, "linkedca.crt")
|
|
keyFile := filepath.Join(base, "linkedca.key")
|
|
|
|
b, err := ioutil.ReadFile(rootFile)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "error reading linkedca root")
|
|
}
|
|
pool := x509.NewCertPool()
|
|
if !pool.AppendCertsFromPEM(b) {
|
|
return nil, errors.Errorf("error reading %s: no certificates were found", rootFile)
|
|
}
|
|
|
|
conn, err := grpc.Dial(endpoint, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{
|
|
RootCAs: pool,
|
|
GetClientCertificate: func(*tls.CertificateRequestInfo) (*tls.Certificate, error) {
|
|
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "error reading linkedca certificate")
|
|
}
|
|
return &cert, nil
|
|
},
|
|
})))
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "error connecting %s", endpoint)
|
|
}
|
|
|
|
return &linkedCaClient{
|
|
client: linkedca.NewMajordomoClient(conn),
|
|
authorityID: authorityID,
|
|
}, nil
|
|
}
|
|
|
|
func (c *linkedCaClient) CreateProvisioner(ctx context.Context, prov *linkedca.Provisioner) error {
|
|
resp, err := c.client.CreateProvisioner(ctx, &linkedca.CreateProvisionerRequest{
|
|
Type: prov.Type,
|
|
Name: prov.Name,
|
|
Details: prov.Details,
|
|
Claims: prov.Claims,
|
|
X509Template: prov.X509Template,
|
|
SshTemplate: prov.SshTemplate,
|
|
})
|
|
if err != nil {
|
|
return errors.Wrap(err, "error creating provisioner")
|
|
}
|
|
prov.Id = resp.Id
|
|
prov.AuthorityId = resp.AuthorityId
|
|
return nil
|
|
}
|
|
|
|
func (c *linkedCaClient) GetProvisioner(ctx context.Context, id string) (*linkedca.Provisioner, error) {
|
|
resp, err := c.client.GetConfiguration(ctx, &linkedca.ConfigurationRequest{
|
|
AuthorityId: c.authorityID,
|
|
})
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "error getting provisioners")
|
|
}
|
|
for _, p := range resp.Provisioners {
|
|
if p.Id == id {
|
|
return p, nil
|
|
}
|
|
}
|
|
return nil, errs.NotFound("provisioner not found")
|
|
}
|
|
|
|
func (c *linkedCaClient) GetProvisioners(ctx context.Context) ([]*linkedca.Provisioner, error) {
|
|
resp, err := c.client.GetConfiguration(ctx, &linkedca.ConfigurationRequest{
|
|
AuthorityId: c.authorityID,
|
|
})
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "error getting provisioners")
|
|
}
|
|
return resp.Provisioners, nil
|
|
}
|
|
|
|
func (c *linkedCaClient) UpdateProvisioner(ctx context.Context, prov *linkedca.Provisioner) error {
|
|
_, err := c.client.UpdateProvisioner(ctx, &linkedca.UpdateProvisionerRequest{
|
|
Id: prov.Id,
|
|
Name: prov.Name,
|
|
Details: prov.Details,
|
|
Claims: prov.Claims,
|
|
X509Template: prov.X509Template,
|
|
SshTemplate: prov.SshTemplate,
|
|
})
|
|
return errors.Wrap(err, "error updating provisioner")
|
|
}
|
|
|
|
func (c *linkedCaClient) DeleteProvisioner(ctx context.Context, id string) error {
|
|
_, err := c.client.DeleteProvisioner(ctx, &linkedca.DeleteProvisionerRequest{
|
|
Id: id,
|
|
})
|
|
return errors.Wrap(err, "error deleting provisioner")
|
|
}
|
|
|
|
func (c *linkedCaClient) CreateAdmin(ctx context.Context, adm *linkedca.Admin) error {
|
|
resp, err := c.client.CreateAdmin(ctx, &linkedca.CreateAdminRequest{
|
|
Subject: adm.Subject,
|
|
ProvisionerId: adm.ProvisionerId,
|
|
Type: adm.Type,
|
|
})
|
|
if err != nil {
|
|
return errors.Wrap(err, "error creating admin")
|
|
}
|
|
adm.Id = resp.Id
|
|
adm.AuthorityId = resp.AuthorityId
|
|
return nil
|
|
}
|
|
|
|
func (c *linkedCaClient) GetAdmin(ctx context.Context, id string) (*linkedca.Admin, error) {
|
|
resp, err := c.client.GetConfiguration(ctx, &linkedca.ConfigurationRequest{
|
|
AuthorityId: c.authorityID,
|
|
})
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "error getting admins")
|
|
}
|
|
for _, a := range resp.Admins {
|
|
if a.Id == id {
|
|
return a, nil
|
|
}
|
|
}
|
|
return nil, errs.NotFound("admin not found")
|
|
}
|
|
|
|
func (c *linkedCaClient) GetAdmins(ctx context.Context) ([]*linkedca.Admin, error) {
|
|
resp, err := c.client.GetConfiguration(ctx, &linkedca.ConfigurationRequest{
|
|
AuthorityId: c.authorityID,
|
|
})
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "error getting admins")
|
|
}
|
|
return resp.Admins, nil
|
|
}
|
|
|
|
func (c *linkedCaClient) UpdateAdmin(ctx context.Context, adm *linkedca.Admin) error {
|
|
_, err := c.client.UpdateAdmin(ctx, &linkedca.UpdateAdminRequest{
|
|
Id: adm.Id,
|
|
Type: adm.Type,
|
|
})
|
|
return errors.Wrap(err, "error updating admin")
|
|
}
|
|
|
|
func (c *linkedCaClient) DeleteAdmin(ctx context.Context, id string) error {
|
|
_, err := c.client.DeleteAdmin(ctx, &linkedca.DeleteAdminRequest{
|
|
Id: id,
|
|
})
|
|
return errors.Wrap(err, "error deleting admin")
|
|
}
|