Articles sur : Développement

Premiers pas avec notre API

Saviez-vous que toutes les actions sur Nua.ge étaient automatisables ? Maintenant oui !

Il s'agit d'une API au format REST, dont la documentation est entièrement au format OpenAPI. Vous pouvez donc l'importer facilement dans des outils comme Postman ou Insomnia.

La spec technique est lisible ici : https://api.nua.ge/docs/.


Dans cet article nous allons créer notre premier projet et notre premier serveur. Il vous faut au préalable un compte déjà créé sur Nua.ge avec des droits "Administrateur".

Logiciels nécessaires


Pour cet article, nous utiliserons uniquement "curl", un logiciel permettant de faire des appels HTTP en ligne de commande. Il est disponible de base sous Linux et sous MAC. Sous Windows, vous devez d'abord installer les packages officiels puis utiliser Powershell.

Obtention du token JWT


L'authentification sur Nua.ge se fait à base de token JWT. Il s'agit d'une grande chaîne de caractère qui contient la liste de vos autorisations. Pour cela, on se connecte de la manière suivante :
curl -s -XPOST https://api.nua.ge/arya/auth -H "Content-Type: application/json" -d '{"name": "email@example.com", "password": "MySup3rP4ssw0rd", "organization": "acmecorp"}'

Qu'avons-nous fait ici ?
nous avons envoyé un contenu de type POST
nous avons précisé au serveur que notre contenu est au format JSON.
nous avons précisé notre email, notre mot de passe et notre organisation, qui correspond au sous-domaine Nua.ge que nous utilisons.

Le serveur nous répond alors avec une structure json contenant deux clés :
token : la chaîne d'authentification qu'il va falloir fournir pour les appels API, mais utilisable seulement pendant un délai assez court (quelques minutes).
refresh_token : une chaine plus courte mais valable plusieurs jours, et nous permettant d'obtenir un nouveau token facilement sans resaisir notre login ou notre mot de passe. Nous ne nous en servirons pas dans ce tutorial.

Si vous êtes curieux, sachez que le contenu de la chaîne token est lisible en la copiant sur https://jwt.io

Pour cet article nous allons rester en mode manuel et allons simplement copier la chaine "token" à la main et la mettre dans une variable d'env :
export TOKEN="eyJ0..........................................."


Pour la suite on va aussi avoir besoin de notre UUID d'organisation. Pour l'obtenir :
curl -s https://api.nua.ge/arya/organizations -H "Content-Type: application/json" -H "Accept: application/json" -H "Authorization: Bearer $TOKEN"

Et notez bien le champ "id" retourné


Création d'un nouveau projet


Toutes les ressources sont rangées dans un projet. Les projets sont cloisonnés entre eux et la facturation sera établie par projet. Pratique si vous avez plusieurs sites pour savoir réellement qui vous coûte combien.

curl -s -XPOST https://api.nua.ge/arya/projects -H "Content-Type: application/json" -H "Accept: application/json" -H "Authorization: Bearer $TOKEN" -d '{"description": "Super projet qui tue", "organization": "/arya/organizations/4e99f1ed-abf3-4be0-ac25-1a7aa71579c3"}'

Qu'avons-nous fait ici ?
nous avons précisé la description de notre projet (qui peut être contenir des espaces ... et même des emojis!)
nous avons précisé sur quelle organisation le créer.

Qu'avons-nous obtenu ? Cette structure JSON :
{
  "id":"dc2eef5e-6325-4b13-a084-db45e5d48992",
  "driverType":"openstack",
  "name":"k3ytx9ir76ke4xt0",
  "description":"Super projet qui tue",
  "createdAt":"2021-12-14T11:21:46+00:00"
}

Soit :
id : l'uuid du projet
driverType : la techno utilisée derrière votre projet. Oui, c'est bien de l'OpenStack derrière Nua.ge :)
name: son nom de code pour notre usage interne.
description : on retrouve la chaîne de caractère fournie au préalable
createdAt : la date de création du projet

Création d'une keyPair



Si votre utilisateur n'a pas encore de clé SSH, il va falloir en créer une pour la suite ...

Si vous n'en avez pas du tout, générez d'abord une clé en local :
ssh-keygen -t rsa -b 4096 -C "email@example.com"

La commande va créer deux fichiers :
id_rsa : la véritable clé, qui ne doit pas quitter votre ordinateur
id_rsa.pub : la clé publique, qui par définition peut être communiquée à des tiers. C'est son contenu que vous devez copier pour la suite.

Pour ajouter votre clé publique dans Nua.ge :
curl -s -XPOST https://api.nua.ge/arya/keypairs -H "Content-Type: application/json" -H "Accept: application/json" -H "Authorization: Bearer $TOKEN" -d '{"publicKey":"le-contenu-du-fichier-id_rsa.pub"}'

Et vous obtenez une réponse positive avec un ID de clé.

Création d'une instance


La création d'une instance dans Nua.ge demande un certain nombre d'informations :
le nom du serveur (ça c'est facile).
la clé publique à provisionner pour s'y connecter (nous venons de le faire).
le système d'exploitation à installer.
les caractéristiques matérielles de l'instance.

Commençons par le choix de l'OS. Nua.ge fournit plusieurs possibilités. Toutes les images sont listables sur l'appel API https://api.nua.ge/rockefeller/images ; mais si nous voulons filtrer sur les images de type ubuntu c'est très simple :
curl -H "Accept: application/json" -g 'https://api.nua.ge/rockefeller/images?osName=ubuntu'

En retour l'API nous retourne la liste des images qui correspondent à ce critère. Nous notons l'ID de celle souhaitée de côté.

Passons aux caractéristiques physiques. Nous voulons une instance avec 2 coeurs et 4Go de RAM. Est-ce que ce modèle existe ?
curl -H "Accept: application/json" -g 'https://api.oxv.dev/rockefeller/flavors?core=2&ram=4'

Oui, nous avons une réponse ! Notons son ID également.

Nous avons donc :
notre ID de flavor, correspondant à la configuration matérielle de l'instance
notre ID d' image, correspondant au système d'exploitation à installer
notre ID de keypair, correspondant à la clé publique à installer


Lançons notre instance maintenant :
curl -v -XPOST https://api.nua.ge/rockefeller/servers -H "Content-Type: application/json" -H "Accept: application/json" -H "Authorization: Bearer $TOKEN" -d '{"name":"monsuperserveur", "keypair": "/arya/keypairs/9941f1cb-4a61-4c72-9a26-0d5bbc893a68", "project": "/arya/projects/dc2eef5e-6325-4b13-a084-db45e5d48992", "image": "/rockefeller/images/cd983ba6-a49c-424b-9c97-55a0e86ec9ce", "flavor": "/rockefeller/flavors/4e93117c-5bdb-4667-80af-37bf7dc3d730"}'

Et la réponse :
{
  "id":"69648ccd-05b4-4a18-9dc0-641284f4d212",
  "project":"\/arya\/projects\/dc2eef5e-6325-4b13-a084-db45e5d48992",
  "securityGroups":[],
  "ips":[{
    "id":"77d3ae37-cbc2-40ac-8147-c248d226a171",
    "addressFamily":"ipv4",
    "type":"private",
    "address":null
  }],
  "name":"monsuperserveur",
  "description":null,
  "flavor":"\/rockefeller\/flavors\/4e93117c-5bdb-4667-80af-37bf7dc3d730",
  "image":"\/rockefeller\/images\/cd983ba6-a49c-424b-9c97-55a0e86ec9ce",
  "createdAt":"2021-12-14T13:35:52+00:00",
  "status":"on",
  "state":null
}

Quelques infos :
securityGroup : les règles de sécurité appliquées à l'instance. Par défaut, aucune règle n'est appliquée, ce qui veut dire que cette instance ne sera pas joignable en public.
ips : la liste des IPs attribuées à cette instance. On a forcément une adresse IP privée, et à la création on ne la connait pas tout de suite. Elle arrive :)
status : l'état souhaité de l'instance. Ici par défaut on la veut allumée, donc "on".
state : l'état réel de l'instance. Là elle est trop récente donc on ne sait pas encore son état.

Attendons quelques secondes, et redemandons au serveur des infos sur notre instance :
curl "https://api.oxv.dev/rockefeller/servers/69648ccd-05b4-4a18-9dc0-641284f4d212" -H "Accept: application/json" -H "Authorization: Bearer $TOKEN"

Nous avons alors de nouvelles infos :
{
  "id": "69648ccd-05b4-4a18-9dc0-641284f4d212",
  "project": "/arya/projects/dc2eef5e-6325-4b13-a084-db45e5d48992",
  "securityGroups": [],
  "ips": [
    {
      "id": "77d3ae37-cbc2-40ac-8147-c248d226a171",
      "addressFamily": "ipv4",
      "type": "private",
      "address": "192.168.1.65"
    }
  ],
  "name": "monsuperserveur",
  "description": null,
  "flavor": "/rockefeller/flavors/4e93117c-5bdb-4667-80af-37bf7dc3d730",
  "image": "/rockefeller/images/cd983ba6-a49c-424b-9c97-55a0e86ec9ce",
  "createdAt": "2021-12-14T13:35:52+00:00",
  "status": "on",
  "state": "on"
}

on voit que state vaut maintenant "on". C'est bon, notre VM est prête !
on a maintenant une IP privée qui est 192.168.1.65

Avons-nous terminé ? Pas vraiment ... En effet, on veut maintenant pouvoir se connecter à cette instance, sauf qu'elle n'est joignable que depuis son réseau privée, c'est à dire uniquement par les autres instances du même projet.

Ajout d'une IP publique


On doit donc ajouter une IP publique à cette instance. C'est très simple :
curl -v -XPOST https://api.nua.ge/rockefeller/ips -H "Content-Type: application/json" -H "Accept: application/json" -H "Authorization: Bearer $TOKEN" -d '{"server": "/rockefeller/servers/69648ccd-05b4-4a18-9dc0-641284f4d212", "type": "public", "addressFamily": "ipv4"}'

Dans cet appel, nous avons précisé :
l'ID (ou plutôt l'IRI) de notre serveur
le type d'IP souhaité (public ou private).
et le type d'IPV4 (ipv4 ou ipv6).

Attendons encore quelques secondes et redemandons les infos sur notre serveur :

curl -s "https://api.nua.ge/rockefeller/servers/69648ccd-05b4-4a18-9dc0-641284f4d212" -H "Accept: application/json" -H "Authorization: Bearer $TOKEN"


{
  "id": "69648ccd-05b4-4a18-9dc0-641284f4d212",
  "project": "/arya/projects/dc2eef5e-6325-4b13-a084-db45e5d48992",
  "securityGroups": [],
  "ips": [
    {
      "id": "77d3ae37-cbc2-40ac-8147-c248d226a171",
      "addressFamily": "ipv4",
      "type": "private",
      "address": "192.168.1.65"
    },
    {
      "id": "86cbbcbd-d2dc-4275-a0e6-cd43b5a38964",
      "addressFamily": "ipv4",
      "type": "public",
      "address": "185.189.159.128"
    }
  ],
  "name": "monsuperserveur",
  "description": null,
  "flavor": "/rockefeller/flavors/4e93117c-5bdb-4667-80af-37bf7dc3d730",
  "image": "/rockefeller/images/cd983ba6-a49c-424b-9c97-55a0e86ec9ce",
  "createdAt": "2021-12-14T13:35:52+00:00",
  "status": "on",
  "state": "on"
}

On a maintenant une IP publique ! Et pourtant, impossible de s'y connecter ! Et oui, nous avons oublié d'ajouter des règles de sécurité. Chez Nua.ge, notre philosophie est "la sécurité avant tout". Votre instance n'est donc pas joignable du net par défaut, il va falloir autoriser des flux.

Ajout de règles de firewall


Ce que nous appelons des securityRules chez nous. Pour éviter de devoir en manipuler trop en même temps, nous avons des securityGroup qui sont des groupes de règles. C'est cela que nous allons attacher à notre instance.
Pour ce premier test, nous voulons pouvoir accéder à notre instance en SSH ainsi que lancer un serveur web dessus.
Récupérons déjà les ID des deux groupes de sécurité en question :
curl "https://api.nua.ge/rockefeller/security_groups?name[]=web&name[]=ssh" -H "Accept: application/json" -H "Authorization: Bearer $TOKEN"

L'API vous retourne également le détail des règles qui seront appliquées à votre instance. Ajoutons maintenant les deux securityGroup à notre instance :

curl -XPOST "https://api.nua.ge/rockefeller/servers/69648ccd-05b4-4a18-9dc0-641284f4d212/security_groups/7b898385-4f0c-4181-afb5-a30f7f58d220" -H "Authorization: Bearer $TOKEN"
curl -XPOST "https://api.nua.ge/rockefeller/servers/69648ccd-05b4-4a18-9dc0-641284f4d212/security_groups/22dcb1a7-ffdb-42fa-88ee-f09c3c0e5535" -H "Authorization: Bearer $TOKEN"

Ces deux appels ne retournent aucun contenu. Un code 204 est affiché en cas de succès et 404 si le serveur ou le securityGroup ne sont pas trouvés.

On se connecte maintenant à notre instance, avec notre clé SSH créé précédemment :
ssh ubuntu@185.189.159.128

Et oui, ça fonctionne !


Conclusion


Félicitations ! Si vous êtes arrivés jusque là vous avez créé avec succès votre première instance uniquement avec l'API. Vous avez pu utiliser quelques uns des nombreux filtres possibles sur l'API également.
Pour aller plus loin :
vous pouvez explorer la spec technique détaillée pour voir tout ce qu'il est possible de faire sur Nua.ge : https://api.nua.ge/docs/
vous pouvez suivre la suite de cet article.

Mis à jour le : 23/06/2022

Cet article a-t-il répondu à vos questions ?

Partagez vos commentaires

Annuler

Merci !