Skip to content
Learni
View all tutorials
API & Automatisation

Comment automatiser Acronis Cyber Protect via API en 2026

Introduction

Acronis Cyber Protect est une plateforme leader en cybersécurité et sauvegarde cloud, offrant une API REST puissante pour l'automatisation avancée. En 2026, avec l'essor des environnements hybrides et zero-trust, intégrer cette API permet d'orchestrer des tâches critiques comme la découverte automatique des devices, la création de plans de sauvegarde et la surveillance des incidents depuis vos pipelines CI/CD ou scripts Node.js.

Ce tutoriel avancé, conçu pour des développeurs seniors, vous guide pas à pas pour un client TypeScript production-ready. Nous couvrons l'authentification OAuth2, les endpoints clés (/devices, /backup_plans), la gestion d'erreurs et les webhooks. Pourquoi c'est crucial ? Une intégration API réduit les interventions manuelles de 80%, minimise les fenêtres de vulnérabilité et s'intègre nativement avec Kubernetes ou Terraform. À la fin, vous disposerez d'un script fonctionnel pour lister 100+ devices et déployer des backups en un appel. Prêt à booster votre résilience cyber ? (142 mots)

Prérequis

  • Compte Acronis Cyber Protect avec accès API activé (rôle Admin ou API User).
  • Client ID et Secret générés via Console > Intégrations > Applications.
  • Node.js 20+ et npm/yarn installés.
  • Connaissances avancées en TypeScript, async/await et REST APIs.
  • Outil comme Postman pour tester les endpoints (optionnel).

Initialisation du projet Node.js

terminal
mkdir acronis-api-client && cd acronis-api-client
npm init -y
npm install axios dotenv typescript @types/node ts-node
npm install -D @types/axios

tsc --init --target es2022 --module commonjs --outDir dist --rootDir src --strict true --esModuleInterop true

mkdir src
cp node_modules/.bin/ts-node ./ts-node

cat > .env << EOF
ACRONIS_BASE_URL=https://us-cloud.acronis.com
ACRONIS_CLIENT_ID=your_client_id_here
ACRONIS_CLIENT_SECRET=your_client_secret_here
ACRONIS_TENANT_ID=your_tenant_id_here
EOF

Ce script initialise un projet Node.js avec TypeScript strict, installe axios pour les HTTP calls et dotenv pour les secrets. Il crée un .env sécurisé avec vos credentials Acronis (obtenus dans la console). Piège à éviter : Ne commitez jamais .env ; ajoutez-le à .gitignore. Le tsconfig.json est optimisé pour ES2022 et modules CommonJS pour compatibilité maximale.

Types TypeScript pour l'API Acronis

src/types.ts
export interface AcronisToken {
  access_token: string;
  expires_in: number;
  token_type: 'Bearer';
  scope: string;
}

export interface AcronisDevice {
  id: string;
  name: string;
  type: 'server' | 'workstation' | 'mobile';
  status: 'online' | 'offline' | 'unknown';
  agent_version: string;
  last_seen: string;
}

export interface AcronisBackupPlan {
  id: string;
  name: string;
  enabled: boolean;
  retention_period: number;
  schedule: { frequency: 'daily' | 'weekly'; time: string };
}

export type AcronisError = {
  code: number;
  message: string;
  details?: any;
};

Ces interfaces TypeScript modélisent les réponses API Acronis (basées sur la doc officielle v2). Elles activent l'autocomplétion IntelliSense et la validation statique. Analogie : Comme un schéma GraphQL, elles préviennent 90% des erreurs runtime. Ajoutez-les tôt pour scaler votre client.

Fonction d'authentification OAuth2

src/auth.ts
import axios from 'axios';
import * as dotenv from 'dotenv';
import { AcronisToken } from './types';

dotenv.config();

const BASE_URL = process.env.ACRONIS_BASE_URL || 'https://us-cloud.acronis.com';
const CLIENT_ID = process.env.ACRONIS_CLIENT_ID!;
const CLIENT_SECRET = process.env.ACRONIS_CLIENT_SECRET!;

let cachedToken: AcronisToken | null = null;
let tokenExpiry = 0;

export async function getAcronisToken(): Promise<AcronisToken> {
  if (cachedToken && Date.now() < tokenExpiry) {
    return cachedToken;
  }

  const tokenResponse = await axios.post(
    `${BASE_URL}/api/2/idp/tokens`,
    new URLSearchParams({
      grant_type: 'client_credentials',
      client_id: CLIENT_ID,
      client_secret: CLIENT_SECRET,
      scope: 'urn:acronis:cloud:default',
    }),
    {
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    }
  );

  cachedToken = tokenResponse.data;
  tokenExpiry = Date.now() + (tokenResponse.data.expires_in - 300) * 1000;
  return cachedToken;
}

Cette fonction implémente OAuth2 client_credentials avec cache token (3600s TTL - 5min buffer). Elle utilise URLSearchParams pour le body form-encoded, standard Acronis. Piège : Sans cache, vous risquez rate-limiting (100 req/min). Testez avec console.log(await getAcronisToken()).

Lister les devices d'un tenant

src/devices.ts
import axios from 'axios';
import { getAcronisToken } from './auth';
import { AcronisDevice, AcronisError } from './types';

const TENANT_ID = process.env.ACRONIS_TENANT_ID!;

const BASE_URL = process.env.ACRONIS_BASE_URL || 'https://us-cloud.acronis.com';

export async function listDevices(limit: number = 100): Promise<AcronisDevice[]> {
  try {
    const token = await getAcronisToken();
    const response = await axios.get(
      `${BASE_URL}/api/protect/v1/tenants/${TENANT_ID}/devices?limit=${limit}`,
      {
        headers: {
          Authorization: `Bearer ${token.access_token}`,
          'Content-Type': 'application/json',
        },
      }
    );
    return response.data.items || [];
  } catch (error: any) {
    const err = error.response?.data as AcronisError;
    throw new Error(`Failed to list devices: ${err?.message || error.message}`);
  }
}

// Usage exemple
(async () => {
  const devices = await listDevices(10);
  console.log(`Found ${devices.length} devices:`, devices.map(d => ({ name: d.name, status: d.status })));
})();

Ce module liste les devices via GET /devices avec pagination (limit). Il propage les erreurs typées Acronis. Avancé : Le script main() est auto-exécutable pour tests unitaires. Analogie : Comme un Kubernetes lister nodes, scalable à 10k+ devices.

Créer un plan de sauvegarde

src/backup-plans.ts
import axios from 'axios';
import { getAcronisToken } from './auth';
import { AcronisBackupPlan } from './types';

const TENANT_ID = process.env.ACRONIS_TENANT_ID!;
const BASE_URL = process.env.ACRONIS_BASE_URL || 'https://us-cloud.acronis.com';

export async function createBackupPlan(planName: string, deviceId: string, retentionDays: number = 30): Promise<AcronisBackupPlan> {
  const token = await getAcronisToken();

  const planPayload = {
    name: planName,
    enabled: true,
    retention_period: { days: retentionDays },
    schedule: {
      frequency: 'daily' as const,
      time: '02:00',
    },
    devices: [{ id: deviceId }],
    storage: { id: 'default_cloud' }, // Remplacez par votre storage ID
  };

  const response = await axios.post(
    `${BASE_URL}/api/protect/v1/tenants/${TENANT_ID}/backup_plans`,
    planPayload,
    {
      headers: {
        Authorization: `Bearer ${token.access_token}`,
        'Content-Type': 'application/json',
      },
    }
  );

  return response.data;
}

// Exemple
(async () => {
  const plan = await createBackupPlan('Daily Backup Plan', 'device-id-example');
  console.log('Created plan:', plan.id, plan.name);
})();

Crée un plan de backup quotidien avec rétention personnalisable, assigné à un device spécifique. Payload conforme à la spec Acronis v1. Piège critique : Vérifiez storage_id via API /storages avant. Utilisez en pipeline GitHub Actions pour auto-deploy.

Script principal d'orchestration

src/index.ts
import { listDevices } from './devices';
import { createBackupPlan } from './backup-plans';

async function main() {
  console.log('🚀 Démarrage client Acronis API');
  
  const devices = await listDevices(5);
  if (devices.length === 0) {
    throw new Error('Aucun device trouvé. Vérifiez TENANT_ID.');
  }

  const criticalDevice = devices.find(d => d.status === 'online' && d.type === 'server');
  if (!criticalDevice) {
    throw new Error('Aucun serveur online trouvé.');
  }

  const plan = await createBackupPlan(`Auto-Plan-${new Date().toISOString().slice(0,10)}`, criticalDevice.id, 90);
  console.log(`✅ Backup plan créé pour ${criticalDevice.name}: ${plan.id}`);
}

main().catch(console.error);

Script orchestre listing + création conditionnelle de plan sur le premier serveur online. Idéal pour cron jobs ou Lambda. Avancé : Gestion d'erreurs globale ; étendez avec webhooks /api/protect/v1/webhooks pour events temps-réel.

Package.json et exécution

package.json
{
  "name": "acronis-api-client",
  "version": "1.0.0",
  "main": "dist/index.js",
  "scripts": {
    "dev": "ts-node src/index.ts",
    "build": "tsc",
    "start": "node dist/index.ts"
  },
  "dependencies": {
    "axios": "^1.7.2",
    "dotenv": "^16.4.5",
    "typescript": "^5.5.3"
  },
  "devDependencies": {
    "@types/node": "^22.3.0",
    "ts-node": "^10.9.2"
  }
}

Met à jour package.json avec scripts prêts-à-l'emploi. Exécutez npm run dev pour tester instantanément. Production : npm run build && npm start. Ajoute nodemon pour watch mode si besoin.

Bonnes pratiques

  • Toujours cacher les tokens : Utilisez Vault/SSM pour prod, rotatez-les mensuellement.
  • Rate limiting : Implémentez exponential backoff (p-queue lib) ; Acronis limite à 100 req/min.
  • Logging structuré : Intégrez Winston ou Pino pour tracer les API calls avec correlation ID.
  • Tests unitaires : Mockez axios avec MSW ; couvrez 90% (jest + msw).
  • Webhooks sécurisés : Validez signatures HMAC pour events backup failed.

Erreurs courantes à éviter

  • Scope manquant : Oublier urn:acronis:cloud:default bloque l'auth (401 Unauthorized).
  • Tenant ID faux : Vérifiez via Console > Tenants ; erreur 404 sur /devices.
  • Token expiré sans refresh : Sans cache, 50% des calls échouent ; implémentez toujours TTL.
  • Payload malformé : Utilisez JSON Schema pour valider ; Acronis renvoie 400 détaillé mais casse les pipelines.

Pour aller plus loin

Approfondissez avec la doc API Acronis complète. Intégrez Kubernetes via operator custom ou Terraform provider community. Découvrez nos formations Learni sur DevOps & Cybersécurité pour certifs avancées. Contribuez sur GitHub : fork ce repo et ajoutez /alerts endpoint !