In the rapidly evolving landscape of software development, CI/CD pipelines have become an indispensable part of the software supply chain. Among these, GitHub Actions has emerged as a popular choice for developers and organizations alike. However, as we integrate these tools more deeply into our workflows, we must also consider the security implications they bring, particularly when interacting with external resources like AWS APIs.
In a previous blog post here, we discussed how secrets are exposed in execution environments. Today, we're diving deeper into a specific, often overlooked area: GitHub Actions. Whether hosted by GitHub or self-hosted, these environments play a crucial role in modern CI/CD operations and, by extension, are an intrinsic part of the supply chain.
Consider a typical scenario where your GitHub Action needs to interact with AWS services. To do this, it requires AWS credentials, usually in the form of an access token. Various methodologies exist to generate the short lived tokens, including OIDC, but in the end the tokens end up in the runner environment. This means the environment is trusted, which violates the very core concept of zero trust. According to GitHub's own documentation: "Anyone with collaborator access to this repository can use these secrets and variables for actions." This statement should give us pause. Said differently, these credentials, including the short-lived access tokens, which often have substantial privileges, are potentially accessible to a wide range of individuals and processes. This exposure creates a significant security risk that many organizations underestimate.
The risks associated with this exposure are multifaceted. Malware from supply-chain attacks could potentially access these tokens. A malicious collaborator might exploit them for nefarious purposes. Even well-intentioned developers might accidentally expose these secrets through logs or other means (yes Github will mask the secrets as much as possible but I can not cover everything). The consequences of such exposures can be severe, especially considering the capabilities these credentials often possess.
To understand the gravity of the situation, let's consider what these exposed credentials might be capable of:
Now, imagine what a malicious actor could do with these capabilities. They could exfiltrate the malicious secrets (that they installed) for later use, perform actions that compromise your deployment security, or even access sensitive production data. The potential for damage is significant and far-reaching.
Monitoring and verifying your AWS operation is important and must not be neglected. It is crucial to detect suspicious activities and remedy any bad operation that may have taken place. But this does not mean that prevention isn’t necessary. In fact, any solution is perfectible and must be complemented with different methods. By combining pre-breach prevention and post-breach detection and remedy you significantly improve your security posture.
The most recommended approach to secure workflows is to establish a trust relationship between the GitHub repository and the tool responsible to create the tokens. As said earlier this may be the OIDC flow offered by Github, but can also simply be an AWS IAM role. While these do offer many crucial benefits, they fall short in several crucial areas.
Firstly, access is granted to everything in the runner, not just the specific step needed to perform a particular task. See this from the AWS credential action helper: “exports session environment variables for your other Actions to use”. This violates the principle of zero trust, potentially exposes your AWS infrastructure.
Secondly, it doesn't protect against insider threats. A disgruntled employee or collaborator with access to the repository could still misuse this trust relationship.
Moreover, this approach lacks specificity and independent authorization. It doesn't provide detailed audit logs or real-time notifications of access attempts. Perhaps most importantly, it can't enforce complex business rules using real-time, independent data – a crucial feature in today's dynamic and complex development environments.
To address these security concerns, we need a more robust, granular approach. This is where NSL comes in, offering a zero trust model that significantly enhances the security of your GitHub Actions, particularly when interacting with AWS resources.
NSL provides several key features that set it apart:
By implementing NSL in your GitHub Actions workflows, you gain several significant advantages. You achieve true zero trust, as neither the repository nor the workflow is inherently trusted. Access is granted at a granular level to specific applications rather than the entire environment. This separation of concerns – where the workflow performs actions, NSL manages authorization, and AWS remains isolated – significantly reduces your attack surface and enhances overall security.
Moreover, NSL’s approach offers flexibility through dynamic business policy enforcement and improved auditability. This means you can adapt your security posture in real-time based on changing conditions or requirements.
In conclusion, as our software supply chains grow more complex, it's crucial to address security concerns at every stage of the development and deployment process. By implementing a zero trust approach with NSL in your GitHub Actions workflows, particularly when interacting with AWS resources, you can significantly enhance your security posture, reduce risks, and maintain better control over your CI/CD pipeline.
Don't let your GitHub Actions become the weak link in your security chain. Embrace the zero trust model and take control of your secrets today.
To use NSL in a Github workflow in combination with the aws-cli tool you simply need to instantiate the NSL Action and supply it with the necessary JWE encrypted credentials. The NSL Action can be obtained at: nearedgelock/ghactions/actions/aws-cli@main
name: AWS GetCallerId
on:
push:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install AWS CLI - Pulling it from AWS
shell: bash
run: |
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install --update
echo "AWS_PAGER=" >> $GITHUB_ENV
- uses: nearedgelock/ghactions/actions/aws-cli@main
with:
aws-credentail-jwe: ${{ secrets.AWSCREDJSON }}
#
# The below is your code, using aws-cli in some way
#
- name: As a test, simply get caller ID
shell: bash
run: aws --no-cli-pager sts get-caller-identity
env:
AWS_EC2_METADATA_DISABLED: true The NSL Action is providing a credential process as defined by AWS. See https://docs.aws.amazon.com/cli/v1/userguide/cli-configure-sourcing-external.html. You will see an important Warning at the top of this AWS page. The NSL tool addresses the concerns presented by AWS by only using encrypted data (the JWE) and by helping at making sure only the aws-cli tool gets access to the decrypted credentials. That is in fact the crucial service delivered by NSL.
The other data needed is the AWSCREDJSON. This data MUST be delivered to NSL in the form of a JWE. This JWE includes the expected JSON object that aws-cli needs and is encrypted inside the JWE. The JSON payload that aws-cli expects is this:
{"Version": 1, "AccessKeyId": "<yourKeyID>", "SecretAccessKey": "yourSecretKey"}For Debian based OS use
sudo apt install clevisFor Fedora based OS use this instead
sudo dnf install clevisOnce installed you simply need to do
echo ‘{"Version": 1,"AccessKeyId":"<yourKeyID>","SecretAccessKey":"yourSecretKey"}’ | clevis encrypt tang ‘{“url”:“<your NSL tang url>”}’ -y > awscred.json.jwe
Now that you have a JWE, you simply need to add it to the Github secret manager. Match the secet's name with the expected environment variable name (AWSCREDJSON in the sample workflow above). See Github instructions on using secrets.
A tang URL is necessary when creating the JWE content. This matches a specific tang server and provides an endpoint to perform the key exchange. For more information, see the tang project.
A subscription is necessary to obtain your dedicated tang URL. The same subscription also gives you access to the JWECreator Web tool and will enable you to authorize the NSL Action. Once authorized, the NSL Action is able to decrypt the AWS credentials and deliver them directly to aws-cli without exposing them to the runner environment. The authorization is valid for only 1 NSL Action operation and must be repeated.
To perform the authorization, you can use the Grantor mobile App (which is free) or the NSL Web dashboard.
Create your free (forever) account at https://nsl.nearedge.io/createprofile and start protecting your Github Actions