Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add "build.secrets" field to devcontainer.json #4841

Open
NathanDeMaria opened this issue Apr 6, 2021 · 23 comments
Open

Add "build.secrets" field to devcontainer.json #4841

NathanDeMaria opened this issue Apr 6, 2021 · 23 comments
Assignees
Labels
containers Issue in vscode-remote containers under-discussion Issue is under discussion for relevance, priority, approach

Comments

@NathanDeMaria
Copy link

I'd like a way to use build secrets BuildKit's --secret in remote containers. Seemingly straightforward implementation: add a field for secrets underneath build in devcontainer.json (list of strings), and map each entry in that list to a --secret arg whenever the docker build command gets created

This is related to #1409, but that's not required (if users have some other way to make sure they're using BuildKit, this feature could be independently useful).

@github-actions github-actions bot added the containers Issue in vscode-remote containers label Apr 7, 2021
@PavelSosin-320
Copy link

I would like to support it but with one reservation: if the devcontainer.json will be published in a repository secret will be available in the boilerplate form unlike in the Docker image. Their secrets are encoded. It is a problem with buildkit too. Other Image builders prefer to attach secrets to containers in a very tricky way, as separate artifacts, to separate them from the published code.

@NathanDeMaria
Copy link
Author

I don't think I'm following. If somebody wants devcontainer.json published to the repository, they can use the src argument to point to a file containing the secret, and then include the secret file in their .gitignore. So only the name of the file containing the secret is published, not the value

@chrmarti chrmarti added the under-discussion Issue is under discussion for relevance, priority, approach label Apr 8, 2021
@chrmarti chrmarti self-assigned this Apr 8, 2021
@PavelSosin-320
Copy link

I'm testing Podman 3.1 on WSL and found that the implementation of such a feature is feasible and even easy. Podman, unlike Docker supports secrets out-of-the-box with no pre-requisites like builglit or swarm.
1st, I created rsa key in the regular way in my Windows Home directory:
ls /mnt/c/Users/Pavel/idrsa
/mnt/c/Users/Pavel/id_rsa

Then I created The myidRsa artifact using podman secret create MyidRsa /mnt/c/Users/Pavel/id_rsa
Then I run UBI ubuntu image passing the secret to the container podman run -it --secret MyidRsa ubuntu
and finally, I got my secret available inside the container:
ls /run/secrets
MyidRsa

The secret is stored as
podman secret inspect MyidRsa
[
{
"ID": "d6079304f365d8a66913df6a5",
"CreatedAt": "2021-04-22T09:33:09.1095971+03:00",
"UpdatedAt": "2021-04-22T09:33:09.1095971+03:00",
"Spec": {
"Name": "MyidRsa",
"Driver": {
"Name": "file",
"Options": null
}
}
}
]
using file driver.
Podman's secret implementation is not fully secure unless its storage root is not bitlocked but very convenient. On another hand my original secret file doesn't move to any place and not published to the git repository because it is not inside my development workspace.
It will be a great, very useful feature!

@pspelman
Copy link

I don't think I'm following. If somebody wants devcontainer.json published to the repository, they can use the src argument to point to a file containing the secret, and then include the secret file in their .gitignore. So only the name of the file containing the secret is published, not the value

@NathanDeMaria Could you give an example of what this might look like?

@tevansuk
Copy link

I can give an example:

  • Our private python packages are stored in Artifactory, and we use Artifactory as the sole package resource
  • As developers, we run a custom tool to authenticate and generate temporary oauth tokens that allow us to access them that we store in a temporary file.
  • We use buildkit secrets to inject those credentials in to the docker build so that we can access Artifactory

Eg, for a project using poetry:

# run the tool and generate a temporary `.netrc` style file
docker build . --secret id=netrc,src=$$NETRC
# In Dockerfile..
RUN --mount=type=secret,id=netrc,dst=/app/.netrc NETRC=/app/.netrc poetry install --no-interaction

This is also how we inject creds in our CI pipeline, so we're not looking to change our build process to accommodate editor nuances, as this way leaves no trace of the credentials in the docker image (as opposed to passing them as ARG or environment variables.)

We can already generate the temporary credentials file and remove it with the initializeCommand and postCreateCommand options, but currently no way to enable buildkit and pass secrets, so for now we can only create images outside of vscode.

To be honest, a more flexible approach would not be to add build.secrets, but to allow us to specify buildCommand, buildArgs and buildEnv. Otherwise, you're constantly chasing whatever features are added to docker.

@pachchigarsnehi
Copy link

I can give an example:

  • Our private python packages are stored in Artifactory, and we use Artifactory as the sole package resource
  • As developers, we run a custom tool to authenticate and generate temporary oauth tokens that allow us to access them that we store in a temporary file.
  • We use buildkit secrets to inject those credentials in to the docker build so that we can access Artifactory

Eg, for a project using poetry:

# run the tool and generate a temporary `.netrc` style file
docker build . --secret id=netrc,src=$$NETRC
# In Dockerfile..
RUN --mount=type=secret,id=netrc,dst=/app/.netrc NETRC=/app/.netrc poetry install --no-interaction

This is also how we inject creds in our CI pipeline, so we're not looking to change our build process to accommodate editor nuances, as this way leaves no trace of the credentials in the docker image (as opposed to passing them as ARG or environment variables.)

We can already generate the temporary credentials file and remove it with the initializeCommand and postCreateCommand options, but currently no way to enable buildkit and pass secrets, so for now we can only create images outside of vscode.

To be honest, a more flexible approach would not be to add build.secrets, but to allow us to specify buildCommand, buildArgs and buildEnv. Otherwise, you're constantly chasing whatever features are added to docker.

I am trying to achieve something similar in one of my use cases of making codespaces usable for my team.
My use case is to have a built container with the packages being stored in Artifactory and tokens are to be set in the .condarc for authentication.
For the same I am using Dockerfile to prepare a conda environment which will have these packages, but having trouble with environment variables to authenticate to the Artifactory

Can you please give an idea of if you are generating the tokens on fly in the initializeCommand or are you fetching it from somewhere?

I tried adding secrets in codespaces secret in my user account. They are available in terminal but if I pass them as docker args, they arent available.
Any thoughts would be appreciated!

@tevansuk
Copy link

This is slightly orthogonal to the actual problem here, but we are generating the tokens on the fly in initializeCommand.

We have a custom in house tool that authenticates to JFrog via SAML. The tool prompts users on the command line for username/password/2fa that allows them to authenticate to an on-prem Shibboleth Identity Provider. Once authenticated to JFrog, it uses their token service to generate a temporary access token.

In vscode, I believe that prompt appears in the console.

We are using containers, we aren't using codespaces, if that makes a difference. I'm not sure that it would, initializeCommand runs on the local machine, not the remote.

@bueti
Copy link

bueti commented Jan 11, 2022

did anybody manage to get --secrets working?

@markuskreitzer
Copy link

I can give an example:

* Our private python packages are stored in Artifactory, and we use Artifactory as the sole package resource

* As developers, we run a custom tool to authenticate and generate temporary oauth tokens that allow us to access them that we store in a temporary file.

* We use buildkit secrets to inject those credentials in to the docker build so that we can access Artifactory

Eg, for a project using poetry:

# run the tool and generate a temporary `.netrc` style file
docker build . --secret id=netrc,src=$$NETRC
# In Dockerfile..
RUN --mount=type=secret,id=netrc,dst=/app/.netrc NETRC=/app/.netrc poetry install --no-interaction

This is also how we inject creds in our CI pipeline, so we're not looking to change our build process to accommodate editor nuances, as this way leaves no trace of the credentials in the docker image (as opposed to passing them as ARG or environment variables.)

We can already generate the temporary credentials file and remove it with the initializeCommand and postCreateCommand options, but currently no way to enable buildkit and pass secrets, so for now we can only create images outside of vscode.

To be honest, a more flexible approach would not be to add build.secrets, but to allow us to specify buildCommand, buildArgs and buildEnv. Otherwise, you're constantly chasing whatever features are added to docker.

We have the exact same workflow with Gitlab and need a solution.

@DougPlumley
Copy link

We're in the same situation, we use buildkit to inject secrets for private Python packages, having a different build process just for running containers locally isn't ideal.

@blacktaxi
Copy link

Would be great to have working support for --secrets. Dev containers are amazing otherwise. Added support for custom build args would be sufficient in my case. Thanks.

@DougPlumley
Copy link

@blacktaxi I ended up using "runArgs" in the devcontainer.json file, it seems to be working well so far.

https://code.visualstudio.com/docs/remote/devcontainerjson-reference

@blacktaxi
Copy link

That's great, thanks for sharing @DougPlumley. I wonder if it's possible to do the same while building the dev container image? I'm trying to install packages from local repository as part of the image.

@DougPlumley
Copy link

@blacktaxi based on my limited experience with the devcontainer and how I'm using it I felt comfortable including my secrets in the environment since I'm not building to publish the image and I'm only using the devcontainter locally.

I have a separate Dockerfile for building the image we'd use in production.

So for the Python development I'm doing for example I'm providing a PIP_EXTRA_INDEX_URL environment variable with the necessary details to install from a local package index.

@maciek16180
Copy link

@DougPlumley Just a small warning, offtopic: be very careful with PIP_EXTRA_INDEX_URL. You don't have control over package names in global PyPI. If you privately host my-package-xyz and global PyPI also has a package my-package-xyz, pip can't tell the difference between them. pip install my-package-xyz will install the version with the highest number, but you have no idea where it came from.

@DougPlumley
Copy link

@DougPlumley Just a small warning, offtopic: be very careful with PIP_EXTRA_INDEX_URL. You don't have control over package names in global PyPI. If you privately host my-package-xyz and global PyPI also has a package my-package-xyz, pip can't tell the difference between them. pip install my-package-xyz will install the version with the highest number, but you have no idea where it came from.

Appreciate the warning @maciek16180! I'll look into alternative methods as well.

@yn-tvlk
Copy link

yn-tvlk commented May 25, 2022

i was happy to find this thread, and disappointed that it's still an open issue. anybody managed to find a workaround?

@DougPlumley
Copy link

i was happy to find this thread, and disappointed that it's still an open issue. anybody managed to find a workaround?

I opted to use "runArgs": ["--env-file=.env"] in my .devcontainer.json configuration, that's where I'm mounting the secrets into the running container (not during build), I then trigger a shell script post create with "postCreateCommand": "/bin/bash -c .devcontainer/postCreateCommand.sh" that's installing my remaining dependencies which need the secrets to access private repositories.

@NathanDeMaria
Copy link
Author

The workaround we've been using is:

  • Include the full build command (including --secrets) as part of initializeCommand in the devcontainer.json, building to some hard-coded image name
    • Our secret is getting an auth token for AWS CodeBuild, so the command is something like ./generate_token.sh && docker build ...
  • Point the devcontainer.json's image property to that hard-coded image name

It mostly feels the same to a user as the ideal workflow, the only real difference we've noticed is the error is displayed a bit differently if the image build fails

@jamiet-msm
Copy link

jamiet-msm commented Jun 13, 2022

The workaround we've been using is:

  • Include the full build command (including --secrets) as part of initializeCommand in the devcontainer.json, building to some hard-coded image name

    • Our secret is getting an auth token for AWS CodeBuild, so the command is something like ./generate_token.sh && docker build ...
  • Point the devcontainer.json's image property to that hard-coded image name

It mostly feels the same to a user as the ideal workflow, the only real difference we've noticed is the error is displayed a bit differently if the image build fails

Thank you @NathanDeMaria, after reading your comment here I took the same approach (although we're not using initializeCommand because our developer workflow means that in our case the image should already exist anyway).

Specifying image works great, though I agree that build.secrets should be supported.

@JSeluga
Copy link

JSeluga commented Jul 19, 2022

Would really like --secrets to be able to be implemented. Or addition docker build command line arguments in a json/ dict style arguments inside the devcontainer.json file. Currently just using the command line outside and keeping the --secret layer early in the build so most changes allow the docker image to build once and the later layers changes can be done natively from vs code extension. This won't work as a solution for codespaces but good for local development environment. Posted on github for anyone that wants it.

@MShekow
Copy link

MShekow commented Oct 15, 2022

I found another nice workaround: use a docker-compose.yml file and make use of the build.secrets feature as documented here. Reference the docker-compose.yml file in your devcontainer.json file as documented here.

Note: VS Code uses docker-compose ... (not docker compose ...). At least on macOS, docker-compose ... does not support build-secrets, but docker compose does. Simply open the Docker Desktop settings and check the "Use Docker Compose V2" checkbox to fix this.

@Dcooley1350
Copy link

Dcooley1350 commented May 18, 2024

This thread has been stale for a while, but thought I would share another solution that I landed on after trying a few suggested in this thread. Maybe help the next person out.

The build.options field in the devcontainer.json can be leveraged to pass a --secret flag to the docker build command that the dev container build calls. The secret can then be mounted to a run command in the dockerfile.

devcontainer.json:

{
  "build": {
      "options": [
        "--secret=id=credentials,src=/home/user/.config/credentials.json"
      ],
    }
}

Dockerfile:

RUN --mount=type=secret,id=credentials,dst=/home/user/whateverdestination install_command

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
containers Issue in vscode-remote containers under-discussion Issue is under discussion for relevance, priority, approach
Projects
None yet
Development

No branches or pull requests

17 participants