Skip to content

Commit f05208b

Browse files
author
Muhamad Azmy
authored
Encrypt zdb password (#481)
* Encrypt zdb password * Fix tests * Encrypt password on provision * use hex encoding * fix tests again
1 parent 6d4f04f commit f05208b

File tree

4 files changed

+93
-6
lines changed

4 files changed

+93
-6
lines changed

pkg/provision/zdb.go

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package provision
22

33
import (
44
"context"
5+
"encoding/hex"
56
"encoding/json"
67
"fmt"
78
"net"
@@ -11,6 +12,7 @@ import (
1112
"time"
1213

1314
"github.com/cenkalti/backoff/v3"
15+
"github.com/threefoldtech/zbus"
1416
"github.com/threefoldtech/zos/pkg/network/ifaceutil"
1517
"github.com/threefoldtech/zos/pkg/zdb"
1618

@@ -35,6 +37,8 @@ type ZDB struct {
3537
Password string `json:"password"`
3638
DiskType pkg.DeviceType `json:"disk_type"`
3739
Public bool `json:"public"`
40+
41+
PlainPassword string `json:"-"`
3842
}
3943

4044
// ZDBResult is the information return to the BCDB
@@ -49,6 +53,21 @@ func zdbProvision(ctx context.Context, reservation *Reservation) (interface{}, e
4953
return zdbProvisionImpl(ctx, reservation)
5054
}
5155

56+
func decryptPassword(client zbus.Client, password string) (string, error) {
57+
if len(password) == 0 {
58+
return "", nil
59+
}
60+
identitry := stubs.NewIdentityManagerStub(client)
61+
62+
bytes, err := hex.DecodeString(password)
63+
if err != nil {
64+
return "", err
65+
}
66+
67+
out, err := identitry.Decrypt(bytes)
68+
return string(out), err
69+
}
70+
5271
func zdbProvisionImpl(ctx context.Context, reservation *Reservation) (ZDBResult, error) {
5372
var (
5473
client = GetZBus(ctx)
@@ -62,6 +81,12 @@ func zdbProvisionImpl(ctx context.Context, reservation *Reservation) (ZDBResult,
6281
return ZDBResult{}, errors.Wrap(err, "failed to decode reservation schema")
6382
}
6483

84+
var err error
85+
config.PlainPassword, err = decryptPassword(client, config.Password)
86+
if err != nil {
87+
return ZDBResult{}, errors.Wrap(err, "failed to decrypt namespace password")
88+
}
89+
6590
// if we reached here, we need to create the 0-db namespace
6691
log.Debug().Msg("allocating storage for namespace")
6792
allocation, err := storage.Allocate(nsID, config.DiskType, config.Size*gigabyte, config.Mode)
@@ -271,8 +296,8 @@ func createZDBNamespace(containerID pkg.ContainerID, nsID string, config ZDB) er
271296
}
272297
}
273298

274-
if config.Password != "" {
275-
if err := zdbCl.NamespaceSetPassword(nsID, config.Password); err != nil {
299+
if config.PlainPassword != "" {
300+
if err := zdbCl.NamespaceSetPassword(nsID, config.PlainPassword); err != nil {
276301
return errors.Wrapf(err, "failed to set password namespace %s in 0-db: %s", nsID, containerID)
277302
}
278303
}

pkg/provision/zdb_test.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package provision
22

33
import (
44
"context"
5+
"encoding/hex"
56
"fmt"
67
"net"
78
"strings"
@@ -56,10 +57,11 @@ func TestZDBProvision(t *testing.T) {
5657
ctx := context.Background()
5758
ctx = WithZBus(ctx, &client)
5859

60+
passwd := "pa$$w0rd"
5961
conf := ZDB{
6062
Size: 280682,
6163
Mode: pkg.ZDBModeSeq,
62-
Password: "pa$$w0rd",
64+
Password: hex.EncodeToString([]byte(passwd)),
6365
DiskType: pkg.SSDDevice,
6466
Public: true,
6567
}
@@ -98,14 +100,18 @@ func TestZDBProvision(t *testing.T) {
98100
},
99101
}, nil)
100102

103+
client.On("Request", "identityd", zbus.ObjectID{Name: "manager", Version: "0.0.1"},
104+
"Decrypt", []byte(passwd)).
105+
Return("password", nil)
106+
101107
client.On("Request", "network", zbus.ObjectID{Name: "network", Version: "0.0.1"},
102108
"Addrs",
103109
"zdb0", "net-ns").Return([]net.IP{net.ParseIP("2001:cdba::3257:9652")}, nil)
104110

105111
var zdbClient zdbTestClient
106112
zdbClient.On("Exist", reservation.ID).Return(false, nil)
107113
zdbClient.On("CreateNamespace", reservation.ID).Return(nil)
108-
zdbClient.On("NamespaceSetPassword", reservation.ID, conf.Password).Return(nil)
114+
zdbClient.On("NamespaceSetPassword", reservation.ID, "password").Return(nil)
109115
zdbClient.On("NamespaceSetPublic", reservation.ID, conf.Public).Return(nil)
110116
zdbClient.On("NamespaceSetSize", reservation.ID, conf.Size*gigabyte).Return(nil)
111117

@@ -128,10 +134,11 @@ func TestZDBProvisionNoMappingContainerDoesNotExists(t *testing.T) {
128134
ctx := context.Background()
129135
ctx = WithZBus(ctx, &client)
130136

137+
passwd := "pa$$w0rd"
131138
zdb := ZDB{
132139
Size: 10,
133140
Mode: pkg.ZDBModeSeq,
134-
Password: "pa$$w0rd",
141+
Password: hex.EncodeToString([]byte(passwd)),
135142
DiskType: pkg.SSDDevice,
136143
Public: true,
137144
}
@@ -148,6 +155,10 @@ func TestZDBProvisionNoMappingContainerDoesNotExists(t *testing.T) {
148155
// it's followed by allocation request to see if there is already a
149156
// zdb instance running that has enough space for the ns
150157

158+
client.On("Request", "identityd", zbus.ObjectID{Name: "manager", Version: "0.0.1"},
159+
"Decrypt", []byte(passwd)).
160+
Return("password", nil)
161+
151162
client.On("Request", "storage", zbus.ObjectID{Name: "storage", Version: "0.0.1"},
152163
"Allocate",
153164
reservation.ID, zdb.DiskType, zdb.Size*gigabyte, zdb.Mode,

tools/tfuser/cmds_provision.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package main
22

33
import (
4+
"encoding/hex"
45
"encoding/json"
56
"fmt"
67
"io/ioutil"
@@ -9,6 +10,8 @@ import (
910
"time"
1011

1112
"github.com/pkg/errors"
13+
"github.com/threefoldtech/zos/pkg"
14+
"github.com/threefoldtech/zos/pkg/crypto"
1215
"github.com/threefoldtech/zos/pkg/identity"
1316
"github.com/threefoldtech/zos/pkg/provision"
1417

@@ -20,6 +23,43 @@ var (
2023
defaultDuration = day * 30
2124
)
2225

26+
func encryptPassword(password, nodeID string) (string, error) {
27+
if len(password) == 0 {
28+
return "", nil
29+
}
30+
31+
pubkey, err := crypto.KeyFromID(pkg.StrIdentifier(nodeID))
32+
if err != nil {
33+
return "", err
34+
}
35+
36+
encrypted, err := crypto.Encrypt([]byte(password), pubkey)
37+
return hex.EncodeToString(encrypted), err
38+
}
39+
40+
func provisionCustomZDB(r *provision.Reservation) error {
41+
var config provision.ZDB
42+
if err := json.Unmarshal(r.Data, &config); err != nil {
43+
return errors.Wrap(err, "failed to load zdb reservation schema")
44+
}
45+
46+
encrypted, err := encryptPassword(config.Password, r.NodeID)
47+
if err != nil {
48+
return err
49+
}
50+
51+
config.Password = encrypted
52+
r.Data, err = json.Marshal(config)
53+
54+
return err
55+
}
56+
57+
var (
58+
provCustomModifiers = map[provision.ReservationType]func(r *provision.Reservation) error{
59+
provision.ZDBReservation: provisionCustomZDB,
60+
}
61+
)
62+
2363
func cmdsProvision(c *cli.Context) error {
2464
var (
2565
schema []byte
@@ -66,6 +106,13 @@ func cmdsProvision(c *cli.Context) error {
66106
for _, nodeID := range nodeIDs {
67107
r.NodeID = nodeID
68108

109+
custom, ok := provCustomModifiers[r.Type]
110+
if ok {
111+
if err := custom(r); err != nil {
112+
return err
113+
}
114+
}
115+
69116
if err := r.Sign(keypair.PrivateKey); err != nil {
70117
return errors.Wrap(err, "failed to sign the reservation")
71118
}

tools/tfuser/main.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ func main() {
7676
Flags: []cli.Flag{
7777
cli.StringFlag{
7878
Name: "schema,s",
79-
Usage: `location of the generated schema.
79+
Usage: `location of the generated schema.
8080
For the network sub-commands add-node and add-user this flag is
8181
also used to read the network schema before modifying it`,
8282
},
@@ -253,6 +253,10 @@ func main() {
253253
Name: "password, p",
254254
Usage: "optional password",
255255
},
256+
cli.StringFlag{
257+
Name: "node, n",
258+
Usage: "node ID. Required if password is set to encrypt the password",
259+
},
256260
cli.BoolFlag{
257261
Name: "public",
258262
Usage: "TODO",

0 commit comments

Comments
 (0)