When we come to setting up the CI/CD pipelines in GitLab CI further along in the book, we're going to be using CI variables to store sensitive secrets to GitLab itself and the AWS API. I want to address any concerns a person might have about how and why we're going to be doing it this way versus some other, much better way.
Readers with some industry experience might not like the idea of storing the AWS API credentials in GitLab CI variables. This is understandable because anyone with access to the repository, and the right permissions (
owner), can view the credentials in plain text. The key here, however, is to ensure that only the right people can view the CI variables.
But a more important point to make about how we're approaching this problem is accessibility.
This book is aimed at people who are looking to get a complete, holistic view of what being a DevOps engineer involves. To accomplish this we're going to be using the easiest route available to get the work of building our CI/CD pipelines done, because we're interested in getting across the knowledge and skills.
Further down the line, as the book evolves, we will cover the better solutions I have listed below. That's also another objective of this book: get something simple in place today and then evolve it into something more complex.
I'll cover below for the sake of clarity and so the reader can get a better idea of better security practices.
Instead of the AWS API credentials being stored in the CI variable we could store them in some remote secrets management system and then retrieve them from there inside of our CI pipeline's shell script.
This would remove them from the GitLab UI and prevent anyone from extracting them. This isn't a perfect solution, however.
If your repository isn't protecting the
.gitlab-ci.yml file and anyone can push to it, extracting the secrets is just a case of changing a
script: block inside the
.gitlab-ci.yml and running the pipeline - the secrets will be printed to the log.
This attack vector is more involved, for sure, but it's hardly difficult to pull off.
That being said it's still a better option.
IAM Instance Policy¶
The best solution, by far, is to use custom GitLab CI Runners inside of your AWS account with an IAM Instance Policy that permits the Runner to only do what you need it to.
This removes the need for storing any secrets at all. There are no secrets in fact. Just an instance with its permissions directly attached to it.
But even this approach has its attack vectors and flaws. For example simply updating an unprotected
.gitlab-ci.yml file would allow a malicious employee or attacker to run whatever code they liked against your infrastructure, which one can safely assume is why they would steal your credentials to being with.
No system is perfect, but the use of an IAM Instance Policy is the best solution of the lot.
Don't think that security doesn't matter to us. It does. It's super critical. But so is getting you, the reader, skilled up and building systems so that you can get employed. This is a fine balance between knowledge transfer and security, with the latter being solved further down the line.
Now that we've covered the theory of what we're doing let's look at implementing it into a working, real-world solution.