From 3d7b7160e59e51b7aa9d91f9caf48e3f703129f0 Mon Sep 17 00:00:00 2001 From: Muhamad Azamy Date: Fri, 31 Jan 2020 16:59:06 +0200 Subject: [PATCH 1/2] Add support to secret env vars for containers --- .../tfgrid_reservation_container_1.go | 2 ++ pkg/provision/container.go | 12 +++++++ pkg/provision/kubernetes.go | 2 +- pkg/provision/zdb.go | 19 +--------- tools/tfuser/cmds_provision.go | 35 ++++++++++++++++--- 5 files changed, 46 insertions(+), 24 deletions(-) diff --git a/pkg/gedis/types/provision/tfgrid_reservation_container_1.go b/pkg/gedis/types/provision/tfgrid_reservation_container_1.go index 1aab7bc5f..9bae4cf37 100644 --- a/pkg/gedis/types/provision/tfgrid_reservation_container_1.go +++ b/pkg/gedis/types/provision/tfgrid_reservation_container_1.go @@ -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"` @@ -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)), diff --git a/pkg/provision/container.go b/pkg/provision/container.go index 320841ea2..30021a6b1 100644 --- a/pkg/provision/container.go +++ b/pkg/provision/container.go @@ -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 @@ -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 { diff --git a/pkg/provision/kubernetes.go b/pkg/provision/kubernetes.go index ad8ed1084..da5526531 100644 --- a/pkg/provision/kubernetes.go +++ b/pkg/provision/kubernetes.go @@ -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") } diff --git a/pkg/provision/zdb.go b/pkg/provision/zdb.go index 9d5e028b5..f39d07556 100644 --- a/pkg/provision/zdb.go +++ b/pkg/provision/zdb.go @@ -2,7 +2,6 @@ package provision import ( "context" - "encoding/hex" "encoding/json" "fmt" "net" @@ -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" @@ -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) @@ -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") } diff --git a/tools/tfuser/cmds_provision.go b/tools/tfuser/cmds_provision.go index 207c1bae9..f907fa122 100644 --- a/tools/tfuser/cmds_provision.go +++ b/tools/tfuser/cmds_provision.go @@ -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 } @@ -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 } @@ -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 } @@ -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, } ) From 6125b69724dad6e5a4dec7a42babbf5a647da752 Mon Sep 17 00:00:00 2001 From: Muhamad Azamy Date: Wed, 5 Feb 2020 10:38:35 +0200 Subject: [PATCH 2/2] Add missing file --- pkg/provision/crypt.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 pkg/provision/crypt.go diff --git a/pkg/provision/crypt.go b/pkg/provision/crypt.go new file mode 100644 index 000000000..bd4c78d52 --- /dev/null +++ b/pkg/provision/crypt.go @@ -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 +}