{"id":13582450,"url":"https://github.com/aquasecurity/manifesto","last_synced_at":"2025-10-13T07:22:35.853Z","repository":{"id":66728562,"uuid":"61980358","full_name":"aquasecurity/manifesto","owner":"aquasecurity","description":"Use Manifesto to store and query metadata for container images. ","archived":false,"fork":false,"pushed_at":"2018-12-18T08:57:02.000Z","size":94,"stargazers_count":163,"open_issues_count":8,"forks_count":12,"subscribers_count":14,"default_branch":"master","last_synced_at":"2025-04-06T14:36:30.816Z","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/aquasecurity.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2016-06-26T08:30:19.000Z","updated_at":"2024-11-28T16:32:44.000Z","dependencies_parsed_at":"2023-04-07T22:16:37.727Z","dependency_job_id":null,"html_url":"https://github.com/aquasecurity/manifesto","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/aquasecurity/manifesto","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aquasecurity%2Fmanifesto","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aquasecurity%2Fmanifesto/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aquasecurity%2Fmanifesto/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aquasecurity%2Fmanifesto/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aquasecurity","download_url":"https://codeload.github.com/aquasecurity/manifesto/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aquasecurity%2Fmanifesto/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279014111,"owners_count":26085463,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-13T02:00:06.723Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":"2024-08-01T15:02:43.691Z","updated_at":"2025-10-13T07:22:35.795Z","avatar_url":"https://github.com/aquasecurity.png","language":"Go","funding_links":[],"categories":["Go","Image"],"sub_categories":[],"readme":"# manifesto\nManifesto lets users store and query metadata for Docker images. This metadata can be information that you want to store about an image *post-build* - where labels are not sufficient. \n\n[![Build Status](https://travis-ci.org/aquasecurity/manifesto.svg?branch=master)](https://travis-ci.org/aquasecurity/manifesto)\n\n## Use cases\n* **Managing QA approval status** After an image has been built, it needs to go through various testing and approval processes before your organization is ready to use it in production. Keep track of approval status, and who has given sign-off by storing it alongside the image itself. \n* **Storing security profiles for an image** Manifesto makes it easy to associate a Seccomp or AppArmor profile with an image, so that you can automatically retrieve the correct profile at the point you want to run a container. \n* **Storing vulnerability scan reports** Images should be scanned regularly for vulnerabilities as new ones may be found in existing code. Manifesto enables storing the latest scan report for an image without modifying the image itself. \n* **Support contacts** Store the phone number or Slack channel to contact in the event this container image starts causing problems in your live deployment. Update these details without needing to update the image. \n* **Tracking active images** With CI/CD it's easy to end up with hundreds of thousands of container images in your registry. Use manifesto to store whether an image is actively being used in production - or to indicate the images that can safely be pruned.\n\nThe intention is that each piece of metadata could be signed using Notary. This means you can reliably get back the most recent version of that piece of metadata and know that it was put in place by someone with the authority to do so. \n\nAt the moment this is a Proof of Concept - feedback and ideas very welcome. \n\n## Demo \n\n[![asciicast](https://asciinema.org/a/128283.png)](https://asciinema.org/a/128283)\n\n## Installation\n\nWe automatically build binary executables for Mac, Linux and Windows, or you can rebuild from source. Whichever approach you take, **you'll also need to set up credentials** - see below. \n\n### Installing binaries\nDownload the latest binary for your platform from the [releases tab](https://github.com/aquasecurity/manifesto/releases) and unzip it. \n\nYou may find it easiest to move the binary into your path once you have downloaded it. For example \n\n```\n$ wget https://github.com/aquasecurity/manifesto/releases/download/\u003crelease tag\u003e/manifesto-darwin-amd64.tar.gz\n$ tar xf manifesto-darwin-amd64.tar.gz\n$ cp bin/darwin/amd64/manifesto /us/local/bin\n```\n\n### Building from source\n* Clone this repo (or `go get github.com/aquasecurity/manifesto`)\n* Go to the directory and `go build .`\n\n### Set up credentials\nIn this release you will need to be logged in to the Docker Registry - do this with [`docker login`](https://docs.docker.com/engine/reference/commandline/login/). This means that manifesto can execute docker commands directly. \n\nIn addition, since we are now using the Registry API directly to store and retrieve metadata in blobs, you need to pass in your username and password to manifesto itself. You can do this with the command line, environment variables REGISTRY\\_USERNAME and REGISTRY\\_PASSWORD, or by responding to prompts. \n\n## Usage\n\n```\n$ ./manifesto --help\nStore, retrieve and list pieces of metadata alongside your container images in the registry.\nMetadata is associated with specific images (by hash).\n\nUsage:\n  manifesto [command]\n\nAvailable Commands:\n  get         Show metadata for the container image\n  help        Help about any command\n  list        List currently stored metadata for the container image\n  put         Put metadata for the container image\n\nFlags:\n  -h, --help              help for manifesto\n  -p, --password string   Registry password (can also be passed in with the env var REGISTRY_PASSWORD)\n  -u, --username string   Registry username (can also be passed in with the env var REGISTRY_USERNAME)\n  -v, --verbose           Send debug output to stderr\n\nUse \"manifesto [command] --help\" for more information about a command.\n```\n\nBy default (like Docker images) manifesto assumes the 'latest' tag if a tag is not given. \n\n### Example\n\n```\n$ ./manifesto put myorg/imagetest something ~/temp.json\nStoring metadata 'something' for 'myorg/imagetest:latest'\nMetadata 'something' for 'myorg/imagetest:latest' stored at sha256:7be34480285971f16eed284b13fa7d417649f18c7d1af9b2de6970ce99e3cbbd\nUpdating manifesto for myorg/imagetest\nReplacing 'something' metadata in manifesto for 'myorg/imagetest:latest'\n\n$ ./manifesto list myorg/imagetest\nMetadata types stored for image 'myorg/imagetest:latest':\n    something\n\n$ ./manifesto get myorg/imagetest something\n{\n  \"key\" : \"value\",\n  \"createdBy\" : \"liz\",\n  \"number\" : 56\n}\n```\n\n# Proof of concept status\n\nIn this proof of concept:  \n\n* we store arbitrary metadata within the Docker registry \n* we store a \"manifesto\" for the repository with the fixed tag \"_manifesto\"\n* the manifesto is a json file with references to all the metadata stored for this repository\n\n![Manifesto is stored as an image, which references the data blobs for individual pieces of metadata](https://docs.google.com/drawings/d/1IGm4WnhL3J0hp2hdELrevyn3SMbgs0tlKNHjYIQHqtM/pub?w=960\u0026h=720)\n\n### Note - use of image tags in this prototype\nIn v 0.0.1 the metadata was stored as separate images, tagged as \\_manifesto\\_*metadata-type*. This allowed us to build the initial prototype very easily, but it meant there were additional repository tags for each piece of metadata, which seems undesirable.  \n\nIn this version we use the Registry API to store metadata directly in blobs, as shown in the diagram above. This will mean there will just be one additional tag in the repository, \\_manifesto. \n\n## Can I store metadata for any image?\n\nAs the metadata is stored in the same repository as the image itself, you can only store metadata for images you own. You could of course save a copy of a third-party image in your own repository, and store metadata alongside it. \n\n## How is this better than labels pointing to some arbitrary location where information is stored? \n\nPutting metadata into the registry itself allows us to leverage both existing technology and existing infrastructure. An organisation that stores images in its own on-premise registry can simply store metadata in it, and if they are using Notary again they can simply re-use the same deployment. The signing of metadata uses exactly the same process as the signing of images, so any existing audits and controls can be re-used. \n\n## Manifesto data\n\nThe manifesto associated with a repository is built using a Dockerfile like this: \n\n```\nFROM scratch\nADD \u003cfilename\u003e /data\n```\n\nWhere \u003cfilename\u003e contains all the metadata references for this repository. An example might look like this:\n\n```\n{\n\t\"images\": [{\n\t\t\"image_digest\": \"70d2f067eb94ec8ab0530068a414d8dbe8c203244ae5d5ad4ba6eb1babd1c1c1\",\n\t\t\"manifesto\": [{\n\t\t\t\t\"type\": \"seccomp\",\n\t\t\t\t\"digest\": \"sha256:a2fe22a6d44aa86432adad99481c3ad526ba35af2223df126620d20e38c70fac\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"type\": \"approvals\",\n\t\t\t\t\"digest\": \"sha256:6ced8eb4e6a61639601e7073963ec04a80f70a11442157e1dd825f042879a6da\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"type\": \"contact\",\n\t\t\t\t\"digest\": \"sha256:e896a0012a3450d9cef7e040eea8bed3fe06188957439fea501a65b62c65b4f1\"\n\t\t\t}\n\t\t]\n\t}, \n    {\n\t\t\"image_digest\": \"51d2f067eb94ec8ab0531987a414d8dbe8c203244ae5d5ad4ba6eb1babd1d54a\",\n\t\t\"manifesto\": [{\n\t\t\t\t\"type\": \"seccomp\",\n\t\t\t\t\"digest\": \"sha256:b2f72296d04ea36435adae99481c3ad526ba35af2223df126620d20e38c9763c\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"type\": \"documentation\",\n\t\t\t\t\"digest\": \"sha256:9ce18eb4e6a66639601e7073963ec04aa0f70a11442157e1d9825f042879abb1\"\n\t\t\t}\n\t\t]\n    }]\n}\n```\n\nThe *type* of each piece of metadata is simply an arbitrary string to identify that type of data. One possibility is to use standardized names (possibly as defined in the OCI image spec or similar) for the type to indicate that the associated data blob contains JSON in a standardized format (such as the vulnerability scanning report format).\n\n## Wait - in Docker, it's *tags* that get signed in Notary. Why is metadata associated with image digests?\nWhen you pull a Docker image tagged, say, 1.4 you'll get whatever the latest signed version tagged 1.4 is. The tag can move between different images (i.e. with different digests) as updates are made, for example to update from 1.4.3 to 1.4.4. \n\nFor many types of image metadata (e.g. approval status, vulnerability scan report), a piece of metadata must be associated with a particular build i.e. identified by the digest. \n\nWhen metadata is added, if signing is enabled the metadata blob gets signed in Notary, as does the manifesto with the references to the metadata blobs. \n\n# To Do's \n\n* Add data signing capabilities and verification with Notary. \n* Code currently execs out to the docker client executable - would be better to use the go client and call the API directly. \n* You need to enter your Docker Hub username and password to put metadata (or pass them in as env vars or parameters). Other commands currently exec out to docker, which means an existing `docker login` is sufficient for the credentials.  It would be better to be consistent, and even better if there were a way of using the credentials from that `docker login`\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faquasecurity%2Fmanifesto","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faquasecurity%2Fmanifesto","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faquasecurity%2Fmanifesto/lists"}