Check Notary audit logs

Estimated reading time: 6 minutes

These are the docs for DTR version 2.4.0

To select a different version, use the selector below.

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 DTR API.

Get an authentication token

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.

curl --insecure --silent \
--user <user>:<password> \
"https://<dtr-url>/auth/token?realm=dtr&service=dtr&scope=registry:catalog:*"

curl --insecure --silent \
--user <user>:<password> \
"https://<dtr-url>/auth/token?realm=dtr&service=dtr&scope=repository:<dtr-url>/<repository>:pull"

DTR 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 DTR repositories.

The JSON file returned has the following structure:

{
  "token": "<token>",
  "access_token": "<token>",
  "expires_in": "<expiration in seconds>",
  "issued_at": "<time>"
}

Learn more about the authentication API.

Changefeed API

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/<dtr-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 0 indicates records should be returned starting from the beginning of time.

The value 1 indicates records should be returned starting from the most recent record. If 1 is provided, the implementation will also assume the records value is meant to be negative, regardless of the given sign.

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.

Response

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:

Field name Description
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 DTR 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 0 for events representing trusted data being removed from the repository.

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:

  • If the user is an admin they can see the audit logs for any repositories,
  • All other users can only see audit logs for repositories they have read access.

Example - Get audit logs for all repositories

Before going through this example, make sure that you:

  • Are a DTR admin user.
  • Configured your machine to trust DTR.
  • Created the library/wordpress repository.
  • Installed 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 <dtr-url>/library/wordpress:1

# Log into DTR
docker login <dtr-url>

# Push the image to DTR and sign it
DOCKER_CONTENT_TRUST=1 docker push <dtr-url>/library/wordpress:1

# Get global-scope authorization token, and store it in TOKEN
export TOKEN=$(curl --insecure --silent \
--user '<user>:<password>' \
'https://<dtr-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 DTR doesn't show any events. Retry the command after a while.
curl --insecure --silent \
--header "Authorization: Bearer $TOKEN" \
"https://<dtr-url>/v2/_trust/changefeed?records=10&change_id=0" | jq .

Example - Get audit logs for a single repository

Before going through this example, make sure that you:

  • Configured your machine to trust DTR.
  • Created the library/nginx repository.
  • Installed 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 <dtr-url>/library/nginx:1

# Log into DTR
docker login <dtr-url>

# Push the image to DTR and sign it
DOCKER_CONTENT_TRUST=1 docker push <dtr-url>/library/nginx:1

# Get global-scope authorization token, and store it in TOKEN
export TOKEN=$(curl --insecure --silent \
--user '<user>:<password>' \
'https://<dtr-url>/auth/token?realm=dtr&service=dtr&scope=repository:<dtr-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://<dtr-url>/v2/<dtr-url>/<dtr-repo>/_trust/changefeed?records=10&change_id=0" | jq .
registry, monitor, troubleshoot