Docker Content Trust (DCT) keeps audit logs of changes made to trusted repositories. Every time you push a signed image to a repository, or delete trust data for a repository, DCT logs that information.
These logs are only available from the MSR API.
To access the audit logs you need to authenticate your requests using an authentication token. You can get an authentication token for all repositories, or one that is specific to a single repository.
MSR returns a JSON file with a token, even when the user doesn’t have access to the repository to which they requested the authentication token. This token doesn’t grant access to MSR repositories.
The JSON file returned has the following structure:
{
"token": "<token>",
"access_token": "<token>",
"expires_in": "<expiration in seconds>",
"issued_at": "<time>"
}
Once you have an authentication token you can use the following endpoints to get audit logs:
URL | Description | Authorization |
---|---|---|
GET /v2/_trust/changefeed |
Get audit logs for all repositories. | Global scope token |
GET /v2/<msr-url>/<repository>/_trust/changefeed |
Get audit logs for a specific repository. | Repository-specific token |
Both endpoints have the following query string parameters:
Field name | Required | Type | Description |
---|---|---|---|
change_id |
Yes | String | A non-inclusive starting change ID from which to start returning results. This will typically be the first or last change ID from the previous page of records requested, depending on which direction your are paging in. The value The value |
records |
Yes | Signed integer | The number of records to return. A negative value indicates the number
of records preceding the change_id should be returned. Records are
always returned sorted from oldest to newest. |
The response is a JSON like:
{
"count": 1,
"records": [
{
"ID": "0a60ec31-d2aa-4565-9b74-4171a5083bef",
"CreatedAt": "2017-11-06T18:45:58.428Z",
"GUN": "dtr.example.org/library/wordpress",
"Version": 1,
"SHA256": "a4ffcae03710ae61f6d15d20ed5e3f3a6a91ebfd2a4ba7f31fc6308ec6cc3e3d",
"Category": "update"
}
]
}
Below is the description for each of the fields in the response:
count |
The number of records returned. |
---|---|
ID |
The ID of the change record. Should be used in the change_id field
of requests to provide a non-exclusive starting index. It should be
treated as an opaque value that is guaranteed to be unique within an
instance of notary. |
CreatedAt |
The time the change happened. |
GUN |
The MSR repository that was changed. |
Version |
The version that the repository was updated to. This increments every time there’s a change to the trust repository. This is always |
SHA256 |
The checksum of the timestamp being updated to. This can be used with the existing notary APIs to request said timestamp. This is always an empty string for events representing trusted data being removed from the repository |
Category |
The kind of change that was made to the trusted repository. Can be
update , or deletion . |
The results only include audit logs for events that happened more than 60 seconds ago, and are sorted from oldest to newest.
Even though the authentication API always returns a token, the changefeed API validates if the user has access to see the audit logs or not:
Before going through this example, make sure that you:
library/wordpress
repository.jq
, to make it easier to parse the JSON responses.# Pull an image from Docker Hub
docker pull wordpress:latest
# Tag that image
docker tag wordpress:latest <msr-url>/library/wordpress:1
# Log into DTR
docker login <msr-url>
# Push the image to DTR and sign it
DOCKER_CONTENT_TRUST=1 docker push <msr-url>/library/wordpress:1
# Get global-scope authorization token, and store it in TOKEN
export TOKEN=$(curl --insecure --silent \
--user '<user>:<password>' \
'https://<msr-url>/auth/token?realm=dtr&service=dtr&scope=registry:catalog:*' | jq --raw-output .token)
# Get audit logs for all repositories and pretty-print it
# If you pushed the image less than 60 seconds ago, it's possible
# That MSR doesn't show any events. Retry the command after a while.
curl --insecure --silent \
--header "Authorization: Bearer $TOKEN" \
"https://<msr-url>/v2/_trust/changefeed?records=10&change_id=0" | jq .
Before going through this example, make sure that you:
library/nginx
repository.jq
, to make it easier to parse the JSON responses.# Pull an image from Docker Hub
docker pull nginx:latest
# Tag that image
docker tag nginx:latest <msr-url>/library/nginx:1
# Log into DTR
docker login <msr-url>
# Push the image to DTR and sign it
DOCKER_CONTENT_TRUST=1 docker push <msr-url>/library/nginx:1
# Get global-scope authorization token, and store it in TOKEN
export TOKEN=$(curl --insecure --silent \
--user '<user>:<password>' \
'https://<msr-url>/auth/token?realm=dtr&service=dtr&scope=repository:<msr-url>/<repository>:pull' | jq --raw-output .token)
# Get audit logs for all repositories and pretty-print it
# If you pushed the image less than 60 seconds ago, it's possible that
# Docker Content Trust won't show any events. Retry the command after a while.
curl --insecure --silent \
--header "Authorization: Bearer $TOKEN" \
"https://<msr-url>/v2/<msr-url>/<msr-repo>/_trust/changefeed?records=10&change_id=0" | jq .