Skip to content

Instantly share code, notes, and snippets.

@Cdaprod
Last active May 21, 2024 15:15
Show Gist options
  • Save Cdaprod/8d3de4c27e705d2c06af6b74d3a309b3 to your computer and use it in GitHub Desktop.
Save Cdaprod/8d3de4c27e705d2c06af6b74d3a309b3 to your computer and use it in GitHub Desktop.
A refined example of a MinIO Webhook that will ensure that it captures and enumerates these events correctly as provenance attestations.

The goal is to ensure that when an object is uploaded to the subscribed bucket, it is captured as part of the provenance attestations. This can be achieved by setting up a webhook on the MinIO bucket to notify your Flask application whenever an object is uploaded. The Flask application will then log this event and store it as part of the provenance data.

Let's ensure that it captures and enumerates these events correctly as provenance attestations.

Step-by-Step Guide

  1. Set up MinIO with Webhook notifications.
  2. Create a Flask application to handle webhook notifications.
  3. Extend the ProvenanceAttestationEngine to log these webhook events.

Implementation

Setting Up MinIO Webhook Notifications

First, configure your MinIO bucket to send notifications to your Flask application. Here’s a brief example of how to set up MinIO notifications using the MinIO client or console:

  1. Configure Notification via MinIO Client:

    mc admin config set myminio/ notify_webhook:1 endpoint="http://YOUR_FLASK_APP_IP:5000/webhook" event="put" enable="on"
    mc admin service restart myminio
  2. Alternatively, use the MinIO Console:

    • Go to the MinIO console.
    • Navigate to your bucket.
    • Set up a notification to trigger on object uploads, pointing to your Flask app's webhook endpoint.

Flask Application for Handling Webhook Notifications

from flask import Flask, request, jsonify
from minio import Minio
import hashlib
import json
import os
from datetime import datetime

app = Flask(__name__)

class ProvenanceAttestationEngine:
    def __init__(self, minio_client, output_file):
        self.minio_client = minio_client
        self.output_file = output_file
        self.provenance_data = {
            "environment": self.get_environment_details(),
            "interactions": []
        }

    def get_environment_details(self):
        return {
            "os": os.name,
            "python_version": os.sys.version,
            "hostname": os.uname().nodename
        }

    def log_interaction(self, interaction_type, details):
        interaction = {
            "timestamp": datetime.now().isoformat(),
            "type": interaction_type,
            "details": details
        }
        self.provenance_data["interactions"].append(interaction)

    def upload_to_minio(self, bucket_name, object_name, file_path):
        self.minio_client.fput_object(bucket_name, object_name, file_path)
        self.log_interaction("upload", {
            "bucket_name": bucket_name,
            "object_name": object_name,
            "file_path": file_path,
            "file_hash": self.hash_file(file_path)
        })

    def download_from_minio(self, bucket_name, object_name, file_path):
        self.minio_client.fget_object(bucket_name, object_name, file_path)
        self.log_interaction("download", {
            "bucket_name": bucket_name,
            "object_name": object_name,
            "file_path": file_path
        })

    def hash_file(self, file_path):
        sha256_hash = hashlib.sha256()
        with open(file_path, "rb") as f:
            for byte_block in iter(lambda: f.read(4096), b""):
                sha256_hash.update(byte_block)
        return sha256_hash.hexdigest()

    def handle_webhook_event(self, event_data):
        for record in event_data['Records']:
            event_name = record['eventName']
            bucket_name = record['s3']['bucket']['name']
            object_name = record['s3']['object']['key']
            self.log_interaction(event_name, {
                "bucket_name": bucket_name,
                "object_name": object_name,
                "event_time": record['eventTime']
            })

    def export_attestation(self):
        with open(self.output_file, "w") as f:
            json.dump(self.provenance_data, f, indent=4)

minio_client = Minio(
    "play.min.io",
    access_key="YOUR_ACCESS_KEY",
    secret_key="YOUR_SECRET_KEY",
    secure=True
)

attestation_engine = ProvenanceAttestationEngine(minio_client, "provenance_attestation.json")

@app.route("/webhook", methods=["POST"])
def webhook():
    event_data = request.json
    attestation_engine.handle_webhook_event(event_data)
    return jsonify({"status": "success"}), 200

if __name__ == "__main__":
    app.run(port=5000, debug=True)

Explanation

  1. ProvenanceAttestationEngine Class:

    • Initialization: Takes a MinIO client and output file path as inputs.
    • Environment Details: Captures details about the operating system, Python version, and hostname.
    • Log Interaction: Logs interactions such as uploads, downloads, and webhook events.
    • Upload to MinIO: Uploads a file to MinIO and logs the interaction.
    • Download from MinIO: Downloads a file from MinIO and logs the interaction.
    • Hash File: Computes SHA-256 hash of a file for integrity verification.
    • Handle Webhook Event: Logs webhook event data, including bucket name, object name, event name, and event time.
    • Export Attestation: Exports the provenance data to a JSON file.
  2. Flask Application:

    • Webhook Endpoint: Receives POST requests at /webhook and processes the event data.
    • Run Server: Starts the Flask server on port 5000.

Running the Application

  1. Install Flask and MinIO SDK:

    pip install flask minio
  2. Save the provided code into a Python file, e.g., provenance_attestation.py.

  3. Run the Flask application:

    python provenance_attestation.py
  4. Configure MinIO to send webhook events to your Flask application's /webhook endpoint.

  5. Use the ProvenanceAttestationEngine methods to perform MinIO operations and log interactions as needed.

  6. Export the provenance attestation data to a JSON file using the export_attestation method.

By following these steps, you ensure that any object uploaded to the subscribed bucket triggers a webhook event, which is then logged as a provenance attestation. This setup provides a comprehensive system for tracking and documenting all interactions with the MinIO service.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment