Backend Integration Guide

Integrate BoxVault with your existing infrastructure and CI/CD pipelines.

Table of contents

  1. Overview
  2. CI/CD Integration
    1. GitHub Actions
    2. GitLab CI
    3. Jenkins Pipeline
  3. Infrastructure as Code
    1. Terraform Integration
    2. Ansible Integration
  4. API Integration Examples
    1. Python SDK
    2. Node.js SDK
  5. Webhook Integration
    1. Setting up Webhooks
    2. Webhook Handler Example
  6. Monitoring and Observability
    1. Health Checks
    2. Metrics Integration
    3. Log Aggregation
  7. Best Practices
    1. Error Handling
    2. Security
    3. Performance
    4. Reliability

Overview

BoxVault provides comprehensive APIs for integrating with existing development workflows, CI/CD pipelines, and infrastructure automation tools.

CI/CD Integration

GitHub Actions

name: Build and Upload Vagrant Box

on:
  push:
    tags:
      - 'v*'

jobs:
  build-and-upload:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Build Vagrant Box
        run: |
          packer build ubuntu.pkr.hcl
          
      - name: Upload to BoxVault
        env:
          BOXVAULT_URL: $
          BOXVAULT_CLIENT_ID: $
          BOXVAULT_CLIENT_SECRET: $
        run: |
          # Get authentication token
          TOKEN=$(curl -s -X POST $BOXVAULT_URL/api/auth/service-account \
            -H "Content-Type: application/json" \
            -d "{\"clientId\":\"$BOXVAULT_CLIENT_ID\",\"clientSecret\":\"$BOXVAULT_CLIENT_SECRET\"}" \
            | jq -r '.accessToken')
          
          # Extract version from tag
          VERSION=${GITHUB_REF#refs/tags/v}
          
          # Upload box file
          curl -X POST $BOXVAULT_URL/api/organization/myorg/box/ubuntu-20.04/version/$VERSION/provider/virtualbox/architecture/amd64/file \
            -H "x-access-token: $TOKEN" \
            -F "file=@ubuntu-20.04.box"

GitLab CI

stages:
  - build
  - upload

build-box:
  stage: build
  script:
    - packer build ubuntu.pkr.hcl
  artifacts:
    paths:
      - "*.box"

upload-box:
  stage: upload
  script:
    - |
      TOKEN=$(curl -s -X POST $BOXVAULT_URL/api/auth/service-account \
        -H "Content-Type: application/json" \
        -d "{\"clientId\":\"$BOXVAULT_CLIENT_ID\",\"clientSecret\":\"$BOXVAULT_CLIENT_SECRET\"}" \
        | jq -r '.accessToken')
      
      curl -X POST $BOXVAULT_URL/api/organization/myorg/box/ubuntu-20.04/version/$CI_COMMIT_TAG/provider/virtualbox/architecture/amd64/file \
        -H "x-access-token: $TOKEN" \
        -F "file=@ubuntu-20.04.box"
  only:
    - tags

Jenkins Pipeline

pipeline {
    agent any
    
    environment {
        BOXVAULT_URL = credentials('boxvault-url')
        BOXVAULT_CLIENT_ID = credentials('boxvault-client-id')
        BOXVAULT_CLIENT_SECRET = credentials('boxvault-client-secret')
    }
    
    stages {
        stage('Build') {
            steps {
                sh 'packer build ubuntu.pkr.hcl'
            }
        }
        
        stage('Upload') {
            steps {
                script {
                    def token = sh(
                        script: """
                            curl -s -X POST \$BOXVAULT_URL/api/auth/service-account \
                                -H "Content-Type: application/json" \
                                -d '{"clientId":"'\$BOXVAULT_CLIENT_ID'","clientSecret":"'\$BOXVAULT_CLIENT_SECRET'"}' \
                                | jq -r '.accessToken'
                        """,
                        returnStdout: true
                    ).trim()
                    
                    sh """
                        curl -X POST \$BOXVAULT_URL/api/organization/myorg/box/ubuntu-20.04/version/${env.BUILD_NUMBER}/provider/virtualbox/architecture/amd64/file \
                            -H "x-access-token: ${token}" \
                            -F "file=@ubuntu-20.04.box"
                    """
                }
            }
        }
    }
}

Infrastructure as Code

Terraform Integration

# Configure BoxVault provider (hypothetical)
terraform {
  required_providers {
    boxvault = {
      source = "boxvault/boxvault"
      version = "~> 1.0"
    }
  }
}

provider "boxvault" {
  endpoint = var.boxvault_url
  token    = var.boxvault_token
}

# Create organization
resource "boxvault_organization" "example" {
  name        = "example-org"
  description = "Example organization"
  is_public   = false
}

# Create box
resource "boxvault_box" "ubuntu" {
  organization = boxvault_organization.example.name
  name         = "ubuntu-20.04"
  description  = "Ubuntu 20.04 LTS"
  is_public    = true
}

Ansible Integration

---
- name: Upload Vagrant Box to BoxVault
  hosts: localhost
  vars:
    boxvault_url: "https://boxvault.example.com"
    organization: "myorg"
    box_name: "ubuntu-20.04"
    version: "1.0.0"
    
  tasks:
    - name: Get authentication token
      uri:
        url: "/api/auth/service-account"
        method: POST
        body_format: json
        body:
          clientId: ""
          clientSecret: ""
      register: auth_response
      
    - name: Upload box file
      uri:
        url: "/api/organization//box//version//provider/virtualbox/architecture/amd64/file"
        method: POST
        headers:
          x-access-token: ""
        body_format: form-multipart
        body:
          file:
            filename: ".box"
            content: ""
            mime_type: application/octet-stream

API Integration Examples

Python SDK

import requests
import os

class BoxVaultClient:
    def __init__(self, base_url, client_id=None, client_secret=None):
        self.base_url = base_url.rstrip('/')
        self.token = None
        
        if client_id and client_secret:
            self.authenticate_service_account(client_id, client_secret)
    
    def authenticate_service_account(self, client_id, client_secret):
        response = requests.post(
            f"{self.base_url}/api/auth/service-account",
            json={"clientId": client_id, "clientSecret": client_secret}
        )
        response.raise_for_status()
        self.token = response.json()["accessToken"]
    
    def upload_box(self, org, box, version, provider, arch, file_path):
        with open(file_path, 'rb') as f:
            response = requests.post(
                f"{self.base_url}/api/organization/{org}/box/{box}/version/{version}/provider/{provider}/architecture/{arch}/file",
                headers={"x-access-token": self.token},
                files={"file": f}
            )
        response.raise_for_status()
        return response.json()
    
    def list_boxes(self, org):
        response = requests.get(
            f"{self.base_url}/api/organization/{org}/box",
            headers={"x-access-token": self.token}
        )
        response.raise_for_status()
        return response.json()

# Usage
client = BoxVaultClient(
    "https://boxvault.example.com",
    os.environ["BOXVAULT_CLIENT_ID"],
    os.environ["BOXVAULT_CLIENT_SECRET"]
)

# Upload a box
client.upload_box("myorg", "ubuntu-20.04", "1.0.0", "virtualbox", "amd64", "ubuntu.box")

# List boxes
boxes = client.list_boxes("myorg")
print(f"Found {len(boxes)} boxes")

Node.js SDK

const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');

class BoxVaultClient {
    constructor(baseUrl, clientId, clientSecret) {
        this.baseUrl = baseUrl.replace(/\/$/, '');
        this.token = null;
        
        if (clientId && clientSecret) {
            this.authenticateServiceAccount(clientId, clientSecret);
        }
    }
    
    async authenticateServiceAccount(clientId, clientSecret) {
        const response = await axios.post(`${this.baseUrl}/api/auth/service-account`, {
            clientId,
            clientSecret
        });
        this.token = response.data.accessToken;
    }
    
    async uploadBox(org, box, version, provider, arch, filePath) {
        const form = new FormData();
        form.append('file', fs.createReadStream(filePath));
        
        const response = await axios.post(
            `${this.baseUrl}/api/organization/${org}/box/${box}/version/${version}/provider/${provider}/architecture/${arch}/file`,
            form,
            {
                headers: {
                    'x-access-token': this.token,
                    ...form.getHeaders()
                }
            }
        );
        return response.data;
    }
    
    async listBoxes(org) {
        const response = await axios.get(
            `${this.baseUrl}/api/organization/${org}/box`,
            {
                headers: { 'x-access-token': this.token }
            }
        );
        return response.data;
    }
}

// Usage
const client = new BoxVaultClient(
    'https://boxvault.example.com',
    process.env.BOXVAULT_CLIENT_ID,
    process.env.BOXVAULT_CLIENT_SECRET
);

// Upload a box
await client.uploadBox('myorg', 'ubuntu-20.04', '1.0.0', 'virtualbox', 'amd64', 'ubuntu.box');

// List boxes
const boxes = await client.listBoxes('myorg');
console.log(`Found ${boxes.length} boxes`);

Webhook Integration

Setting up Webhooks

BoxVault can send webhooks for various events:

# Create webhook
curl -X POST http://localhost:3000/api/admin/webhooks \
  -H "x-access-token: ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/webhooks/boxvault",
    "events": ["box.uploaded", "box.deleted", "user.created"],
    "secret": "webhook-secret"
  }'

Webhook Handler Example

const express = require('express');
const crypto = require('crypto');

const app = express();
app.use(express.json());

app.post('/webhooks/boxvault', (req, res) => {
    const signature = req.headers['x-boxvault-signature'];
    const payload = JSON.stringify(req.body);
    const secret = process.env.WEBHOOK_SECRET;
    
    // Verify signature
    const expectedSignature = crypto
        .createHmac('sha256', secret)
        .update(payload)
        .digest('hex');
    
    if (signature !== `sha256=${expectedSignature}`) {
        return res.status(401).send('Invalid signature');
    }
    
    // Handle event
    const { event, data } = req.body;
    
    switch (event) {
        case 'box.uploaded':
            console.log(`Box uploaded: ${data.organization}/${data.box} v${data.version}`);
            // Trigger deployment, notifications, etc.
            break;
            
        case 'box.deleted':
            console.log(`Box deleted: ${data.organization}/${data.box}`);
            // Clean up references, notify teams, etc.
            break;
            
        case 'user.created':
            console.log(`New user: ${data.username}`);
            // Send welcome email, setup permissions, etc.
            break;
    }
    
    res.status(200).send('OK');
});

Monitoring and Observability

Health Checks

# Basic health check
curl http://localhost:3000/health

# Detailed status
curl http://localhost:3000/api/status

Metrics Integration

# Prometheus configuration
scrape_configs:
  - job_name: 'boxvault'
    static_configs:
      - targets: ['localhost:3000']
    metrics_path: '/metrics'
    scrape_interval: 30s

Log Aggregation

# Fluentd configuration
<source>
  @type tail
  path /var/log/boxvault/boxvault.log
  pos_file /var/log/fluentd/boxvault.log.pos
  tag boxvault
  format json
</source>

<match boxvault>
  @type elasticsearch
  host elasticsearch.example.com
  port 9200
  index_name boxvault
</match>

Best Practices

Error Handling

  • Implement exponential backoff for API calls
  • Handle rate limiting gracefully
  • Log all API interactions for debugging
  • Use circuit breakers for external dependencies

Security

  • Store credentials securely (environment variables, secrets management)
  • Use service accounts for automation
  • Implement proper token rotation
  • Validate webhook signatures

Performance

  • Use connection pooling for HTTP clients
  • Implement caching where appropriate
  • Monitor API response times
  • Set appropriate timeouts

Reliability

  • Implement retry logic with backoff
  • Use health checks in load balancers
  • Monitor disk space for box storage
  • Set up alerting for critical failures