storj/pkg/certificates/config.go

140 lines
3.6 KiB
Go
Raw Normal View History

// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package certificates
import (
"context"
"os"
"github.com/zeebo/errs"
"go.uber.org/zap"
2019-02-06 13:19:14 +00:00
"golang.org/x/sync/errgroup"
"storj.io/storj/internal/dbutil"
"storj.io/storj/pkg/identity"
"storj.io/storj/pkg/pb"
"storj.io/storj/pkg/peertls/extensions"
"storj.io/storj/pkg/peertls/tlsopts"
2019-01-28 15:04:53 +00:00
"storj.io/storj/pkg/server"
"storj.io/storj/pkg/transport"
"storj.io/storj/storage/boltdb"
"storj.io/storj/storage/redis"
)
// CertClientConfig is a config struct for use with a certificate signing service client
type CertClientConfig struct {
2019-01-24 15:41:16 +00:00
Address string `help:"address of the certificate signing rpc service"`
TLS tlsopts.Config
}
// CertServerConfig is a config struct for use with a certificate signing service server
type CertServerConfig struct {
2019-02-26 08:55:52 +00:00
Overwrite bool `default:"false" help:"if true, overwrites config AND authorization db is truncated" setup:"true"`
AuthorizationDBURL string `default:"bolt://$CONFDIR/authorizations.db" help:"url to the certificate signing authorization database"`
MinDifficulty uint `default:"30" help:"minimum difficulty of the requester's identity required to claim an authorization"`
CA identity.FullCAConfig
}
// Sign submits a certificate signing request given the config
func (c CertClientConfig) Sign(ctx context.Context, ident *identity.FullIdentity, authToken string) (_ [][]byte, err error) {
defer mon.Task()(&ctx)(&err)
tlsOpts, err := tlsopts.NewOptions(ident, c.TLS)
if err != nil {
return nil, err
}
client, err := NewClient(ctx, transport.NewClient(tlsOpts), c.Address)
if err != nil {
return nil, err
}
2019-01-24 15:41:16 +00:00
return client.Sign(ctx, authToken)
}
// NewAuthDB creates or opens the authorization database specified by the config
func (c CertServerConfig) NewAuthDB() (*AuthorizationDB, error) {
// TODO: refactor db selection logic?
driver, source, err := dbutil.SplitConnstr(c.AuthorizationDBURL)
if err != nil {
return nil, extensions.ErrRevocationDB.Wrap(err)
}
authDB := new(AuthorizationDB)
switch driver {
case "bolt":
_, err := os.Stat(source)
if c.Overwrite && err == nil {
if err := os.Remove(source); err != nil {
return nil, err
}
}
authDB.DB, err = boltdb.New(source, AuthorizationsBucket)
if err != nil {
return nil, ErrAuthorizationDB.Wrap(err)
}
case "redis":
redisClient, err := redis.NewClientFrom(c.AuthorizationDBURL)
if err != nil {
return nil, ErrAuthorizationDB.Wrap(err)
}
if c.Overwrite {
if err := redisClient.FlushDB(); err != nil {
return nil, err
}
}
authDB.DB = redisClient
default:
return nil, ErrAuthorizationDB.New("database scheme not supported: %s", driver)
}
return authDB, nil
}
// Run implements the responsibility interface, starting a certificate signing server.
2019-02-06 16:40:55 +00:00
func (c CertServerConfig) Run(ctx context.Context, srv *server.Server) (err error) {
defer mon.Task()(&ctx)(&err)
authDB, err := c.NewAuthDB()
if err != nil {
return err
}
defer func() {
err = errs.Combine(err, authDB.Close())
}()
signer, err := c.CA.Load()
if err != nil {
return err
}
2019-02-06 16:40:55 +00:00
certSrv := NewServer(
zap.L(),
signer,
authDB,
uint16(c.MinDifficulty),
)
2019-02-06 16:40:55 +00:00
pb.RegisterCertificatesServer(srv.GRPC(), certSrv)
2019-02-06 16:40:55 +00:00
certSrv.log.Info(
"Certificate signing server running",
2019-02-06 16:40:55 +00:00
zap.String("address", srv.Addr().String()),
)
2019-02-06 13:19:14 +00:00
ctx, cancel := context.WithCancel(ctx)
var group errgroup.Group
group.Go(func() error {
defer cancel()
<-ctx.Done()
2019-02-06 16:40:55 +00:00
return srv.Close()
2019-02-06 13:19:14 +00:00
})
group.Go(func() error {
defer cancel()
2019-02-06 16:40:55 +00:00
return srv.Run(ctx)
2019-02-06 13:19:14 +00:00
})
return group.Wait()
}