Lambda Function: S3 Auto Fingerprint Handler

This AWS Lambda function is automatically triggered when a new file is uploaded to a monitored Amazon S3 bucket. It generates a pre-signed URL for the uploaded file, invokes the /v1/files/fingerprint API with that URL, and stores the file's SHA-256 fingerprint and metadata on the Algorand blockchain.

Code: fingerprint_lambda/s3_auto_fingerprint_handler.py

import json
import boto3
import requests
from urllib.parse import unquote_plus

# Constants
FINGERPRINT_API_URL = "https://sandbox.qudefense.com/v1/files/fingerprint"
EXPIRATION_SECONDS = 86400

HEADERS = {
    "Content-Type": "application/json",
    "qudefense-client-id": "qudefense-outlook-api",
    "qudefense-secret-access-key": "G4ZsFDoS2Px7Jqy6oApxN1_onjxLPoH2-nqQnYXBeqo"
}

def lambda_handler(event, context):
    try:
        # Parse S3 event info
        record = event["Records"][0]
        bucket = record["s3"]["bucket"]["name"]
        key = unquote_plus(record["s3"]["object"]["key"])

        # Generate pre-signed URL for the uploaded object
        try:
            s3 = boto3.client("s3")
            presigned_url = s3.generate_presigned_url(
                ClientMethod="get_object",
                Params={"Bucket": bucket, "Key": key},
                ExpiresIn=EXPIRATION_SECONDS,
                HttpMethod="GET",
            )
            print(f"Generated pre-signed URL: {presigned_url}")
        except Exception as e:
            print(f"Error generating pre-signed URL: {str(e)}")
            return

        payload = {
            "s3_presigned_url": presigned_url
        }

        try:
            response = requests.post(FINGERPRINT_API_URL, json=payload, headers=HEADERS)
            print(f"API Response: {response.status_code} - {response.text}")
            return {
                "statusCode": 200,
                "body": json.dumps({"message": "Fingerprint API called successfully"})
            }
        except Exception as e:
            print(f"Error calling fingerprint API: {str(e)}")


    except Exception as e:
        print(f"Error in Lambda: {str(e)}")
        return {
            "statusCode": 500,
            "body": json.dumps({"error": str(e)})
        }

Trigger

API Invocation

Authentication

The following headers are used for API authentication and are hardcoded in the Lambda function:

Required IAM Policies

Ensure the Lambda function role has the following AWS permissions:

Sample S3 Event Trigger

{
  "Records": [
    {
      "s3": {
        "bucket": {
          "name": "your-s3-bucket"
        },
        "object": {
          "key": "user1/invoice.pdf"
        }
      }
    }
  ]
}

Example API Response

{
  "status": "success",
  "fingerprint": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
  "metadata_hash": "7c4a8d09ca3762af61e59520943dc26494f8941b",
  "file_metadata": {
    "file_name": "invoice.pdf",
    "file_size": 12345,
    "file_type": "application/pdf",
    "modified_date": "2024-01-01T12:00:00Z"
  },
  "blockchain_app_id": "123456789",
  "blockchain_txid": "ABCDEF123456789",
  "file_id": "550e8400-e29b-41d4-a716-446655440000"
}