Skip to main content

Cours

DEVOPS - Du commit au déploiement.pdf

Bloc 1

Culture : né en 2009 par Patrick Debois
Accélérer les délais de livraison, le time-to-market et la fiabilité des déploiements. (un livre  : The phoenix project)

Les 3 piliers du DevOps

La culture : 

You build it, you run it

Werner Vogels CTO d'Amazon

  • Collaboration
  • Responsabilité partagée
  • Amélioration continue

L'automatisation : 

Pulumi, Terraform, Ansible (OpenSource, agentless)

  • CI/CD Pipeline
  • Infra as code
  • Tests automatisés

La mesure :

Prometheus + Grafana

  • Monitoring
  • Feedback loop
  • Métriques DORA

CI/CD : définition et différences

Continuous integration Continuous delivery/deployment
Intégration fréquent Delivery : déploiement en 1 clic
Test auto a chaque commit Deployment automatique
Détection rapide des régressions Environnement staging -> production
Build automatique de l'artefact Rollback auto

3 environnements : Dev/Sandbox -> Staging release -> Production

Les bénéfices du CI/CD
  • Reduction du time-to-market de 50 à 80%
  • Détection des bugs en minutes et pas en jours
  • Déploiement plus fréquents et plus sûr
  • Meilleur collaboration Dev/Ops
  • Traçabilité complète du code à la production
  • Capacité de rollback instantané
Flux CI/CD

CODE -> COMMIT -> TEST -> BUILD -> PUSH -> DEPLOY
Développeur -> git push -> npm test -> Docker build -> Docker hub -> Netlify
CI CD

Tour des outils :

Github action, GitLab CI, Jenkins (Orienté CD), Docker, Netlify (fronted), N8N

Nous on va utiliser GitHub action, qui se base sur des fichiers YAML

Les GitHub Actions

Workflow > Event > Job > Step > Runner

Bloc 2

No-code low code Full code
Zapier, make n8n, Retool Scripts Python
Interface visuelle Nodes + expressions

Terraform, Ansible

Aucun code requis Code optionnel

Contrôle total

n8n, concepts clés

Webhook, trigger -> IF, Condition -> HTTP Request -> Message Discord et/ou notification email

Cas d'usage métier 

CI/CI notif Monitoring Onboarding Sécurité Data Sync Reporting
Pipeline -> Slack/Discord Alertes infra -> ticket Nouvel employé -> comptes CVE détectée -> Scan CRm -> ERP sync KPI quotidien - PDF
Alerte échec build Jira/ServiceNow automatique AD, Email, Slack, VPN Rapport - équipe sécu Transformation + routing Email auto au manages

Bloc 3

TP dans le support de cours.

 

N8N

CyberWatch-TP-Guide.pdf

Workflow fait pour le TP (jusqu'à la partie metabase)

{
  "name": "Cyberwatch - MSA",
  "nodes": [
    {
      "parameters": {},
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        384,
        -168
      ],
      "id": "453c733d-675e-4ebe-9a53-4fd65e000333",
      "name": "When clicking ‘Execute workflow’"
    },
    {
      "parameters": {
        "jsCode": "const row = $input.first().json;\nreturn [{ json: { body: JSON.stringify(row) } }];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1280,
        -240
      ],
      "id": "cd7e689f-ea56-4fda-bd2a-823419a914c5",
      "name": "Prepare Body"
    },
    {
      "parameters": {
        "url": "https://services.nvd.nist.gov/rest/json/cves/2.0",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "pubStartDate",
              "value": "2025-01-01T00:00:00.000"
            },
            {
              "name": "pubEndDate",
              "value": "2025-04-16T23:59:59.999"
            },
            {
              "name": "cvssV3Severity",
              "value": "CRITICAL"
            },
            {
              "name": "resultsPerPage",
              "value": "10"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        608,
        -168
      ],
      "id": "e6087f2e-7eba-4e17-a0b8-a598496a3c0d",
      "name": "HTTP Request6"
    },
    {
      "parameters": {
        "jsCode": "const items = $input.all();\nconst parsed = [];\nfor (const item of items) {\n  const vulnerabilities = item.json.vulnerabilities || [];\n  for (const vuln of vulnerabilities) {\n    const cve = vuln.cve;\n    if (!cve) continue;\n    const desc = (cve.descriptions || []).find(d => d.lang === 'en');\n    const cvssV3 = (cve.metrics?.cvssMetricV31 ||\n      cve.metrics?.cvssMetricV30 || [])[0]?.cvssData || {};\n    let vendor = null, product = null;\n    outer: for (const config of (cve.configurations || [])) {\n      for (const node of (config.nodes || [])) {\n        for (const cpe of (node.cpeMatch || [])) {\n          const parts = (cpe.criteria || '').split(':');\n          if (parts.length >= 5) {\n            vendor  = parts[3] !== '*' ? parts[3] : null;\n            product = parts[4] !== '*' ? parts[4] : null;\n            break outer;\n          }\n        }\n      }\n    }\n    parsed.push({ json: {\n      cve_id:              cve.id,\n      published_at:        cve.published,\n      last_modified:       cve.lastModified,\n      status:              cve.vulnStatus,\n      cvss_v3_score:       cvssV3.baseScore ?? null,\n      cvss_v3_severity:    cvssV3.baseSeverity ?? null,\n      attack_vector:       cvssV3.attackVector ?? null,\n      attack_complexity:   cvssV3.attackComplexity ?? null,\n      privileges_required: cvssV3.privilegesRequired ?? null,\n      user_interaction:    cvssV3.userInteraction ?? null,\n      confidentiality:     cvssV3.confidentialityImpact ?? null,\n      integrity:           cvssV3.integrityImpact ?? null,\n      availability:        cvssV3.availabilityImpact ?? null,\n      affected_vendor:     vendor,\n      affected_product:    product,\n      description:         desc?.value ?? null,\n      collected_at:        new Date().toISOString()\n    }});\n  }\n}\nreturn parsed;"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        832,
        -168
      ],
      "id": "90b50001-d634-4574-be03-8b0e1d50cace",
      "name": "Code in JavaScript3"
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        1056,
        -168
      ],
      "id": "2d70e2f4-80ef-43e6-80fa-74123f211673",
      "name": "Split In Batches2"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{ $json.Supabase_URL }}/rest/v1/cve",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "on_conflict",
              "value": "cve_id"
            }
          ]
        },
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "apikey",
              "value": "={{ $json.Supabase_secret }}"
            },
            {
              "name": "Authorization",
              "value": "=Bearer {{ $json.Supabase_secret }}"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Prefer",
              "value": "resolution=merge-duplicates"
            }
          ]
        },
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ $json.body }}",
        "options": {
          "batching": {
            "batch": {
              "batchSize": 1,
              "batchInterval": 250
            }
          }
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        1728,
        -168
      ],
      "id": "91d6986d-3422-439a-9fce-deedd6aca126",
      "name": "HTTP Request7"
    },
    {
      "parameters": {
        "mode": "raw",
        "jsonOutput": "{\n  \"Supabase_secret\": \"sb_secret_ici\",\n  \"Supabase_URL\":\"Supabase_URL_ici\"\n}\n",
        "includeOtherFields": true,
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        1504,
        -240
      ],
      "id": "a8a2ba10-992b-4e4c-8d11-6e7ebb9de4a7",
      "name": "Secret Supabase"
    }
  ],
  "pinData": {},
  "connections": {
    "When clicking ‘Execute workflow’": {
      "main": [
        [
          {
            "node": "HTTP Request6",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Body": {
      "main": [
        [
          {
            "node": "Secret Supabase",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request6": {
      "main": [
        [
          {
            "node": "Code in JavaScript3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript3": {
      "main": [
        [
          {
            "node": "Split In Batches2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split In Batches2": {
      "main": [
        [],
        [
          {
            "node": "Prepare Body",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request7": {
      "main": [
        [
          {
            "node": "Split In Batches2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Secret Supabase": {
      "main": [
        [
          {
            "node": "HTTP Request7",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate"
  },
  "versionId": "ffd8ee42-0806-4696-b09a-17ede870e426",
  "meta": {
    "templateCredsSetupCompleted": true,
    "instanceId": "3bf30934ba51ff8b01281907dd297e33866b7d2872975c43b1d7af51d9aa78aa"
  },
  "id": "ai9avvidlbvQkEKs",
  "tags": []
}