Detecting intrusion with canary tokens
What is a canary token
A canary token is a resource that is monitored for access or tampering. Usually, canary tokens come in the form of a URL, file, API key, or email, etc., and trigger alerts whenever someone (presumably an attacker) trips over them.
How to detect compromised developer and DevOps environments with canary tokens
Canary tokens can be created and deployed in your code repositories, CI/CD pipelines, project management and ticketing systems like Jira or even instant messaging tools like Slack. When triggered, canary tokens can help alert you of an intrusion in your developer environments.
Project description
The purpose of the ggcanary project is to provide you with a simple Terraform configuration to create and manage GitGuardian Canary Tokens. We chose to focus on AWS credentials as it is one of the most seeked secret by hackers. It can be found and deployed in multiple places of the SDLC: in source code, in docker containers, as secrets variable in various CI. If a hacker breach your software development toolchain, its first action will be to look for secrets and especially AWS credentials.
Deploying this project will:
- create AWS credentials for their use as GitGuardian Canary Tokens. The users associated with these credentials do not have any permissions, so they cannot perform any action.
- create the related AWS infrastructure required to store any activities related to these credentials with AWS CloudTrail and AWS S3.
- create the related AWS infrastructure required to send alerts when one of the tokens is tampered to different integration such as email, native webhook and Slack.
Project setup
Requirements
To use this project, you will need:
- Terraform
- An AWS account. We recommend using an account dedicated to GitGuardian Canary Tokens to avoid all possible security issues.
- AWS cli
- jq (usually available through your package manager)
Setup
The main steps to set up the project are the following:
- Create an AWS user in your account:
- Give it sufficient rights to perform its task.
- Create an access key for that user, that you will use in the next step.
- Configure your AWS profile for the project. You can run
aws configure --profile YOUR_AWS_ACCOUNT
- Setup the Terraform backend: fill
backend.tf
with appropriate values - Fill a
terraform.tfvars
file that will contain the configuration of the project (AWS profile to use and notifiers to activate):- Examples can be found in
examples/tf_vars
. - See also the variables reference.
- Be sure to provide a unique value for
global_prefix
, to avoid name collisions (especially, AWS S3 bucket names have to be unique across all AWS accounts).
- Examples can be found in
- Create ggcanaries in
ggcanaries.auto.tfvars
- If needed, create the S3 bucket and DynamoDB to store the main project state. We provide the
tf_backend
project to do so:- In the
tf_backend
directory, runterraform init
- In the same directory, run
terraform apply -var-file="../terraform.tfvars"
- In the
- Run
./scripts/check_setup.sh
to check that you have all the required dependencies, and that you have correctly setup the project - Run
terraform init
- Run
terraform apply
(this will create all resources for the ggcanaries)
Note: this step requires apython3.8
to be available in your$PATH
. If you usepipenv
, you can for example use the virtualenv associated with the./lambda
directory (by runningcd lambda; pipenv shell; cd ..
.). - ggcanary tokens can be listed using
./scripts/list_keys.sh
How-tos
Use your project
We provide some scripts to help you manage your project once you have deployed it:
Test the project
Run ./scripts/ggcanary_call.sh <GGCANARY_NAME>
(e.g. ggtoken1
in the example below) to perform an AWS call with one of the created GitGuardian Canary Tokens. It will try to list S3 buckets with the given ggcanary and send you a notification since one of the ggcanary tokens was used to perform the call.
The script should return the following AWS error message:
An error occurred (AccessDenied) when calling the ListBuckets operation: Access Denied
List created keys
Run ./scripts/list_keys.sh
to output the list of created keys (secret keys will be displayed as well, be sure to be in a safe environment).
Display the keys of a given ggcanary
In order to display the keys of a given ggcanary <GGCANARY_NAME>
from the command line, run ./scripts/display_ggcanary_credentials.sh <GGCANARY_NAME>
.
Configure your notifications
GitGuardian Canary Tokens support several notification backends such as Amazon SES, Slack, or SendGrid.
The notification backends use the variables defined in the terraform.tfvars
values for the configuration.
Examples can be found in tf vars examples
.
It is possible to add custom notification backend following this procedure.
Manage your ggcanaries
In the sample configuration, ggcanaries are specified with the following block:
users = {
ggtoken1 = {
tag_1 = "John Doe"
source = "email"
},
ggtoken2 = {}
}
It will create the ggcanaries:
ggtoken1
with tags{"tag_1": "John Doe", "source": "email"}
ggtoken2
with no tags
Add a new ggcanary
To add a new ggcanary, you will need to modify the list of ggcanaries. For example, to create a third ggcanary ggtoken3
, change the value of the users
block in ggcanaries.auto.tfvars
to
users = {
ggtoken1 = {
tag_1 = "John Doe"
source = "email"
}
ggtoken2 = {},
ggtoken3 = {
some_other_key = "some_other_value"
}
}
Then run terraform apply
.
Remove a ggcanary
To remove a ggcanary, delete it in the ggcanaries.auto.tfvars
and run terraform apply
. For example, to remove ggcanary ggtoken1
from the test configuration, change the value of the users
block in ggcanaries.auto.tfvars
to
users = {
ggtoken2 = {}
}
Then run terraform apply
.
Delete the project
- Run
terraform destroy
in the main directory. - Delete the S3 bucket holding the state (Terraform cannot destroy it for safety reasons).
- Run
terraform destroy -var-file="../terraform.tfvars"
in thetf_backend
directory.
Limitations
Number of ggcanaries
The number of ggcanaries is limited to 5000 (max number of users linked to an AWS account).
Number of tags
Each ggcanary can have at most 30 tags. The tag names can be different for each ggcanary.