{"id":37100510,"url":"https://github.com/chainguard-dev/cosign-ecs-verify","last_synced_at":"2026-01-14T12:14:30.584Z","repository":{"id":39885050,"uuid":"451497592","full_name":"chainguard-dev/cosign-ecs-verify","owner":"chainguard-dev","description":"Lambda function for verifying signed images in ECS ","archived":true,"fork":false,"pushed_at":"2024-03-09T22:28:10.000Z","size":1840,"stargazers_count":32,"open_issues_count":11,"forks_count":7,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-22T00:05:29.178Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chainguard-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-01-24T14:29:43.000Z","updated_at":"2025-02-11T21:35:30.000Z","dependencies_parsed_at":"2024-06-19T01:30:34.818Z","dependency_job_id":"20725821-063e-4b71-8812-067d5c4c35ae","html_url":"https://github.com/chainguard-dev/cosign-ecs-verify","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/chainguard-dev/cosign-ecs-verify","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chainguard-dev%2Fcosign-ecs-verify","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chainguard-dev%2Fcosign-ecs-verify/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chainguard-dev%2Fcosign-ecs-verify/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chainguard-dev%2Fcosign-ecs-verify/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chainguard-dev","download_url":"https://codeload.github.com/chainguard-dev/cosign-ecs-verify/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chainguard-dev%2Fcosign-ecs-verify/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28419748,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T10:47:48.104Z","status":"ssl_error","status_checked_at":"2026-01-14T10:46:19.031Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-14T12:14:29.919Z","updated_at":"2026-01-14T12:14:30.564Z","avatar_url":"https://github.com/chainguard-dev.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cosign-ecs-verify\n\nA prototype analog of a [Kubernetes admission controller] for Amazon [Elastic\nContainer Service (ECS)][ECS] which:\n\n- Terminates any running images without a valid [cosign] signature.\n- Sends alerts to an [SNS] topic (which can forward to your email).\n- Supports configurable keys to use for signature validation.\n\n**NOTE:** This is **Proof of Concept code** and not yet production-ready. In the\nevent of a bug or misconfiguration, it can prevent *any* ECS tasks from running.\nThis system intercepts tasks as they start (not before) and may not fully\nprevent unsigned containers.\n\nIf you'd like to learn more or give feedback, please file an issue or send an\nemail to [interest@chainguard.dev].\n\n[Kubernetes admission controller]: https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/\n[ECS]: https://aws.amazon.com/ecs/\n[cosign]: https://github.com/sigstore/cosign\n[KMS]: https://aws.amazon.com/kms/\n[SNS]: https://aws.amazon.com/sns/\n[interest@chainguard.dev]: mailto:interest@chainguard.dev\n\n## How it works\n\n![](aws-ecs-cosign-verify.png)\n\nThis system comprises a Lambda function (4) which listens to EventBridge events\n(3) triggered on every ECS task run (1). The function checks that the task's\ncontainer image has a valid [cosign] signature in ECR (2) with a specific public\nkey, provided directly or stored in KMS (5). If the check fails, the function\nterminates the task and sends a notification to an SNS topic (7) which you can\nsubscribe to via email.\n\nIn order:\n\n1. Start an ECS task in the cluster\n2. The task definition has the container image stored in ECR\n3. EventBridge sends a notification to Lambda\n4. Cluster and Task definition is sent to function \n5. KMS key that has signed an image \n6. Lambda function evaluates if container image is signed w/ KMS\n7. If not signed with specified key it does two things\n   1. Stop task definition\n   2. SNS notification email to alert that the service/task has been stopped\n\n## Quickstart\n\n### Requirements and preliminaries.\n\nYou will need the following tools installed:\n\n- `make` (e.g., [GNU make])\n- [Terraform]: for local testing\n- [AWS CLI] and [AWS SAM CLI]: for deploying\n- [`cosign`]: for generating keys\n- [`docker`]: if you need to make images\n\n[AWS CLI]: https://aws.amazon.com/cli/\n[AWS SAM CLI]: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html\n[GNU make]: https://www.gnu.org/software/make/\n[Terraform]: https://www.terraform.io/downloads\n[`cosign`]: https://github.com/sigstore/cosign\n[`docker`]: https://docs.docker.com/get-docker/\n\nYou should [configure the AWS CLI] for your project and account.\n\n[configure the AWS CLI]: https://docs.aws.amazon.com/cli/latest/reference/configure/\n\n### Deploy\nTo deploy, run:\n\n```shell\nmake sam_deploy\n```\n\nIt will check against the key in `cosign.pub` (see detailed instructions for how\nto change this).\n\n### Test it\n\nTo test, we need an ECS cluster on which to run our signed/unsigned tasks.\nThe `terraform` subdirectory contains a Terraform template for such a cluster,\nwith corresponding task definitions. First, initialize (to download the AWS\nprovider for Terraform), then deploy:\n\n``` shell\nmake tf_init\nmake tf_apply  # run `make tf_plan` to see the plan first\n```\n\nWe can then run our tasks (these will run two public \"hello world\" Alpine images\nwith and without a signature):\n\n``` shell\nmake run_unsigned_task\nmake run_signed_task\n```\n\nCheck that it worked. You should see the unsigned task in the `STOPPED` tasks\nand the signed task in the `RUNNING` tasks:\n\n``` shell\nmake task_status\n```\n\n### Cleanup\n\nTo clean up, run:\n\n``` shell\nmake stop_tasks\nmake tf_destroy\nmake sam_delete\n```\n\n## Detailed instructions\n\n`cosign-ecs-verify` uses a SAM template (`template.yml`) to create:\n\n- A Lambda function (source in `cosign-ecs-function/`) which:\n  - Runs on every ECS task state change, triggered by EventBridge.\n  - Gets the key for signature verification.\n  - For each container in the event:\n    - Verifies the container image, terminating the task and sending a\n      notification if it is invalid.\n- An Amazon [SNS] topic: if the function stops an unsigned container image, it\n  will send a message to this topic.\n  - You can [configure email notifications][sns-email] for this topic to be\n    alerted whenever an unverified image is stopped.\n  - Messages sent to the topic are [encrypted using a key in KMS][sns-kms].\n  \nTo configure, run `sam deploy` with either the `KeyArn` set to a KMS key to use, or\n`KeyPem` set to a full public key in PEM format. In the provided `Makefile`, we\nhardcode the key in `cosign.pub`.\n\n[SNS]: https://aws.amazon.com/sns/\n[sns-email]: https://docs.aws.amazon.com/sns/latest/dg/sns-email-notifications.html\n[sns-kms]: https://aws.amazon.com/blogs/compute/encrypting-messages-published-to-amazon-sns-with-aws-kms/\n\nWe provide a test ECS cluster configuration (in `terraform/`), containing;\n\n- An ECS cluster:\n  - Configured to log to CloudWatch (which will trigger the Lambda via EventBridge).\n  - Associated task definitions `signed` and `unsigned`, which (by default) run images.\n- KMS keys and IAM permissions for the above.\n\nIf you would like to use your own images (for example, from a [previous post on\nthe Chainguard blog][previous-blog]), export `$IMAGE_URL_SIGNED` and\n`$IMAGE_URL_UNSIGNED` before running `make tf_apply`. We give instructions below\nfor making your own to test.\n\n[previous-blog]: https://blog.chainguard.dev/cosign-image-signing-in-aws-codepipeline/\n\n### Key Pair for `cosign`\n\nWe need a key against which to verify image signatures. If you have an existing keypair for cosign in AWS KMS, set it:\n\n``` shell\nexport KEY_ALIAS=my-key\n```\n\nOtherwise, we can make one:\n\n``` shell\nexport KEY_ALIAS=my-key\nexport AWS_SDK_LOAD_CONFIG=true\nmake key_gen\n```\n\n### Signed and unsigned images\n\nTo see `cosign-ecs-verify` in action, you need an example of a signed and\nunsigned image. Here, we'll build two simple images, push them to Amazon [ECR],\nand sign only one.\n\n[ECR]: https://aws.amazon.com/ecr/\n\nFirst, login to ECR with Docker. We recommend using a [credential helper] for\ndocker, but we also provide a make target `make ecr_auth` that will authenticate\nyou to the default registry.\n\n[credential helper]: https://aws.amazon.com/blogs/compute/authenticating-amazon-ecr-repositories-for-docker-cli-with-credential-helper/\n\nThen, we can create a repository for the signed/unsigned images.\n\n```shell\nREPO_URL=$(aws ecr create-repository \\\n    --repository-name $REPO_NAME \\\n    --query repository.repositoryUri \\\n    --output text)\n```\nFinally, we can build and push two simple images (see `Dockerfile`):\n\n``` shell\n# Export these so we can make ECR task definitions for running them.\nexport IMAGE_URL_SIGNED=$REPO_URL:signed\nexport IMAGE_URL_UNSIGNED=$REPO_URL:unsigned\n# Make 2 example images and push both.\n# The --build-arg is to make sure the images have different digests.\ndocker build . --build-arg signed=true --tag $IMAGE_URL_SIGNED\ndocker build . --build-arg signed=false --tag $IMAGE_URL_UNSIGNED\ndocker push $IMAGE_URL_SIGNED\ndocker push $IMAGE_URL_UNSIGNED\n```\n\nAnd sign *only one of them* (make sure you have a key pair):\n\n``` shell\ncosign sign --key awskms:///alias/$KEY_ALIAS $IMAGE_URL_SIGNED\n```\n\nNow, you can proceed with the Terraform instructions.\n\n### Local Development and Testing\n\nWe require Go 1.17 for development.\n\nYou can also use the SAM local feature to run in a simulated Lambda environment:\n\n``` shell\nmake sam_local\nmake sam_local_debug\n```\n\n### License\n\n[Apache License 2.0](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchainguard-dev%2Fcosign-ecs-verify","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchainguard-dev%2Fcosign-ecs-verify","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchainguard-dev%2Fcosign-ecs-verify/lists"}