Get Approved/Blocked Audit Logs API

JFrog REST APIs

Content Type
REST API
ft:sourceType
Paligo

Description: An API to get Approved/Blocked audit events for packages (allowing full export). 

Note: A synchronous REST API, to get Approved/Blocked audit events for packages.

Since: 3.82.x

Security: Requires a valid user with the "VIEW_POLICIES" permission.

Usage: GET /xray/api/v1/curation/audit/packages

Parameters:

Parameter

Type

Mandatory/Optional

Default Value

Description

order_by

string

optional

id

Order result by column name

direction

string

optional

desc

Order direction

num_of_rows

int

optional

100

Maximum number of rows in result, Valid values 1- 2000

created_at_start

datetime

optional

@todayDate - 7 days

Get logs starting from this date , date format example 2023-08-13T22:00:00.000Z

created_at_end

datetime

optional

@todayDate

Get logs that happen before this date

offset

int

optional

0

Get data starting from this offset

include_total

boolean

optional

false

Get the total_count field in the result

dry_run

boolean

optional

false

  • When false, outputs audit events. In each event the non-dry-run policies that affected it are included(including blocking, bypassed and waived). This is what is displayed in the UI on the Blocked/approved tab.

  • When true , outputs dry run events, one per dry run policy. This is what is displayed in the UI in the Dry Run tab.

format

string

optional

json

Possible Values:  jsonand csv. When format=csv is used then:

  • The output will be a zip file containing a csv file

  • include_total=true is not allowed

  • When using dry_run=false (the default), the pagination counts audit events, not csv rows. Each event is flattened into possibly multiple csv rows (one row per policy in the event), so you can get more csv rows than the number of events you asked for.

  • The csv file in the zip file will be called audit_packages.csv , or it will be called audit_packages_incomplete.csv if the data according to timestamp filter doesn't fit into 500,000 events. In that case, to get all the events in the range, you can use the timestamp filter to narrow the time range so that all events in the range will fit.

Status Code

Description

200

OK

400

Bad request

404

Not found

Sample Request

GET /xray/api/v1/curation/audit/packages?
	order_by=id&
	direction=desc&
	num_of_rows=2&
	created_at_start=2023-07-20T22:00:00.000Z&
	created_at_end=2023-07-26T22:00:00.000Z&
	include_total=true&
            offset=0

Sample Response

200 OK
{
    "data": [
        {
            "id": 174,
            "created_at": "2023-08-30T05:45:52Z",
            "action": "blocked",
            "package_type": "Docker",
            "package_name": "pumevnezdiroorg/drupal",
            "package_version": "latest",
            "package_url": "https://registry-1.docker.io/v2/pumevnezdiroorg/drupal/manifests/latest",
            "reason": "Policy violations",
            "curated_repository_server_name": "",
            "curated_repository_name": "aviv-docker1",
            "curated_project": "default",
            "username": "admin",
            "user_mail": "",
            "origin_repository_server_name": "z0curdocktest",
            "origin_repository_name": "aviv-docker1",
            "origin_project": "default",
            "public_repo_url": "https://registry-1.docker.io",
            "public_repo_name": "Docker Hub",
            "policies": [
                {
                    "policy_name": "onlyOffical",
                    "policy_id": 3,
                    "dry_run": false,
                    "condition_name": "Image is not Docker Hub official",
                    "condition_category": "operational"
                }
            ]
        }
    ],
    "meta": {
        "total_count": 174,
        "result_count": 1,
        "next_offset": 1,
        "order_by": "id",
        "direction": "desc",
        "num_of_rows": 1,
        "offset": 0,
        "include_total": true,
        "include_explanation_and_recommendation": false,
        "created_at_start": "2023-08-23T05:48:32Z",
        "created_at_end": "2023-08-30T05:48:32Z"
    }
}

Python Example

import datetime


import requests
from requests.auth import HTTPBasicAuth


session = requests.Session()
auth = HTTPBasicAuth('username', 'password')


now = datetime.datetime.now(datetime.timezone.utc).replace(microsecond=0)
print(now.isoformat(), 'start')
last_print = now


start = datetime.datetime.now(datetime.timezone.utc).replace(microsecond=0)
curr = start - datetime.timedelta(days=30)


events_fetched = 0
while curr < start:
    offset = 0
    while True:
        now = datetime.datetime.now(datetime.timezone.utc).replace(microsecond=0)
        if now != last_print:
            last_print = now
            print(now.isoformat(), 'created_at_start: %s, events_fetched: %d, offset: %d' % (curr.isoformat(), events_fetched, offset))
        response = session.get(
            'http://env_domain/xray/api/v1/curation/audit/packages',
            params={
                'include_total': 'false',
                'order_by': 'id',
                'direction': 'asc',
                'num_of_rows': 1000,
                'created_at_start': curr.isoformat(),
                'offset': offset,
            },
            auth=auth)
        response.raise_for_status()
        output = response.json()
        next_offset = output['meta']['next_offset']
        if not next_offset:
            break
        offset = next_offset
        events_fetched += output['meta']['result_count']
    curr += datetime.timedelta(days=7)


now = datetime.datetime.now(datetime.timezone.utc).replace(microsecond=0)
print(now.isoformat(), 'fetched %d events' % events_fetched)