Explorar o código

add support for setting secret from env variable

Signed-off-by: Nicolas De Loof <[email protected]>
Nicolas De Loof %!s(int64=3) %!d(string=hai) anos
pai
achega
005fc25823

+ 2 - 0
pkg/compose/convergence.go

@@ -523,6 +523,8 @@ func (s *composeService) createMobyContainer(ctx context.Context, project *types
 			return created, err
 		}
 	}
+
+	err = s.injectSecrets(ctx, project, service, created.ID)
 	return created, err
 }
 

+ 4 - 0
pkg/compose/create.go

@@ -889,6 +889,10 @@ func buildContainerSecretMounts(p types.Project, s types.ServiceConfig) ([]mount
 			return nil, fmt.Errorf("unsupported external secret %s", definedSecret.Name)
 		}
 
+		if definedSecret.Environment != "" {
+			continue
+		}
+
 		mount, err := buildMount(p, types.ServiceVolumeConfig{
 			Type:     types.VolumeTypeBind,
 			Source:   definedSecret.File,

+ 88 - 0
pkg/compose/secrets.go

@@ -0,0 +1,88 @@
+/*
+   Copyright 2020 Docker Compose CLI authors
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package compose
+
+import (
+	"archive/tar"
+	"bytes"
+	"context"
+	"fmt"
+	"time"
+
+	"github.com/compose-spec/compose-go/types"
+	moby "github.com/docker/docker/api/types"
+)
+
+func (s *composeService) injectSecrets(ctx context.Context, project *types.Project, service types.ServiceConfig, id string) error {
+	for _, config := range service.Secrets {
+		secret := project.Secrets[config.Source]
+		if secret.Environment == "" {
+			continue
+		}
+
+		env, ok := project.Environment[secret.Environment]
+		if !ok {
+			return fmt.Errorf("environment variable %q required by secret %q is not set", secret.Environment, secret.Name)
+		}
+		b, err := createTar(env, config)
+		if err != nil {
+			return err
+		}
+
+		err = s.apiClient().CopyToContainer(ctx, id, "/", &b, moby.CopyToContainerOptions{
+			CopyUIDGID: true,
+		})
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func createTar(env string, config types.ServiceSecretConfig) (bytes.Buffer, error) {
+	value := []byte(env)
+	b := bytes.Buffer{}
+	tarWriter := tar.NewWriter(&b)
+	mode := uint32(0400)
+	if config.Mode != nil {
+		mode = *config.Mode
+	}
+
+	target := config.Target
+	if config.Target == "" {
+		target = "/run/secrets/" + config.Source
+	} else if !isUnixAbs(config.Target) {
+		target = "/run/secrets/" + config.Target
+	}
+
+	header := &tar.Header{
+		Name:    target,
+		Size:    int64(len(value)),
+		Mode:    int64(mode),
+		ModTime: time.Now(),
+	}
+	err := tarWriter.WriteHeader(header)
+	if err != nil {
+		return bytes.Buffer{}, err
+	}
+	_, err = tarWriter.Write(value)
+	if err != nil {
+		return bytes.Buffer{}, err
+	}
+	err = tarWriter.Close()
+	return b, err
+}

+ 11 - 0
pkg/e2e/fixtures/env-secret/compose.yaml

@@ -0,0 +1,11 @@
+services:
+  foo:
+    image: alpine
+    secrets:
+      - bar
+    command: cat /run/secrets/bar
+
+secrets:
+  bar:
+    environment: SECRET
+

+ 35 - 0
pkg/e2e/secrets_test.go

@@ -0,0 +1,35 @@
+/*
+   Copyright 2020 Docker Compose CLI authors
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package e2e
+
+import (
+	"testing"
+
+	"gotest.tools/v3/icmd"
+)
+
+func TestSecretFromEnv(t *testing.T) {
+	c := NewParallelE2eCLI(t, binDir)
+
+	t.Run("compose run", func(t *testing.T) {
+		res := icmd.RunCmd(c.NewDockerCmd("compose", "-f", "./fixtures/env-secret/compose.yaml", "run", "foo"),
+			func(cmd *icmd.Cmd) {
+				cmd.Env = append(cmd.Env, "SECRET=BAR")
+			})
+		res.Assert(t, icmd.Expected{Out: "BAR"})
+	})
+}