When developing a Web App, and trying to adhere to what is generally considered best practice, e.g. The 12 factor app methodology etc. One key concept is to keep configuration and sensitive data out of your source code - access keys, connection strings etc. Using something like .env
files to set different connection strings for a dev, test and production environment.
However, another key point (not sure is is mentioned in the 12 factor app), seems to be Infrastructure as Code. I completely see the benefit of this, however, I don't see how it can be reconciled with not storing/hard coding sensative data. Surely to entirely automate the provisioning of a new environment, a series of env variables has to be specified - in code...
How can these two seemingly contradictory pieces of standard practices be reconciled?
My current approach is something like this:
Hosted Git Repo with however many dev branches and a master branch
When dev branches are merged with master branch, the CI build is triggered, this builds the project and runs unit and integration tests.
The git repo also has a production branch, when master is merged into production, the same build runs, but if it is successful, a CD release is created. (In my case this is a deployment to an Azure App Service)
So my three environments are the local dev machines (before a PR into the master branch in the hosted repo), the CI build server and the production app service. At the moment, locally we have a .env
file which isn't checked into the git repo. On the CI server, the NODE_ENV
value is set to test, so the code uses hard-coded unit test values (nothing sensitive). Then in production we manually set the connection strings etc. in the app service settings. This, I feel, is potentially an issue.
So possibly I could add an infrastructure folder to the repo, with Terraform code in it, then as part of the release process, terraform plan could see if there is anything that needs changing between the code's infrastrucutre and the real world infrastructure (and if so, execute it). But where do I store the production env variables?