Azure / kubernetes-keyvault-flexvol

Azure keyvault integration with Kubernetes via a Flex Volume
MIT License
253 stars 83 forks source link

Run containers as non-root #144

Closed muellermatthias closed 4 years ago

muellermatthias commented 4 years ago

Describe the request Running containers in Kubernetes as root can be a security issue and should be avoided if possible (see https://kubernetes.io/blog/2018/07/18/11-ways-not-to-get-hacked/#8-run-containers-as-a-non-root-user). It should be possible to run the containers used for the Key Vault FlexVolume as non-root.

Explain why Key Vault FlexVolume needs it Key Vault FlexVolume would be more secure and it will also help some users of this project to meet their compliance.

Describe the solution you'd like The image should be changed so that the container will run as non-root by default.

This can be achieved by using a distroless image and adding USER 65532 to the Dockerfile.

Describe alternatives you've considered It's also possible to create a user in the Dockerfile and give him the required permissions to run the application.

Additional context

i7c commented 4 years ago

Hi,

I’ve rewritten the install.sh script in go and it seems to work with a distroless image then

package main

import "fmt"
import "io"
import "os"
import "time"

func main() {
    target_dir := os.Getenv("TARGET_DIR")
    if target_dir == "" {
        fmt.Fprintf(os.Stderr, "Error: TARGET_DIR is not set\n")
        os.Exit(1)
    }
    kv_vol_dir := fmt.Sprintf("%s/azure~kv", target_dir)

    os.MkdirAll(kv_vol_dir, os.ModePerm)

    target_kv := fmt.Sprintf("%s/kv", kv_vol_dir)
    target_flexvol := fmt.Sprintf("%s/azurekeyvault-flexvolume", kv_vol_dir)
    copy("/bin/kv", target_kv)
    copy("/bin/azurekeyvault-flexvolume", target_flexvol)
    os.Chmod(target_kv, 0777)
    os.Chmod(target_flexvol, 0777)

    for {
        fmt.Printf("install done, daemonset sleeping\n")
        time.Sleep(60 * time.Second)
    }
}

func copy(src string, dst string) {
    source, err := os.Open(src)
    if err != nil {
        fmt.Fprintf(os.Stderr, "Error: could not open file.")
        os.Exit(2)
    }
    defer source.Close()

    destination, err := os.Create(dst)
    if err != nil {
        fmt.Fprintf(os.Stderr, "Error: could not write file.")
        os.Exit(2)
    }
    defer destination.Close()
    io.Copy(destination, source)
}
FROM gcr.io/distroless/static

WORKDIR /bin

ADD ./kv /bin/kv
ADD ./azurekeyvault-flexvolume /bin/azurekeyvault-flexvolume
ADD ./install_kv /bin/install_kv

ENTRYPOINT ["/bin/install_kv"] 

Test it with:

docker build -t banana .
docker run -e TARGET_DIR=/tmp/x -v /tmp/somedir:/tmp/x -u 1001  banana:latest

And it seems to work: the files appear on the host in /tmp/somedir

Would you be interested in merging something like this? Then I can try to integrate this in your CI configuration and create a PR.

Cheers, Constantin

muellermatthias commented 4 years ago

Running the container as non-root doesn't seem to be possible at the moment as root-access is needed to copy the binaries to the host, see https://github.com/kubernetes/community/issues/4171#issuecomment-547182573