UNPKG

@binlebin/c2pa-ssl

Version:

Node.js wrapper for C2PA content authentication using Rust CLI backend

314 lines (244 loc) 7.56 kB
# Firebase Functions Deployment Guide This guide explains how to deploy the C2PA-SSL service to Firebase Functions. ## Prerequisites 1. Firebase CLI installed (`npm install -g firebase-tools`) 2. A Firebase project with Functions enabled 3. The Linux binary built (`npm run build:linux`) ## Setup Steps ### 1. Create a Firebase Functions Project ```bash mkdir my-c2pa-firebase-functions cd my-c2pa-firebase-functions firebase init functions ``` Choose: - Language: JavaScript - ESLint: No (optional) - Install dependencies: Yes ### 2. Install the C2PA-SSL Package ```bash cd functions npm install /path/to/c2pa-ssl # or if published to npm: # npm install c2pa-ssl ``` ### 3. Create the Function Edit `functions/index.js`: ```javascript const functions = require("firebase-functions"); const C2PAService = require("c2pa-ssl"); let serviceInstance = null; // Initialize the service once const getService = async () => { if (!serviceInstance) { serviceInstance = new C2PAService(); await serviceInstance.start(); } return serviceInstance; }; // Health check endpoint exports.health = functions .runWith({ memory: "1GB", timeoutSeconds: 60, }) .https.onRequest(async (req, res) => { try { await getService(); // Ensure service is started res.json({ status: "healthy", platform: process.platform, timestamp: new Date().toISOString(), }); } catch (error) { res.status(500).json({ error: error.message }); } }); // Sign endpoint exports.sign = functions .runWith({ memory: "2GB", timeoutSeconds: 300, secrets: ["C2PA_PRIVATE_KEY"], }) .https.onRequest(async (req, res) => { try { const service = await getService(); // Forward the request to the internal service // The service runs on port 8080 internally const proxyReq = require("http").request({ host: "localhost", port: 8080, path: "/sign", method: req.method, headers: req.headers, }, (proxyRes) => { res.writeHead(proxyRes.statusCode, proxyRes.headers); proxyRes.pipe(res); }); req.pipe(proxyReq); } catch (error) { res.status(500).json({ error: error.message }); } }); // Verify endpoint exports.verify = functions .runWith({ memory: "1GB", timeoutSeconds: 300, secrets: ["C2PA_PRIVATE_KEY"], }) .https.onRequest(async (req, res) => { try { const service = await getService(); // Similar proxy logic for verify const proxyReq = require("http").request({ host: "localhost", port: 8080, path: "/verify", method: req.method, headers: req.headers, }, (proxyRes) => { res.writeHead(proxyRes.statusCode, proxyRes.headers); proxyRes.pipe(res); }); req.pipe(proxyReq); } catch (error) { res.status(500).json({ error: error.message }); } }); ``` ### 4. Configure Secrets Set up the private key as a Firebase secret: ```bash # Create the secret firebase functions:secrets:create C2PA_PRIVATE_KEY # When prompted, paste your private key content ``` ### 5. Update firebase.json Add the following to your `firebase.json`: ```json { "functions": { "runtime": "nodejs18", "source": "functions", "ignore": [ "node_modules", ".git", "firebase-debug.log", "firebase-debug.*.log" ] } } ``` ### 6. Deploy ```bash firebase deploy --only functions ``` ## Important Considerations ### Memory and Timeout Settings - **Memory**: Minimum 1GB recommended, 2GB for video processing - **Timeout**: 300 seconds for large file processing - **Cold Start**: First request may take 10-20 seconds ### File Size Limits Firebase Functions has the following limits: - Request size: 10MB (HTTP trigger) - Response size: 10MB - Memory: Max 8GB - Timeout: Max 540 seconds For larger files, consider using Cloud Storage: ```javascript exports.signFromStorage = functions .runWith({ memory: "4GB", timeoutSeconds: 540, secrets: ["C2PA_PRIVATE_KEY"], }) .storage.object().onFinalize(async (object) => { // Process files uploaded to Cloud Storage const bucket = admin.storage().bucket(object.bucket); const file = bucket.file(object.name); // Download, sign, and upload back to storage }); ``` ### Environment Variables The service expects: - `C2PA_PRIVATE_KEY`: Set via Firebase secrets - Certificate is embedded in the package ### Monitoring View logs: ```bash firebase functions:log ``` ### Cost Optimization 1. Use minimum memory needed 2. Implement caching for repeated operations 3. Consider using Cloud Run for better control over instances ## Troubleshooting ### Binary not found - Ensure the Linux binary exists in `node_modules/c2pa-ssl/bin/c2pa-service-linux` - Check that the package was built with `npm run build:linux` ### Certificate errors - Verify the private key secret is properly set - Check logs for detailed error messages ### Memory errors - Increase memory allocation in `runWith` options - For video files, use at least 4GB ### Timeout errors - Increase timeout in `runWith` options - Consider breaking large operations into chunks ## Example Client Usage ```javascript const FormData = require("form-data"); const fs = require("fs"); const axios = require("axios"); async function signFile(filePath) { const form = new FormData(); form.append("file", fs.createReadStream(filePath)); form.append("title", "My signed content"); const response = await axios.post( "https://your-project.cloudfunctions.net/sign", form, { headers: form.getHeaders(), maxContentLength: Infinity, maxBodyLength: Infinity, }, ); // Response contains base64 encoded signed file const signedData = Buffer.from(response.data.signed_data, "base64"); fs.writeFileSync("signed-output.jpg", signedData); } ``` ## Performance Tips 1. **Reuse Service Instance**: The example above reuses the service instance across invocations 2. **Warm Functions**: Use Cloud Scheduler to ping the health endpoint every 5 minutes 3. **Regional Deployment**: Deploy to regions close to your users 4. **VPC Connector**: Not needed unless accessing private resources ## Security Best Practices 1. Use Firebase App Check to prevent abuse 2. Implement rate limiting 3. Validate file types and sizes 4. Use Cloud Armor for DDoS protection 5. Enable audit logging ## Alternative: Cloud Run For more control and better performance, consider deploying to Cloud Run instead: ```bash # Build container docker build -t gcr.io/YOUR_PROJECT/c2pa-service . # Push to Container Registry docker push gcr.io/YOUR_PROJECT/c2pa-service # Deploy to Cloud Run gcloud run deploy c2pa-service \ --image gcr.io/YOUR_PROJECT/c2pa-service \ --platform managed \ --region us-central1 \ --memory 2Gi \ --timeout 300 \ --set-env-vars "CERTIFICATE_PATH=/app/certs/anh_ec.pem" \ --set-secrets "PRIVATE_KEY_CONTENT=C2PA_PRIVATE_KEY:latest" ```