Prebuilding a docker image *within* a Github Codespace when the image relies on the organization's other private repositories? - docker

I'm exploring how best to use Github Codespaces for my organization. Our dev environment consists of a Docker dev environment that we run on local machines. It relies on pulling other private repos we maintain via the local machine's ssh-agent. I'd ideally like to keep things as consistent as possible and have our Codespaces solution use the same Docker dev environment from within the codespace.
There's a naive solution of just building a new codespace with no devcontainer.json and going through all the setup for a dev environment each time you create a new one... but I'd like to avoid this. Ideally, I keep the same dev experience and am able to get the codespace to prebuild by building the docker image and somehow getting access to our other private repos.
An extremely hacky-feeling solution that works for automated building is creating an ssh key and storing it as a user codespace secret, then setting up the ssh-agent with that ssh-key as part of the postCreateCommand. My understanding is that this would not work with the onCreateCommand because "it will not typically have access to user-scoped assets or secrets.". To reiterate, this works for automated building, but not pre-building.
From this Github issue it looks like cloning via ssh is a complete no-go with prebuilds because ssh will need a user-defined ssh key, which isn't available from the onCreateCommand. The only potential workaround I can see for this is having an organization-wide read-only ssh-key... which seems potentially even sketchier than having user-created ssh keys as user secrets.
The other possibility I can think of is switching to https for the git clones. This would require adding access to the other repos, which is no big deal. BUT I can't quite see how to get access from within the docker image. When I tried this, I was getting errors because I was asked for a username and password when I ran a git clone from within docker... even though git clone worked fine in the base codespace. Is there a way to forward whatever tokens Github uses for access to other repos into the docker build process? Is there a way to have user-generated tokens get passed into the docker build process and use that for access instead?
Thoughts and roasts welcome.

Related

Configuring a Gitlab runner secret that is not visible to the repos using it

I want to implement a SAST tool (with a docker image) on my Gitlab that is integrated with my vulnerability reporting dashboard, but I dont want any of the repos maintainer/dev to be able to access the docker secret_key besides in its intended flow.
The flow should be like this:
Gitlab Runner (+ docker secret key) -> Docker image (contains SAST Tool + admin-level dashboard credential) -> Code Vulnerability reporting dashboard
I have considered several solutions (eg making the dashboard credential unique for each repos and making it supplied from the user instead of being saved in the docker image), but it requires either considerable maintenance effort or somehow enabling the repos maintainer to get the info.
Do you know that you can declare variables which are also could be masked and only available via deployment-process?
If not, this might this helps you out: How to Setup GitLab Enviroment Variable in save way?

Strategy for building docker and pushing it in different CI build steps without tar

I want to build some docker images in a certain step of my Google Cloud Build, then push them in another step. I'm thinking the CI used doesn't really matter here.
This is because some of the push commands are dependent on some other conditions and I don't want to re-build the images.
I can docker save to some tar in the mounted workspace, then docker load it later. However that's fairly slow. Is there any better strategy? I thought of trying to copy to/from /var/lib/docker, but that seems ill advised.
The key here is doing the docker push from the same host on which you have done the docker build.
The docker build, however, doesn’t need to take place on the CICD build machine itself, because you can point its local docker client to a remote docker host.
To point your docker client to a remote docker host you need to set three environment variables.
On a Linux environment:
DOCKER_HOST=tcp:<IP Address Of Remote Server>:2376
DOCKER_CERT_PATH=/some/path/to/docker/client/certs
DOCKER_TLS_VERIFY=1
This is a very powerful concept that has many uses. One can for example, point to a dev|tst|prod docker swarm manager node. Or, point from Linux to a remote Windows machine and initiate the build of a Windows container. This latter use case might be useful if you have common CICD tooling that implements some proprietary image labeling that you want to re-use also for Windows containers.
The authentication here is mutual SSL/TLS and so there need to be both client and server private/public keys generated with a common CA. This might be a little tricky at first and so you may want to see how it works using docker-machine first using the environment setting shortcuts initially:
https://docs.docker.com/machine/reference/env/
Once you’ve mastered this concept you’ll then need to script the setting of these environment variables in your CICD scripts making client certs available in a secure way.

Is it safe to fetch secure credentials in Travis CI in an open-source repo?

My open-source app uses AWS's Parameter Store feature to keep secure copies of app secrets (database passwords, etc). When my app is deployed to EC2 a script fetches these secrets and makes them available to the code, and I run this same script locally too.
Some of my tests need database access to run and therefore I need my Travis build script to have access.
Is it safe for me to run that script on my (public) Travis build? As far as I can tell, Travis doesn't expose the build artefacts anywhere (beyond what's on GitHub, which doesn't have my secrets). I know I can encrypt config items in my .travis.yml file but ideally there'd be a single place where this data lives, then I can rotate config keys without updating them in multiple places.
Is there a safe/better way I can do this?
Not really.
If you're accepting pull requests, it's trivially easy to create a pull request that dumps the publicly dumps the keys to the Travis console. Since there's no restrictions on what PRs can modify, edit, etc., wherever the keys are, someone could easily modify the code & print them.
Travis built it secure environment variables to prevent this type of attack, i.e. by not exposing the variables to PRs. That means that tests requiring secure environment variables can't be run with encrypted variables, but that's a trade off that one has to make.
As StephenG has mentioned it is trivial to expose a secret as it is simply an environment variable that the CI systems try to mask.
Example with Bash:
$ SECRET=mysecret
$ rev <<< $SECRET
tercesym
Since the secret is now longer a perfect string match TravisCI, Jenkins, GitHub Actions will not be able to mask you secret anymore and let it be displayed on the console. There are other ways such as uploading a secret to an external server, and so on. For example one could just do env >> debug.log and if that debug.log file is archived, then the secret would be in that file.
Rather than connecting to your real backends, which is not a good idea for CI pipelines anyways, I would much rather recommend that you use a service container.
We do not use TravisCI so I don't how practical it is with Travis, but with Jenkins on Kubernetes and GitHub Actions you can add a service container that runs parallel to your tests.
For example if your integration tests need DB access to mysql or PSQL just run the containers for them. For dynamoDB Amazon provides a container implementation for the explicit purpose of testing your code against the DynamoDB API. If you need more AWS services, LocalStack offers fake AWS core services such as S3.
Now if you actually need to write data to your DBs in AWS ... you should probably expose that data as build artifacts and trigger a notification event instead so that a custom backend on your side can fetch the data on the trigger. Something like a small Lambda function for example.

Docker and SSH for development with phpStorm

I am trying to setup a small development environment using Docker. phpStorm team is working hard on get Docker integrated for remote interpreter and therefore for debugging but sadly is not working yet (see here). The only way I have to add such capabilities for debugging is by creating and enabling an SSH access to the container which works like a charm.
Now, I have read a lot about this and some people like the one on this post says is not recommended. I have read others which says to have a dedicated SSH Docker container which I don't get how to fit on this environment.
I am already creating a user docker-user (check repo here) for certain tasks like run composer without root permissions. That could be used for this SSH stuff easily by adding a default password to it.
How would you handle this under such circumstances?
I too have implemented the ssh server workaround when using jetbrains IDEs.
Usually what I do is add a public ssh key to the ~/.ssh/authorized_keys file for the SSH user in the target container/system, and enable passwordless sudo.
One solution that I've thought of, but not yet had the time to implement, would be to make some sort of SSH service that would be a gateway to a docker exec command. That would potentially allow at least some functionality without having to modify your images in any way for this dev requirement.

How can I add private information to OpenShift environment variables?

Authentication information such as database connection strings or passwords should almost never be stored in version control systems.
It looks like the only method of specifying environment variables for an app hosted on OpenShift is to commit them to the Git repository. There is a discussion about this on the OpenShift forums, but no useful suggested workarounds for the problem.
Is there another approach I can use to add authentication information to my app without having to commit it to the repository?
SSH into you application and navigate to your data directory
cd app-root/data
in this directory create a file with your variables (e.g. ".myenv") with content like
export MY_VAR="something"
and then in your repository in ".openshift/action_hooks/pre_start" add this line
source ${OPENSHIFT_DATA_DIR}/.myenv
Openshift supports now setting environment vaiables with the rhc commandline tool like this:
rhc set-env HEROKU_POSTGRESQL_DB_URL='jdbc:postgresql://myurl' -a myapp
I think thats way easier than all the other answers...
See: https://blog.openshift.com/taking-advantage-of-environment-variables-in-openshift-php-apps/
Adding .openshift/action_hooks/pre_start_* is not very cool, because you have to modify your repository in addition to add a file by SSH.
For nodejs, editting nodejs/configuration/node.env works well for some days, but I experienced the file got reverted several times. So it is not stable.
I found a much better solution.
echo -n foobar > ~/.env/user_vars/MY_SECRET
This works perfectly.
(Maybe this is what is done with rhc set-env ...?)
Hope this helps!
Your other option is to create an openshift branch of your project on your local machine. You can create a folder/files for the private information that only lives in your openshift branch. You would still need to source the files in your pre_start hook, something like source ${OPENSHIFT_REPO_DIR}/.private.
Then develop in your master branch, merge into your openshift branch, and push from your openshift branch to OpenShift master branch. This sound convoluted at first, but does make for a very easy workflow, especially if you're origin is shared.
This would be the workflow if your origin was on GitHub.
github/master <--> local/master --> local/openshift --> openshift/master
Notice the only bidirectional link is between github and your local master, so there should be no reason for your credentials to "escape".
This approach also has the added benefit of being able to keep any OpenShift specific changes confined to the openshift branch (like for Gemfiles, ENV variables, paths, etc).
As for security, on the OpenShift server, the repo should have the same security as your $OPENSHIFT_DATA_DIR, so you're not really exposing yourself any more.
Caveat:
Depending on your framework, the files in your $OPENSHIFT_REPO_DIR may be directly accessible via HTTP. You should be able to prevent this with an .htaccess file.

Resources