Home > Software engineering >  Pass sensitive data as argument using docker in Golang
Pass sensitive data as argument using docker in Golang

Time:07-12

I have created a program in Go which receives to arguments, project_id and private_token. Basically that is how I do it:

project_id := flag.String("project", "", "The id of the project")
private_token := flag.String("pat", "", "The personal access token with api and read user permissions")
flag.Parse()

I have created the following docker image:

FROM golang:1.16-alpine

WORKDIR /app

COPY . /app

RUN go build

ENV PROJECT=""
ENV PRIVATE_TOKEN=""

ENTRYPOINT "./my-program" "-project" $PROJECT "-pat" $PRIVATE_TOKEN

I run the image by running:

docker run -e PROJECT=29065042 -e PRIVATE_TOKEN="glpat-1CHf9T8Nz98W8ZzyT7V4" --rm -it my-image-name

As you can see, I'm passing a private token, which is a sensitive data. I wanted to know if this is the best approach of passing sensitive data from docker to my go program or if there is a better pattern?

CodePudding user response:

There are different ways to store and use sensitive data inside your Go application with docker. Every method has its pros and cons.

1. Hard-code the secrets inside the code.(never do this)

const (
    PROJECT_NAME = "MyProject"
    PRIVATE_TOKEN="kjdnioqvnocw"

)

  • Pros: None. Never do this.
  • Cons: Developers will see your production secrets as part of their regular work. Your secrets will be checked into source control. Both are security risks. Also, you have to modify the code to use it in different environments, like dev, test, and production.

2. Put secrets in environment variables, loaded from a .env file. There is two package to use .env file easily , godotenv and viper , I prefer godotenv beacuse it's much easier .

  • Pros: Developers won't see your production secrets. You can use different secrets in dev, test, and production, without having to modify the code.
  • Cons: Malicious code can read your secrets. The bulk of your application's code is probably open-source libraries. Bad code may creep in without you knowing it.

3. Put secrets in a dedicated secret manager, like Vault by HashiCorp , Secret Manager by Google Cloud. Parameter Store by AWS , Azure Key Vault from Azure

  • Pros: It's harder for malicious code to read your secrets. You get auditing of who accessed secrets when. You can assign fine-grained roles for who updates secrets and who can read them. You can update and version your secrets.
  • Cons: It's additional technology that you have learn. It may be an additional piece of software that you need to set up and manage, unless it's included in the cloud platform you're using.

So the choice is really between items 2 and 3 above. Which one you pick will depend on how sensitive your secrets are and how much extra work it would be to use a dedicated secret manager. For example, if your project is running on Google Cloud Platform, the Secret Manager is just one API call away. It may be just as easy on the other major cloud platforms, but I don't have first-hand experience with them.

CodePudding user response:

ENTRYPOINT "./my-program" "-project" $PROJECT "-pat" $PRIVATE_TOKEN is an independent shell and cannot share variables from previous Dokerfile lines, this is a tradeoff of using Dockerfiles.

I would like to suggest to modify ./my-program to read a config-file like kubectl does. There is a good Viper package that helps to achieve this approach.

ie: ENTRYPOINT "./my-program" "--config-file" "config.yaml"

You should save all the secrets in the config.yaml before ENTRYPOINT

References: https://github.com/spf13/viper

  • Related