Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support to secret env vars for containers #502

Merged
merged 3 commits into from
Feb 11, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions pkg/gedis/types/provision/tfgrid_reservation_container_1.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type TfgridReservationContainer1 struct {
Flist string `json:"flist"`
HubURL string `json:"hub_url"`
Environment map[string]string `json:"environment"`
SecretEnvironment map[string]string `json:"secret_environment"`
Entrypoint string `json:"entrypoint"`
Interactive bool `json:"interactive"`
Volumes []TfgridReservationContainerMount1 `json:"volumes"`
Expand All @@ -27,6 +28,7 @@ func (c TfgridReservationContainer1) ToProvisionType() (provision.Container, str
FList: c.Flist,
FlistStorage: c.HubURL,
Env: c.Environment,
SecretEnv: c.SecretEnvironment,
Entrypoint: c.Entrypoint,
Interactive: c.Interactive,
Mounts: make([]provision.Mount, len(c.Volumes)),
Expand Down
12 changes: 12 additions & 0 deletions pkg/provision/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ type Container struct {
FlistStorage string `json:"flist_storage"`
// Env env variables to container in format
Env map[string]string `json:"env"`
// Env env variables to container that the value is encrypted
// with the node public key. the env will be exposed to plain
// text to the entrypoint.
SecretEnv map[string]string `json:"secret_env"`
// Entrypoint the process to start inside the container
Entrypoint string `json:"entrypoint"`
// Interactivity enable Core X as PID 1 on the container
Expand Down Expand Up @@ -110,6 +114,14 @@ func containerProvisionImpl(ctx context.Context, reservation *Reservation) (Cont
env = append(env, fmt.Sprintf("%s=%s", k, v))
}

for k, v := range config.SecretEnv {
v, err := decryptSecret(client, v)
if err != nil {
return ContainerResult{}, errors.Wrapf(err, "failed to decrypt secret env var '%s'", k)
}
env = append(env, fmt.Sprintf("%s=%s", k, v))
}

var mounts []pkg.MountInfo
for _, mount := range config.Mounts {

Expand Down
23 changes: 23 additions & 0 deletions pkg/provision/crypt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package provision

import (
"encoding/hex"

"github.com/threefoldtech/zbus"
"github.com/threefoldtech/zos/pkg/stubs"
)

func decryptSecret(client zbus.Client, secret string) (string, error) {
if len(secret) == 0 {
return "", nil
}
identity := stubs.NewIdentityManagerStub(client)

bytes, err := hex.DecodeString(secret)
if err != nil {
return "", err
}

out, err := identity.Decrypt(bytes)
return string(out), err
}
2 changes: 1 addition & 1 deletion pkg/provision/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func kubernetesProvisionImpl(ctx context.Context, reservation *Reservation) (res
result.ID = reservation.ID
result.IP = config.IP.String()

config.PlainClusterSecret, err = decryptPassword(client, config.ClusterSecret)
config.PlainClusterSecret, err = decryptSecret(client, config.ClusterSecret)
if err != nil {
return result, errors.Wrap(err, "failed to decrypt namespace password")
}
Expand Down
19 changes: 1 addition & 18 deletions pkg/provision/zdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package provision

import (
"context"
"encoding/hex"
"encoding/json"
"fmt"
"net"
Expand All @@ -12,7 +11,6 @@ import (
"time"

"github.com/cenkalti/backoff/v3"
"github.com/threefoldtech/zbus"
"github.com/threefoldtech/zos/pkg/network/ifaceutil"
"github.com/threefoldtech/zos/pkg/zdb"

Expand Down Expand Up @@ -53,21 +51,6 @@ func zdbProvision(ctx context.Context, reservation *Reservation) (interface{}, e
return zdbProvisionImpl(ctx, reservation)
}

func decryptPassword(client zbus.Client, password string) (string, error) {
if len(password) == 0 {
return "", nil
}
identity := stubs.NewIdentityManagerStub(client)

bytes, err := hex.DecodeString(password)
if err != nil {
return "", err
}

out, err := identity.Decrypt(bytes)
return string(out), err
}

func zdbProvisionImpl(ctx context.Context, reservation *Reservation) (ZDBResult, error) {
var (
client = GetZBus(ctx)
Expand All @@ -82,7 +65,7 @@ func zdbProvisionImpl(ctx context.Context, reservation *Reservation) (ZDBResult,
}

var err error
config.PlainPassword, err = decryptPassword(client, config.Password)
config.PlainPassword, err = decryptSecret(client, config.Password)
if err != nil {
return ZDBResult{}, errors.Wrap(err, "failed to decrypt namespace password")
}
Expand Down
35 changes: 30 additions & 5 deletions tools/tfuser/cmds_provision.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ var (
defaultDuration = day * 30
)

func encryptPassword(password, nodeID string) (string, error) {
if len(password) == 0 {
func encryptSecret(plain, nodeID string) (string, error) {
if len(plain) == 0 {
return "", nil
}

Expand All @@ -33,7 +33,7 @@ func encryptPassword(password, nodeID string) (string, error) {
return "", err
}

encrypted, err := crypto.Encrypt([]byte(password), pubkey)
encrypted, err := crypto.Encrypt([]byte(plain), pubkey)
return hex.EncodeToString(encrypted), err
}

Expand All @@ -43,7 +43,7 @@ func provisionCustomZDB(r *provision.Reservation) error {
return errors.Wrap(err, "failed to load zdb reservation schema")
}

encrypted, err := encryptPassword(config.Password, r.NodeID)
encrypted, err := encryptSecret(config.Password, r.NodeID)
if err != nil {
return err
}
Expand All @@ -54,9 +54,34 @@ func provisionCustomZDB(r *provision.Reservation) error {
return err
}

func provisionCustomContainer(r *provision.Reservation) error {
var config provision.Container
var err error
if err := json.Unmarshal(r.Data, &config); err != nil {
return errors.Wrap(err, "failed to load zdb reservation schema")
}

if config.SecretEnv == nil {
config.SecretEnv = make(map[string]string)
}

for k, v := range config.Env {
v, err := encryptSecret(v, r.NodeID)
if err != nil {
return errors.Wrapf(err, "failed to encrypt env with key '%s'", k)
}
config.SecretEnv[k] = v
}
config.Env = make(map[string]string)
r.Data, err = json.Marshal(config)

return err
}

var (
provCustomModifiers = map[provision.ReservationType]func(r *provision.Reservation) error{
provision.ZDBReservation: provisionCustomZDB,
provision.ZDBReservation: provisionCustomZDB,
provision.ContainerReservation: provisionCustomContainer,
}
)

Expand Down