From 57afb7514d5c123779601cae77d016bf6de8a5f1 Mon Sep 17 00:00:00 2001 From: umohnani8 Date: Thu, 19 Apr 2018 10:25:01 -0400 Subject: Add FIPS mode secret If the host is in FIPS mode and /etc/system-fips exists /run/secrets/system-fips is created in the container so that the container can run in FIPS mode as well. Signed-off-by: umohnani8 --- pkg/secrets/secrets.go | 81 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 7 deletions(-) (limited to 'pkg') diff --git a/pkg/secrets/secrets.go b/pkg/secrets/secrets.go index be825d906..9b328575b 100644 --- a/pkg/secrets/secrets.go +++ b/pkg/secrets/secrets.go @@ -2,7 +2,6 @@ package secrets import ( "bufio" - "fmt" "io/ioutil" "os" "path/filepath" @@ -127,9 +126,35 @@ func getMountsMap(path string) (string, string, error) { return "", "", errors.Errorf("unable to get host and container dir") } -// SecretMounts copies the contents of host directory to container directory +// SecretMounts copies, adds, and mounts the secrets to the container root filesystem +func SecretMounts(mountLabel, containerWorkingDir string) []rspec.Mount { + var secretMounts []rspec.Mount + // Add secrets from paths given in the mounts.conf files + for _, file := range []string{OverrideMountsFile, DefaultMountsFile} { + mounts, err := addSecretsFromMountsFile(file, mountLabel, containerWorkingDir) + if err != nil { + logrus.Warnf("error mounting secrets, skipping: %v", err) + } + secretMounts = append(secretMounts, mounts...) + } + + // Add FIPS mode secret if /etc/system-fips exists on the host + _, err := os.Stat("/etc/system-fips") + if err == nil { + if err := addFIPSsModeSecret(&secretMounts, containerWorkingDir); err != nil { + logrus.Warnf("error adding FIPS mode secret to container: %v", err) + } + } else if os.IsNotExist(err) { + logrus.Debug("/etc/system-fips does not exist on host, not mounting FIPS mode secret") + } else { + logrus.Errorf("error stating /etc/system-fips for FIPS mode secret: %v", err) + } + return secretMounts +} + +// addSecretsFromMountsFile copies the contents of host directory to container directory // and returns a list of mounts -func SecretMounts(filePath, mountLabel, containerWorkingDir string) ([]rspec.Mount, error) { +func addSecretsFromMountsFile(filePath, mountLabel, containerWorkingDir string) ([]rspec.Mount, error) { var mounts []rspec.Mount defaultMountsPaths := getMounts(filePath) for _, path := range defaultMountsPaths { @@ -144,15 +169,12 @@ func SecretMounts(filePath, mountLabel, containerWorkingDir string) ([]rspec.Mou } ctrDirOnHost := filepath.Join(containerWorkingDir, ctrDir) - if err = os.RemoveAll(ctrDirOnHost); err != nil { - return nil, fmt.Errorf("remove container directory failed: %v", err) - } // In the event of a restart, don't want to copy secrets over again as they already would exist in ctrDirOnHost _, err = os.Stat(ctrDirOnHost) if os.IsNotExist(err) { if err = os.MkdirAll(ctrDirOnHost, 0755); err != nil { - return nil, fmt.Errorf("making container directory failed: %v", err) + return nil, errors.Wrapf(err, "making container directory failed") } hostDir, err = resolveSymbolicLink(hostDir) @@ -190,6 +212,51 @@ func SecretMounts(filePath, mountLabel, containerWorkingDir string) ([]rspec.Mou return mounts, nil } +// addFIPSModeSecret creates /run/secrets/system-fips in the container +// root filesystem if /etc/system-fips exists on hosts. +// This enables the container to be FIPS compliant and run openssl in +// FIPS mode as the host is also in FIPS mode. +func addFIPSsModeSecret(mounts *[]rspec.Mount, containerWorkingDir string) error { + secretsDir := "/run/secrets" + ctrDirOnHost := filepath.Join(containerWorkingDir, secretsDir) + if _, err := os.Stat(ctrDirOnHost); os.IsNotExist(err) { + if err = os.MkdirAll(ctrDirOnHost, 0755); err != nil { + return errors.Wrapf(err, "making container directory on host failed") + } + } + fipsFile := filepath.Join(ctrDirOnHost, "system-fips") + // In the event of restart, it is possible for the FIPS mode file to already exist + if _, err := os.Stat(fipsFile); os.IsNotExist(err) { + file, err := os.Create(fipsFile) + if err != nil { + return errors.Wrapf(err, "error creating system-fips file in container for FIPS mode") + } + defer file.Close() + } + + if !mountExists(*mounts, secretsDir) { + m := rspec.Mount{ + Source: ctrDirOnHost, + Destination: secretsDir, + Type: "bind", + Options: []string{"bind"}, + } + *mounts = append(*mounts, m) + } + + return nil +} + +// mountExists checks if a mount already exists in the spec +func mountExists(mounts []rspec.Mount, dest string) bool { + for _, mount := range mounts { + if mount.Destination == dest { + return true + } + } + return false +} + // resolveSymbolicLink resolves a possbile symlink path. If the path is a symlink, returns resolved // path; if not, returns the original path. func resolveSymbolicLink(path string) (string, error) { -- cgit v1.2.3-54-g00ecf