Skip to content

Commit

Permalink
configurable watermark backend
Browse files Browse the repository at this point in the history
  • Loading branch information
e-asphyx committed Aug 14, 2024
1 parent 6914188 commit 2e42e61
Show file tree
Hide file tree
Showing 12 changed files with 90 additions and 37 deletions.
10 changes: 5 additions & 5 deletions cmd/commands/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ func NewRootCommand(c *Context, name string) *cobra.Command {
}
}

if baseDir == "" {
baseDir = conf.BaseDir
if baseDir != "" {
conf.BaseDir = baseDir
}
baseDir = os.ExpandEnv(baseDir)
if err := os.MkdirAll(baseDir, 0770); err != nil {
conf.BaseDir = os.ExpandEnv(conf.BaseDir)
if err := os.MkdirAll(conf.BaseDir, 0770); err != nil {
return err
}

Expand All @@ -79,7 +79,7 @@ func NewRootCommand(c *Context, name string) *cobra.Command {
return err
}

watermark, err := watermark.NewFileWatermark(baseDir)
watermark, err := watermark.Registry().New(cmd.Context(), conf.Watermark.Driver, &conf.Watermark.Config, conf)
if err != nil {
return err
}
Expand Down
5 changes: 1 addition & 4 deletions docs/aws_kms.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ vaults:
aws:
driver: awskms
config:
user_name: <iam_username>
access_key_id: <aws_access_key_id>
secret_access_key: <aws_secret_access_key>
region: <aws_region>
Expand All @@ -29,7 +28,6 @@ vaults:
Name | Type | Required | Description
-----|------|:--------:|------------
user_name | string |✅| IAM user name
access_key_id | string | OPTIONAL | IAM user detail
secret_access_key | string | OPTIONAL | IAM user detail
region | string | ✅ | Region where key is created
Expand All @@ -54,7 +52,7 @@ To generate a new private key withing AWS, you must:

## Example Configuration for the AWS KMS vault in Signatory

This example shows a Signatory vault configuration for AWS KMS. Text in `{}` must be replaced, for example, `{AWS_User_Name}` should be replaced with your AWS username.
This example shows a Signatory vault configuration for AWS KMS. Text in `{}` must be replaced.


```
Expand All @@ -63,7 +61,6 @@ vaults:
awskms:
driver: awskms
config:
user_name: {AWS_User_Name}
access_key_id: {Access_Key_ID_In_AWS_User_Profile}
secret_access_key: {Secret_access_Key_ID_In_AWS_User_Profile}
region: {AWS_Region}
Expand Down
21 changes: 19 additions & 2 deletions docs/start.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ vaults:
config:
file: /etc/signatory/secret.json

watermark:
# Default
driver: file

# List enabled public keys hashes here
tezos:
# Default policy allows "block" and "endorsement" operations
Expand Down Expand Up @@ -111,7 +115,7 @@ tezos:
]
```

## Configuration Example - AWS KMS Vault
### Configuration Example - AWS KMS Vault
This configuration example uses AWS KMS as

```yaml
Expand All @@ -128,7 +132,6 @@ vaults:
aws:
driver: awskms
config:
user_name: signatory_testnets # IAM User or Role
access_key_id: <redacted> # Optional
secret_access_key: <redacted> # Optional
region: us-west-2
Expand All @@ -145,6 +148,20 @@ tezos:
- transaction
```

### Watermark backend

Basic syntax:

```yaml
# Optional
watermark:
driver: <driver>
# Optional
config: <config_object>
```

Currently three backends are supported: `file` (a default one), `mem` (for testing purpose only) and `aws`. See [AWS KMS][aws] for configuration syntax.

## Backends
* [AWS KMS](aws_kms.md)
* [Azure Key Vault](azure_kms.md)
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ go 1.21

require (
cloud.google.com/go/kms v1.15.5
github.com/aws/aws-sdk-go-v2 v1.30.3
github.com/aws/aws-sdk-go-v2/config v1.27.27
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.14.10
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.34.4
github.com/aws/aws-sdk-go-v2/service/kms v1.35.3
github.com/aws/smithy-go v1.20.3
github.com/certusone/yubihsm-go v0.3.0
Expand Down Expand Up @@ -34,14 +37,11 @@ require (
cloud.google.com/go/compute v1.23.3 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
cloud.google.com/go/iam v1.1.5 // indirect
github.com/aws/aws-sdk-go-v2 v1.30.3 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.27 // indirect
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.14.10 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.34.4 // indirect
github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.22.3 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.9.16 // indirect
Expand Down
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/karalabe/hid v1.0.0 h1:+/CIMNXhSU/zIJgnIvBD2nKHxS/bnRHhhs9xBryLpPo=
github.com/karalabe/hid v1.0.0/go.mod h1:Vr51f8rUOLYrfrWDFlV12GGQgM5AT8sVh+2fY4MPeu8=
Expand Down Expand Up @@ -364,6 +365,8 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Expand Down
10 changes: 10 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ type Config struct {
Server ServerConfig `yaml:"server"`
PolicyHook *PolicyHook `yaml:"policy_hook"`
BaseDir string `yaml:"base_dir" validate:"required"`
Watermark *WatermarkConfig `yaml:"watermark"`
}

// WatermarkConfig represents watermark backend configuration
type WatermarkConfig struct {
Driver string `yaml:"driver" validate:"required"`
Config yaml.Node `yaml:"config"`
}

var defaultConfig = Config{
Expand All @@ -59,6 +66,9 @@ var defaultConfig = Config{
UtilityAddress: ":9583",
},
BaseDir: "/var/lib/signatory",
Watermark: &WatermarkConfig{
Driver: "file",
},
}

// Read read the config from a file
Expand Down
22 changes: 18 additions & 4 deletions pkg/signatory/watermark/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ import (
tz "github.com/ecadlabs/gotez/v2"
"github.com/ecadlabs/gotez/v2/crypt"
"github.com/ecadlabs/gotez/v2/protocol"
"github.com/ecadlabs/signatory/pkg/config"
"github.com/ecadlabs/signatory/pkg/signatory/request"
awskms "github.com/ecadlabs/signatory/pkg/vault/aws"
log "github.com/sirupsen/logrus"
"gopkg.in/yaml.v3"
)

const (
Expand All @@ -26,24 +28,24 @@ const (
defaultTable = "watermark"
)

type Config struct {
type AWSConfig struct {
awskms.Config
Table string `yaml:"table"`
}

func (c *Config) table() string {
func (c *AWSConfig) table() string {
if c.Table != "" {
return c.Table
}
return defaultTable
}

type AWS struct {
cfg Config
cfg AWSConfig
client *dynamodb.Client
}

func NewAWSWatermark(ctx context.Context, config *Config) (*AWS, error) {
func NewAWSWatermark(ctx context.Context, config *AWSConfig) (*AWS, error) {
cfg, err := awskms.NewConfig(ctx, &config.Config)
if err != nil {
return nil, err
Expand Down Expand Up @@ -188,3 +190,15 @@ func (a *AWS) IsSafeToSign(ctx context.Context, pkh crypt.PublicKeyHash, req pro
// retry
}
}

func init() {
RegisterWatermark("aws", func(ctx context.Context, node *yaml.Node, global *config.Config) (Watermark, error) {
var conf AWSConfig
if node != nil {
if err := node.Decode(&conf); err != nil {
return nil, err
}
}
return NewAWSWatermark(ctx, &conf)
})
}
9 changes: 8 additions & 1 deletion pkg/signatory/watermark/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ import (
"github.com/ecadlabs/gotez/v2/b58"
"github.com/ecadlabs/gotez/v2/crypt"
"github.com/ecadlabs/gotez/v2/protocol"
"github.com/ecadlabs/signatory/pkg/config"
"github.com/ecadlabs/signatory/pkg/hashmap"
"github.com/ecadlabs/signatory/pkg/signatory/request"
log "github.com/sirupsen/logrus"
"gopkg.in/yaml.v3"
)

type File struct {
Expand Down Expand Up @@ -71,6 +73,7 @@ func tryLoad(baseDir string) (map[tz.ChainID]delegateMap, error) {
}

func NewFileWatermark(baseDir string) (*File, error) {

wm := File{
baseDir: baseDir,
}
Expand Down Expand Up @@ -164,4 +167,8 @@ func (f *File) IsSafeToSign(ctx context.Context, pkh crypt.PublicKeyHash, req pr
return writeWatermarkData(f.baseDir, f.mem.chains[*chain], chain)
}

var _ Watermark = (*File)(nil)
func init() {
RegisterWatermark("file", func(ctx context.Context, node *yaml.Node, global *config.Config) (Watermark, error) {
return NewFileWatermark(global.BaseDir)
})
}
8 changes: 7 additions & 1 deletion pkg/signatory/watermark/mem.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import (
tz "github.com/ecadlabs/gotez/v2"
"github.com/ecadlabs/gotez/v2/crypt"
"github.com/ecadlabs/gotez/v2/protocol"
"github.com/ecadlabs/signatory/pkg/config"
"github.com/ecadlabs/signatory/pkg/signatory/request"
"gopkg.in/yaml.v3"
)

// InMemory keep previous operation in memory
Expand Down Expand Up @@ -56,4 +58,8 @@ func (w *InMemory) isSafeToSignUnlocked(pkh crypt.PublicKeyHash, req protocol.Si
return nil
}

var _ Watermark = (*InMemory)(nil)
func init() {
RegisterWatermark("mem", func(context.Context, *yaml.Node, *config.Config) (Watermark, error) {
return new(InMemory), nil
})
}
11 changes: 7 additions & 4 deletions pkg/signatory/watermark/watermark.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (

"github.com/ecadlabs/gotez/v2/crypt"
"github.com/ecadlabs/gotez/v2/protocol"
"github.com/ecadlabs/signatory/pkg/config"
log "github.com/sirupsen/logrus"
"gopkg.in/yaml.v3"
)

Expand All @@ -25,16 +27,17 @@ func (w Ignore) IsSafeToSign(context.Context, crypt.PublicKeyHash, protocol.Sign
var _ Watermark = (*Ignore)(nil)

type Factory interface {
New(ctx context.Context, name string, conf *yaml.Node) (Watermark, error)
New(ctx context.Context, name string, conf *yaml.Node, global *config.Config) (Watermark, error)
}

type newWMBackendFunc func(ctx context.Context, conf *yaml.Node) (Watermark, error)
type newWMBackendFunc func(ctx context.Context, conf *yaml.Node, global *config.Config) (Watermark, error)

type registry map[string]newWMBackendFunc

func (r registry) New(ctx context.Context, name string, conf *yaml.Node) (Watermark, error) {
func (r registry) New(ctx context.Context, name string, conf *yaml.Node, global *config.Config) (Watermark, error) {
if newFunc, ok := r[name]; ok {
return newFunc(ctx, conf)
log.WithField("backend", name).Info("Initializing watermark backend")
return newFunc(ctx, conf, global)
}
return nil, fmt.Errorf("unknown watermark backend: %s", name)
}
Expand Down
17 changes: 5 additions & 12 deletions pkg/vault/aws/awskms.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"github.com/aws/aws-sdk-go-v2/service/kms/types"
"github.com/aws/smithy-go"
"github.com/ecadlabs/gotez/v2/crypt"
"github.com/ecadlabs/signatory/pkg/config"
"github.com/ecadlabs/signatory/pkg/cryptoutils"
"github.com/ecadlabs/signatory/pkg/vault"

Expand All @@ -23,7 +22,7 @@ import (
type Config struct {
AccessKeyID string `yaml:"access_key_id"`
AccessKey string `yaml:"secret_access_key"`
Region string `yaml:"region" validate:"required"`
Region string `yaml:"region"`
}

type Vault struct {
Expand Down Expand Up @@ -183,17 +182,11 @@ func New(ctx context.Context, config *Config) (*Vault, error) {
func init() {
vault.RegisterVault("awskms", func(ctx context.Context, node *yaml.Node) (vault.Vault, error) {
var conf Config
if node == nil || node.Kind == 0 {
return nil, errors.New("(AWSKMS): config is missing")
}
if err := node.Decode(&conf); err != nil {
return nil, err
}

if err := config.Validator().Struct(&conf); err != nil {
return nil, err
if node != nil {
if err := node.Decode(&conf); err != nil {
return nil, err
}
}

return New(ctx, &conf)
})
}
5 changes: 4 additions & 1 deletion signatory.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ server:
secret: secret2
jwt_exp: 30


vaults:
# Name is used to identify backend during import process
kms:
Expand Down Expand Up @@ -49,6 +48,10 @@ vaults:
transitConfig:
mountPoint: "transit/"

watermark:
# Default
driver: file

# List enabled public keys hashes here
tezos:
# This example does not specifiy a policy, and be default will allow signing of "block" and "endorsement" operations only.
Expand Down

0 comments on commit 2e42e61

Please sign in to comment.