Skip to content

Commit 6a3397a

Browse files
author
Sean Young
authored
Merge pull request #46 from gregdhill/conf-fixups
fixup config, secrets and add granting example
2 parents 2d6cc85 + acd0476 commit 6a3397a

File tree

13 files changed

+107
-68
lines changed

13 files changed

+107
-68
lines changed

Diff for: cmd/hoarctl/encryption.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,16 @@ import (
1313

1414
// Decrypt does what it says on the tin
1515
func (client *Client) Decrypt(cmd *cli.Cmd) {
16-
secretKey := addOpt(cmd, "key", secretOpt, "").(*string)
17-
salt := addOpt(cmd, "salt", saltOpt, "").(*string)
16+
secretKey := addStringOpt(cmd, "key", secretOpt)
17+
salt := addStringOpt(cmd, "salt", saltOpt)
1818

1919
cmd.Action = func() {
2020
encryptedData := readData()
2121
plaintext, err := client.encryption.Decrypt(context.Background(),
2222
&hoard.ReferenceAndCiphertext{
2323
Reference: &reference.Ref{
24-
SecretKey: readBase64(*secretKey),
25-
Salt: parseSalt(*salt),
24+
SecretKey: readBase64(secretKey),
25+
Salt: parseSalt(salt),
2626
},
2727
Ciphertext: &hoard.Ciphertext{
2828
EncryptedData: encryptedData,
@@ -37,7 +37,7 @@ func (client *Client) Decrypt(cmd *cli.Cmd) {
3737

3838
// Encrypt also does what it says on the tin
3939
func (client *Client) Encrypt(cmd *cli.Cmd) {
40-
salt := addOpt(cmd, "salt", saltOpt, "").(*string)
40+
salt := addStringOpt(cmd, "salt", saltOpt)
4141

4242
cmd.Action = func() {
4343
data, err := ioutil.ReadAll(os.Stdin)
@@ -47,7 +47,7 @@ func (client *Client) Encrypt(cmd *cli.Cmd) {
4747
refAndCiphertext, err := client.encryption.Encrypt(context.Background(),
4848
&hoard.Plaintext{
4949
Data: data,
50-
Salt: parseSalt(*salt),
50+
Salt: parseSalt(salt),
5151
})
5252
if err != nil {
5353
fatalf("Error encrypting: %v", err)
@@ -58,14 +58,14 @@ func (client *Client) Encrypt(cmd *cli.Cmd) {
5858

5959
// Ref encrypts as above, but then packages the data in a ref
6060
func (client *Client) Ref(cmd *cli.Cmd) {
61-
salt := addOpt(cmd, "salt", saltOpt, "").(*string)
61+
salt := addStringOpt(cmd, "salt", saltOpt)
6262

6363
cmd.Action = func() {
6464
data := readData()
6565
refAndCiphertext, err := client.encryption.Encrypt(context.Background(),
6666
&hoard.Plaintext{
6767
Data: data,
68-
Salt: parseSalt(*salt),
68+
Salt: parseSalt(salt),
6969
})
7070
if err != nil {
7171
fatalf("Error generating reference: %v", err)

Diff for: cmd/hoarctl/grants.go

+12-13
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,18 @@ import (
1212

1313
// PutSeal encrypts and stores data then prints a grant
1414
func (client *Client) PutSeal(cmd *cli.Cmd) {
15-
salt := addOpt(cmd, "salt", saltOpt, "").(*string)
16-
key := addOpt(cmd, "key", saltOpt, "").(*string)
15+
salt := addStringOpt(cmd, "salt", saltOpt)
16+
key := addStringOpt(cmd, "key", keyOpt)
1717

1818
cmd.Action = func() {
19-
2019
var seal *grant.Grant
2120
var err error
2221

2322
spec := grant.Spec{Plaintext: &grant.PlaintextSpec{}}
24-
if key != nil {
23+
if *key != "" {
2524
spec = grant.Spec{
2625
Plaintext: nil,
27-
Symmetric: &grant.SymmetricSpec{SecretID: string(parseSalt(*key))},
26+
Symmetric: &grant.SymmetricSpec{SecretID: *key},
2827
}
2928
}
3029

@@ -33,7 +32,7 @@ func (client *Client) PutSeal(cmd *cli.Cmd) {
3332
&hoard.PlaintextAndGrantSpec{
3433
Plaintext: &hoard.Plaintext{
3534
Data: data,
36-
Salt: parseSalt(*salt),
35+
Salt: parseSalt(salt),
3736
},
3837
GrantSpec: &spec,
3938
},
@@ -48,15 +47,15 @@ func (client *Client) PutSeal(cmd *cli.Cmd) {
4847

4948
// Seal reads encrypted data then prints a grant
5049
func (client *Client) Seal(cmd *cli.Cmd) {
51-
address := addOpt(cmd, "address", addrOpt, "").(*string)
52-
key := addOpt(cmd, "key", saltOpt, "").(*string)
50+
address := addStringOpt(cmd, "address", addrOpt)
51+
key := addStringOpt(cmd, "key", keyOpt)
5352

5453
cmd.Action = func() {
5554
spec := grant.Spec{Plaintext: &grant.PlaintextSpec{}}
56-
if key != nil {
55+
if *key != "" {
5756
spec = grant.Spec{
5857
Plaintext: nil,
59-
Symmetric: &grant.SymmetricSpec{SecretID: string(parseSalt(*key))},
58+
Symmetric: &grant.SymmetricSpec{SecretID: *key},
6059
}
6160
}
6261

@@ -77,16 +76,16 @@ func (client *Client) Seal(cmd *cli.Cmd) {
7776

7877
// Reseal reads a grant then prints a new grant
7978
func (client *Client) Reseal(cmd *cli.Cmd) {
80-
salt := addOpt(cmd, "salt", saltOpt, "").(*string)
79+
key := addStringOpt(cmd, "key", keyOpt)
8180

8281
cmd.Action = func() {
8382
prev := readGrant()
8483
next := grant.Spec{Plaintext: &grant.PlaintextSpec{}}
8584

86-
if salt != nil {
85+
if *key != "" {
8786
next = grant.Spec{
8887
Plaintext: nil,
89-
Symmetric: &grant.SymmetricSpec{SecretID: string(parseSalt(*salt))},
88+
Symmetric: &grant.SymmetricSpec{SecretID: *key},
9089
}
9190
}
9291

Diff for: cmd/hoarctl/main.go

+14-15
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ import (
2121
)
2222

2323
const (
24-
addrOpt string = "The address of the data to retrieve as base64-encoded string"
24+
addrOpt string = "The address of the data to retrieve as base64-encoded string."
25+
keyOpt string = "The ID of the symmetric secret to use."
2526
saltOpt string = "Token to use for encryption and decryption. " +
2627
"Will be parsed as base64 encoded string if this is possible, " +
2728
"otherwise will be interpreted as the bytes of the string itself."
@@ -92,26 +93,21 @@ func main() {
9293
}
9394

9495
// extra cli options
95-
func addOpt(cmd *cli.Cmd, arg, desc string, def interface{}) (opt interface{}) {
96-
switch d := def.(type) {
97-
case string:
98-
opt = cmd.StringOpt(fmt.Sprintf("%s %s", string(arg[0]), arg), d, desc)
99-
case bool:
100-
opt = cmd.BoolOpt(fmt.Sprintf("%s %s", string(arg[0]), arg), d, desc)
101-
}
96+
func addStringOpt(cmd *cli.Cmd, arg, desc string) *string {
97+
opt := cmd.StringOpt(fmt.Sprintf("%s %s", string(arg[0]), arg), "", desc)
10298
cmd.Spec += fmt.Sprintf("[-%s | --%s]", string(arg[0]), arg)
10399
return opt
104100
}
105101

106-
func parseSalt(saltString string) []byte {
107-
if saltString == "" {
102+
func parseSalt(saltString *string) []byte {
103+
if saltString == nil {
108104
return nil
109105
}
110-
saltBytes, err := base64.StdEncoding.DecodeString(saltString)
106+
saltBytes, err := base64.StdEncoding.DecodeString(*saltString)
111107
if err == nil {
112108
return saltBytes
113109
}
114-
return ([]byte)(saltString)
110+
return ([]byte)(*saltString)
115111
}
116112

117113
func jsonString(v interface{}) string {
@@ -134,7 +130,7 @@ func readData() []byte {
134130
func readReference(address *string) *reference.Ref {
135131
ref := new(reference.Ref)
136132
if address != nil && *address != "" {
137-
ref.Address = readBase64(*address)
133+
ref.Address = readBase64(address)
138134
return ref
139135
}
140136
err := parseObject(os.Stdin, ref)
@@ -165,8 +161,11 @@ func parseObject(r io.Reader, o interface{}) error {
165161
return nil
166162
}
167163

168-
func readBase64(base64String string) []byte {
169-
secretKeyBytes, err := base64.StdEncoding.DecodeString(base64String)
164+
func readBase64(base64String *string) []byte {
165+
if base64String == nil {
166+
return nil
167+
}
168+
secretKeyBytes, err := base64.StdEncoding.DecodeString(*base64String)
170169
if err != nil {
171170
fatalf("Could not decode '%s' as base64-encoded string", base64String)
172171
}

Diff for: cmd/hoarctl/store.go

+10-10
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212

1313
// Cat retrieves encrypted data from store
1414
func (client *Client) Cat(cmd *cli.Cmd) {
15-
address := addOpt(cmd, "address", addrOpt, "").(*string)
15+
address := addStringOpt(cmd, "address", addrOpt)
1616

1717
cmd.Action = func() {
1818
ref := readReference(address)
@@ -27,9 +27,9 @@ func (client *Client) Cat(cmd *cli.Cmd) {
2727

2828
// Get retrieves and decrypts data from store
2929
func (client *Client) Get(cmd *cli.Cmd) {
30-
address := addOpt(cmd, "address", addrOpt, "").(*string)
31-
secretKey := addOpt(cmd, "key", secretOpt, "").(*string)
32-
salt := addOpt(cmd, "salt", saltOpt, "").(*string)
30+
address := addStringOpt(cmd, "address", addrOpt)
31+
secretKey := addStringOpt(cmd, "key", secretOpt)
32+
salt := addStringOpt(cmd, "salt", saltOpt)
3333

3434
cmd.Action = func() {
3535
// If given address then try to read reference from arguments and option
@@ -39,9 +39,9 @@ func (client *Client) Get(cmd *cli.Cmd) {
3939
fatalf("A secret key must be provided in order to decrypt")
4040
}
4141
ref = &reference.Ref{
42-
Address: readBase64(*address),
43-
SecretKey: readBase64(*secretKey),
44-
Salt: parseSalt(*salt),
42+
Address: readBase64(address),
43+
SecretKey: readBase64(secretKey),
44+
Salt: parseSalt(salt),
4545
}
4646
}
4747
plaintext, err := client.cleartext.Get(context.Background(), ref)
@@ -68,14 +68,14 @@ func (client *Client) Insert(cmd *cli.Cmd) {
6868

6969
// Put encrypts data and stores it
7070
func (client *Client) Put(cmd *cli.Cmd) {
71-
salt := addOpt(cmd, "salt", saltOpt, "").(*string)
71+
salt := addStringOpt(cmd, "salt", saltOpt)
7272

7373
cmd.Action = func() {
7474
data := readData()
7575
ref, err := client.cleartext.Put(context.Background(),
7676
&hoard.Plaintext{
7777
Data: data,
78-
Salt: parseSalt(*salt),
78+
Salt: parseSalt(salt),
7979
})
8080
if err != nil {
8181
fatalf("Error storing data: %v", err)
@@ -86,7 +86,7 @@ func (client *Client) Put(cmd *cli.Cmd) {
8686

8787
// Stat retrieves info about the stored data
8888
func (client *Client) Stat(cmd *cli.Cmd) {
89-
address := addOpt(cmd, "address", addrOpt, "").(*string)
89+
address := addStringOpt(cmd, "address", addrOpt)
9090

9191
cmd.Action = func() {
9292
ref := readReference(address)

Diff for: cmd/hoard/main.go

-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ func main() {
6969
if *listenAddressOpt != "" {
7070
conf.ListenAddress = *listenAddressOpt
7171
}
72-
7372
symmetricProvider := secrets.ProviderFromConfig(conf.Secrets)
7473
openPGPConf := secrets.OpenPGPFromConfig(conf.Secrets)
7574
sm := secrets.Manager{Provider: symmetricProvider, OpenPGP: openPGPConf}

Diff for: config/logging/logging.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ const (
2121
Json LoggingType = "json"
2222
)
2323

24+
// LoggingConfig describes the channels to listen on,
25+
// messages not on these channels will be filtered
26+
// and leaving empty disables logging
2427
type LoggingConfig struct {
25-
// Channels to listen on, messages not on these channels will be filtered
26-
// leaving empty disables logging
2728
LoggingType LoggingType
2829
Channels []structure.Channel
2930
}

Diff for: config/secrets/secrets.go

+23-14
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
package secrets
22

3-
import "io/ioutil"
3+
import (
4+
"io/ioutil"
5+
)
46

7+
// SecretsConfig lists the configured secrets,
8+
// Symmetric secrets are those local to the running daemon
9+
// and OpenPGP identifies an entity in the given keyring
510
type SecretsConfig struct {
6-
Secrets []SymmetricSecret
7-
OpenPGP *OpenPGPSecret
11+
Symmetric []SymmetricSecret
12+
OpenPGP OpenPGPSecret
813
}
914

1015
type SymmetricSecret struct {
@@ -13,48 +18,52 @@ type SymmetricSecret struct {
1318
}
1419

1520
type OpenPGPSecret struct {
16-
ID uint64
21+
ID string
1722
File string
1823
Data []byte
1924
}
2025

21-
type SymmetricProvider func(secretID string) []byte
22-
2326
type Manager struct {
2427
Provider SymmetricProvider
2528
OpenPGP *OpenPGPSecret
2629
}
2730

28-
func NoopSymmetricProvider(_ string) []byte {
29-
return nil
30-
}
31+
type SymmetricProvider func(secretID string) []byte
3132

33+
// NoopSecretManager is an empty secret manager
3234
var NoopSecretManager = Manager{
3335
Provider: NoopSymmetricProvider,
3436
OpenPGP: nil,
3537
}
3638

39+
// NoopSymmetricProvider returns an empty provider
40+
func NoopSymmetricProvider(_ string) []byte {
41+
return nil
42+
}
43+
44+
// ProviderFromConfig creates a secret reader from a set of symmetric secrets
3745
func ProviderFromConfig(conf *SecretsConfig) SymmetricProvider {
38-
if conf == nil {
46+
if conf == nil || len(conf.Symmetric) == 0 {
3947
return NoopSymmetricProvider
4048
}
41-
secs := make(map[string][]byte, len(conf.Secrets))
42-
for _, s := range conf.Secrets {
49+
secs := make(map[string][]byte, len(conf.Symmetric))
50+
for _, s := range conf.Symmetric {
4351
secs[s.ID] = []byte(s.Passphrase)
4452
}
4553
return func(id string) []byte {
4654
return secs[id]
4755
}
4856
}
4957

58+
// OpenPGPFromConfig reads a given PGP keyring
5059
func OpenPGPFromConfig(conf *SecretsConfig) *OpenPGPSecret {
51-
if conf == nil {
60+
if conf == nil || conf.OpenPGP.File == "" {
5261
return nil
5362
}
5463
keyRing, err := ioutil.ReadFile(conf.OpenPGP.File)
5564
if err != nil {
5665
return nil
5766
}
5867
conf.OpenPGP.Data = keyRing
59-
return conf.OpenPGP
68+
return &conf.OpenPGP
6069
}

Diff for: config/storage/storage.go

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const (
2828
IPFS StorageType = "ipfs"
2929
)
3030

31+
// StorageConfig identifies the configured back-end
3132
type StorageConfig struct {
3233
// Acts a string enum
3334
StorageType StorageType

Diff for: docs/design/examples.md

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Examples
2+
3+
To configure hoard with a fully-functioning secret back-end use the following example config:
4+
5+
```toml
6+
ListenAddress = "tcp://:53431"
7+
8+
[Storage]
9+
StorageType = "memory"
10+
AddressEncoding = "base64"
11+
12+
[Logging]
13+
LoggingType = "json"
14+
Channels = ["info", "trace"]
15+
16+
[Secrets.OpenPGP]
17+
ID = "10449759736975846181"
18+
File = "${HOME}/go/src/github.com/monax/hoard/grant/private.key.asc"
19+
20+
[[Secrets.Symmetric]]
21+
ID = "test"
22+
Passphrase = "test"
23+
```
24+
25+
Remember to change the provided values before deploying to production.

0 commit comments

Comments
 (0)