Backend Integration Guide
Integrate BoxVault with your existing infrastructure and CI/CD pipelines.
Table of contents
- TOC
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