Security

API Security

CSRF token

As a countermeasure to prevent Cross-Site Request Forgeries (CSRF), the Ardexa API requires a CSRF token be submitted with any request that modifies data, e.g. POST.

Two cookies are provided by the API for any request: connect.sid and XSRF-TOKEN. The CSRF token, XSRF-TOKEN, must be passed as an HTTP header, X-XSRF-TOKEN, for any POST, PUT or DELETE operation.

Usage

Here are three examples of fetching and using a CSRF token in Linux shell, Javascript and Python. All three are command line tool that read the TOKEN from the environment and take two arguments: the workgroup ID and the name of the new device, e.g.

./create.sh 123123123 "test sh"
node create.mjs 123123123 "test js"
python3 create.py 123123123 "test py"

Linux shell

#!/bin/sh

# $TOKEN is imported from the environment, it is the API token
ardexa_cloud=app.ardexa.com
arch="Linux 64 bit (x86_64)"
workgroup_id=$1
device_name=$2

# Needs an XSRF token to use POST
xsrf_token=$(curl -s --cookie-jar /tmp/ardexa-cookie.txt -i https://$ardexa_cloud/api/v1/version | grep '^set-cookie: XSRF-TOKEN' | sed -e 's/.*TOKEN=\([^;]*\).*/\1/' -e 's/%2f/\//gi' -e 's/%2b/+/gi' -e 's/%3d/=/gi')

# Create the agent
curl -s -H "X-XSRF-TOKEN: $xsrf_token" -H "authorization: Bearer $TOKEN" -H "content-type: application/json" --cookie /tmp/ardexa-cookie.txt -X POST --output /tmp/agent-sh.zip "https://$ardexa_cloud/api/v1/devices/$workgroup_id" -d "{\"name\": \"$device_name\", \"arch\": \"$arch\"}"

echo "Agent zip file can be found at /tmp/agent-sh.zip"

Javascript

import { writeFileSync } from 'node:fs';
import got from 'got';
import {CookieJar} from 'tough-cookie';

const ardexaCloud = 'app.ardexa.com'
const arch = 'Linux 64 bit (x86_64)'
const workgroupId = process.argv[2]
const deviceName = process.argv[3]

function getXsrf (cookieJar) {
  const cookies = cookieJar.getCookiesSync(`https://${ardexaCloud}`)
  for (const cookie of cookies) {
    if (cookie.key === 'XSRF-TOKEN') return decodeURIComponent(cookie.value)
  }
  throw new Error('Failed to find XSRF token')
}

async function main () {
  const cookieJar = new CookieJar();
  const client =  got.extend({ cookieJar });
  await client.get(`https://${ardexaCloud}/api/v1/version`);
  const xsrf = getXsrf(cookieJar)
  const res = await client.post(`https://${ardexaCloud}/api/v1/devices/${workgroupId}`, {
    headers: {
      'X-XSRF-TOKEN': xsrf,
      authorization: `bearer ${process.env.TOKEN}`
    },
    json: {
      name: deviceName,
      arch
    }
  });
  writeFileSync('/tmp/agent-js.zip', res.rawBody)
  console.log('Agent zip file can be found at /tmp/agent-js.zip')
}

main()

Python

import sys
import os
import requests

ardexa_cloud = 'app.ardexa.com'
arch = 'Linux 64 bit (x86_64)'
workgroup_id = sys.argv[1]
device_name = sys.argv[2]

s = requests.Session()
s.get(f'https://{ardexa_cloud}/api/v1/version');
xsrf = requests.utils.unquote(s.cookies.get_dict().get('XSRF-TOKEN'))
headers = {
  'X-XSRF-TOKEN': xsrf,
  'authorization': f'bearer {os.environ["TOKEN"]}'
}
json = {
    'name': device_name,
    'arch': arch
}
r = s.post(f'https://{ardexa_cloud}/api/v1/devices/{workgroup_id}', headers=headers, json=json)
with open('/tmp/agent-py.zip', 'wb') as f:
    f.write(r.content)

print('Agent zip file can be found at /tmp/agent-py.zip')

Last updated