Add user tracking for deploy tokens from registry events
🚁 Overview
This MR utilizes the existing webhook notifications and existing tracking to also track events from deploy tokens (previously we only had tracking for users).
New events:
- i_container_registry_delete_tag_deploy_token
- i_container_registry_push_tag_deploy_token
- i_container_registry_create_repository_deploy_token
- i_container_registry_delete_repository_deploy_token
- i_container_registry_push_repository_deploy_token
For groupcontainer registry, we want to have weekly
and monthly
aggregations of these events thus the monthly and weekly metric definitions (same as what we already have for User
). For this MR, we consider events from a Deploy Token
.
See below for the event
structure (reference) that Gitlab Rails receives.
Important Note: Compared to before, we have a new key user
, under actor
, which was added in !127622 (merged). The value for this new user
key is a JWT containing user information. To get the correct actor for the event, we will decode this token and use that information.
{
"events": [
{
"id": "a582a0f3-e620-43e6-8e98-ff850fc9d984",
"timestamp": "2023-01-25T14:45:54.17327+11:00",
"action": "push",
"target": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 528,
"digest": "sha256:xxxx",
"length": 528,
"repository": "root/test",
"url": "http://registry.test:5000/v2/root/test/manifests/sha256:xxxxx",
"tag": "more-auth"
},
"request": {
"id": "8ef8d69b-f957-45ab-ba2c-9153291f47b6",
"addr": "172.16.123.1:56969",
"host": "registry.test:5000",
"method": "PUT",
"useragent": "docker/20.10.18 go/go1.18.6 git-commit/e42327a6d3c55ceda3bd5475be7aae6036d02db3 kernel/5.15.68-0-virt os/linux arch/arm64 UpstreamClient(Docker-Client/20.10.22 \\(darwin\\))"
},
"actor": {
"name": "root",
"user_type": "deploy_token",
"user": "tokentokentoken"
},
"source": {
"addr": "127.0.0.1:5000",
"instanceID": "45681f21-a006-42f2-ab7c-4cc37d8906b4"
}
}
]
The value under user
, once decoded, will have a structure similar to the following if the actor is a Deploy Token:
Token claims
------------
{
"exp": 1704947819,
"iat": 1704947759,
"jti": "ee559f2b",
"nbf": 1704947754,
"user_info": {
"deploy_token_id": 1,
"token_type": "deploy_token",
"username": "january2024"
}
}
if the actor is a user, we will find user_id
instead of deploy_token_id
.
🙌 Validating Locally
To validate locally, we first need to setup the Service Ping locally with this guide. And after that, we verify that the counts are incremented when an event is received.
The counters are incremented whenever the above events are emitted. They are emitted whenever:
- a tag gets pushed
- a tag gets deleted
- a repository gets deleted
- a repository gets created
- a repository gets pushed
To be able to do this, we will have to setup the Container Registry standalone on a fresh master
(outside the GDK) and enable notifications
with the help of the instructions here.
An alternative is to call the endpoint with the ContainerRegistry event payload format as documented in container-registry!1205 (merged) and simulate what the container registry would send to Gitlab Rails.
Sending Events to the /events endpoint
In this section, we will simulate Gitlab Rails receiving an event from the container registry.
Before we do that, let's check if we have any usage data from a deploy token. We do this now and compare it with the counts later and see that it has been increased
[27] pry(main)> Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: 'i_container_registry_push_tag_deploy_token',
start_date: Date.current.beginning_of_week, end_date: Date.current.next_week)
=> 0
A. Authentication
Now, let's start! Sending events to Gitlab Rails require some token and authentication. For simplicity, we can skip the token checks and curl without any tokens:
- Open
api/container_registry_event.rb
and - Comment out the line
before { authenticate_registry_notification! }
user
token
B. Generating the As mentioned above, we have a new key user
which we need a JWT for. To get that token:
NOTE: The token expires in a few seconds so please do the steps right after one another.
- Create a deploy token (or use an existing one) and take note of the username and password. Guide to creating deploy tokens here.
- Request a JWT for the user:
http -a deploytokenusername:'deploytokenpassword' http://gdk.test:3000/jwt/auth client_id=="docker" service=="container_registry" scope=="repository:october-group/proj-lalalo/proj-lalalo:pull"
- You will get a return value with a
token
key. Copy that token and decode it:
Return value:
HTTP/1.1 200 OK
Cache-Control: max-age=0, private, must-revalidate
Content-Length: 1885
Permissions-Policy: interest-cohort=()
Referrer-Policy: strict-origin-when-cross-origin
Set-Cookie: perf_bar_enabled=true; path=/
Vary: Accept
{
"token": <token>
}
Get the token and decode:
jwt decode <token>
- The return value will contain a
user
key. Get that token and replace in the curl command below.
Token claims
------------
{
"access": [
{
"actions": [
"pull"
],
"meta": {
"project_path": "october-group/proj-lalalo"
},
"name": "october-group/proj-lalalo/proj-lalalo",
"type": "repository"
}
],
"aud": "container_registry",
"auth_type": "deploy_token",
"user": "tokentokentoken-get-this-token-and-put-it-in-curl-command"
}
curl
Command
C. Below is a curl
command that we can use to send events to Rails.
curl -d '{
"events": [
{
"id": "a582a0f3-e620-43e6-8e98-ff850fc9d984",
"timestamp": "2023-01-25T14:45:54.17327+11:00",
"action": "push",
"target": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 528,
"digest": "sha256:af06af3514c44a964d3b905b498cf6493db8f1cde7c10e078213a89c87308ba0",
"length": 528,
"repository": "root/test",
"url": "http://registry.test:5000/v2/root/test/manifests/sha256:02399a844fe2a14d062382fd6b3e048b742e8d647bc1ce4ce421decfb31ca938",
"tag": "latest"
},
"request": {
"id": "8ef8d69b-f957-45ab-ba2c-9153291f47b6",
"addr": "172.16.123.1:56969",
"host": "registry.test:5000",
"method": "PUT",
"useragent": "docker/20.10.18 go/go1.18.6 git-commit/e42327a6d3c55ceda3bd5475be7aae6036d02db3 kernel/5.15.68-0-virt os/linux arch/arm64 UpstreamClient(Docker-Client/20.10.22 \\(darwin\\))"
},
"actor": {
"deploy_token_id": "1",
"user_type": "deploy_token",
"user": <token-from-earlier>
},
"source": {
"addr": "127.0.0.1:5000",
"instanceID": "45681f21-a006-42f2-ab7c-4cc37d8906b4"
}
}
]
}' -H "Content-Type: application/vnd.docker.distribution.events.v1+json" -X POST 'http://gdk.test:3000/api/v4/container_registry_event/events'
NOTE: The token expires within a few seconds so if you get an error at this point, try again as the token might have expired.
D. Check that the metric increased
And then to verify that the metric was counted, do a:
[28] pry(main)> Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: 'i_container_registry_push_tag_deploy_token',
start_date: Date.current.beginning_of_week, end_date: Date.current.next_week)
=> 1
Replace i_container_registry_delete_tag_deploy_token
with the event that you tried.
Notes:
- Feel free to replace
deploy_token_id: "1"
to other deploy tokens in your local machine. - Feel free to replace
"action": "push"
which is for a push event - Removing the line
"tag": "latest"
and the preceding comma will make it a repository event.
MR acceptance checklist
This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.
-
I have evaluated the MR acceptance checklist for this MR.
MR acceptance checklist
This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.
-
I have evaluated the MR acceptance checklist for this MR.
Related to #390874 (closed)