Skip to content

Commit

Permalink
DynamoDB Watermark Backend (#499)
Browse files Browse the repository at this point in the history
* migrate to aws-sdk-go-v2

* mod tidy

* watermark moved to subpackage

* oops

* AWS watermark backend

* configurable watermark backend

---------

Co-authored-by: GImbrailo <[email protected]>
  • Loading branch information
e-asphyx and GImbrailo authored Oct 25, 2024
1 parent 09ab433 commit e4ff429
Show file tree
Hide file tree
Showing 20 changed files with 437 additions and 97 deletions.
3 changes: 2 additions & 1 deletion cmd/approve-list-svc/server/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/ecadlabs/signatory/pkg/config"
"github.com/ecadlabs/signatory/pkg/hashmap"
"github.com/ecadlabs/signatory/pkg/signatory"
"github.com/ecadlabs/signatory/pkg/signatory/watermark"
"github.com/ecadlabs/signatory/pkg/vault"
"github.com/ecadlabs/signatory/pkg/vault/memory"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -57,7 +58,7 @@ func testServer(t *testing.T, addr []net.IP) error {

conf := signatory.Config{
Vaults: map[string]*config.VaultConfig{"mock": {Driver: "mock"}},
Watermark: signatory.IgnoreWatermark{},
Watermark: watermark.Ignore{},
VaultFactory: vault.FactoryFunc(func(ctx context.Context, name string, conf *yaml.Node) (vault.Vault, error) {
return memory.New([]*memory.PrivateKey{
{
Expand Down
11 changes: 6 additions & 5 deletions cmd/commands/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/ecadlabs/signatory/pkg/config"
"github.com/ecadlabs/signatory/pkg/metrics"
"github.com/ecadlabs/signatory/pkg/signatory"
"github.com/ecadlabs/signatory/pkg/signatory/watermark"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -49,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 @@ -78,7 +79,7 @@ func NewRootCommand(c *Context, name string) *cobra.Command {
return err
}

watermark, err := signatory.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
19 changes: 18 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ toolchain go1.23.1

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
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0
github.com/ecadlabs/goblst v1.0.0
Expand Down Expand Up @@ -33,6 +39,18 @@ 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/credentials v1.17.27 // 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/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
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.22.4 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 // indirect
github.com/cenkalti/backoff/v3 v3.2.2 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/ecadlabs/pretty v0.0.0-20230412124801-f948fc689a04 // indirect
Expand Down Expand Up @@ -64,7 +82,6 @@ require (
)

require (
github.com/aws/aws-sdk-go v1.48.11
github.com/beorn7/perks v1.0.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/enceve/crypto v0.0.0-20160707101852-34d48bb93815 // indirect
Expand Down
38 changes: 36 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,42 @@ cloud.google.com/go/kms v1.15.5 h1:pj1sRfut2eRbD9pFRjNnPNg/CzJPuQAzUujMIM1vVeM=
cloud.google.com/go/kms v1.15.5/go.mod h1:cU2H5jnp6G2TDpUGZyqTCoy1n16fbubHZjmVXSMtwDI=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/aws/aws-sdk-go v1.48.11 h1:9YbiSbaF/jWi+qLRl+J5dEhr2mcbDYHmKg2V7RBcD5M=
github.com/aws/aws-sdk-go v1.48.11/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go-v2 v1.30.3 h1:jUeBtG0Ih+ZIFH0F4UkmL9w3cSpaMv9tYYDbzILP8dY=
github.com/aws/aws-sdk-go-v2 v1.30.3/go.mod h1:nIQjQVp5sfpQcTc9mPSr1B0PaWK5ByX9MOoDadSN4lc=
github.com/aws/aws-sdk-go-v2/config v1.27.27 h1:HdqgGt1OAP0HkEDDShEl0oSYa9ZZBSOmKpdpsDMdO90=
github.com/aws/aws-sdk-go-v2/config v1.27.27/go.mod h1:MVYamCg76dFNINkZFu4n4RjDixhVr51HLj4ErWzrVwg=
github.com/aws/aws-sdk-go-v2/credentials v1.17.27 h1:2raNba6gr2IfA0eqqiP2XiQ0UVOpGPgDSi0I9iAP+UI=
github.com/aws/aws-sdk-go-v2/credentials v1.17.27/go.mod h1:gniiwbGahQByxan6YjQUMcW4Aov6bLC3m+evgcoN4r4=
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.14.10 h1:orAIBscNu5aIjDOnKIrjO+IUFPMLKj3Lp0bPf4chiPc=
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.14.10/go.mod h1:GNjJ8daGhv10hmQYCnmkV8HuY6xXOXV4vzBssSjEIlU=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 h1:KreluoV8FZDEtI6Co2xuNk/UqI9iwMrOx/87PBNIKqw=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11/go.mod h1:SeSUYBLsMYFoRvHE0Tjvn7kbxaUhl75CJi1sbfhMxkU=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 h1:SoNJ4RlFEQEbtDcCEt+QG56MY4fm4W8rYirAmq+/DdU=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15/go.mod h1:U9ke74k1n2bf+RIgoX1SXFed1HLs51OgUSs+Ph0KJP8=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15 h1:C6WHdGnTDIYETAm5iErQUiVNsclNx9qbJVPIt03B6bI=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15/go.mod h1:ZQLZqhcu+JhSrA9/NXRm8SkDvsycE+JkV3WGY41e+IM=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.34.4 h1:utG3S4T+X7nONPIpRoi1tVcQdAdJxntiVS2yolPJyXc=
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.34.4/go.mod h1:q9vzW3Xr1KEXa8n4waHiFt1PrppNDlMymlYP+xpsFbY=
github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.22.3 h1:r27/FnxLPixKBRIlslsvhqscBuMK8uysCYG9Kfgm098=
github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.22.3/go.mod h1:jqOFyN+QSWSoQC+ppyc4weiO8iNQXbzRbxDjQ1ayYd4=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 h1:dT3MqvGhSoaIhRseqw2I0yH81l7wiR2vjs57O51EAm8=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3/go.mod h1:GlAeCkHwugxdHaueRr4nhPuY+WW+gR8UjlcqzPr1SPI=
github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.9.16 h1:lhAX5f7KpgwyieXjbDnRTjPEUI0l3emSRyxXj1PXP8w=
github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.9.16/go.mod h1:AblAlCwvi7Q/SFowvckgN+8M3uFPlopSYeLlbNDArhA=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 h1:HGErhhrxZlQ044RiM+WdoZxp0p+EGM62y3L6pwA4olE=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17/go.mod h1:RkZEx4l0EHYDJpWppMJ3nD9wZJAa8/0lq9aVC+r2UII=
github.com/aws/aws-sdk-go-v2/service/kms v1.35.3 h1:UPTdlTOwWUX49fVi7cymEN6hDqCwe3LNv1vi7TXUutk=
github.com/aws/aws-sdk-go-v2/service/kms v1.35.3/go.mod h1:gjDP16zn+WWalyaUqwCCioQ8gU8lzttCCc9jYsiQI/8=
github.com/aws/aws-sdk-go-v2/service/sso v1.22.4 h1:BXx0ZIxvrJdSgSvKTZ+yRBeSqqgPM89VPlulEcl37tM=
github.com/aws/aws-sdk-go-v2/service/sso v1.22.4/go.mod h1:ooyCOXjvJEsUw7x+ZDHeISPMhtwI3ZCB7ggFMcFfWLU=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 h1:yiwVzJW2ZxZTurVbYWA7QOrAaCYQR72t0wrSBfoesUE=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4/go.mod h1:0oxfLkpz3rQ/CHlx5hB7H69YUpFiI1tql6Q6Ne+1bCw=
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 h1:ZsDKRLXGWHk8WdtyYMoGNO7bTudrvuKpDKgMVRlepGE=
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3/go.mod h1:zwySh8fpFyXp9yOr/KVzxOl8SRqgf/IDw5aUt9UKFcQ=
github.com/aws/smithy-go v1.20.3 h1:ryHwveWzPV5BIof6fyDvor6V3iUL7nTfiTKXHiW05nE=
github.com/aws/smithy-go v1.20.3/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
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
5 changes: 3 additions & 2 deletions pkg/signatory/policy_hook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/ecadlabs/signatory/pkg/config"
"github.com/ecadlabs/signatory/pkg/hashmap"
"github.com/ecadlabs/signatory/pkg/signatory"
"github.com/ecadlabs/signatory/pkg/signatory/watermark"
"github.com/ecadlabs/signatory/pkg/vault"
"github.com/ecadlabs/signatory/pkg/vault/memory"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -99,7 +100,7 @@ func testPolicyHookAuth(t *testing.T, status int) error {

conf := signatory.Config{
Vaults: map[string]*config.VaultConfig{"mock": {Driver: "mock"}},
Watermark: signatory.IgnoreWatermark{},
Watermark: watermark.Ignore{},
VaultFactory: vault.FactoryFunc(func(ctx context.Context, name string, conf *yaml.Node) (vault.Vault, error) {
return memory.New([]*memory.PrivateKey{
{
Expand Down Expand Up @@ -138,7 +139,7 @@ func testPolicyHook(t *testing.T, status int) error {

conf := signatory.Config{
Vaults: map[string]*config.VaultConfig{"mock": {Driver: "mock"}},
Watermark: signatory.IgnoreWatermark{},
Watermark: watermark.Ignore{},
VaultFactory: vault.FactoryFunc(func(ctx context.Context, name string, conf *yaml.Node) (vault.Vault, error) {
return memory.New([]*memory.PrivateKey{
{
Expand Down
5 changes: 3 additions & 2 deletions pkg/signatory/signatory.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/ecadlabs/signatory/pkg/errors"
"github.com/ecadlabs/signatory/pkg/hashmap"
"github.com/ecadlabs/signatory/pkg/signatory/request"
"github.com/ecadlabs/signatory/pkg/signatory/watermark"
"github.com/ecadlabs/signatory/pkg/vault"
log "github.com/sirupsen/logrus"
"gopkg.in/yaml.v3"
Expand Down Expand Up @@ -393,7 +394,7 @@ func (s *Signatory) Sign(ctx context.Context, req *SignRequest) (crypt.Signature
l.WithField(logRaw, hex.EncodeToString(req.Message)).Log(level, "About to sign raw bytes")
digest := crypt.DigestFunc(req.Message)
signFunc := func(ctx context.Context, message []byte, key vault.StoredKey) (crypt.Signature, error) {
if err = s.config.Watermark.IsSafeToSign(req.PublicKeyHash, msg, &digest); err != nil {
if err = s.config.Watermark.IsSafeToSign(ctx, req.PublicKeyHash, msg, &digest); err != nil {
err = errors.Wrap(err, http.StatusConflict)
l.Error(err)
return nil, err
Expand Down Expand Up @@ -544,7 +545,7 @@ type Config struct {
Policy Policy
Vaults map[string]*config.VaultConfig
Interceptor SignInterceptor
Watermark Watermark
Watermark watermark.Watermark
Logger log.FieldLogger
VaultFactory vault.Factory
PolicyHook *PolicyHook
Expand Down
7 changes: 4 additions & 3 deletions pkg/signatory/signatory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/ecadlabs/signatory/pkg/config"
"github.com/ecadlabs/signatory/pkg/hashmap"
"github.com/ecadlabs/signatory/pkg/signatory"
"github.com/ecadlabs/signatory/pkg/signatory/watermark"
"github.com/ecadlabs/signatory/pkg/vault"
"github.com/ecadlabs/signatory/pkg/vault/memory"
"github.com/stretchr/testify/require"
Expand All @@ -23,7 +24,7 @@ const privateKey = "edsk4FTF78Qf1m2rykGpHqostAiq5gYW4YZEoGUSWBTJr2njsDHSnd"
func TestImport(t *testing.T) {
conf := signatory.Config{
Vaults: map[string]*config.VaultConfig{"mock": {Driver: "mock"}},
Watermark: signatory.IgnoreWatermark{},
Watermark: watermark.Ignore{},
VaultFactory: vault.FactoryFunc(func(ctx context.Context, name string, conf *yaml.Node) (vault.Vault, error) {
v, err := memory.New(nil, "Mock")
if err != nil {
Expand Down Expand Up @@ -310,7 +311,7 @@ func TestPolicy(t *testing.T) {
t.Run(c.title, func(t *testing.T) {
conf := signatory.Config{
Vaults: map[string]*config.VaultConfig{"mock": {Driver: "mock"}},
Watermark: signatory.IgnoreWatermark{},
Watermark: watermark.Ignore{},
VaultFactory: vault.FactoryFunc(func(ctx context.Context, name string, conf *yaml.Node) (vault.Vault, error) {
return memory.NewUnparsed([]*memory.UnparsedKey{{Data: privateKey}}, "Mock"), nil
}),
Expand Down Expand Up @@ -400,7 +401,7 @@ func TestListPublicKeys(t *testing.T) {
t.Run(c.title, func(t *testing.T) {
conf := signatory.Config{
Vaults: map[string]*config.VaultConfig{"test": {Driver: "test"}},
Watermark: signatory.IgnoreWatermark{},
Watermark: watermark.Ignore{},
VaultFactory: vault.FactoryFunc(func(ctx context.Context, name string, conf *yaml.Node) (vault.Vault, error) {
return NewTestVault(nil, c.lpk, nil, nil, "test"), nil
}),
Expand Down
21 changes: 0 additions & 21 deletions pkg/signatory/watermark.go

This file was deleted.

Loading

0 comments on commit e4ff429

Please sign in to comment.