Compare commits
4 Commits
v2023.5.24
...
v2023.6.22
Author | SHA1 | Date | |
---|---|---|---|
8b5a97da54 | |||
d73e027ee3 | |||
054744e3e9 | |||
0e664bce44 |
@ -1,3 +1,7 @@
|
||||
<div style="text-align:center">
|
||||
<img style="width:250px" src="./misc/resources/logo.svg" />
|
||||
</div>
|
||||
|
||||
# Emissary
|
||||
|
||||
Control plane for "edge" (and OpenWRT-based) devices.
|
||||
|
@ -5,6 +5,8 @@
|
||||
## Tutorials
|
||||
|
||||
- (FR) - [Premiers pas](./tutorials/fr/first-steps.md)
|
||||
- (FR) - [Déployer un serveur mandataire inverse sur un agent](./tutorials/fr/deploy-reverse-proxy.md)
|
||||
- (FR) - [Déployer une configuration UCI personnalisée sur un agent](./tutorials/fr/deploy-uci-configuration.md)
|
||||
|
||||
## References
|
||||
|
||||
|
3
doc/tutorials/fr/deploy-reverse-proxy.md
Normal file
3
doc/tutorials/fr/deploy-reverse-proxy.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Déployer un serveur mandataire inverse sur un agent
|
||||
|
||||
> TODO
|
130
doc/tutorials/fr/deploy-uci-configuration.md
Normal file
130
doc/tutorials/fr/deploy-uci-configuration.md
Normal file
@ -0,0 +1,130 @@
|
||||
# Déployer une configuration UCI personnalisée sur un agent
|
||||
|
||||
Via la spécification [`uci.emissary.cadoles.com`](../../../internal/spec/uci/schema.json) il est possible de configurer un agent avec un système OpenWRT. Dans ce tutoriel nous verrons:
|
||||
|
||||
- Comment exporter une configuration UCI existante au format attendu par Emissary;
|
||||
- Comment modifier la spécification d'un agent Emissary pour mettre à jour sa configuration via le serveur de pilotage.
|
||||
|
||||
## Étapes
|
||||
|
||||
### Identifier l'empreinte de votre agent
|
||||
|
||||
1. Sur la machine agent, utiliser la commande intégrée pour récupérer l'empreinte ("thumbprint") identifiant l'agent:
|
||||
|
||||
```
|
||||
emissary agent show-thumbprint
|
||||
```
|
||||
|
||||
**Noter la valeur retournée. Elle sera utilisée dans les étapes suivantes.**
|
||||
|
||||
### Exporter la configuration UCI de votre agent au format Emissary
|
||||
|
||||
1. Se connecter en SSH sur votre agent Emissary:
|
||||
|
||||
```
|
||||
ssh root@<agent_ip>
|
||||
```
|
||||
|
||||
2. Sur la machine agent, utiliser la commande intégrée pour exporter la configuration UCI de votre agent au format Emissary:
|
||||
|
||||
```
|
||||
uci export | emissary agent openwrt uci transform > my-agent-config.json
|
||||
```
|
||||
|
||||
> **Astuce**
|
||||
>
|
||||
> Par défaut, l'outil [LuCi](https://openwrt.org/fr/doc/howto/luci.essentials) est disponible sur votre agent. Vous pouvez y accéder via l'URL `http://<agent_ip>/`.
|
||||
>
|
||||
> Vous pouvez utiliser LuCi pour modifier la configuration de l'agent (par exemple, configurer le WiFi, créer des règles réseaux, etc) avant d'exporter la configuration.
|
||||
>
|
||||
> De cette manière, il est possible de répliquer celle ci sur plusieurs agents via Emissary !
|
||||
|
||||
3. Transférer le fichier `my-agent-config.json` sur la machine hébergeant votre serveur de pilotage Emissary.
|
||||
|
||||
### Transformer la configuration en spécification
|
||||
|
||||
#### Prérequis
|
||||
|
||||
- [`jq`](https://stedolan.github.io/jq/)
|
||||
- [`sponge`](https://linux.die.net/man/1/sponge) (paquet `moreutils` sur Ubuntu)
|
||||
|
||||
#### Étapes
|
||||
|
||||
1. Sur la machine hébergeant le serveur de pilotage Emissary, utiliser l'outil `jq` pour créer un objet JSON correspondant au schéma attendu par la spécification [`uci.emissary.cadoles.com`](../../../internal/spec/uci/schema.json):
|
||||
|
||||
```bash
|
||||
# Créer la structure de base de la spécification UCI
|
||||
cat >> my-uci-spec.json <<EOF
|
||||
{
|
||||
"config": null,
|
||||
"postImportCommands": [
|
||||
{ "command": "uci", "args": ["commit"] },
|
||||
{ "command": "reload_config", "args": [] }
|
||||
]
|
||||
}
|
||||
EOF
|
||||
|
||||
# Injecter la configuration récupérée de notre agent dans la spécification
|
||||
cat my-uci-spec.json | jq --slurpfile config my-agent-config.json '.config = $config[0]' | sponge my-uci-spec.json
|
||||
```
|
||||
|
||||
Notre spécification est prête à être assignée à notre agent !
|
||||
|
||||
|
||||
### Assigner la spécification à l'agent
|
||||
|
||||
1. Sur la machine hébergeant le serveur de pilotage Emissary, retrouver l'identifiant associé à l'agent:
|
||||
|
||||
```bash
|
||||
# Déclarer une variable contenant l'empreinte de l'agent précédemment trouvée
|
||||
AGENT_THUMBPRINT="<empreinte agent>"
|
||||
|
||||
# Récupérer l'identifiant de l'agent
|
||||
AGENT_ID=$(emissary api agent query -f json | jq -r --arg thumbprint "$AGENT_THUMBPRINT" '.[] | select(.thumbprint == $thumbprint) | .id')
|
||||
```
|
||||
|
||||
2. Assigner la spécification à l'agent UCI:
|
||||
|
||||
```bash
|
||||
cat my-uci-spec.json | emissary api agent spec update -a ${AGENT_ID} --no-patch --spec-data - --spec-name uci.emissary.cadoles.com
|
||||
```
|
||||
|
||||
**Bravo, vous avez déployé des spécifications UCI sur votre agent !**
|
||||
|
||||
### Exemple: modifier le `hostname` de votre agent
|
||||
|
||||
En intervenant directement sur notre spécification, il est possible de modifier la configuration et appliquer ces changements à notre agent.
|
||||
|
||||
1. Sur la machine hébergeant le serveur de pilotage, faire:
|
||||
|
||||
```bash
|
||||
# On créait une variable avec le nouveau hostname de notre agent
|
||||
MY_NEW_AGENT_HOSTNAME="MyEmissaryAgent"
|
||||
|
||||
# On utilise jq afin de modifier la valeur de configuration dans notre spécification UCI
|
||||
cat my-uci-spec.json | jq --arg hostname "$MY_NEW_AGENT_HOSTNAME" '( .config.packages[] | select(.name == "system") | .configs[].options[] | select(.name == "hostname").value ) |= $hostname' | sponge my-uci-spec.json
|
||||
```
|
||||
|
||||
> **Astuce**
|
||||
>
|
||||
> En utilisant la commande `grep -C 10 hostname my-uci-spec.json`, on peut voir que la valeur de configuration `hostname` a bien été mise à jour dans notre spécification.
|
||||
|
||||
2. Mettre à jour la configuration de l'agent:
|
||||
|
||||
```bash
|
||||
cat my-uci-spec.json | emissary api agent spec update -a ${AGENT_ID} --no-patch --spec-data - --spec-name uci.emissary.cadoles.com
|
||||
```
|
||||
|
||||
3. Sur l'agent, après quelques secondes (par défaut, la fréquence de mise à jour est de 1 fois par minute) l'agent devrait avoir son `hostname` mis à jour:
|
||||
|
||||
```
|
||||
uci show system.@system[].hostname
|
||||
```
|
||||
|
||||
Un message de ce type devrait s'afficher:
|
||||
|
||||
```
|
||||
system.cfg01e48a.hostname='MyEmissaryAgent'
|
||||
```
|
||||
|
||||
La modification devrait être également visible dans le prompt du shell de l'agent.
|
@ -1,3 +1,158 @@
|
||||
# Premiers pas
|
||||
|
||||
> TODO
|
||||
## Prérequis
|
||||
|
||||
- Pour le serveur, une machine [Ubuntu 22.04](https://ubuntu.com/download/server)
|
||||
- Pour l'agent, un [RaspberryPi version 3](https://openwrt.org/toh/raspberry_pi_foundation/raspberry_pi)
|
||||
|
||||
## Étapes
|
||||
|
||||
### Préparer votre RaspberryPi
|
||||
|
||||
1. Sur la page des ["versions"](https://forge.cadoles.com/arcad/emissary-firmware/releases) des firmwares du projet Emissary, télécharger la dernière version disponibles correspondant à votre système cible, dans le cas présent `openwrt-<openwrt_version>-emissary-<emissary_firmware_version>-bcm27xx-bcm2710-rpi-3-ext4-factory.img.gz`
|
||||
|
||||
2. Brancher votre carte SD dans le lecteur, flasher celle ci avec le firmware:
|
||||
|
||||
```bash
|
||||
# Chemin vers le fichier de firmware précédemment téléchargé
|
||||
FIRMWARE_FILE="openwrt-<openwrt_version>-emissary-<emissary_firmware_version>-bcm27xx-bcm2710-rpi-3-ext4-factory.img.gz"
|
||||
|
||||
SDCARD_DEVICE=/dev/sdX # Chemin vers le "device" correspondant à votre carte SD
|
||||
|
||||
# Décompresser le firmware
|
||||
gzip -d "${FIRMWARE_FILE}"
|
||||
|
||||
# Flash la carte SD
|
||||
sudo dd if="${FIRMWARE_FILE%.gz}" of="${SDCARD_DEVICE}" bs=2M conv=fsync
|
||||
|
||||
# Attendre la fin des écritures
|
||||
sudo sync
|
||||
```
|
||||
|
||||
3. Placer votre carte SD dans votre RaspberryPi, le connecter à votre réseau en Ethernet puis l'allumer.
|
||||
|
||||
4. Scanner votre réseau pour trouver l'adresse IP de votre Raspberry Pi. Par exemple, avec l'outil `nmap`:
|
||||
|
||||
```bash
|
||||
sudo nmap -sP 192.168.0.* # À modifier par le préfixe correspondant à votre réseau local
|
||||
```
|
||||
|
||||
Une entrée équivalente à la suivante devrait être affichée:
|
||||
|
||||
```bash
|
||||
Starting Nmap 7.93 ( https://nmap.org ) at 2023-05-25 19:29 CEST
|
||||
Nmap scan report for 192.168.0.24
|
||||
Host is up (0.0034s latency).
|
||||
MAC Address: B8:27:EB:E5:7B:55 (Raspberry Pi Foundation)
|
||||
[...]
|
||||
```
|
||||
|
||||
5. Se connecter en SSH sur votre RaspberryPi et définir un mot de passe pour le compte administrateur:
|
||||
|
||||
```bash
|
||||
ssh root@<ip>
|
||||
|
||||
passwd
|
||||
```
|
||||
|
||||
### Installer le serveur Emissary
|
||||
|
||||
1. Sur la machine Ubuntu 22.04, télécharger les paquets Emissary sur la page ["Versions"](https://forge.cadoles.com/arcad/emissary/releases) du projet. Dans le cas présent, choisir le paquet Debian `emissary-server_<emissary_version>_linux_<arch>.deb` où `<arch>` correspond à l'architecture CPU de votre machine.
|
||||
|
||||
2. Installer le paquet télécharger via `dpkg`:
|
||||
|
||||
```
|
||||
sudo dpkg -i emissary-server_<emissary_version>_linux_<arch>.deb
|
||||
```
|
||||
|
||||
3. Appliquer les migrations sur la base de données:
|
||||
|
||||
```shell
|
||||
sudo emissary --workdir /usr/share/emissary --config /etc/emissary/server.yml server database migrate
|
||||
```
|
||||
|
||||
4. Redémarrer le service:
|
||||
|
||||
```shell
|
||||
sudo systemctl restart emissary-server
|
||||
```
|
||||
|
||||
5. Créer un jeton d'administration:
|
||||
|
||||
```shell
|
||||
sudo emissary --workdir /usr/share/emissary --config /etc/emissary/server.yml server auth create-token --role writer --subject $(whoami) > .emissary-token
|
||||
```
|
||||
|
||||
6. Vérifier l'authentification sur l'API:
|
||||
|
||||
```shell
|
||||
emissary api agent query
|
||||
```
|
||||
|
||||
Une réponse équivalente à la suivante devrait s'afficher:
|
||||
|
||||
```shell
|
||||
+----+-------+------------+--------+-------------+-----------+
|
||||
| ID | LABEL | THUMBPRINT | STATUS | CONTACTEDAT | UPDATEDAT |
|
||||
+----+-------+------------+--------+-------------+-----------+
|
||||
+----+-------+------------+--------+-------------+-----------+
|
||||
```
|
||||
|
||||
### Appairer l'agent avec votre serveur
|
||||
|
||||
1. Sur le RaspberryPi, exécuter la commande suivante:
|
||||
|
||||
```shell
|
||||
uci set emissary.agent.server_url='http://<server_ip>:3000'
|
||||
uci commit emissary
|
||||
reload_config
|
||||
```
|
||||
|
||||
2. Via la commande `logread`, vérifier que l'agent arrive à se connecter avec le serveur:
|
||||
|
||||
```shell
|
||||
logread -f
|
||||
```
|
||||
|
||||
Un message de ce type devrait s'afficher:
|
||||
|
||||
```
|
||||
Thu May 25 18:48:51 2023 daemon.info emissary[2202]: 2023-05-25 18:48:51.611 [INFO] <./internal/agent/controller/persistence/controller.go:58> (*Controller).Reconcile no changes detected, doing nothing {"controller": "persistence-controller"}
|
||||
Thu May 25 18:48:51 2023 daemon.info emissary[2202]: 2023-05-25 18:48:51.675 [ERROR] <./internal/agent/controller/spec/controller.go:43>(*Controller).reconcileAgent unexpected agent status {"controller": "spec-controller", "agentID": 1, "status": 0}
|
||||
Thu May 25 18:48:51 2023 daemon.info emissary[2202]: 2023-05-25 18:48:51.676 [INFO] <./internal/agent/controller/openwrt/uci_controller.go:32> (*UCIController).Reconcile could not find uci spec, doing nothing {"controller": "uci-controller"}
|
||||
Thu May 25 18:48:51 2023 daemon.info emissary[2202]: 2023-05-25 18:48:51.677 [INFO] <./internal/agent/controller/app/controller.go:43> (*Controller).Reconcile could not find app spec {"controller": "app-controller"}
|
||||
Thu May 25 18:48:51 2023 daemon.info emissary[2202]: 2023-05-25 18:48:51.678 [INFO] <./internal/agent/controller/proxy/controller.go:35>(*Controller).Reconcile could not find proxy spec {"controller": "proxy-controller"}
|
||||
Thu May 25 18:48:51 2023 daemon.info emissary[2202]: 2023-05-25 18:48:51.680 [INFO] <./internal/agent/controller/mdns/controller.go:38>(*Controller).Reconcile could not find mdns spec {"controller": "mdns-controller"}
|
||||
Thu May 25 18:48:51 2023 daemon.info emissary[2202]: 2023-05-25 18:48:51.680 [INFO] <./internal/agent/controller/openwrt/sysupgrade_controller.go:36> (*SysUpgradeController).Reconcile could not find sysupgrade spec, doing nothing {"controller": "sysupgrade-controller"}
|
||||
```
|
||||
|
||||
3. Sur le serveur, vérifier que l'agent a pu s'enregistrer:
|
||||
|
||||
```shell
|
||||
emissary api agent query
|
||||
```
|
||||
|
||||
Un message de ce type devrait s'afficher:
|
||||
|
||||
```
|
||||
+----+-------+-----------------------------------+--------+-----------------------------------+-----------------------------------+
|
||||
| ID | LABEL | THUMBPRINT | STATUS | CONTACTEDAT | UPDATEDAT |
|
||||
+----+-------+-----------------------------------+--------+-----------------------------------+-----------------------------------+
|
||||
| 1 | | 21CnUATcboKCaheb2uczWCuoxTZtnp... | 0 | 2023-05-25 18:49:51.652680196 ... | "2023-05-25T18:49:51.589225817... |
|
||||
+----+-------+-----------------------------------+--------+-----------------------------------+-----------------------------------+
|
||||
```
|
||||
|
||||
Noter l'identifiant associé à l'agent.
|
||||
|
||||
4. Mettre à jour le statut de l'agent afin qu'il soit en capacité à récupérer ses spécifications:
|
||||
|
||||
```
|
||||
emissary api agent update --agent-id <agent_id> --status 1
|
||||
```
|
||||
|
||||
**Bravo, vous avez appairé votre premier agent et son serveur Emissary !**
|
||||
|
||||
## Aller plus loin
|
||||
|
||||
- [Déployer une configuration UCI personnalisée sur un agent](./deploy-uci-configuration.md)
|
||||
- [Déployer un serveur mandataire inverse sur votre agent](./deploy-reverse-proxy.md)
|
@ -6,7 +6,7 @@ After=network.target
|
||||
Type=simple
|
||||
Restart=always
|
||||
WorkingDirectory=/usr/share/emissary
|
||||
ExecStart=/usr/bin/emissary --config /etc/emissary/config.yml agent run
|
||||
ExecStart=/usr/bin/emissary --config /etc/emissary/agent.yml agent run
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
@ -4,9 +4,9 @@ After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Restart=always
|
||||
Restart=on-failure
|
||||
WorkingDirectory=/usr/share/emissary
|
||||
ExecStart=/usr/bin/emissary --config /etc/emissary/config.yml server run
|
||||
ExecStart=/usr/bin/emissary --config /etc/emissary/server.yml server run
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
339
misc/resources/logo.svg
Normal file
339
misc/resources/logo.svg
Normal file
@ -0,0 +1,339 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 620 620"
|
||||
version="1.1"
|
||||
id="svg110"
|
||||
sodipodi:docname="logo.svg"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview112"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.38064516"
|
||||
inkscape:cx="310"
|
||||
inkscape:cy="306.05932"
|
||||
inkscape:current-layer="svg110" />
|
||||
<defs
|
||||
id="defs50">
|
||||
<style
|
||||
id="style2">.cls-1{fill:#fff;}.cls-2{fill:url(#Dégradé_sans_nom_22);}.cls-3{fill:url(#Dégradé_sans_nom_22-2);}.cls-4{fill:url(#Dégradé_sans_nom_22-3);}.cls-5{fill:#acdce9;}.cls-6{fill:none;}.cls-7{fill:url(#Dégradé_sans_nom_14);}.cls-8{fill:url(#Dégradé_sans_nom_14-2);}.cls-9{fill:url(#Dégradé_sans_nom_14-3);}.cls-10{fill:url(#Dégradé_sans_nom_14-4);}.cls-11{fill:url(#Dégradé_sans_nom_14-5);}.cls-12{fill:url(#Dégradé_sans_nom_14-6);}.cls-13{fill:url(#Dégradé_sans_nom_14-7);}</style>
|
||||
<linearGradient
|
||||
id="Dégradé_sans_nom_22"
|
||||
x1="389.04"
|
||||
y1="577.91"
|
||||
x2="843.52"
|
||||
y2="444.49"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
offset="0"
|
||||
stop-color="#f9b233"
|
||||
id="stop4" />
|
||||
<stop
|
||||
offset="0.05"
|
||||
stop-color="#ef9630"
|
||||
id="stop6" />
|
||||
<stop
|
||||
offset="0.12"
|
||||
stop-color="#e2742c"
|
||||
id="stop8" />
|
||||
<stop
|
||||
offset="0.2"
|
||||
stop-color="#d65729"
|
||||
id="stop10" />
|
||||
<stop
|
||||
offset="0.29"
|
||||
stop-color="#cd3f26"
|
||||
id="stop12" />
|
||||
<stop
|
||||
offset="0.39"
|
||||
stop-color="#c72d24"
|
||||
id="stop14" />
|
||||
<stop
|
||||
offset="0.51"
|
||||
stop-color="#c22023"
|
||||
id="stop16" />
|
||||
<stop
|
||||
offset="0.66"
|
||||
stop-color="#bf1822"
|
||||
id="stop18" />
|
||||
<stop
|
||||
offset="0.99"
|
||||
stop-color="#be1622"
|
||||
id="stop20" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="Dégradé_sans_nom_22-2"
|
||||
x1="347.14"
|
||||
y1="435.21"
|
||||
x2="801.63"
|
||||
y2="301.79"
|
||||
xlink:href="#Dégradé_sans_nom_22" />
|
||||
<linearGradient
|
||||
id="Dégradé_sans_nom_22-3"
|
||||
x1="363.28"
|
||||
y1="490.17"
|
||||
x2="817.76"
|
||||
y2="356.75"
|
||||
xlink:href="#Dégradé_sans_nom_22" />
|
||||
<linearGradient
|
||||
id="Dégradé_sans_nom_14"
|
||||
x1="295.82"
|
||||
y1="531.3"
|
||||
x2="915.72"
|
||||
y2="148.45"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
offset="0"
|
||||
stop-color="#36a9e1"
|
||||
id="stop25" />
|
||||
<stop
|
||||
offset="0.01"
|
||||
stop-color="#35a3db"
|
||||
id="stop27" />
|
||||
<stop
|
||||
offset="0.09"
|
||||
stop-color="#3281b9"
|
||||
id="stop29" />
|
||||
<stop
|
||||
offset="0.17"
|
||||
stop-color="#2f649c"
|
||||
id="stop31" />
|
||||
<stop
|
||||
offset="0.26"
|
||||
stop-color="#2d4c85"
|
||||
id="stop33" />
|
||||
<stop
|
||||
offset="0.37"
|
||||
stop-color="#2b3a72"
|
||||
id="stop35" />
|
||||
<stop
|
||||
offset="0.49"
|
||||
stop-color="#2a2d66"
|
||||
id="stop37" />
|
||||
<stop
|
||||
offset="0.65"
|
||||
stop-color="#29255e"
|
||||
id="stop39" />
|
||||
<stop
|
||||
offset="0.99"
|
||||
stop-color="#29235c"
|
||||
id="stop41" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="Dégradé_sans_nom_14-2"
|
||||
x1="302.24"
|
||||
y1="541.68"
|
||||
x2="922.14"
|
||||
y2="158.84"
|
||||
xlink:href="#Dégradé_sans_nom_14" />
|
||||
<linearGradient
|
||||
id="Dégradé_sans_nom_14-3"
|
||||
x1="308.78"
|
||||
y1="537.64"
|
||||
x2="795.27"
|
||||
y2="237.19"
|
||||
xlink:href="#Dégradé_sans_nom_14" />
|
||||
<linearGradient
|
||||
id="Dégradé_sans_nom_14-4"
|
||||
x1="416.02"
|
||||
y1="726.54"
|
||||
x2="1047.24"
|
||||
y2="336.7"
|
||||
xlink:href="#Dégradé_sans_nom_14" />
|
||||
<linearGradient
|
||||
id="Dégradé_sans_nom_14-5"
|
||||
x1="422.84"
|
||||
y1="722.33"
|
||||
x2="909.33"
|
||||
y2="421.88"
|
||||
xlink:href="#Dégradé_sans_nom_14" />
|
||||
<linearGradient
|
||||
id="Dégradé_sans_nom_14-6"
|
||||
x1="265.42"
|
||||
y1="482.7"
|
||||
x2="896.65"
|
||||
y2="92.86"
|
||||
xlink:href="#Dégradé_sans_nom_14" />
|
||||
<linearGradient
|
||||
id="Dégradé_sans_nom_14-7"
|
||||
x1="272.25"
|
||||
y1="478.49"
|
||||
x2="758.74"
|
||||
y2="178.04"
|
||||
xlink:href="#Dégradé_sans_nom_14" />
|
||||
</defs>
|
||||
<g
|
||||
id="Calque_4"
|
||||
data-name="Calque 4">
|
||||
<circle
|
||||
class="cls-1"
|
||||
cx="310"
|
||||
cy="310"
|
||||
r="310"
|
||||
id="circle52" />
|
||||
</g>
|
||||
<g
|
||||
id="Calque_3"
|
||||
data-name="Calque 3">
|
||||
<path
|
||||
class="cls-2"
|
||||
d="M382.43,551.91c-2.64,12.13-5,37.74,16.31,54a11.79,11.79,0,0,0,10.58,1.87L536.08,569a11.7,11.7,0,0,0,7.55-7.05c3.86-10.27,8.25-33.2-17.06-54.7A11.78,11.78,0,0,0,515.5,505l-7.95,2.44L446.89,526l-56.42,17.28A11.72,11.72,0,0,0,382.43,551.91Z"
|
||||
transform="translate(-270.7 -127.63)"
|
||||
id="path55" />
|
||||
<path
|
||||
class="cls-3"
|
||||
d="M479,384.26c4-2.64,8.43-5.3,13.2-7.93l.27-.14,0,0a4.79,4.79,0,0,0-4.38-.81l-88.29,27a4.79,4.79,0,0,0-3.24,3.35c-1.38,5.29-3.62,17.74,2.13,28.71a4.83,4.83,0,0,0,7.07,1.77,382.78,382.78,0,0,1,40.87-24.81,4.88,4.88,0,0,0,1.67-1.49C453.94,401.88,464.6,393.06,479,384.26Z"
|
||||
transform="translate(-270.7 -127.63)"
|
||||
id="path57" />
|
||||
<path
|
||||
class="cls-4"
|
||||
d="M681.16,333.19a.1.1,0,0,0,0,.2c11.53,2.22,19,6.52,21,12.92,6.28,20.52-46.38,54.83-117.63,76.63-57.32,17.55-109.18,21.65-130.54,11.9-5.18-2.37-8.59-5.55-9.82-9.55a12.49,12.49,0,0,1-.15-6.41.13.13,0,0,0-.19-.14A342.31,342.31,0,0,0,405.47,443c-23.59,17.58-35.56,33.72-31.8,46,4.78,15.62,34.14,22.17,78.27,20.26a.12.12,0,0,1,.13.16l-3,9.55a.13.13,0,0,0,.16.16L508.59,501l13.77-4.21a.13.13,0,0,1,.12,0c1.58,1.16,3,2.32,4.45,3.49a.1.1,0,0,0,.1,0A977.1,977.1,0,0,0,638.75,472.9c136.34-41.74,238.73-102.19,228.68-135C859.38,311.6,781.74,311,681.16,333.19Z"
|
||||
transform="translate(-270.7 -127.63)"
|
||||
id="path59" />
|
||||
<path
|
||||
class="cls-5"
|
||||
d="M694.39,348.33c-2-6.73-12.15-10.44-27.62-11.29a154.33,154.33,0,0,0-16.61.08c16,24.86-14.65,54-30.44,66.73C667.12,384.85,698.66,362.27,694.39,348.33Z"
|
||||
transform="translate(-270.7 -127.63)"
|
||||
id="path61" />
|
||||
<path
|
||||
class="cls-6"
|
||||
d="M873.93,336.73c-2.86-12.89-15.64-20-33.51-23.45A283.91,283.91,0,0,1,861,371.4C871.09,360.09,876.52,348.34,873.93,336.73Z"
|
||||
transform="translate(-270.7 -127.63)"
|
||||
id="path63" />
|
||||
<path
|
||||
class="cls-7"
|
||||
d="M299.08,479.05a2.32,2.32,0,0,0-2.2,2.73A309.22,309.22,0,0,0,323.68,562a2.27,2.27,0,0,0,2.43,1.21A283.59,283.59,0,0,1,299.91,479Z"
|
||||
transform="translate(-270.7 -127.63)"
|
||||
id="path65" />
|
||||
<path
|
||||
class="cls-8"
|
||||
d="M363,548.81q6.94-2.13,13.73-3.79a2.31,2.31,0,0,0,1.63-1.53c.36-1.14.75-2.3,1.18-3.47a2.3,2.3,0,0,1,1.5-1.43l59.3-18.15a2.31,2.31,0,0,0-.74-4.52c-14.07.37-63.57-.07-72-24.18,0,0-5.47-10.13,4.16-25.33-1.49.5-3,1-4.51,1.45-18.64,5.7-46.44,10.25-67.28,11.15a283.59,283.59,0,0,0,26.2,84.17,2.25,2.25,0,0,0,.62-.15A298.13,298.13,0,0,1,363,548.81Z"
|
||||
transform="translate(-270.7 -127.63)"
|
||||
id="path67" />
|
||||
<path
|
||||
class="cls-9"
|
||||
d="M363,548.81q6.94-2.13,13.73-3.79a2.31,2.31,0,0,0,1.63-1.53c.36-1.14.75-2.3,1.18-3.47a2.3,2.3,0,0,1,1.5-1.43l59.3-18.15a2.31,2.31,0,0,0-.74-4.52c-14.07.37-63.57-.07-72-24.18,0,0-5.47-10.13,4.16-25.33-1.49.5-3,1-4.51,1.45-18.64,5.7-46.44,10.25-67.28,11.15a283.59,283.59,0,0,0,26.2,84.17,2.25,2.25,0,0,0,.62-.15A298.13,298.13,0,0,1,363,548.81Z"
|
||||
transform="translate(-270.7 -127.63)"
|
||||
id="path69" />
|
||||
<path
|
||||
class="cls-10"
|
||||
d="M582.7,722.94c157.87,0,285.85-128,285.85-285.85A286.63,286.63,0,0,0,861,371.4c-37.61,42-140.24,77.8-140.27,77.8s-98,40.65-188,55.81c0,0,0,0,0,0,.64.42,36.32,24.49,13,68.42h0L403.46,615.88h0a41.35,41.35,0,0,1-5.21-3.19h0q-6.9,2.55-14.24,4.81c-5.69,1.74-12.1,3.41-18.87,5A285.19,285.19,0,0,0,582.7,722.94Z"
|
||||
transform="translate(-270.7 -127.63)"
|
||||
id="path71" />
|
||||
<path
|
||||
class="cls-11"
|
||||
d="M582.7,722.94c157.87,0,285.85-128,285.85-285.85A286.63,286.63,0,0,0,861,371.4c-37.61,42-140.24,77.8-140.27,77.8s-98,40.65-188,55.81c0,0,0,0,0,0,.64.42,36.32,24.49,13,68.42h0L403.46,615.88h0a41.35,41.35,0,0,1-5.21-3.19h0q-6.9,2.55-14.24,4.81c-5.69,1.74-12.1,3.41-18.87,5A285.19,285.19,0,0,0,582.7,722.94Z"
|
||||
transform="translate(-270.7 -127.63)"
|
||||
id="path73" />
|
||||
<path
|
||||
class="cls-12"
|
||||
d="M390,402.12h0a42,42,0,0,1,1.88-5.3h0l102.24-31.3h0l5.49,5.94h0c.52-.28,89.13-46.1,171-40.81h0c.13,0,111.77-28.45,169.78-17.37-46.14-95.88-144.2-162-257.72-162-156.72,0-284,126.12-285.81,282.4,16.25-9.51,36.55-18.94,52.53-23.83A177.82,177.82,0,0,1,390,402.12Z"
|
||||
transform="translate(-270.7 -127.63)"
|
||||
id="path75" />
|
||||
<path
|
||||
class="cls-13"
|
||||
d="M390,402.12h0a42,42,0,0,1,1.88-5.3h0l102.24-31.3h0l5.49,5.94h0c.52-.28,89.13-46.1,171-40.81h0c.13,0,111.77-28.45,169.78-17.37-46.14-95.88-144.2-162-257.72-162-156.72,0-284,126.12-285.81,282.4,16.25-9.51,36.55-18.94,52.53-23.83A177.82,177.82,0,0,1,390,402.12Z"
|
||||
transform="translate(-270.7 -127.63)"
|
||||
id="path77" />
|
||||
<path
|
||||
class="cls-5"
|
||||
d="M613.5,341.7a453.93,453.93,0,0,0-50.22,12.41c-26.81,8.2-50.89,18-69.82,28-20.21,10.63-34.52,21.39-40,30.47-2.22,3.7-3,7.13-2.08,10.14,1,3.39,4.13,6,8.91,7.89,19,7.48,64.86,3.18,116.58-12C635.88,378.72,622.92,352.06,613.5,341.7Z"
|
||||
transform="translate(-270.7 -127.63)"
|
||||
id="path79" />
|
||||
<circle
|
||||
class="cls-1"
|
||||
cx="432.9"
|
||||
cy="112.17"
|
||||
r="8.82"
|
||||
id="circle81" />
|
||||
<circle
|
||||
class="cls-1"
|
||||
cx="360.51"
|
||||
cy="174.46"
|
||||
r="4.41"
|
||||
id="circle83" />
|
||||
<circle
|
||||
class="cls-1"
|
||||
cx="253.85"
|
||||
cy="124.11"
|
||||
r="6.72"
|
||||
id="circle85" />
|
||||
<circle
|
||||
class="cls-1"
|
||||
cx="140.55"
|
||||
cy="150.46"
|
||||
r="4.41"
|
||||
id="circle87" />
|
||||
<circle
|
||||
class="cls-1"
|
||||
cx="221.77"
|
||||
cy="190.68"
|
||||
r="5.03"
|
||||
id="circle89" />
|
||||
<circle
|
||||
class="cls-1"
|
||||
cx="316"
|
||||
cy="56.58"
|
||||
r="4.41"
|
||||
id="circle91" />
|
||||
<circle
|
||||
class="cls-1"
|
||||
cx="272.6"
|
||||
cy="497.14"
|
||||
r="8.82"
|
||||
id="circle93" />
|
||||
<circle
|
||||
class="cls-1"
|
||||
cx="370.54"
|
||||
cy="480.67"
|
||||
r="4.41"
|
||||
id="circle95" />
|
||||
<circle
|
||||
class="cls-1"
|
||||
cx="434.95"
|
||||
cy="420.7"
|
||||
r="6.72"
|
||||
id="circle97" />
|
||||
<circle
|
||||
class="cls-1"
|
||||
cx="546.81"
|
||||
cy="388.76"
|
||||
r="4.41"
|
||||
id="circle99" />
|
||||
<circle
|
||||
class="cls-1"
|
||||
cx="495.3"
|
||||
cy="463.34"
|
||||
r="5.03"
|
||||
id="circle101" />
|
||||
<circle
|
||||
class="cls-1"
|
||||
cx="347.84"
|
||||
cy="391.81"
|
||||
r="4.41"
|
||||
id="circle103" />
|
||||
<circle
|
||||
class="cls-1"
|
||||
cx="346.13"
|
||||
cy="559.72"
|
||||
r="6.72"
|
||||
id="circle105" />
|
||||
<circle
|
||||
class="cls-1"
|
||||
cx="499.71"
|
||||
cy="334.37"
|
||||
r="4.41"
|
||||
id="circle107" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 11 KiB |
Reference in New Issue
Block a user