Compare commits
83 Commits
feat-compa
...
master
Author | SHA1 | Date |
---|---|---|
core | 2120ec06f9 | |
core | 12a24b135a | |
core | 0b807b351d | |
core | 51bb540ab4 | |
core | ec8cc4f1ca | |
core | 30a8d59ba8 | |
core | 47a3199336 | |
core | 3ed98c8d8a | |
core | 8ed4d1768e | |
core | c9d37f41ac | |
core | 057e9e3ce3 | |
core | a5fb79288b | |
core | d8888e8f6e | |
core | 13dec2963c | |
core | f7de7ff592 | |
core | c1762169b7 | |
core | bda0ac2a52 | |
core | 011737c527 | |
core | 026d00b9cb | |
core | 71604380a1 | |
core | 908e1b845c | |
core | e4ab3769ba | |
core | 420d7f9788 | |
core | 80d9bdff92 | |
core | 7cb2dc86e2 | |
core | 5f6b3fde83 | |
core | 7fcb20a823 | |
core | 1a2ad44d58 | |
core | c0ceed09fb | |
core | d44a6c1166 | |
core | 2045d7b636 | |
core | 74f045ed62 | |
core | 5813aef8de | |
core | f108db3f23 | |
core | 646340b637 | |
core | 2a5a2bb910 | |
core | 19332e519b | |
core | a1ae83fa5f | |
core | 4180bdd162 | |
core | 68627b0c92 | |
core | e7e49f9255 | |
core | 51b6d3a85a | |
core | cd07ff5310 | |
core | 5204994769 | |
core | 79b1765ed5 | |
core | 53c6fb18fd | |
core | cec6c72380 | |
core | ef679a085c | |
core | 7e4289755a | |
core | 18edf13e3c | |
core | 39090a9f0a | |
core | 431a1b3b37 | |
core | ceecf9cea1 | |
core | d61667a231 | |
core | 0193ffb828 | |
core | b09c7e3e57 | |
core | d5c0b6461a | |
core | e94ad5a5e6 | |
core | 45c8ad5913 | |
core | 6cebc0cef0 | |
core | 585bec1a2a | |
core | 89315a3e9d | |
core | 256a38d66b | |
core | 12c3fe8d2a | |
core | 65f641329d | |
core | 380d38229d | |
core | 36227f99e5 | |
core | 31229a1172 | |
core | aadd420f71 | |
core | ae990cf977 | |
core | 7d1bdf07e0 | |
core | e519700530 | |
core | 27bf92d2cd | |
core | 3d24ee60cb | |
core | 2eee055f2a | |
core | bc5c9560f5 | |
core | 0b3ba39532 | |
core | eeb624b058 | |
core | 4eec05762c | |
core | a21c4bff08 | |
core | 11a37ff909 | |
core | be14179c2d | |
core | 1da76da1a0 |
|
@ -0,0 +1,18 @@
|
|||
on:
|
||||
push:
|
||||
branches:
|
||||
master
|
||||
jobs:
|
||||
build:
|
||||
runs_on: docker
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Install dependencies
|
||||
run: cd docs && yarn install
|
||||
- name: Install additional dependencies
|
||||
run: apt update && apt-get install -y sshpass rsync
|
||||
- name: Build static site
|
||||
run: cd docs && yarn build
|
||||
- name: Upload site
|
||||
run: sshpass -p "${{ secrets.TRIFID_WEBSITE_NEXT_PASSWORD }}" rsync -Ia --mkpath -e 'ssh -p ${{ secrets.TRIFID_WEBSITE_NEXT_PORT }} -o StrictHostKeyChecking=no' docs/build ${{ secrets.TRIFID_WEBSITE_NEXT_USER }}@${{ secrets.TRIFID_WEBSITE_NEXT_IP }}:${{ secrets.TRIFID_WEBSITE_NEXT_PATH }}
|
|
@ -22,15 +22,13 @@ jobs:
|
|||
override: true
|
||||
- name: Install additional dependencies
|
||||
run: apt update && apt-get install -y libclang-dev clang sshpass rsync
|
||||
- name: Enable Rust dependency caching
|
||||
uses: https://github.com/Swatinem/rust-cache@v2
|
||||
- name: Compile release binary
|
||||
uses: https://github.com/actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --release --bin tfclient
|
||||
args: --bin tfclient --profile release-ci
|
||||
- name: Upload binary
|
||||
run: sshpass -p "${{ secrets.TRIFID_DLCDN_PASSWORD }}" rsync --mkpath -e 'ssh -p ${{ secrets.TRIFID_DLCDN_PORT }} -o StrictHostKeyChecking=no' target/release/tfclient ${{ secrets.TRIFID_DLCDN_USER }}@${{ secrets.TRIFID_DLCDN_IP }}:${{ secrets.TRIFID_DLCDN_PATH }}/tfclient/amd64/$GITHUB_SHA/tfclient
|
||||
run: sshpass -p "${{ secrets.TRIFID_DLCDN_PASSWORD }}" rsync --mkpath -e 'ssh -p ${{ secrets.TRIFID_DLCDN_PORT }} -o StrictHostKeyChecking=no' target/release-ci/tfclient ${{ secrets.TRIFID_DLCDN_USER }}@${{ secrets.TRIFID_DLCDN_IP }}:${{ secrets.TRIFID_DLCDN_PATH }}/tfclient/amd64/$GITHUB_SHA/tfclient
|
||||
build_arm64:
|
||||
runs_on: docker-arm64
|
||||
steps:
|
||||
|
@ -46,12 +44,44 @@ jobs:
|
|||
profile: minimal
|
||||
toolchain: stable
|
||||
override: true
|
||||
- name: Install aarch64 target
|
||||
run: rustup target add aarch64-unknown-linux-gnu
|
||||
- name: Install additional dependencies
|
||||
run: apt update && apt-get install -y libclang-dev clang sshpass rsync
|
||||
run: apt update && apt-get install -y libclang-dev clang sshpass rsync gcc-arm-linux-gnueabi gcc-aarch64-linux-gnu
|
||||
- name: Compile release binary
|
||||
uses: https://github.com/actions-rs/cargo@v1
|
||||
env:
|
||||
RUSTFLAGS: "-C linker=aarch64-linux-gnu-gcc"
|
||||
with:
|
||||
command: build
|
||||
args: --bin tfclient --target aarch64-unknown-linux-gnu --profile release-ci
|
||||
- name: Upload binary
|
||||
run: sshpass -p "${{ secrets.TRIFID_DLCDN_PASSWORD }}" rsync --mkpath -e 'ssh -p ${{ secrets.TRIFID_DLCDN_PORT }} -o StrictHostKeyChecking=no' target/aarch64-unknown-linux-gnu/release-ci/tfclient ${{ secrets.TRIFID_DLCDN_USER }}@${{ secrets.TRIFID_DLCDN_IP }}:${{ secrets.TRIFID_DLCDN_PATH }}/tfclient/arm64/$GITHUB_SHA/tfclient
|
||||
build_win64:
|
||||
runs_on: docker
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Setup Go toolchain
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.20'
|
||||
- name: Setup Rust toolchain
|
||||
uses: https://github.com/actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
override: true
|
||||
- name: Install cross-compilation toolchain
|
||||
run: rustup target add x86_64-pc-windows-gnu
|
||||
- name: Install additional dependencies
|
||||
run: apt update && apt-get install -y libclang-dev clang sshpass rsync mingw-w64 zip
|
||||
- name: Compile release binary
|
||||
uses: https://github.com/actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --release --bin tfclient
|
||||
args: --bin tfclient --target x86_64-pc-windows-gnu --profile release-ci
|
||||
- name: Compile release bundle
|
||||
run: ./build_windows.sh
|
||||
- name: Upload binary
|
||||
run: sshpass -p "${{ secrets.TRIFID_DLCDN_PASSWORD }}" rsync --mkpath -e 'ssh -p ${{ secrets.TRIFID_DLCDN_PORT }} -o StrictHostKeyChecking=no' target/release/tfclient ${{ secrets.TRIFID_DLCDN_USER }}@${{ secrets.TRIFID_DLCDN_IP }}:${{ secrets.TRIFID_DLCDN_PATH }}/tfclient/arm64/$GITHUB_SHA/tfclient
|
||||
run: sshpass -p "${{ secrets.TRIFID_DLCDN_PASSWORD }}" rsync --mkpath -e 'ssh -p ${{ secrets.TRIFID_DLCDN_PORT }} -o StrictHostKeyChecking=no' target/x86_64-pc-windows-gnu/release-ci/tfclient.zip ${{ secrets.TRIFID_DLCDN_USER }}@${{ secrets.TRIFID_DLCDN_IP }}:${{ secrets.TRIFID_DLCDN_PATH }}/tfclient/win64/$GITHUB_SHA/tfclient.zip
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
on:
|
||||
push:
|
||||
branches:
|
||||
master
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
jobs:
|
||||
build_x64:
|
||||
runs_on: docker
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Setup Rust toolchain
|
||||
uses: https://github.com/actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
override: true
|
||||
- name: Install additional dependencies
|
||||
run: apt update && apt-get install -y libclang-dev clang sshpass rsync
|
||||
- name: Compile release binary
|
||||
uses: https://github.com/actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --bin trifid-api --profile release-ci
|
||||
- name: Upload binary
|
||||
run: sshpass -p "${{ secrets.TRIFID_DLCDN_PASSWORD }}" rsync --mkpath -e 'ssh -p ${{ secrets.TRIFID_DLCDN_PORT }} -o StrictHostKeyChecking=no' target/release-ci/trifid-api ${{ secrets.TRIFID_DLCDN_USER }}@${{ secrets.TRIFID_DLCDN_IP }}:${{ secrets.TRIFID_DLCDN_PATH }}/trifid-api/amd64/$GITHUB_SHA/trifid-api
|
||||
build_arm64:
|
||||
runs_on: docker-arm64
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Setup Rust toolchain
|
||||
uses: https://github.com/actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
override: true
|
||||
- name: Install aarch64 target
|
||||
run: rustup target add aarch64-unknown-linux-gnu
|
||||
- name: Install additional dependencies
|
||||
run: apt update && apt-get install -y libclang-dev clang sshpass rsync gcc-arm-linux-gnueabi gcc-aarch64-linux-gnu
|
||||
- name: Compile release binary
|
||||
uses: https://github.com/actions-rs/cargo@v1
|
||||
env:
|
||||
RUSTFLAGS: "-C linker=aarch64-linux-gnu-gcc"
|
||||
with:
|
||||
command: build
|
||||
args: --bin trifid-api --target aarch64-unknown-linux-gnu --profile release-ci
|
||||
- name: Upload binary
|
||||
run: sshpass -p "${{ secrets.TRIFID_DLCDN_PASSWORD }}" rsync --mkpath -e 'ssh -p ${{ secrets.TRIFID_DLCDN_PORT }} -o StrictHostKeyChecking=no' target/aarch64-unknown-linux-gnu/release-ci/trifid-api ${{ secrets.TRIFID_DLCDN_USER }}@${{ secrets.TRIFID_DLCDN_IP }}:${{ secrets.TRIFID_DLCDN_PATH }}/trifid-api/arm64/$GITHUB_SHA/trifid-api
|
||||
build_win64:
|
||||
runs_on: docker
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Setup Rust toolchain
|
||||
uses: https://github.com/actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
override: true
|
||||
- name: Install cross-compilation toolchain
|
||||
run: rustup target add x86_64-pc-windows-gnu
|
||||
- name: Install additional dependencies
|
||||
run: apt update && apt-get install -y libclang-dev clang sshpass rsync mingw-w64 zip
|
||||
- name: Compile release binary
|
||||
uses: https://github.com/actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --bin trifid-api --target x86_64-pc-windows-gnu --profile release-ci
|
||||
- name: Upload binary
|
||||
run: sshpass -p "${{ secrets.TRIFID_DLCDN_PASSWORD }}" rsync --mkpath -e 'ssh -p ${{ secrets.TRIFID_DLCDN_PORT }} -o StrictHostKeyChecking=no' target/x86_64-pc-windows-gnu/release-ci/trifid-api.exe ${{ secrets.TRIFID_DLCDN_USER }}@${{ secrets.TRIFID_DLCDN_IP }}:${{ secrets.TRIFID_DLCDN_PATH }}/trifid-api/win64/$GITHUB_SHA/trifid-api.exe
|
|
@ -8,3 +8,4 @@ packages/void_amd64_tfclient/work
|
|||
packages/void_amd64_tfclient/*.xbps
|
||||
*.pem
|
||||
*.xbps
|
||||
tfweb/build
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||
<data-source source="LOCAL" name="trifid@localhost" uuid="39c81b89-3fc4-493f-b203-7a00527cffe6">
|
||||
<data-source source="LOCAL" name="trifidapi@localhost" uuid="39c81b89-3fc4-493f-b203-7a00527cffe6">
|
||||
<driver-ref>postgresql</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
|
||||
|
|
|
@ -1,15 +1,20 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="CPP_MODULE" version="4">
|
||||
<component name="Go" enabled="true" />
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/tfclient/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/trifid-api/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/trifid-pki/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/dnapi-rs/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/trifid-api/trifid_api_entities/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/trifid-api/trifid_api_migration/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/tfcli/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/nebula-ffi/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/sagittariusdb/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/trifid-api-old/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/trifid-api-old/trifid_api_entities/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/trifid-api-old/trifid_api_migration/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/trifid-api-derive/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/nebula-config/src" isTestSource="false" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
|
|
14
Cargo.toml
|
@ -1,12 +1,18 @@
|
|||
[workspace]
|
||||
members = [
|
||||
"trifid-api",
|
||||
"trifid-api/trifid_api_migration",
|
||||
"trifid-api/trifid_api_entities",
|
||||
"tfclient",
|
||||
"trifid-pki",
|
||||
"dnapi-rs",
|
||||
"tfcli",
|
||||
"nebula-ffi"
|
||||
"nebula-ffi",
|
||||
"nebula-config",
|
||||
"trifid-api",
|
||||
"trifid-api-derive",
|
||||
"trifid_mobile_bridge"
|
||||
]
|
||||
resolver = "2"
|
||||
|
||||
[profile.release-ci]
|
||||
inherits = "release"
|
||||
lto = true
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@ FROM rust:latest
|
|||
|
||||
COPY trifid-pki /trifid-pki
|
||||
COPY dnapi-rs /dnapi-rs
|
||||
COPY trifid-api /trifid-api
|
||||
COPY trifid-api-old /trifid-api
|
||||
|
||||
RUN cd /trifid-api && cargo build --release && cp target/release/trifid-api /bin/trifid-api
|
||||
RUN cd /trifid-api-old && cargo build --release && cp target/release/trifid-api-old /bin/trifid-api-old
|
||||
|
||||
CMD ["/bin/trifid-api"]
|
||||
|
|
10
README.md
|
@ -14,7 +14,7 @@ The API implementation is tested with the official dnclient implementaiton, and
|
|||
|
||||
# Documentation
|
||||
|
||||
You can find the documentation [here](https://man.e3t.cc/~core/trifid-docs)!
|
||||
You can find the documentation [here](https://trifid.e3t.cc)! You can find the latest, bleeding-edge docs [here](https://next.trifid.e3t.cc)!
|
||||
|
||||
Documentation work is underway. Parts of the documentation may be broken or unfinished.
|
||||
|
||||
|
@ -25,10 +25,10 @@ tfclient is designed to be self-contained and as cross-platform as possible. Whe
|
|||
In addition, not all clients support connecting to trifid-api. Both tfclient support tiers and trifid-api connectivity capability are listed below.
|
||||
|
||||
| Operating System / Architecture | tfclient support tier | trifid-api compatible? |
|
||||
|---------------------------------|-----------------------------------|-------------------------------------|
|
||||
| Windows (all architectures) | Tier 2 - external nebula required | Yes (tfclient/dnclient) |
|
||||
| Darwin (OSX, MacOS) | Tier 2 - untested, maybe T1 | Yes (tfclient/dnclient) |
|
||||
| FreeBSD (amd64) | Tier 1 - untested | Yes (tfclient/dnclient) |
|
||||
|---------------------------------|-----------------------|-------------------------------------|
|
||||
| Windows (all architectures) | Tier 1 | Yes (tfclient/dnclient) |
|
||||
| Darwin (OSX, MacOS) | Tier 1 | Yes (tfclient/dnclient) |
|
||||
| FreeBSD (amd64) | Tier 1 | Yes (tfclient/dnclient) |
|
||||
| Linux (most architectures) | Tier 1 | Yes (tfclient/dnclient) |
|
||||
| Android | Unsupported | No (almost - help wanted! see docs) |
|
||||
| iOS | Unsupported | No (almost - help wanted! see docs) |
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
cargo build --target x86_64-pc-windows-gnu --profile release-ci --bin tfclient
|
||||
rm -rf target/x86_64-pc-windows-gnu/release-ci/tfclient_dist/
|
||||
mkdir -p target/x86_64-pc-windows-gnu/release-ci/tfclient_dist/
|
||||
cp target/x86_64-pc-windows-gnu/release-ci/tfclient.exe target/x86_64-pc-windows-gnu/release-ci/tfclient_dist/tfclient.exe
|
||||
echo "[*] Downloading WinTun"
|
||||
mkdir -p target/x86_64-pc-windows-gnu/release-ci/tfclient_dist/dist/windows/
|
||||
wget https://www.wintun.net/builds/wintun-0.14.1.zip -O /tmp/wintun.zip
|
||||
echo "[*] Unzipping WinTun"
|
||||
unzip -d target/x86_64-pc-windows-gnu/release-ci/tfclient_dist/dist/windows/ /tmp/wintun.zip
|
||||
echo "[*] Building zip bundle"
|
||||
cd target/x86_64-pc-windows-gnu/release-ci
|
||||
zip -r tfclient.zip tfclient_dist/*
|
||||
cd ../../../
|
||||
echo "[*] Windows production build success!"
|
|
@ -0,0 +1,2 @@
|
|||
Users
|
||||
\-
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "dnapi-rs"
|
||||
version = "0.2.0"
|
||||
version = "0.2.3"
|
||||
edition = "2021"
|
||||
description = "A rust client for the Defined Networking API"
|
||||
license = "AGPL-3.0-or-later"
|
||||
|
|
|
@ -13,6 +13,7 @@ use log::{debug, error};
|
|||
use reqwest::StatusCode;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::error::Error;
|
||||
use reqwest::header::HeaderValue;
|
||||
use trifid_pki::cert::serialize_ed25519_public;
|
||||
use trifid_pki::ed25519_dalek::{Signature, Signer, SigningKey, Verifier};
|
||||
use url::Url;
|
||||
|
@ -89,10 +90,15 @@ impl Client {
|
|||
.send()
|
||||
.await?;
|
||||
|
||||
let empty_hval;
|
||||
#[allow(clippy::unwrap_used)] {
|
||||
empty_hval = HeaderValue::from_str("").unwrap();
|
||||
};
|
||||
|
||||
let req_id = resp
|
||||
.headers()
|
||||
.get("X-Request-ID")
|
||||
.ok_or("Response missing X-Request-ID")?
|
||||
.unwrap_or(&empty_hval)
|
||||
.to_str()?;
|
||||
debug!("enrollment request complete {{req_id: {}}}", req_id);
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ use log::{debug, error, trace};
|
|||
use reqwest::StatusCode;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::error::Error;
|
||||
use reqwest::header::HeaderValue;
|
||||
use trifid_pki::cert::serialize_ed25519_public;
|
||||
use trifid_pki::ed25519_dalek::{Signature, Signer, SigningKey, Verifier};
|
||||
use url::Url;
|
||||
|
@ -90,10 +91,15 @@ impl Client {
|
|||
.body(req_json)
|
||||
.send()?;
|
||||
|
||||
let empty_hval;
|
||||
#[allow(clippy::unwrap_used)] {
|
||||
empty_hval = HeaderValue::from_str("").unwrap();
|
||||
};
|
||||
|
||||
let req_id = resp
|
||||
.headers()
|
||||
.get("X-Request-ID")
|
||||
.ok_or("Response missing X-Request-ID")?
|
||||
.unwrap_or(&empty_hval)
|
||||
.to_str()?;
|
||||
debug!("enrollment request complete {{req_id: {}}}", req_id);
|
||||
|
||||
|
@ -254,7 +260,10 @@ impl Client {
|
|||
|
||||
ed_privkey.verify(b64_msg_bytes, &Signature::from_slice(&signature)?)?;
|
||||
debug!("signature valid via clientside check");
|
||||
debug!("signed with key: {:x?}", ed_privkey.verifying_key().as_bytes());
|
||||
debug!(
|
||||
"signed with key: {:x?}",
|
||||
ed_privkey.verifying_key().as_bytes()
|
||||
);
|
||||
|
||||
let body = RequestV1 {
|
||||
version: 1,
|
||||
|
|
|
@ -13,7 +13,7 @@ pub const DO_UPDATE: &str = "DoUpdate";
|
|||
|
||||
base64_serde_type!(Base64Standard, base64::engine::general_purpose::STANDARD);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
/// `RequestV1` is the version 1 `DNClient` request message.
|
||||
pub struct RequestV1 {
|
||||
/// Version is always 1
|
||||
|
@ -30,7 +30,7 @@ pub struct RequestV1 {
|
|||
pub signature: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
/// `RequestWrapper` wraps a `DNClient` request message. It consists of a
|
||||
/// type and value, with the type string indicating how to interpret the value blob.
|
||||
pub struct RequestWrapper {
|
||||
|
@ -48,14 +48,14 @@ pub struct RequestWrapper {
|
|||
pub timestamp: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
/// `SignedResponseWrapper` contains a response message and a signature to validate inside `data`.
|
||||
pub struct SignedResponseWrapper {
|
||||
/// The response data contained in this message
|
||||
pub data: SignedResponse,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
/// `SignedResponse` contains a response message and a signature to validate.
|
||||
pub struct SignedResponse {
|
||||
/// The API version - always 1
|
||||
|
@ -68,14 +68,14 @@ pub struct SignedResponse {
|
|||
pub signature: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
/// `CheckForUpdateResponseWrapper` contains a response to `CheckForUpdate` inside "data."
|
||||
pub struct CheckForUpdateResponseWrapper {
|
||||
/// The response data contained in this message
|
||||
pub data: CheckForUpdateResponse,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
/// `CheckForUpdateResponse` is the response generated for a `CheckForUpdate` request.
|
||||
pub struct CheckForUpdateResponse {
|
||||
#[serde(rename = "updateAvailable")]
|
||||
|
@ -83,7 +83,7 @@ pub struct CheckForUpdateResponse {
|
|||
pub update_available: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
/// `DoUpdateRequest` is the request sent for a `DoUpdate` request.
|
||||
pub struct DoUpdateRequest {
|
||||
#[serde(rename = "edPubkeyPEM")]
|
||||
|
@ -100,7 +100,7 @@ pub struct DoUpdateRequest {
|
|||
pub nonce: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
/// A server response to a `DoUpdateRequest`, with the updated config and key information
|
||||
pub struct DoUpdateResponse {
|
||||
#[serde(with = "Base64Standard")]
|
||||
|
@ -141,7 +141,7 @@ pub struct EnrollRequest {
|
|||
pub timestamp: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(untagged)]
|
||||
/// The response to an `EnrollRequest`
|
||||
pub enum EnrollResponse {
|
||||
|
@ -157,7 +157,7 @@ pub enum EnrollResponse {
|
|||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
/// The data included in an successful enrollment.
|
||||
pub struct EnrollResponseData {
|
||||
#[serde(with = "Base64Standard")]
|
||||
|
@ -176,7 +176,7 @@ pub struct EnrollResponseData {
|
|||
pub organization: EnrollResponseDataOrg,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
/// The organization data that this node is now a part of
|
||||
pub struct EnrollResponseDataOrg {
|
||||
/// The organization ID that this node is now a part of
|
||||
|
@ -185,7 +185,7 @@ pub struct EnrollResponseDataOrg {
|
|||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
/// `APIError` represents a single error returned in an API error response.
|
||||
pub struct APIError {
|
||||
/// The error code
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
# Dependencies
|
||||
/node_modules
|
||||
|
||||
# Production
|
||||
/build
|
||||
|
||||
# Generated files
|
||||
.docusaurus
|
||||
.cache-loader
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
|
@ -0,0 +1,41 @@
|
|||
# Website
|
||||
|
||||
This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator.
|
||||
|
||||
### Installation
|
||||
|
||||
```
|
||||
$ yarn
|
||||
```
|
||||
|
||||
### Local Development
|
||||
|
||||
```
|
||||
$ yarn start
|
||||
```
|
||||
|
||||
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
|
||||
|
||||
### Build
|
||||
|
||||
```
|
||||
$ yarn build
|
||||
```
|
||||
|
||||
This command generates static content into the `build` directory and can be served using any static contents hosting service.
|
||||
|
||||
### Deployment
|
||||
|
||||
Using SSH:
|
||||
|
||||
```
|
||||
$ USE_SSH=true yarn deploy
|
||||
```
|
||||
|
||||
Not using SSH:
|
||||
|
||||
```
|
||||
$ GIT_USER=<Your GitHub username> yarn deploy
|
||||
```
|
||||
|
||||
If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
|
|
@ -0,0 +1,3 @@
|
|||
module.exports = {
|
||||
presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
|
||||
};
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
slug: first-blog-post
|
||||
title: First Blog Post
|
||||
authors: core
|
||||
tags: [hola, docusaurus]
|
||||
---
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
|
@ -0,0 +1,44 @@
|
|||
---
|
||||
slug: long-blog-post
|
||||
title: Long Blog Post
|
||||
authors: core
|
||||
tags: [hello, docusaurus]
|
||||
---
|
||||
|
||||
This is the summary of a very long blog post,
|
||||
|
||||
Use a `<!--` `truncate` `-->` comment to limit blog post size in the list view.
|
||||
|
||||
<!--truncate-->
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
slug: mdx-blog-post
|
||||
title: MDX Blog Post
|
||||
authors: [core]
|
||||
tags: [docusaurus]
|
||||
---
|
||||
|
||||
Blog posts support [Docusaurus Markdown features](https://docusaurus.io/docs/markdown-features), such as [MDX](https://mdxjs.com/).
|
||||
|
||||
:::tip
|
||||
|
||||
Use the power of React to create interactive blog posts.
|
||||
|
||||
```js
|
||||
<button onClick={() => alert('button clicked!')}>Click me!</button>
|
||||
```
|
||||
|
||||
<button onClick={() => alert('button clicked!')}>Click me!</button>
|
||||
|
||||
:::
|
After Width: | Height: | Size: 94 KiB |
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
slug: welcome
|
||||
title: Welcome
|
||||
authors: [core]
|
||||
tags: [facebook, hello, docusaurus]
|
||||
---
|
||||
|
||||
[Docusaurus blogging features](https://docusaurus.io/docs/blog) are powered by the [blog plugin](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-blog).
|
||||
|
||||
Simply add Markdown files (or folders) to the `blog` directory.
|
||||
|
||||
Regular blog authors can be added to `authors.yml`.
|
||||
|
||||
The blog post date can be extracted from filenames, such as:
|
||||
|
||||
- `2019-05-30-welcome.md`
|
||||
- `2019-05-30-welcome/index.md`
|
||||
|
||||
A blog post folder can be convenient to co-locate blog post images:
|
||||
|
||||
![Docusaurus Plushie](./docusaurus-plushie-banner.jpeg)
|
||||
|
||||
The blog supports tags as well!
|
||||
|
||||
**And if you don't want a blog**: just delete this directory, and use `blog: false` in your Docusaurus config.
|
|
@ -0,0 +1,5 @@
|
|||
core:
|
||||
name: core
|
||||
title: Project Founder & Maintainer
|
||||
url: https://coredoes.dev
|
||||
image_url: https://github.com/c0repwn3r.png
|
|
@ -0,0 +1,3 @@
|
|||
# Disclaimer
|
||||
|
||||
trifid-api and the Trifid project are in no way intended to disrupt Defined Networking's buisness. Please, if you are a commercial customer, use their service instead. Trifid was developed and released with the full knowledge and permission of the Defined Networking team.
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Trifid Introduction
|
||||
|
||||
Welcome to the Trifid project documentation! Trifid is a free and open-source reimplementation of the [Defined Networking](https://defined.net) protocol for managing [Nebula](https://github.com/slackhq/nebula) networks.
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"label": "tfcli",
|
||||
"position": 5,
|
||||
"link": {
|
||||
"type": "generated-index",
|
||||
"description": "Documentation for tfcli, the CLI for the management API."
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Introduction
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"label": "tfclient",
|
||||
"position": 4,
|
||||
"link": {
|
||||
"type": "generated-index",
|
||||
"description": "Documentation for tfclient, trifid's VPN client reimplementation."
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 9.9 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 5.1 KiB |
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Introduction
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
# Troubleshooting
|
||||
|
||||
This page lists common issues with tfclient and how to resolve them. This page will be updated occasionally as needed.
|
||||
|
||||
## On Windows, traffic can leave but cannot enter
|
||||
|
||||
This is [a known issue with Nebula](https://github.com/slackhq/nebula/issues/621), and by extension tfclient. [A workaround is available - see here for details.](/docs/tfclient/windows_firewall)
|
|
@ -0,0 +1,45 @@
|
|||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Windows Firewall Setup
|
||||
|
||||
:::info
|
||||
This is only needed on Windows-based platforms. On macOS and Linux, the firewall works correctly out-of-the-box.
|
||||
:::
|
||||
|
||||
On Windows-based platforms, Nebula (and by extension tfclient) cannot properly configure Windows Defender Firewall automatically, thus preventing any inbound traffic from reaching your machine over your network (outbound traffic will still work). To fix this, you need to add a firewall rule to Windows Defender Firewall.
|
||||
|
||||
It is recommended that you add a rule allowing **all inbound traffic from your network.** Nebula has a built-in firewall, thus it is preferred to allow the Nebula firewall to function as intended and leave Windows Defender Firewall essentially disabled for your VPN's subnet, allowing Nebula to function in it's place.
|
||||
|
||||
## Adding the inbound rule
|
||||
|
||||
1. Search for "Windows Defender Firewall with Advanced Security" and open it. This requires administrator privileges. You should see the window below.
|
||||
|
||||
![Windows Defender Firewall Window](img/firewall_main.png)
|
||||
|
||||
2. Select "Inbound Rules" on the left, and then click "New Rule" to open the New Inbound Rule Wizard. You should see the window below.
|
||||
|
||||
![New Inbound Rule Wizard](img/new_rule_1.png)
|
||||
|
||||
3. Select the Custom option, and click Next.
|
||||
4. Click the Next button for the Program step.
|
||||
5. Click the Next button for the Protocol and Port step.
|
||||
6. Select the "These IP addresses" checkbox under "Which remote IP addresses does this rule apply to?" as shown below.
|
||||
|
||||
![These IP addresses radio](img/new_rule_2.png)
|
||||
|
||||
7. Select the Add button next to "These IP addresses" to open the window shown below.
|
||||
|
||||
![IP Address popup](img/new_rule_3.png)
|
||||
|
||||
8. In the box under "This IP address or subnet" enter the CIDR notation of your network i.e. `10.16.0.0/15`. Ask your network administrator for this value if you do not know it.
|
||||
9. Click the "OK" button.
|
||||
10. Click the "Next" button.
|
||||
11. Under "What action should be taken when a connection matches the specified conditions?", select "Allow the connection", then click Next.
|
||||
12. Click "Next" on the Profile page.
|
||||
13. Enter a title for the rule. We recommend using something like `tfclient/nebula/YOUR_NETWORK_NAME/YOUR_NETWORK_CIDR`, such as `tfclient/nebula/corporate/10.16.0.0/15`.
|
||||
14. If desired, enter additional descriptions in the second text box.
|
||||
15. Select the "Finish" option.
|
||||
|
||||
The changes should take effect immediately, and traffic should begin flowing 5-10 seconds after applying the rule (give Nebula time to perform handshakes and establish tunnels). If it does not take effect immediately, rebooting the affected machine typically resolves any issues.
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"label": "tfweb",
|
||||
"position": 3,
|
||||
"link": {
|
||||
"type": "generated-index",
|
||||
"description": "Documentation for tfweb, trifid's web UI."
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Introduction
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"label": "trifid-api",
|
||||
"position": 2,
|
||||
"link": {
|
||||
"type": "generated-index",
|
||||
"description": "Documentation for trifid-api, the API server reimplementation."
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
# API Support
|
||||
|
||||
This document is valid for: `trifid-api 0.3.0`.
|
||||
|
||||
This document is only useful for developers, and it lists what endpoint versions are currently supported by trifid-api. This is subject to change at any time according to SemVer constraints.
|
||||
|
||||
Endpoint types:
|
||||
- **Documented** is an endpoint available in the official documentation
|
||||
- **Reverse-engineered** is an endpoint that was reverse-engineered
|
||||
|
||||
| Endpoint Name | Version | Endpoint | Type | Added In |
|
||||
|---------------------------|---------|------------------------------------|--------------------|----------------|
|
||||
| Signup | v1 | POST /v1/signup | Reverse-engineered | 0.3.0/79b1765e |
|
||||
| Get Magic Link | v1 | POST /v1/auth/magic-link | Reverse-engineered | 0.3.0/52049947 |
|
||||
| Verify Magic Link | v1 | POST /v1/auth/verify-magic-link | Reverse-engineered | 0.3.0/51b6d3a8 |
|
||||
| Create TOTP Authenticator | v1 | POST /v1/totp-authenticators | Reverse-engineered | 0.3.0/4180bdd1 |
|
||||
| Verify TOTP Authenticator | v1 | POST /v1/verify-totp-authenticator | Reverse-engineered | 0.3.0/19332e51 |
|
||||
| Authenticate with TOTP | v1 | POST /v1/auth/totp | Reverse-engineered | 0.3.0/19332e51 |
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"label": "Configuration Reference",
|
||||
"position": 3,
|
||||
"link": {
|
||||
"type": "generated-index",
|
||||
"description": "Configuration options for trifid-api."
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
# cryptography
|
||||
|
||||
Essential, extremely important cryptography settings. Relate directly to key handling and certificate generation.
|
||||
|
||||
```toml title="/etc/trifid/config.toml"
|
||||
[cryptography]
|
||||
data_encryption_key = "010aecf4b545bb9bc918e154181eb6fd59f08430a78a23ec7eac69e6d06c6fed"
|
||||
local_keystore_directory = "/var/lib/trifid"
|
||||
certs_expiry_time = 32140800 # 1 year
|
||||
```
|
||||
|
||||
### cryptography.data_encryption_key (required)
|
||||
|
||||
:::caution
|
||||
**You must change this value!** It controls how CA keys are encrypted. Generate a new value for this with `openssl rand -hex 32`, and never share it with anyone.
|
||||
:::
|
||||
|
||||
:::danger
|
||||
**DO NOT CHANGE THIS VALUE ON AN EXISTING INSTANCE!** Doing so will render all existing CAs and networks permanently unusable, and will require manual database manipulation and re-enrollment of all devices on your instance to fix.
|
||||
:::
|
||||
|
||||
The 32-byte hex-encoded AES-256 key to encrypt CA keys with before storing them to the database.
|
||||
|
||||
### cryptography.local_keystore_directory (required)
|
||||
|
||||
The path to the legacy keystore. This is currently unused and will be removed entirely in a future release.
|
||||
The value of this does not matter.
|
||||
|
||||
### cryptography.certs_expiry_time
|
||||
|
||||
Default: 32140800 (1 year)
|
||||
|
||||
The amount of time to make certs valid for, in seconds.
|
|
@ -0,0 +1,61 @@
|
|||
# database
|
||||
|
||||
Defines the connection details and options for managing the database connection pool.
|
||||
|
||||
```toml title="/etc/trifid/config.toml"
|
||||
[database]
|
||||
url = "postgres://username:password@host/database"
|
||||
max_connections = 100
|
||||
min_connections = 5
|
||||
connect_timeout = 8
|
||||
acquire_timeout = 8
|
||||
idle_timeout = 8
|
||||
max_lifetime = 8
|
||||
sqlx_logging = true
|
||||
```
|
||||
|
||||
### database.url (required)
|
||||
|
||||
The postgres connection URL to access the database. Takes the form `postgres://username:password@host/database`.
|
||||
|
||||
### database.max_connections
|
||||
|
||||
Default: 100
|
||||
|
||||
The maximum number of connections that will be opened to the database at any one time.
|
||||
|
||||
### database.min_connections
|
||||
|
||||
Default: 5
|
||||
|
||||
The minimum number of connections that will be maintained to the database at any one time.
|
||||
|
||||
### database.connect_timeout
|
||||
|
||||
Default: 8
|
||||
|
||||
The timeout, in seconds, to use when creating new connections to the database.
|
||||
|
||||
### database.acquire_timeout
|
||||
|
||||
Defualt: 8
|
||||
|
||||
The timeout, in seconds, to use when acquiring a connection from the connection pool.
|
||||
|
||||
### database.idle_timeout
|
||||
|
||||
Default: 8
|
||||
|
||||
The amount of time, in seconds, that inactive connections will be kept in the pool before they are dropped.
|
||||
|
||||
### database.max_lifetime
|
||||
|
||||
Default: 8
|
||||
|
||||
The maximum amount of time, in seconds, that connections will be maintained for.
|
||||
|
||||
### database.sqlx_logging
|
||||
|
||||
Default: true
|
||||
|
||||
If true, verbose sqlx query logs will be enabled. If false, they will be hidden.
|
|
@ -0,0 +1,19 @@
|
|||
# server
|
||||
|
||||
Settings related to the HTTP server itself.
|
||||
|
||||
```toml title="/etc/trifid/config.toml"
|
||||
[server]
|
||||
bind = "0.0.0.0:8080"
|
||||
workers = 32
|
||||
```
|
||||
|
||||
### server.bind (required)
|
||||
|
||||
A SocketAddr that the server will listen to connections on. Takes the form `IP:PORT`
|
||||
|
||||
### server.workers
|
||||
|
||||
Default: 32
|
||||
|
||||
The number of thread workers that will be created to process incoming requests.
|
|
@ -0,0 +1,42 @@
|
|||
# tokens
|
||||
|
||||
Settings related to the various token types issued by the server.
|
||||
|
||||
```toml title="/etc/trifid/config.toml"
|
||||
[tokens]
|
||||
magic_link_expiry_time_seconds = 3600 # 1 hour
|
||||
session_token_expiry_time_seconds = 15780000 # 6 months
|
||||
totp_setup_timeout_time_seconds = 600 # 10 minutes
|
||||
mfa_tokens_expiry_time_seconds = 600 # 10 minutes
|
||||
enrollment_tokens_expiry_time = 600 # 10 minutes
|
||||
```
|
||||
|
||||
### tokens.magic_link_expiry_time_seconds
|
||||
|
||||
Default: 3600 (1 hour)
|
||||
|
||||
How long magic links should be valid for, in seconds.
|
||||
|
||||
### tokens.session_token_expiry_time_seconds
|
||||
|
||||
Default: 15780000 (6 months)
|
||||
|
||||
How long session tokens should remain valid for, in seconds. This controls how often you need to re-authenticate with magic links.
|
||||
|
||||
### tokens.totp_setup_timeout_time_seconds
|
||||
|
||||
Default: 600 (10 minutes)
|
||||
|
||||
How long TOTP setup tokens should be valid for, in seconds, before a new one must be generated.
|
||||
|
||||
### tokens.mfa_tokens_expiry_time_seconds
|
||||
|
||||
Default: 600 (10 minutes)
|
||||
|
||||
How long MFA tokens should remain valid for, in seconds. This controls how often you need to re-authenticate with 2fa.
|
||||
|
||||
### tokens.enrollment_tokens_expiry_time
|
||||
|
||||
Default: 600 (10 minutes)
|
||||
|
||||
How long enrollment tokens should be valid for, in seconds, before a new one must be generated.
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"label": "Installing trifid-api",
|
||||
"position": 2,
|
||||
"link": {
|
||||
"type": "generated-index",
|
||||
"description": "Directions on installing trifid-api."
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import Admonition from '@theme/Admonition';
|
||||
|
||||
# Compiling trifid-api
|
||||
|
||||
:::info
|
||||
You must have the Rust toolchain installed and a proper Postgres setup *prior* to compiling trifid-api. Follow the instructions [here](./dependencies.mdx) to do so.
|
||||
:::
|
||||
|
||||
trifid-api is currently only distributed via Cargo, the Rust package manager. Download and compile trifid-api with the command:
|
||||
|
||||
```
|
||||
cargo install trifid-api
|
||||
```
|
||||
|
||||
:::note
|
||||
This command may take a very long time to complete (upwards of an hour!) depending on your system. Grab a cup of coffee and wait until it is complete.
|
||||
:::
|
||||
|
||||
Once complete, follow the additional instructions below depending on your system:
|
||||
|
||||
<Tabs groupId="os">
|
||||
<TabItem value="win" label="Windows">
|
||||
<Admonition>
|
||||
It is recommended that you use macOS or Linux for a production deployment.
|
||||
</Admonition>
|
||||
No extra work is needed. The trifid-api binary will be located at: <CodeBlock>C:\Users\yourUser\.cargo\bin\trifid-api</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="osx" label="macOS">
|
||||
<CodeBlock>
|
||||
sudo cp ~/.cargo/bin/trifid-api /usr/local/bin
|
||||
</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="lin" label="Linux">
|
||||
<CodeBlock>
|
||||
sudo cp ~/.cargo/bin/trifid-api /usr/local/bin
|
||||
</CodeBlock>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Run `trifid-api` in a terminal and ensure it produces something along the lines of the following output:
|
||||
|
||||
```
|
||||
ERROR [trifid_api::config] Unable to read config file
|
||||
```
|
||||
|
||||
If this is showing, you are ready to create your configuration file!
|
|
@ -0,0 +1,71 @@
|
|||
---
|
||||
sidebar_position: 3
|
||||
---
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
import Admonition from '@theme/Admonition';
|
||||
|
||||
# Configuring trifid-api
|
||||
|
||||
For trifid-api to run, it needs a configuration file telling it how to run and giving it some basic settings it can't get from the database.
|
||||
|
||||
## Generating the application key
|
||||
|
||||
trifid-api encrypts some sensitive key material with AES-256 before saving it to the database, so you must generate a secure application key for it to use.
|
||||
|
||||
trifid-api expects a **32-byte hex-encoded random key.** A good way of generating this, if you have openssl installed, is `openssl rand -hex 32`.
|
||||
|
||||
Keep this value on hand! It is the only way to recover CA keys from the database if your config is destroyed.
|
||||
|
||||
:::danger
|
||||
Never share this key with anyone!
|
||||
:::
|
||||
|
||||
:::danger
|
||||
**Never change the application key on a running instance!** It will render all existing CAs permanently unusable and will require manual database intervention and a re-enrollment of every single host attached to the instance to fix.
|
||||
:::
|
||||
|
||||
## Creating the configuration file
|
||||
|
||||
trifid-api uses a TOML config file, located in different places depending on your platform. Create this file, and open it with your favorite editor:
|
||||
|
||||
<Tabs groupId="os">
|
||||
<TabItem value="win" label="Windows">
|
||||
<Admonition>
|
||||
It is recommended that you use macOS or Linux for a production deployment.
|
||||
</Admonition>
|
||||
trifid-api will attempt to load the config from a file called config.toml in the same folder as the executable.
|
||||
</TabItem>
|
||||
<TabItem value="osx" label="macOS">
|
||||
<CodeBlock>
|
||||
/etc/trifid/config.toml
|
||||
</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="lin" label="Linux">
|
||||
<CodeBlock>
|
||||
/etc/trifid/config.toml
|
||||
</CodeBlock>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Once you have opened the file, copy this basic configuration in and change to fit your settings:
|
||||
|
||||
```toml
|
||||
[database]
|
||||
url = "<YOUR_POSTGRES_CONNURL_HERE>"
|
||||
sqlx_logging = false
|
||||
|
||||
[server]
|
||||
bind = "0.0.0.0:8080"
|
||||
|
||||
[tokens]
|
||||
|
||||
[crypto]
|
||||
data_encryption_key = "<YOUR_APPLICATION_KEY_HERE>"
|
||||
local_keystore_directory = "./data"
|
||||
```
|
||||
|
||||
:::info
|
||||
Change <YOUR_POSTGRES_CONNURL_HERE> to your Postgres connection url that you got from [configuring the database](/docs/trifid-api/installing_trifid_api/dependencies#creating-the-database), and change `<YOUR_APPLICATION_KEY_HERE>` to the application key you got from [generating it](/docs/trifid-api/installing_trifid_api/configuring#generating-the-application-key).
|
||||
:::
|
|
@ -0,0 +1,68 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
# Dependencies
|
||||
|
||||
trifid-api requires a few dependencies to compile and run.
|
||||
|
||||
In short, you need:
|
||||
- the Rust toolchain
|
||||
- a PostgreSQL database
|
||||
|
||||
More details and instructions follow.
|
||||
|
||||
## Rust Toolchain
|
||||
|
||||
trifid-api is a Rust application, and thus needs the Rust toolchain installed to compile it. Pre-built binaries for trifid-api are planned, but currently not available. It is reccomended that you use [rustup](https://rustup.rs) to install the Rust toolchain.
|
||||
|
||||
<Tabs groupId="os">
|
||||
<TabItem value="win" label="Windows">
|
||||
trifid-api does not run very well on Windows. It is reccomended that you use macOS or Linux for a production deployment.
|
||||
If you wish to continue anyway, download and run <a href="https://win.rustup.rs">the rustup installer</a>.
|
||||
</TabItem>
|
||||
<TabItem value="osx" label="macOS">
|
||||
<CodeBlock>
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="lin" label="Linux">
|
||||
<CodeBlock>
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
</CodeBlock>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## PostgreSQL
|
||||
|
||||
PostgreSQL is the database that trifid-api uses, and you must have a functional PostgreSQL database to do this.
|
||||
Instructions on how to install PostgreSQL is left up to the reader. Once Postgres is installed, come back here for database setup instructions.
|
||||
|
||||
## Creating the database
|
||||
|
||||
trifid-api must run on its own isolated database with its own isolated user, for security. Open a psql prompt with superuser access, and run the following commands to create your database and user:
|
||||
|
||||
:::danger
|
||||
Please use a secure password for your database. A good way to generate this is with `openssl rand -hex 32` if you have OpenSSL installed.
|
||||
:::
|
||||
|
||||
```sql
|
||||
CREATE DATABASE trifid;
|
||||
CREATE USER trifid WITH ENCRYPTED PASSWORD '<your_super_secure_password_here>';
|
||||
GRANT ALL PRIVILEGES ON DATABASE trifid TO trifid;
|
||||
GRANT ALL PRIVILEGES ON SCHEMA public TO trifid;
|
||||
\c trifid
|
||||
GRANT ALL PRIVILEGES ON DATABASE trifid TO trifid;
|
||||
GRANT ALL PRIVILEGES ON SCHEMA public TO trifid;
|
||||
```
|
||||
|
||||
Once this is complete, your Postgres connection url will look like:
|
||||
|
||||
```
|
||||
postgres://trifid:<your_super_secure_password_here>@<postgres_ip>/trifid
|
||||
```
|
||||
|
||||
Once this is complete, you are ready to compile trifid-api!
|
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Introduction
|
||||
|
||||
Welcome to the trifid-api documentation!
|
||||
trifid-api is a complete reimplementation of the [Defined Networking](https://defined.net) API server, designed to allow you to self-host your own networks.
|
||||
|
||||
:::caution
|
||||
Although trifid-api is battle-tested and has been used in production networks for months with no major issues, it should still be considered experimental software. Please, [report any bugs you find](https://git.e3t.cc/core/trifid/issues) to assist with further development of trifid-api.
|
||||
:::
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"label": "Tutorial - Basics",
|
||||
"position": 6,
|
||||
"link": {
|
||||
"type": "generated-index",
|
||||
"description": "5 minutes to learn the most important Docusaurus concepts."
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
---
|
||||
sidebar_position: 6
|
||||
---
|
||||
|
||||
# Congratulations!
|
||||
|
||||
You have just learned the **basics of Docusaurus** and made some changes to the **initial template**.
|
||||
|
||||
Docusaurus has **much more to offer**!
|
||||
|
||||
Have **5 more minutes**? Take a look at **[versioning](../tutorial-extras/manage-docs-versions.md)** and **[i18n](../tutorial-extras/translate-your-site.md)**.
|
||||
|
||||
Anything **unclear** or **buggy** in this tutorial? [Please report it!](https://github.com/facebook/docusaurus/discussions/4610)
|
||||
|
||||
## What's next?
|
||||
|
||||
- Read the [official documentation](https://docusaurus.io/)
|
||||
- Modify your site configuration with [`docusaurus.config.js`](https://docusaurus.io/docs/api/docusaurus-config)
|
||||
- Add navbar and footer items with [`themeConfig`](https://docusaurus.io/docs/api/themes/configuration)
|
||||
- Add a custom [Design and Layout](https://docusaurus.io/docs/styling-layout)
|
||||
- Add a [search bar](https://docusaurus.io/docs/search)
|
||||
- Find inspirations in the [Docusaurus showcase](https://docusaurus.io/showcase)
|
||||
- Get involved in the [Docusaurus Community](https://docusaurus.io/community/support)
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
# Create a Blog Post
|
||||
|
||||
Docusaurus creates a **page for each blog post**, but also a **blog index page**, a **tag system**, an **RSS** feed...
|
||||
|
||||
## Create your first Post
|
||||
|
||||
Create a file at `blog/2021-02-28-greetings.md`:
|
||||
|
||||
```md title="blog/2021-02-28-greetings.md"
|
||||
---
|
||||
slug: greetings
|
||||
title: Greetings!
|
||||
authors:
|
||||
- name: Joel Marcey
|
||||
title: Co-creator of Docusaurus 1
|
||||
url: https://github.com/JoelMarcey
|
||||
image_url: https://github.com/JoelMarcey.png
|
||||
- name: Sébastien Lorber
|
||||
title: Docusaurus maintainer
|
||||
url: https://sebastienlorber.com
|
||||
image_url: https://github.com/slorber.png
|
||||
tags: [greetings]
|
||||
---
|
||||
|
||||
Congratulations, you have made your first post!
|
||||
|
||||
Feel free to play around and edit this post as much you like.
|
||||
```
|
||||
|
||||
A new blog post is now available at [http://localhost:3000/blog/greetings](http://localhost:3000/blog/greetings).
|
|
@ -0,0 +1,57 @@
|
|||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Create a Document
|
||||
|
||||
Documents are **groups of pages** connected through:
|
||||
|
||||
- a **sidebar**
|
||||
- **previous/next navigation**
|
||||
- **versioning**
|
||||
|
||||
## Create your first Doc
|
||||
|
||||
Create a Markdown file at `docs/hello.md`:
|
||||
|
||||
```md title="docs/hello.md"
|
||||
# Hello
|
||||
|
||||
This is my **first Docusaurus document**!
|
||||
```
|
||||
|
||||
A new document is now available at [http://localhost:3000/docs/hello](http://localhost:3000/docs/hello).
|
||||
|
||||
## Configure the Sidebar
|
||||
|
||||
Docusaurus automatically **creates a sidebar** from the `docs` folder.
|
||||
|
||||
Add metadata to customize the sidebar label and position:
|
||||
|
||||
```md title="docs/hello.md" {1-4}
|
||||
---
|
||||
sidebar_label: 'Hi!'
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
# Hello
|
||||
|
||||
This is my **first Docusaurus document**!
|
||||
```
|
||||
|
||||
It is also possible to create your sidebar explicitly in `sidebars.js`:
|
||||
|
||||
```js title="sidebars.js"
|
||||
module.exports = {
|
||||
tutorialSidebar: [
|
||||
'intro',
|
||||
// highlight-next-line
|
||||
'hello',
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Tutorial',
|
||||
items: ['tutorial-basics/create-a-document'],
|
||||
},
|
||||
],
|
||||
};
|
||||
```
|
|
@ -0,0 +1,43 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Create a Page
|
||||
|
||||
Add **Markdown or React** files to `src/pages` to create a **standalone page**:
|
||||
|
||||
- `src/pages/index.js` → `localhost:3000/`
|
||||
- `src/pages/foo.md` → `localhost:3000/foo`
|
||||
- `src/pages/foo/bar.js` → `localhost:3000/foo/bar`
|
||||
|
||||
## Create your first React Page
|
||||
|
||||
Create a file at `src/pages/my-react-page.js`:
|
||||
|
||||
```jsx title="src/pages/my-react-page.js"
|
||||
import React from 'react';
|
||||
import Layout from '@theme/Layout';
|
||||
|
||||
export default function MyReactPage() {
|
||||
return (
|
||||
<Layout>
|
||||
<h1>My React page</h1>
|
||||
<p>This is a React page</p>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
A new page is now available at [http://localhost:3000/my-react-page](http://localhost:3000/my-react-page).
|
||||
|
||||
## Create your first Markdown Page
|
||||
|
||||
Create a file at `src/pages/my-markdown-page.md`:
|
||||
|
||||
```mdx title="src/pages/my-markdown-page.md"
|
||||
# My Markdown page
|
||||
|
||||
This is a Markdown page
|
||||
```
|
||||
|
||||
A new page is now available at [http://localhost:3000/my-markdown-page](http://localhost:3000/my-markdown-page).
|
|
@ -0,0 +1,31 @@
|
|||
---
|
||||
sidebar_position: 5
|
||||
---
|
||||
|
||||
# Deploy your site
|
||||
|
||||
Docusaurus is a **static-site-generator** (also called **[Jamstack](https://jamstack.org/)**).
|
||||
|
||||
It builds your site as simple **static HTML, JavaScript and CSS files**.
|
||||
|
||||
## Build your site
|
||||
|
||||
Build your site **for production**:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
The static files are generated in the `build` folder.
|
||||
|
||||
## Deploy your site
|
||||
|
||||
Test your production build locally:
|
||||
|
||||
```bash
|
||||
npm run serve
|
||||
```
|
||||
|
||||
The `build` folder is now served at [http://localhost:3000/](http://localhost:3000/).
|
||||
|
||||
You can now deploy the `build` folder **almost anywhere** easily, **for free** or very small cost (read the **[Deployment Guide](https://docusaurus.io/docs/deployment)**).
|
|
@ -0,0 +1,150 @@
|
|||
---
|
||||
sidebar_position: 4
|
||||
---
|
||||
|
||||
# Markdown Features
|
||||
|
||||
Docusaurus supports **[Markdown](https://daringfireball.net/projects/markdown/syntax)** and a few **additional features**.
|
||||
|
||||
## Front Matter
|
||||
|
||||
Markdown documents have metadata at the top called [Front Matter](https://jekyllrb.com/docs/front-matter/):
|
||||
|
||||
```text title="my-doc.md"
|
||||
// highlight-start
|
||||
---
|
||||
id: my-doc-id
|
||||
title: My document title
|
||||
description: My document description
|
||||
slug: /my-custom-url
|
||||
---
|
||||
// highlight-end
|
||||
|
||||
## Markdown heading
|
||||
|
||||
Markdown text with [links](./hello.md)
|
||||
```
|
||||
|
||||
## Links
|
||||
|
||||
Regular Markdown links are supported, using url paths or relative file paths.
|
||||
|
||||
```md
|
||||
Let's see how to [Create a page](/create-a-page).
|
||||
```
|
||||
|
||||
```md
|
||||
Let's see how to [Create a page](./create-a-page.md).
|
||||
```
|
||||
|
||||
**Result:** Let's see how to [Create a page](./create-a-page.md).
|
||||
|
||||
## Images
|
||||
|
||||
Regular Markdown images are supported.
|
||||
|
||||
You can use absolute paths to reference images in the static directory (`static/img/docusaurus.png`):
|
||||
|
||||
```md
|
||||
![Docusaurus logo](/img/docusaurus.png)
|
||||
```
|
||||
|
||||
![Docusaurus logo](/img/docusaurus.png)
|
||||
|
||||
You can reference images relative to the current file as well. This is particularly useful to colocate images close to the Markdown files using them:
|
||||
|
||||
```md
|
||||
![Docusaurus logo](./img/docusaurus.png)
|
||||
```
|
||||
|
||||
## Code Blocks
|
||||
|
||||
Markdown code blocks are supported with Syntax highlighting.
|
||||
|
||||
```jsx title="src/components/HelloDocusaurus.js"
|
||||
function HelloDocusaurus() {
|
||||
return (
|
||||
<h1>Hello, Docusaurus!</h1>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
```jsx title="src/components/HelloDocusaurus.js"
|
||||
function HelloDocusaurus() {
|
||||
return <h1>Hello, Docusaurus!</h1>;
|
||||
}
|
||||
```
|
||||
|
||||
## Admonitions
|
||||
|
||||
Docusaurus has a special syntax to create admonitions and callouts:
|
||||
|
||||
:::tip My tip
|
||||
|
||||
Use this awesome feature option
|
||||
|
||||
:::
|
||||
|
||||
:::danger Take care
|
||||
|
||||
This action is dangerous
|
||||
|
||||
:::
|
||||
|
||||
:::tip My tip
|
||||
|
||||
Use this awesome feature option
|
||||
|
||||
:::
|
||||
|
||||
:::danger Take care
|
||||
|
||||
This action is dangerous
|
||||
|
||||
:::
|
||||
|
||||
## MDX and React Components
|
||||
|
||||
[MDX](https://mdxjs.com/) can make your documentation more **interactive** and allows using any **React components inside Markdown**:
|
||||
|
||||
```jsx
|
||||
export const Highlight = ({children, color}) => (
|
||||
<span
|
||||
style={{
|
||||
backgroundColor: color,
|
||||
borderRadius: '20px',
|
||||
color: '#fff',
|
||||
padding: '10px',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
onClick={() => {
|
||||
alert(`You clicked the color ${color} with label ${children}`)
|
||||
}}>
|
||||
{children}
|
||||
</span>
|
||||
);
|
||||
|
||||
This is <Highlight color="#25c2a0">Docusaurus green</Highlight> !
|
||||
|
||||
This is <Highlight color="#1877F2">Facebook blue</Highlight> !
|
||||
```
|
||||
|
||||
export const Highlight = ({children, color}) => (
|
||||
<span
|
||||
style={{
|
||||
backgroundColor: color,
|
||||
borderRadius: '20px',
|
||||
color: '#fff',
|
||||
padding: '10px',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
onClick={() => {
|
||||
alert(`You clicked the color ${color} with label ${children}`);
|
||||
}}>
|
||||
{children}
|
||||
</span>
|
||||
);
|
||||
|
||||
This is <Highlight color="#25c2a0">Docusaurus green</Highlight> !
|
||||
|
||||
This is <Highlight color="#1877F2">Facebook blue</Highlight> !
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"label": "Tutorial - Extras",
|
||||
"position": 7,
|
||||
"link": {
|
||||
"type": "generated-index"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 27 KiB |
|
@ -0,0 +1,55 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Manage Docs Versions
|
||||
|
||||
Docusaurus can manage multiple versions of your docs.
|
||||
|
||||
## Create a docs version
|
||||
|
||||
Release a version 1.0 of your project:
|
||||
|
||||
```bash
|
||||
npm run docusaurus docs:version 1.0
|
||||
```
|
||||
|
||||
The `docs` folder is copied into `versioned_docs/version-1.0` and `versions.json` is created.
|
||||
|
||||
Your docs now have 2 versions:
|
||||
|
||||
- `1.0` at `http://localhost:3000/docs/` for the version 1.0 docs
|
||||
- `current` at `http://localhost:3000/docs/next/` for the **upcoming, unreleased docs**
|
||||
|
||||
## Add a Version Dropdown
|
||||
|
||||
To navigate seamlessly across versions, add a version dropdown.
|
||||
|
||||
Modify the `docusaurus.config.js` file:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
themeConfig: {
|
||||
navbar: {
|
||||
items: [
|
||||
// highlight-start
|
||||
{
|
||||
type: 'docsVersionDropdown',
|
||||
},
|
||||
// highlight-end
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
The docs version dropdown appears in your navbar:
|
||||
|
||||
![Docs Version Dropdown](./img/docsVersionDropdown.png)
|
||||
|
||||
## Update an existing version
|
||||
|
||||
It is possible to edit versioned docs in their respective folder:
|
||||
|
||||
- `versioned_docs/version-1.0/hello.md` updates `http://localhost:3000/docs/hello`
|
||||
- `docs/hello.md` updates `http://localhost:3000/docs/next/hello`
|
|
@ -0,0 +1,88 @@
|
|||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Translate your site
|
||||
|
||||
Let's translate `docs/intro.md` to French.
|
||||
|
||||
## Configure i18n
|
||||
|
||||
Modify `docusaurus.config.js` to add support for the `fr` locale:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
i18n: {
|
||||
defaultLocale: 'en',
|
||||
locales: ['en', 'fr'],
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
## Translate a doc
|
||||
|
||||
Copy the `docs/intro.md` file to the `i18n/fr` folder:
|
||||
|
||||
```bash
|
||||
mkdir -p i18n/fr/docusaurus-plugin-content-docs/current/
|
||||
|
||||
cp docs/intro.md i18n/fr/docusaurus-plugin-content-docs/current/intro.md
|
||||
```
|
||||
|
||||
Translate `i18n/fr/docusaurus-plugin-content-docs/current/intro.md` in French.
|
||||
|
||||
## Start your localized site
|
||||
|
||||
Start your site on the French locale:
|
||||
|
||||
```bash
|
||||
npm run start -- --locale fr
|
||||
```
|
||||
|
||||
Your localized site is accessible at [http://localhost:3000/fr/](http://localhost:3000/fr/) and the `Getting Started` page is translated.
|
||||
|
||||
:::caution
|
||||
|
||||
In development, you can only use one locale at a same time.
|
||||
|
||||
:::
|
||||
|
||||
## Add a Locale Dropdown
|
||||
|
||||
To navigate seamlessly across languages, add a locale dropdown.
|
||||
|
||||
Modify the `docusaurus.config.js` file:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
themeConfig: {
|
||||
navbar: {
|
||||
items: [
|
||||
// highlight-start
|
||||
{
|
||||
type: 'localeDropdown',
|
||||
},
|
||||
// highlight-end
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
The locale dropdown now appears in your navbar:
|
||||
|
||||
![Locale Dropdown](./img/localeDropdown.png)
|
||||
|
||||
## Build your localized site
|
||||
|
||||
Build your site for a specific locale:
|
||||
|
||||
```bash
|
||||
npm run build -- --locale fr
|
||||
```
|
||||
|
||||
Or build your site to include all the locales at once:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
|
@ -0,0 +1,126 @@
|
|||
// @ts-check
|
||||
// Note: type annotations allow type checking and IDEs autocompletion
|
||||
|
||||
const lightCodeTheme = require('prism-react-renderer/themes/github');
|
||||
const darkCodeTheme = require('prism-react-renderer/themes/dracula');
|
||||
|
||||
/** @type {import('@docusaurus/types').Config} */
|
||||
const config = {
|
||||
title: 'Trifid',
|
||||
tagline: 'Open-source mesh networking',
|
||||
favicon: 'img/favicon.ico',
|
||||
|
||||
// Set the production url of your site here
|
||||
url: 'https://docs.trifid.e3t.cc',
|
||||
// Set the /<baseUrl>/ pathname under which your site is served
|
||||
// For GitHub pages deployment, it is often '/<projectName>/'
|
||||
baseUrl: '/',
|
||||
|
||||
// GitHub pages deployment config.
|
||||
// If you aren't using GitHub pages, you don't need these.
|
||||
organizationName: 'facebook', // Usually your GitHub org/user name.
|
||||
projectName: 'docusaurus', // Usually your repo name.
|
||||
|
||||
onBrokenLinks: 'throw',
|
||||
onBrokenMarkdownLinks: 'warn',
|
||||
|
||||
// Even if you don't use internalization, you can use this field to set useful
|
||||
// metadata like html lang. For example, if your site is Chinese, you may want
|
||||
// to replace "en" with "zh-Hans".
|
||||
i18n: {
|
||||
defaultLocale: 'en',
|
||||
locales: ['en'],
|
||||
},
|
||||
|
||||
presets: [
|
||||
[
|
||||
'classic',
|
||||
/** @type {import('@docusaurus/preset-classic').Options} */
|
||||
({
|
||||
docs: {
|
||||
sidebarPath: require.resolve('./sidebars.js'),
|
||||
},
|
||||
blog: {
|
||||
showReadingTime: true,
|
||||
},
|
||||
theme: {
|
||||
customCss: require.resolve('./src/css/custom.css'),
|
||||
},
|
||||
}),
|
||||
],
|
||||
],
|
||||
|
||||
themeConfig:
|
||||
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
|
||||
({
|
||||
// Replace with your project's social card
|
||||
image: 'img/docusaurus-social-card.jpg',
|
||||
navbar: {
|
||||
title: 'Trifid',
|
||||
logo: {
|
||||
alt: 'Trifid Logo',
|
||||
src: 'img/logo.svg',
|
||||
},
|
||||
items: [
|
||||
{
|
||||
type: 'docSidebar',
|
||||
sidebarId: 'tutorialSidebar',
|
||||
position: 'left',
|
||||
label: 'Docs',
|
||||
},
|
||||
{to: '/blog', label: 'Blog', position: 'left'},
|
||||
],
|
||||
},
|
||||
footer: {
|
||||
style: 'dark',
|
||||
links: [
|
||||
{
|
||||
title: 'Docs',
|
||||
items: [
|
||||
{
|
||||
label: 'Overview',
|
||||
to: '/docs/intro',
|
||||
},
|
||||
{
|
||||
label: 'trifid-api',
|
||||
to: '/docs/trifid-api/intro',
|
||||
},
|
||||
{
|
||||
label: 'tfweb',
|
||||
to: '/docs/tfweb/intro',
|
||||
},
|
||||
{
|
||||
label: 'tfclient',
|
||||
to: '/docs/tfclient/intro',
|
||||
},
|
||||
{
|
||||
label: 'tfcli',
|
||||
to: '/docs/tfcli/intro',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'More',
|
||||
items: [
|
||||
{
|
||||
label: 'Blog',
|
||||
to: '/blog',
|
||||
},
|
||||
{
|
||||
label: 'Git',
|
||||
href: 'https://git.e3t.cc/core/trifid',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
copyright: `Copyright © ${new Date().getFullYear()} e3team. Built with Docusaurus.`,
|
||||
},
|
||||
prism: {
|
||||
theme: lightCodeTheme,
|
||||
darkTheme: darkCodeTheme,
|
||||
additionalLanguages: ["toml"]
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
module.exports = config;
|
|
@ -0,0 +1,43 @@
|
|||
{
|
||||
"name": "docs",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"docusaurus": "docusaurus",
|
||||
"start": "docusaurus start",
|
||||
"build": "docusaurus build",
|
||||
"swizzle": "docusaurus swizzle",
|
||||
"deploy": "docusaurus deploy",
|
||||
"clear": "docusaurus clear",
|
||||
"serve": "docusaurus serve",
|
||||
"write-translations": "docusaurus write-translations",
|
||||
"write-heading-ids": "docusaurus write-heading-ids"
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "2.4.3",
|
||||
"@docusaurus/preset-classic": "2.4.3",
|
||||
"@mdx-js/react": "^1.6.22",
|
||||
"clsx": "^1.2.1",
|
||||
"prism-react-renderer": "^1.3.5",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "2.4.3"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.5%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.14"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* Creating a sidebar enables you to:
|
||||
- create an ordered group of docs
|
||||
- render a sidebar for each doc of that group
|
||||
- provide next/previous navigation
|
||||
|
||||
The sidebars can be generated from the filesystem, or explicitly defined here.
|
||||
|
||||
Create as many sidebars as you want.
|
||||
*/
|
||||
|
||||
// @ts-check
|
||||
|
||||
/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */
|
||||
const sidebars = {
|
||||
// By default, Docusaurus generates a sidebar from the docs folder structure
|
||||
tutorialSidebar: [{type: 'autogenerated', dirName: '.'}],
|
||||
|
||||
// But you can create a sidebar manually
|
||||
/*
|
||||
tutorialSidebar: [
|
||||
'intro',
|
||||
'hello',
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Tutorial',
|
||||
items: ['tutorial-basics/create-a-document'],
|
||||
},
|
||||
],
|
||||
*/
|
||||
};
|
||||
|
||||
module.exports = sidebars;
|
|
@ -0,0 +1,61 @@
|
|||
import React from 'react';
|
||||
import clsx from 'clsx';
|
||||
import styles from './styles.module.css';
|
||||
|
||||
const FeatureList = [
|
||||
{
|
||||
title: 'Easy to Use',
|
||||
Svg: require('@site/static/img/undraw_setup_wizard_re_nday.svg').default,
|
||||
description: (
|
||||
<>
|
||||
Trifid is easy to install, simple to configure and is designed to get out of your way so you can focus on what matters most.
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Incredibly Fast',
|
||||
Svg: require('@site/static/img/undraw_fast_loading_re_8oi3.svg').default,
|
||||
description: (
|
||||
<>
|
||||
Trifid was built from the ground-up with speed in mind. Written entirely in Go and Rust, Trifid is fast and safe.
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Simple Security',
|
||||
Svg: require('@site/static/img/undraw_secure_server_re_8wsq.svg').default,
|
||||
description: (
|
||||
<>
|
||||
Built around the Defined Networking protocol, the server never handles any sensitive client keys.
|
||||
</>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
function Feature({Svg, title, description}) {
|
||||
return (
|
||||
<div className={clsx('col col--4')}>
|
||||
<div className="text--center">
|
||||
<Svg className={styles.featureSvg} role="img" />
|
||||
</div>
|
||||
<div className="text--center padding-horiz--md">
|
||||
<h3>{title}</h3>
|
||||
<p>{description}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function HomepageFeatures() {
|
||||
return (
|
||||
<section className={styles.features}>
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
{FeatureList.map((props, idx) => (
|
||||
<Feature key={idx} {...props} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
.features {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 2rem 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.featureSvg {
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* Any CSS included here will be global. The classic template
|
||||
* bundles Infima by default. Infima is a CSS framework designed to
|
||||
* work well for content-centric websites.
|
||||
*/
|
||||
|
||||
/* You can override the default Infima variables here. */
|
||||
:root {
|
||||
--ifm-color-primary: #2e8555;
|
||||
--ifm-color-primary-dark: #29784c;
|
||||
--ifm-color-primary-darker: #277148;
|
||||
--ifm-color-primary-darkest: #205d3b;
|
||||
--ifm-color-primary-light: #33925d;
|
||||
--ifm-color-primary-lighter: #359962;
|
||||
--ifm-color-primary-lightest: #3cad6e;
|
||||
--ifm-code-font-size: 95%;
|
||||
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* For readability concerns, you should choose a lighter palette in dark mode. */
|
||||
[data-theme='dark'] {
|
||||
--ifm-color-primary: #25c2a0;
|
||||
--ifm-color-primary-dark: #21af90;
|
||||
--ifm-color-primary-darker: #1fa588;
|
||||
--ifm-color-primary-darkest: #1a8870;
|
||||
--ifm-color-primary-light: #29d5b0;
|
||||
--ifm-color-primary-lighter: #32d8b4;
|
||||
--ifm-color-primary-lightest: #4fddbf;
|
||||
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3);
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
import React from 'react';
|
||||
import clsx from 'clsx';
|
||||
import Link from '@docusaurus/Link';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import Layout from '@theme/Layout';
|
||||
import HomepageFeatures from '@site/src/components/HomepageFeatures';
|
||||
|
||||
import styles from './index.module.css';
|
||||
|
||||
function HomepageHeader() {
|
||||
const {siteConfig} = useDocusaurusContext();
|
||||
return (
|
||||
<header className={clsx('hero hero--primary', styles.heroBanner)}>
|
||||
<div className="container">
|
||||
<h1 className="hero__title">{siteConfig.title}</h1>
|
||||
<p className="hero__subtitle">{siteConfig.tagline}</p>
|
||||
<div className={styles.buttons}>
|
||||
<Link
|
||||
className="button button--secondary button--lg"
|
||||
to="/docs/intro">
|
||||
Get Started
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Home() {
|
||||
const {siteConfig} = useDocusaurusContext();
|
||||
return (
|
||||
<Layout
|
||||
title={`Hello from ${siteConfig.title}`}
|
||||
description="Documentation for Trifid, an open-source mesh networking tool">
|
||||
<HomepageHeader />
|
||||
<main>
|
||||
<HomepageFeatures />
|
||||
</main>
|
||||
</Layout>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* CSS files with the .module.css suffix will be treated as CSS modules
|
||||
* and scoped locally.
|
||||
*/
|
||||
|
||||
.heroBanner {
|
||||
padding: 4rem 0;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 996px) {
|
||||
.heroBanner {
|
||||
padding: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
title: Markdown page example
|
||||
---
|
||||
|
||||
# Markdown page example
|
||||
|
||||
You don't need React to write simple standalone pages.
|
After Width: | Height: | Size: 54 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 6.3 KiB |
|
@ -0,0 +1,171 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="1088" height="687.962" viewBox="0 0 1088 687.962">
|
||||
<title>Easy to Use</title>
|
||||
<g id="Group_12" data-name="Group 12" transform="translate(-57 -56)">
|
||||
<g id="Group_11" data-name="Group 11" transform="translate(57 56)">
|
||||
<path id="Path_83" data-name="Path 83" d="M1017.81,560.461c-5.27,45.15-16.22,81.4-31.25,110.31-20,38.52-54.21,54.04-84.77,70.28a193.275,193.275,0,0,1-27.46,11.94c-55.61,19.3-117.85,14.18-166.74,3.99a657.282,657.282,0,0,0-104.09-13.16q-14.97-.675-29.97-.67c-15.42.02-293.07,5.29-360.67-131.57-16.69-33.76-28.13-75-32.24-125.27-11.63-142.12,52.29-235.46,134.74-296.47,155.97-115.41,369.76-110.57,523.43,7.88C941.15,276.621,1036.99,396.031,1017.81,560.461Z" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
||||
<path id="Path_84" data-name="Path 84" d="M986.56,670.771c-20,38.52-47.21,64.04-77.77,80.28a193.272,193.272,0,0,1-27.46,11.94c-55.61,19.3-117.85,14.18-166.74,3.99a657.3,657.3,0,0,0-104.09-13.16q-14.97-.675-29.97-.67-23.13.03-46.25,1.72c-100.17,7.36-253.82-6.43-321.42-143.29L382,283.981,444.95,445.6l20.09,51.59,55.37-75.98L549,381.981l130.2,149.27,36.8-81.27L970.78,657.9l14.21,11.59Z" transform="translate(-56 -106.019)" fill="#f2f2f2"/>
|
||||
<path id="Path_85" data-name="Path 85" d="M302,282.962l26-57,36,83-31-60Z" opacity="0.1"/>
|
||||
<path id="Path_86" data-name="Path 86" d="M610.5,753.821q-14.97-.675-29.97-.67L465.04,497.191Z" transform="translate(-56 -106.019)" opacity="0.1"/>
|
||||
<path id="Path_87" data-name="Path 87" d="M464.411,315.191,493,292.962l130,150-132-128Z" opacity="0.1"/>
|
||||
<path id="Path_88" data-name="Path 88" d="M908.79,751.051a193.265,193.265,0,0,1-27.46,11.94L679.2,531.251Z" transform="translate(-56 -106.019)" opacity="0.1"/>
|
||||
<circle id="Ellipse_11" data-name="Ellipse 11" cx="3" cy="3" r="3" transform="translate(479 98.962)" fill="#f2f2f2"/>
|
||||
<circle id="Ellipse_12" data-name="Ellipse 12" cx="3" cy="3" r="3" transform="translate(396 201.962)" fill="#f2f2f2"/>
|
||||
<circle id="Ellipse_13" data-name="Ellipse 13" cx="2" cy="2" r="2" transform="translate(600 220.962)" fill="#f2f2f2"/>
|
||||
<circle id="Ellipse_14" data-name="Ellipse 14" cx="2" cy="2" r="2" transform="translate(180 265.962)" fill="#f2f2f2"/>
|
||||
<circle id="Ellipse_15" data-name="Ellipse 15" cx="2" cy="2" r="2" transform="translate(612 96.962)" fill="#f2f2f2"/>
|
||||
<circle id="Ellipse_16" data-name="Ellipse 16" cx="2" cy="2" r="2" transform="translate(736 192.962)" fill="#f2f2f2"/>
|
||||
<circle id="Ellipse_17" data-name="Ellipse 17" cx="2" cy="2" r="2" transform="translate(858 344.962)" fill="#f2f2f2"/>
|
||||
<path id="Path_89" data-name="Path 89" d="M306,121.222h-2.76v-2.76h-1.48v2.76H299V122.7h2.76v2.759h1.48V122.7H306Z" fill="#f2f2f2"/>
|
||||
<path id="Path_90" data-name="Path 90" d="M848,424.222h-2.76v-2.76h-1.48v2.76H841V425.7h2.76v2.759h1.48V425.7H848Z" fill="#f2f2f2"/>
|
||||
<path id="Path_91" data-name="Path 91" d="M1144,719.981c0,16.569-243.557,74-544,74s-544-57.431-544-74,243.557,14,544,14S1144,703.413,1144,719.981Z" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
||||
<path id="Path_92" data-name="Path 92" d="M1144,719.981c0,16.569-243.557,74-544,74s-544-57.431-544-74,243.557,14,544,14S1144,703.413,1144,719.981Z" transform="translate(-56 -106.019)" opacity="0.1"/>
|
||||
<ellipse id="Ellipse_18" data-name="Ellipse 18" cx="544" cy="30" rx="544" ry="30" transform="translate(0 583.962)" fill="#3f3d56"/>
|
||||
<path id="Path_93" data-name="Path 93" d="M624,677.981c0,33.137-14.775,24-33,24s-33,9.137-33-24,33-96,33-96S624,644.844,624,677.981Z" transform="translate(-56 -106.019)" fill="#ff6584"/>
|
||||
<path id="Path_94" data-name="Path 94" d="M606,690.66c0,15.062-6.716,10.909-15,10.909s-15,4.153-15-10.909,15-43.636,15-43.636S606,675.6,606,690.66Z" transform="translate(-56 -106.019)" opacity="0.1"/>
|
||||
<rect id="Rectangle_97" data-name="Rectangle 97" width="92" height="18" rx="9" transform="translate(489 604.962)" fill="#2f2e41"/>
|
||||
<rect id="Rectangle_98" data-name="Rectangle 98" width="92" height="18" rx="9" transform="translate(489 586.962)" fill="#2f2e41"/>
|
||||
<path id="Path_95" data-name="Path 95" d="M193,596.547c0,55.343,34.719,100.126,77.626,100.126" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
||||
<path id="Path_96" data-name="Path 96" d="M270.626,696.673c0-55.965,38.745-101.251,86.626-101.251" transform="translate(-56 -106.019)" fill="#6c63ff"/>
|
||||
<path id="Path_97" data-name="Path 97" d="M221.125,601.564c0,52.57,22.14,95.109,49.5,95.109" transform="translate(-56 -106.019)" fill="#6c63ff"/>
|
||||
<path id="Path_98" data-name="Path 98" d="M270.626,696.673c0-71.511,44.783-129.377,100.126-129.377" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
||||
<path id="Path_99" data-name="Path 99" d="M254.3,697.379s11.009-.339,14.326-2.7,16.934-5.183,17.757-1.395,16.544,18.844,4.115,18.945-28.879-1.936-32.19-3.953S254.3,697.379,254.3,697.379Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
|
||||
<path id="Path_100" data-name="Path 100" d="M290.716,710.909c-12.429.1-28.879-1.936-32.19-3.953-2.522-1.536-3.527-7.048-3.863-9.591l-.368.014s.7,8.879,4.009,10.9,19.761,4.053,32.19,3.953c3.588-.029,4.827-1.305,4.759-3.2C294.755,710.174,293.386,710.887,290.716,710.909Z" transform="translate(-56 -106.019)" opacity="0.2"/>
|
||||
<path id="Path_101" data-name="Path 101" d="M777.429,633.081c0,38.029,23.857,68.8,53.341,68.8" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
||||
<path id="Path_102" data-name="Path 102" d="M830.769,701.882c0-38.456,26.623-69.575,59.525-69.575" transform="translate(-56 -106.019)" fill="#6c63ff"/>
|
||||
<path id="Path_103" data-name="Path 103" d="M796.755,636.528c0,36.124,15.213,65.354,34.014,65.354" transform="translate(-56 -106.019)" fill="#6c63ff"/>
|
||||
<path id="Path_104" data-name="Path 104" d="M830.769,701.882c0-49.139,30.773-88.9,68.8-88.9" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
||||
<path id="Path_105" data-name="Path 105" d="M819.548,702.367s7.565-.233,9.844-1.856,11.636-3.562,12.2-.958,11.368,12.949,2.828,13.018-19.844-1.33-22.119-2.716S819.548,702.367,819.548,702.367Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
|
||||
<path id="Path_106" data-name="Path 106" d="M844.574,711.664c-8.54.069-19.844-1.33-22.119-2.716-1.733-1.056-2.423-4.843-2.654-6.59l-.253.01s.479,6.1,2.755,7.487,13.579,2.785,22.119,2.716c2.465-.02,3.317-.9,3.27-2.2C847.349,711.159,846.409,711.649,844.574,711.664Z" transform="translate(-56 -106.019)" opacity="0.2"/>
|
||||
<path id="Path_107" data-name="Path 107" d="M949.813,724.718s11.36-1.729,14.5-4.591,16.89-7.488,18.217-3.667,19.494,17.447,6.633,19.107-30.153,1.609-33.835-.065S949.813,724.718,949.813,724.718Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
|
||||
<path id="Path_108" data-name="Path 108" d="M989.228,734.173c-12.86,1.659-30.153,1.609-33.835-.065-2.8-1.275-4.535-6.858-5.2-9.45l-.379.061s1.833,9.109,5.516,10.783,20.975,1.725,33.835.065c3.712-.479,4.836-1.956,4.529-3.906C993.319,732.907,991.991,733.817,989.228,734.173Z" transform="translate(-56 -106.019)" opacity="0.2"/>
|
||||
<path id="Path_109" data-name="Path 109" d="M670.26,723.9s9.587-1.459,12.237-3.875,14.255-6.32,15.374-3.095,16.452,14.725,5.6,16.125-25.448,1.358-28.555-.055S670.26,723.9,670.26,723.9Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
|
||||
<path id="Path_110" data-name="Path 110" d="M703.524,731.875c-10.853,1.4-25.448,1.358-28.555-.055-2.367-1.076-3.827-5.788-4.39-7.976l-.32.051s1.547,7.687,4.655,9.1,17.7,1.456,28.555.055c3.133-.4,4.081-1.651,3.822-3.3C706.977,730.807,705.856,731.575,703.524,731.875Z" transform="translate(-56 -106.019)" opacity="0.2"/>
|
||||
<path id="Path_111" data-name="Path 111" d="M178.389,719.109s7.463-1.136,9.527-3.016,11.1-4.92,11.969-2.409,12.808,11.463,4.358,12.553-19.811,1.057-22.23-.043S178.389,719.109,178.389,719.109Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
|
||||
<path id="Path_112" data-name="Path 112" d="M204.285,725.321c-8.449,1.09-19.811,1.057-22.23-.043-1.842-.838-2.979-4.506-3.417-6.209l-.249.04s1.2,5.984,3.624,7.085,13.781,1.133,22.23.043c2.439-.315,3.177-1.285,2.976-2.566C206.973,724.489,206.1,725.087,204.285,725.321Z" transform="translate(-56 -106.019)" opacity="0.2"/>
|
||||
<path id="Path_113" data-name="Path 113" d="M439.7,707.337c0,30.22-42.124,20.873-93.7,20.873s-93.074,9.347-93.074-20.873,42.118-36.793,93.694-36.793S439.7,677.117,439.7,707.337Z" transform="translate(-56 -106.019)" opacity="0.1"/>
|
||||
<path id="Path_114" data-name="Path 114" d="M439.7,699.9c0,30.22-42.124,20.873-93.7,20.873s-93.074,9.347-93.074-20.873S295.04,663.1,346.616,663.1,439.7,669.676,439.7,699.9Z" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
||||
</g>
|
||||
<g id="docusaurus_keytar" transform="translate(312.271 493.733)">
|
||||
<path id="Path_40" data-name="Path 40" d="M99,52h91.791V89.153H99Z" transform="translate(5.904 -14.001)" fill="#fff" fill-rule="evenodd"/>
|
||||
<path id="Path_41" data-name="Path 41" d="M24.855,163.927A21.828,21.828,0,0,1,5.947,153a21.829,21.829,0,0,0,18.908,32.782H46.71V163.927Z" transform="translate(-3 -4.634)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_42" data-name="Path 42" d="M121.861,61.1l76.514-4.782V45.39A21.854,21.854,0,0,0,176.52,23.535H78.173L75.441,18.8a3.154,3.154,0,0,0-5.464,0l-2.732,4.732L64.513,18.8a3.154,3.154,0,0,0-5.464,0l-2.732,4.732L53.586,18.8a3.154,3.154,0,0,0-5.464,0L45.39,23.535c-.024,0-.046,0-.071,0l-4.526-4.525a3.153,3.153,0,0,0-5.276,1.414l-1.5,5.577-5.674-1.521a3.154,3.154,0,0,0-3.863,3.864L26,34.023l-5.575,1.494a3.155,3.155,0,0,0-1.416,5.278l4.526,4.526c0,.023,0,.046,0,.07L18.8,48.122a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,59.05a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,69.977a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,80.9a3.154,3.154,0,0,0,0,5.464L23.535,89.1,18.8,91.832a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,102.76a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,113.687a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,124.615a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,135.542a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,146.469a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,157.4a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,168.324a3.154,3.154,0,0,0,0,5.464l4.732,2.732A21.854,21.854,0,0,0,45.39,198.375H176.52a21.854,21.854,0,0,0,21.855-21.855V89.1l-76.514-4.782a11.632,11.632,0,0,1,0-23.219" transform="translate(-1.681 -17.226)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_43" data-name="Path 43" d="M143,186.71h32.782V143H143Z" transform="translate(9.984 -5.561)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_44" data-name="Path 44" d="M196.71,159.855a5.438,5.438,0,0,0-.7.07c-.042-.164-.081-.329-.127-.493a5.457,5.457,0,1,0-5.4-9.372q-.181-.185-.366-.367a5.454,5.454,0,1,0-9.384-5.4c-.162-.046-.325-.084-.486-.126a5.467,5.467,0,1,0-10.788,0c-.162.042-.325.08-.486.126a5.457,5.457,0,1,0-9.384,5.4,21.843,21.843,0,1,0,36.421,21.02,5.452,5.452,0,1,0,.7-10.858" transform="translate(10.912 -6.025)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_45" data-name="Path 45" d="M153,124.855h32.782V103H153Z" transform="translate(10.912 -9.271)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_46" data-name="Path 46" d="M194.855,116.765a2.732,2.732,0,1,0,0-5.464,2.811,2.811,0,0,0-.349.035c-.022-.082-.04-.164-.063-.246a2.733,2.733,0,0,0-1.052-5.253,2.7,2.7,0,0,0-1.648.566q-.09-.093-.184-.184a2.7,2.7,0,0,0,.553-1.633,2.732,2.732,0,0,0-5.245-1.07,10.928,10.928,0,1,0,0,21.031,2.732,2.732,0,0,0,5.245-1.07,2.7,2.7,0,0,0-.553-1.633q.093-.09.184-.184a2.7,2.7,0,0,0,1.648.566,2.732,2.732,0,0,0,1.052-5.253c.023-.081.042-.164.063-.246a2.814,2.814,0,0,0,.349.035" transform="translate(12.767 -9.377)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_47" data-name="Path 47" d="M65.087,56.891a2.732,2.732,0,0,1-2.732-2.732,8.2,8.2,0,0,0-16.391,0,2.732,2.732,0,0,1-5.464,0,13.659,13.659,0,0,1,27.319,0,2.732,2.732,0,0,1-2.732,2.732" transform="translate(0.478 -15.068)" fill-rule="evenodd"/>
|
||||
<path id="Path_48" data-name="Path 48" d="M103,191.347h65.565a21.854,21.854,0,0,0,21.855-21.855V93H124.855A21.854,21.854,0,0,0,103,114.855Z" transform="translate(6.275 -10.199)" fill="#ffff50" fill-rule="evenodd"/>
|
||||
<path id="Path_49" data-name="Path 49" d="M173.216,129.787H118.535a1.093,1.093,0,1,1,0-2.185h54.681a1.093,1.093,0,0,1,0,2.185m0,21.855H118.535a1.093,1.093,0,1,1,0-2.186h54.681a1.093,1.093,0,0,1,0,2.186m0,21.855H118.535a1.093,1.093,0,1,1,0-2.185h54.681a1.093,1.093,0,0,1,0,2.185m0-54.434H118.535a1.093,1.093,0,1,1,0-2.185h54.681a1.093,1.093,0,0,1,0,2.185m0,21.652H118.535a1.093,1.093,0,1,1,0-2.186h54.681a1.093,1.093,0,0,1,0,2.186m0,21.855H118.535a1.093,1.093,0,1,1,0-2.186h54.681a1.093,1.093,0,0,1,0,2.186M189.585,61.611c-.013,0-.024-.007-.037-.005-3.377.115-4.974,3.492-6.384,6.472-1.471,3.114-2.608,5.139-4.473,5.078-2.064-.074-3.244-2.406-4.494-4.874-1.436-2.835-3.075-6.049-6.516-5.929-3.329.114-4.932,3.053-6.346,5.646-1.5,2.762-2.529,4.442-4.5,4.364-2.106-.076-3.225-1.972-4.52-4.167-1.444-2.443-3.112-5.191-6.487-5.1-3.272.113-4.879,2.606-6.3,4.808-1.5,2.328-2.552,3.746-4.551,3.662-2.156-.076-3.27-1.65-4.558-3.472-1.447-2.047-3.077-4.363-6.442-4.251-3.2.109-4.807,2.153-6.224,3.954-1.346,1.709-2.4,3.062-4.621,2.977a1.093,1.093,0,0,0-.079,2.186c3.3.11,4.967-1.967,6.417-3.81,1.286-1.635,2.4-3.045,4.582-3.12,2.1-.09,3.091,1.218,4.584,3.327,1.417,2,3.026,4.277,6.263,4.394,3.391.114,5.022-2.42,6.467-4.663,1.292-2,2.406-3.734,4.535-3.807,1.959-.073,3.026,1.475,4.529,4.022,1.417,2.4,3.023,5.121,6.324,5.241,3.415.118,5.064-2.863,6.5-5.5,1.245-2.282,2.419-4.437,4.5-4.509,1.959-.046,2.981,1.743,4.492,4.732,1.412,2.79,3.013,5.95,6.365,6.071l.185,0c3.348,0,4.937-3.36,6.343-6.331,1.245-2.634,2.423-5.114,4.444-5.216Z" transform="translate(7.109 -13.11)" fill-rule="evenodd"/>
|
||||
<path id="Path_50" data-name="Path 50" d="M83,186.71h43.71V143H83Z" transform="translate(4.42 -5.561)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<g id="Group_8" data-name="Group 8" transform="matrix(0.966, -0.259, 0.259, 0.966, 109.327, 91.085)">
|
||||
<rect id="Rectangle_3" data-name="Rectangle 3" width="92.361" height="36.462" rx="2" transform="translate(0 0)" fill="#d8d8d8"/>
|
||||
<g id="Group_2" data-name="Group 2" transform="translate(1.531 23.03)">
|
||||
<rect id="Rectangle_4" data-name="Rectangle 4" width="5.336" height="5.336" rx="1" transform="translate(16.797 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_5" data-name="Rectangle 5" width="5.336" height="5.336" rx="1" transform="translate(23.12 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_6" data-name="Rectangle 6" width="5.336" height="5.336" rx="1" transform="translate(29.444 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_7" data-name="Rectangle 7" width="5.336" height="5.336" rx="1" transform="translate(35.768 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_8" data-name="Rectangle 8" width="5.336" height="5.336" rx="1" transform="translate(42.091 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_9" data-name="Rectangle 9" width="5.336" height="5.336" rx="1" transform="translate(48.415 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_10" data-name="Rectangle 10" width="5.336" height="5.336" rx="1" transform="translate(54.739 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_11" data-name="Rectangle 11" width="5.336" height="5.336" rx="1" transform="translate(61.063 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_12" data-name="Rectangle 12" width="5.336" height="5.336" rx="1" transform="translate(67.386 0)" fill="#4a4a4a"/>
|
||||
<path id="Path_51" data-name="Path 51" d="M1.093,0H14.518a1.093,1.093,0,0,1,1.093,1.093V4.243a1.093,1.093,0,0,1-1.093,1.093H1.093A1.093,1.093,0,0,1,0,4.243V1.093A1.093,1.093,0,0,1,1.093,0ZM75,0H88.426a1.093,1.093,0,0,1,1.093,1.093V4.243a1.093,1.093,0,0,1-1.093,1.093H75a1.093,1.093,0,0,1-1.093-1.093V1.093A1.093,1.093,0,0,1,75,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g id="Group_3" data-name="Group 3" transform="translate(1.531 10.261)">
|
||||
<path id="Path_52" data-name="Path 52" d="M1.093,0H6.218A1.093,1.093,0,0,1,7.31,1.093V4.242A1.093,1.093,0,0,1,6.218,5.335H1.093A1.093,1.093,0,0,1,0,4.242V1.093A1.093,1.093,0,0,1,1.093,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<rect id="Rectangle_13" data-name="Rectangle 13" width="5.336" height="5.336" rx="1" transform="translate(8.299 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_14" data-name="Rectangle 14" width="5.336" height="5.336" rx="1" transform="translate(14.623 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_15" data-name="Rectangle 15" width="5.336" height="5.336" rx="1" transform="translate(20.947 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_16" data-name="Rectangle 16" width="5.336" height="5.336" rx="1" transform="translate(27.271 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_17" data-name="Rectangle 17" width="5.336" height="5.336" rx="1" transform="translate(33.594 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_18" data-name="Rectangle 18" width="5.336" height="5.336" rx="1" transform="translate(39.918 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_19" data-name="Rectangle 19" width="5.336" height="5.336" rx="1" transform="translate(46.242 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_20" data-name="Rectangle 20" width="5.336" height="5.336" rx="1" transform="translate(52.565 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_21" data-name="Rectangle 21" width="5.336" height="5.336" rx="1" transform="translate(58.888 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_22" data-name="Rectangle 22" width="5.336" height="5.336" rx="1" transform="translate(65.212 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_23" data-name="Rectangle 23" width="5.336" height="5.336" rx="1" transform="translate(71.536 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_24" data-name="Rectangle 24" width="5.336" height="5.336" rx="1" transform="translate(77.859 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_25" data-name="Rectangle 25" width="5.336" height="5.336" rx="1" transform="translate(84.183 0)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<g id="Group_4" data-name="Group 4" transform="translate(91.05 9.546) rotate(180)">
|
||||
<path id="Path_53" data-name="Path 53" d="M1.093,0H6.219A1.093,1.093,0,0,1,7.312,1.093v3.15A1.093,1.093,0,0,1,6.219,5.336H1.093A1.093,1.093,0,0,1,0,4.243V1.093A1.093,1.093,0,0,1,1.093,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<rect id="Rectangle_26" data-name="Rectangle 26" width="5.336" height="5.336" rx="1" transform="translate(8.299 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_27" data-name="Rectangle 27" width="5.336" height="5.336" rx="1" transform="translate(14.623 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_28" data-name="Rectangle 28" width="5.336" height="5.336" rx="1" transform="translate(20.947 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_29" data-name="Rectangle 29" width="5.336" height="5.336" rx="1" transform="translate(27.271 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_30" data-name="Rectangle 30" width="5.336" height="5.336" rx="1" transform="translate(33.594 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_31" data-name="Rectangle 31" width="5.336" height="5.336" rx="1" transform="translate(39.918 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_32" data-name="Rectangle 32" width="5.336" height="5.336" rx="1" transform="translate(46.242 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_33" data-name="Rectangle 33" width="5.336" height="5.336" rx="1" transform="translate(52.565 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_34" data-name="Rectangle 34" width="5.336" height="5.336" rx="1" transform="translate(58.889 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_35" data-name="Rectangle 35" width="5.336" height="5.336" rx="1" transform="translate(65.213 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_36" data-name="Rectangle 36" width="5.336" height="5.336" rx="1" transform="translate(71.537 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_37" data-name="Rectangle 37" width="5.336" height="5.336" rx="1" transform="translate(77.86 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_38" data-name="Rectangle 38" width="5.336" height="5.336" rx="1" transform="translate(84.183 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_39" data-name="Rectangle 39" width="5.336" height="5.336" rx="1" transform="translate(8.299 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_40" data-name="Rectangle 40" width="5.336" height="5.336" rx="1" transform="translate(14.623 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_41" data-name="Rectangle 41" width="5.336" height="5.336" rx="1" transform="translate(20.947 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_42" data-name="Rectangle 42" width="5.336" height="5.336" rx="1" transform="translate(27.271 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_43" data-name="Rectangle 43" width="5.336" height="5.336" rx="1" transform="translate(33.594 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_44" data-name="Rectangle 44" width="5.336" height="5.336" rx="1" transform="translate(39.918 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_45" data-name="Rectangle 45" width="5.336" height="5.336" rx="1" transform="translate(46.242 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_46" data-name="Rectangle 46" width="5.336" height="5.336" rx="1" transform="translate(52.565 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_47" data-name="Rectangle 47" width="5.336" height="5.336" rx="1" transform="translate(58.889 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_48" data-name="Rectangle 48" width="5.336" height="5.336" rx="1" transform="translate(65.213 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_49" data-name="Rectangle 49" width="5.336" height="5.336" rx="1" transform="translate(71.537 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_50" data-name="Rectangle 50" width="5.336" height="5.336" rx="1" transform="translate(77.86 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_51" data-name="Rectangle 51" width="5.336" height="5.336" rx="1" transform="translate(84.183 0)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<g id="Group_6" data-name="Group 6" transform="translate(1.531 16.584)">
|
||||
<path id="Path_54" data-name="Path 54" d="M1.093,0h7.3A1.093,1.093,0,0,1,9.485,1.093v3.15A1.093,1.093,0,0,1,8.392,5.336h-7.3A1.093,1.093,0,0,1,0,4.243V1.094A1.093,1.093,0,0,1,1.093,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<g id="Group_5" data-name="Group 5" transform="translate(10.671 0)">
|
||||
<rect id="Rectangle_52" data-name="Rectangle 52" width="5.336" height="5.336" rx="1" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_53" data-name="Rectangle 53" width="5.336" height="5.336" rx="1" transform="translate(6.324 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_54" data-name="Rectangle 54" width="5.336" height="5.336" rx="1" transform="translate(12.647 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_55" data-name="Rectangle 55" width="5.336" height="5.336" rx="1" transform="translate(18.971 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_56" data-name="Rectangle 56" width="5.336" height="5.336" rx="1" transform="translate(25.295 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_57" data-name="Rectangle 57" width="5.336" height="5.336" rx="1" transform="translate(31.619 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_58" data-name="Rectangle 58" width="5.336" height="5.336" rx="1" transform="translate(37.942 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_59" data-name="Rectangle 59" width="5.336" height="5.336" rx="1" transform="translate(44.265 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_60" data-name="Rectangle 60" width="5.336" height="5.336" rx="1" transform="translate(50.589 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_61" data-name="Rectangle 61" width="5.336" height="5.336" rx="1" transform="translate(56.912 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_62" data-name="Rectangle 62" width="5.336" height="5.336" rx="1" transform="translate(63.236 0)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<path id="Path_55" data-name="Path 55" d="M1.094,0H8A1.093,1.093,0,0,1,9.091,1.093v3.15A1.093,1.093,0,0,1,8,5.336H1.093A1.093,1.093,0,0,1,0,4.243V1.094A1.093,1.093,0,0,1,1.093,0Z" transform="translate(80.428 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g id="Group_7" data-name="Group 7" transform="translate(1.531 29.627)">
|
||||
<rect id="Rectangle_63" data-name="Rectangle 63" width="5.336" height="5.336" rx="1" transform="translate(0 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_64" data-name="Rectangle 64" width="5.336" height="5.336" rx="1" transform="translate(6.324 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_65" data-name="Rectangle 65" width="5.336" height="5.336" rx="1" transform="translate(12.647 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_66" data-name="Rectangle 66" width="5.336" height="5.336" rx="1" transform="translate(18.971 0)" fill="#4a4a4a"/>
|
||||
<path id="Path_56" data-name="Path 56" d="M1.093,0H31.515a1.093,1.093,0,0,1,1.093,1.093V4.244a1.093,1.093,0,0,1-1.093,1.093H1.093A1.093,1.093,0,0,1,0,4.244V1.093A1.093,1.093,0,0,1,1.093,0ZM34.687,0h3.942a1.093,1.093,0,0,1,1.093,1.093V4.244a1.093,1.093,0,0,1-1.093,1.093H34.687a1.093,1.093,0,0,1-1.093-1.093V1.093A1.093,1.093,0,0,1,34.687,0Z" transform="translate(25.294 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<rect id="Rectangle_67" data-name="Rectangle 67" width="5.336" height="5.336" rx="1" transform="translate(66.003 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_68" data-name="Rectangle 68" width="5.336" height="5.336" rx="1" transform="translate(72.327 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_69" data-name="Rectangle 69" width="5.336" height="5.336" rx="1" transform="translate(84.183 0)" fill="#4a4a4a"/>
|
||||
<path id="Path_57" data-name="Path 57" d="M5.336,0V1.18A1.093,1.093,0,0,1,4.243,2.273H1.093A1.093,1.093,0,0,1,0,1.18V0Z" transform="translate(83.59 2.273) rotate(180)" fill="#4a4a4a"/>
|
||||
<path id="Path_58" data-name="Path 58" d="M5.336,0V1.18A1.093,1.093,0,0,1,4.243,2.273H1.093A1.093,1.093,0,0,1,0,1.18V0Z" transform="translate(78.255 3.063)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<rect id="Rectangle_70" data-name="Rectangle 70" width="88.927" height="2.371" rx="1.085" transform="translate(1.925 1.17)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_71" data-name="Rectangle 71" width="4.986" height="1.581" rx="0.723" transform="translate(4.1 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_72" data-name="Rectangle 72" width="4.986" height="1.581" rx="0.723" transform="translate(10.923 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_73" data-name="Rectangle 73" width="4.986" height="1.581" rx="0.723" transform="translate(16.173 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_74" data-name="Rectangle 74" width="4.986" height="1.581" rx="0.723" transform="translate(21.421 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_75" data-name="Rectangle 75" width="4.986" height="1.581" rx="0.723" transform="translate(26.671 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_76" data-name="Rectangle 76" width="4.986" height="1.581" rx="0.723" transform="translate(33.232 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_77" data-name="Rectangle 77" width="4.986" height="1.581" rx="0.723" transform="translate(38.48 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_78" data-name="Rectangle 78" width="4.986" height="1.581" rx="0.723" transform="translate(43.73 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_79" data-name="Rectangle 79" width="4.986" height="1.581" rx="0.723" transform="translate(48.978 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_80" data-name="Rectangle 80" width="4.986" height="1.581" rx="0.723" transform="translate(55.54 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_81" data-name="Rectangle 81" width="4.986" height="1.581" rx="0.723" transform="translate(60.788 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_82" data-name="Rectangle 82" width="4.986" height="1.581" rx="0.723" transform="translate(66.038 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_83" data-name="Rectangle 83" width="4.986" height="1.581" rx="0.723" transform="translate(72.599 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_84" data-name="Rectangle 84" width="4.986" height="1.581" rx="0.723" transform="translate(77.847 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_85" data-name="Rectangle 85" width="4.986" height="1.581" rx="0.723" transform="translate(83.097 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
</g>
|
||||
<path id="Path_59" data-name="Path 59" d="M146.71,159.855a5.439,5.439,0,0,0-.7.07c-.042-.164-.081-.329-.127-.493a5.457,5.457,0,1,0-5.4-9.372q-.181-.185-.366-.367a5.454,5.454,0,1,0-9.384-5.4c-.162-.046-.325-.084-.486-.126a5.467,5.467,0,1,0-10.788,0c-.162.042-.325.08-.486.126a5.457,5.457,0,1,0-9.384,5.4,21.843,21.843,0,1,0,36.421,21.02,5.452,5.452,0,1,0,.7-10.858" transform="translate(6.275 -6.025)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_60" data-name="Path 60" d="M83,124.855h43.71V103H83Z" transform="translate(4.42 -9.271)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_61" data-name="Path 61" d="M134.855,116.765a2.732,2.732,0,1,0,0-5.464,2.811,2.811,0,0,0-.349.035c-.022-.082-.04-.164-.063-.246a2.733,2.733,0,0,0-1.052-5.253,2.7,2.7,0,0,0-1.648.566q-.09-.093-.184-.184a2.7,2.7,0,0,0,.553-1.633,2.732,2.732,0,0,0-5.245-1.07,10.928,10.928,0,1,0,0,21.031,2.732,2.732,0,0,0,5.245-1.07,2.7,2.7,0,0,0-.553-1.633q.093-.09.184-.184a2.7,2.7,0,0,0,1.648.566,2.732,2.732,0,0,0,1.052-5.253c.023-.081.042-.164.063-.246a2.811,2.811,0,0,0,.349.035" transform="translate(7.202 -9.377)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_62" data-name="Path 62" d="M143.232,42.33a2.967,2.967,0,0,1-.535-.055,2.754,2.754,0,0,1-.514-.153,2.838,2.838,0,0,1-.471-.251,4.139,4.139,0,0,1-.415-.339,3.2,3.2,0,0,1-.338-.415A2.7,2.7,0,0,1,140.5,39.6a2.968,2.968,0,0,1,.055-.535,3.152,3.152,0,0,1,.152-.514,2.874,2.874,0,0,1,.252-.47,2.633,2.633,0,0,1,.753-.754,2.837,2.837,0,0,1,.471-.251,2.753,2.753,0,0,1,.514-.153,2.527,2.527,0,0,1,1.071,0,2.654,2.654,0,0,1,.983.4,4.139,4.139,0,0,1,.415.339,4.019,4.019,0,0,1,.339.415,2.786,2.786,0,0,1,.251.47,2.864,2.864,0,0,1,.208,1.049,2.77,2.77,0,0,1-.8,1.934,4.139,4.139,0,0,1-.415.339,2.722,2.722,0,0,1-1.519.459m21.855-1.366a2.789,2.789,0,0,1-1.935-.8,4.162,4.162,0,0,1-.338-.415,2.7,2.7,0,0,1-.459-1.519,2.789,2.789,0,0,1,.8-1.934,4.139,4.139,0,0,1,.415-.339,2.838,2.838,0,0,1,.471-.251,2.752,2.752,0,0,1,.514-.153,2.527,2.527,0,0,1,1.071,0,2.654,2.654,0,0,1,.983.4,4.139,4.139,0,0,1,.415.339,2.79,2.79,0,0,1,.8,1.934,3.069,3.069,0,0,1-.055.535,2.779,2.779,0,0,1-.153.514,3.885,3.885,0,0,1-.251.47,4.02,4.02,0,0,1-.339.415,4.138,4.138,0,0,1-.415.339,2.722,2.722,0,0,1-1.519.459" transform="translate(9.753 -15.532)" fill-rule="evenodd"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 31 KiB |
|
@ -0,0 +1,170 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="1041.277" height="554.141" viewBox="0 0 1041.277 554.141">
|
||||
<title>Powered by React</title>
|
||||
<g id="Group_24" data-name="Group 24" transform="translate(-440 -263)">
|
||||
<g id="Group_23" data-name="Group 23" transform="translate(439.989 262.965)">
|
||||
<path id="Path_299" data-name="Path 299" d="M1040.82,611.12q-1.74,3.75-3.47,7.4-2.7,5.67-5.33,11.12c-.78,1.61-1.56,3.19-2.32,4.77-8.6,17.57-16.63,33.11-23.45,45.89A73.21,73.21,0,0,1,942.44,719l-151.65,1.65h-1.6l-13,.14-11.12.12-34.1.37h-1.38l-17.36.19h-.53l-107,1.16-95.51,1-11.11.12-69,.75H429l-44.75.48h-.48l-141.5,1.53-42.33.46a87.991,87.991,0,0,1-10.79-.54h0c-1.22-.14-2.44-.3-3.65-.49a87.38,87.38,0,0,1-51.29-27.54C116,678.37,102.75,655,93.85,629.64q-1.93-5.49-3.6-11.12C59.44,514.37,97,380,164.6,290.08q4.25-5.64,8.64-11l.07-.08c20.79-25.52,44.1-46.84,68.93-62,44-26.91,92.75-34.49,140.7-11.9,40.57,19.12,78.45,28.11,115.17,30.55,3.71.24,7.42.42,11.11.53,84.23,2.65,163.17-27.7,255.87-47.29,3.69-.78,7.39-1.55,11.12-2.28,66.13-13.16,139.49-20.1,226.73-5.51a189.089,189.089,0,0,1,26.76,6.4q5.77,1.86,11.12,4c41.64,16.94,64.35,48.24,74,87.46q1.37,5.46,2.37,11.11C1134.3,384.41,1084.19,518.23,1040.82,611.12Z" transform="translate(-79.34 -172.91)" fill="#f2f2f2"/>
|
||||
<path id="Path_300" data-name="Path 300" d="M576.36,618.52a95.21,95.21,0,0,1-1.87,11.12h93.7V618.52Zm-78.25,62.81,11.11-.09V653.77c-3.81-.17-7.52-.34-11.11-.52ZM265.19,618.52v11.12h198.5V618.52ZM1114.87,279h-74V191.51q-5.35-2.17-11.12-4V279H776.21V186.58c-3.73.73-7.43,1.5-11.12,2.28V279H509.22V236.15c-3.69-.11-7.4-.29-11.11-.53V279H242.24V217c-24.83,15.16-48.14,36.48-68.93,62h-.07v.08q-4.4,5.4-8.64,11h8.64V618.52h-83q1.66,5.63,3.6,11.12h79.39v93.62a87,87,0,0,0,12.2,2.79c1.21.19,2.43.35,3.65.49h0a87.991,87.991,0,0,0,10.79.54l42.33-.46v-97H498.11v94.21l11.11-.12V629.64H765.09V721l11.12-.12V629.64H1029.7v4.77c.76-1.58,1.54-3.16,2.32-4.77q2.63-5.45,5.33-11.12,1.73-3.64,3.47-7.4v-321h76.42Q1116.23,284.43,1114.87,279ZM242.24,618.52V290.08H498.11V618.52Zm267,0V290.08H765.09V618.52Zm520.48,0H776.21V290.08H1029.7Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_301" data-name="Path 301" d="M863.09,533.65v13l-151.92,1.4-1.62.03-57.74.53-1.38.02-17.55.15h-.52l-106.98.99L349.77,551.4h-.15l-44.65.42-.48.01-198.4,1.82v-15l46.65-28,93.6-.78,2-.01.66-.01,2-.03,44.94-.37,2.01-.01.64-.01,2-.01L315,509.3l.38-.01,35.55-.3h.29l277.4-2.34,6.79-.05h.68l5.18-.05,37.65-.31,2-.03,1.85-.02h.96l11.71-.09,2.32-.03,3.11-.02,9.75-.09,15.47-.13,2-.02,3.48-.02h.65l74.71-.64Z" fill="#65617d"/>
|
||||
<path id="Path_302" data-name="Path 302" d="M863.09,533.65v13l-151.92,1.4-1.62.03-57.74.53-1.38.02-17.55.15h-.52l-106.98.99L349.77,551.4h-.15l-44.65.42-.48.01-198.4,1.82v-15l46.65-28,93.6-.78,2-.01.66-.01,2-.03,44.94-.37,2.01-.01.64-.01,2-.01L315,509.3l.38-.01,35.55-.3h.29l277.4-2.34,6.79-.05h.68l5.18-.05,37.65-.31,2-.03,1.85-.02h.96l11.71-.09,2.32-.03,3.11-.02,9.75-.09,15.47-.13,2-.02,3.48-.02h.65l74.71-.64Z" opacity="0.2"/>
|
||||
<path id="Path_303" data-name="Path 303" d="M375.44,656.57v24.49a6.13,6.13,0,0,1-3.5,5.54,6,6,0,0,1-2.5.6l-34.9.74a6,6,0,0,1-2.7-.57,6.12,6.12,0,0,1-3.57-5.57V656.57Z" transform="translate(-79.34 -172.91)" fill="#3f3d56"/>
|
||||
<path id="Path_304" data-name="Path 304" d="M375.44,656.57v24.49a6.13,6.13,0,0,1-3.5,5.54,6,6,0,0,1-2.5.6l-34.9.74a6,6,0,0,1-2.7-.57,6.12,6.12,0,0,1-3.57-5.57V656.57Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_305" data-name="Path 305" d="M377.44,656.57v24.49a6.13,6.13,0,0,1-3.5,5.54,6,6,0,0,1-2.5.6l-34.9.74a6,6,0,0,1-2.7-.57,6.12,6.12,0,0,1-3.57-5.57V656.57Z" transform="translate(-79.34 -172.91)" fill="#3f3d56"/>
|
||||
<rect id="Rectangle_137" data-name="Rectangle 137" width="47.17" height="31.5" transform="translate(680.92 483.65)" fill="#3f3d56"/>
|
||||
<rect id="Rectangle_138" data-name="Rectangle 138" width="47.17" height="31.5" transform="translate(680.92 483.65)" opacity="0.1"/>
|
||||
<rect id="Rectangle_139" data-name="Rectangle 139" width="47.17" height="31.5" transform="translate(678.92 483.65)" fill="#3f3d56"/>
|
||||
<path id="Path_306" data-name="Path 306" d="M298.09,483.65v4.97l-47.17,1.26v-6.23Z" opacity="0.1"/>
|
||||
<path id="Path_307" data-name="Path 307" d="M460.69,485.27v168.2a4,4,0,0,1-3.85,3.95l-191.65,5.1h-.05a4,4,0,0,1-3.95-3.95V485.27a4,4,0,0,1,3.95-3.95h191.6a4,4,0,0,1,3.95,3.95Z" transform="translate(-79.34 -172.91)" fill="#65617d"/>
|
||||
<path id="Path_308" data-name="Path 308" d="M265.19,481.32v181.2h-.05a4,4,0,0,1-3.95-3.95V485.27a4,4,0,0,1,3.95-3.95Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_309" data-name="Path 309" d="M194.59,319.15h177.5V467.4l-177.5,4Z" fill="#39374d"/>
|
||||
<path id="Path_310" data-name="Path 310" d="M726.09,483.65v6.41l-47.17-1.26v-5.15Z" opacity="0.1"/>
|
||||
<path id="Path_311" data-name="Path 311" d="M867.69,485.27v173.3a4,4,0,0,1-4,3.95h0L672,657.42a4,4,0,0,1-3.85-3.95V485.27a4,4,0,0,1,3.95-3.95H863.7a4,4,0,0,1,3.99,3.95Z" transform="translate(-79.34 -172.91)" fill="#65617d"/>
|
||||
<path id="Path_312" data-name="Path 312" d="M867.69,485.27v173.3a4,4,0,0,1-4,3.95h0V481.32h0a4,4,0,0,1,4,3.95Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_313" data-name="Path 313" d="M775.59,319.15H598.09V467.4l177.5,4Z" fill="#39374d"/>
|
||||
<path id="Path_314" data-name="Path 314" d="M663.19,485.27v168.2a4,4,0,0,1-3.85,3.95l-191.65,5.1h0a4,4,0,0,1-4-3.95V485.27a4,4,0,0,1,3.95-3.95h191.6A4,4,0,0,1,663.19,485.27Z" transform="translate(-79.34 -172.91)" fill="#65617d"/>
|
||||
<path id="Path_315" data-name="Path 315" d="M397.09,319.15h177.5V467.4l-177.5,4Z" fill="#4267b2"/>
|
||||
<path id="Path_316" data-name="Path 316" d="M863.09,533.65v13l-151.92,1.4-1.62.03-57.74.53-1.38.02-17.55.15h-.52l-106.98.99L349.77,551.4h-.15l-44.65.42-.48.01-198.4,1.82v-15l202.51-1.33h.48l40.99-.28h.19l283.08-1.87h.29l.17-.01h.47l4.79-.03h1.46l74.49-.5,4.4-.02.98-.01Z" opacity="0.1"/>
|
||||
<circle id="Ellipse_111" data-name="Ellipse 111" cx="51.33" cy="51.33" r="51.33" transform="translate(435.93 246.82)" fill="#fbbebe"/>
|
||||
<path id="Path_317" data-name="Path 317" d="M617.94,550.07s-99.5,12-90,0c3.44-4.34,4.39-17.2,4.2-31.85-.06-4.45-.22-9.06-.45-13.65-1.1-22-3.75-43.5-3.75-43.5s87-41,77-8.5c-4,13.13-2.69,31.57.35,48.88.89,5.05,1.92,10,3,14.7a344.66,344.66,0,0,0,9.65,33.92Z" transform="translate(-79.34 -172.91)" fill="#fbbebe"/>
|
||||
<path id="Path_318" data-name="Path 318" d="M585.47,546c11.51-2.13,23.7-6,34.53-1.54,2.85,1.17,5.47,2.88,8.39,3.86s6.12,1.22,9.16,1.91c10.68,2.42,19.34,10.55,24.9,20s8.44,20.14,11.26,30.72l6.9,25.83c6,22.45,12,45.09,13.39,68.3a2437.506,2437.506,0,0,1-250.84,1.43c5.44-10.34,11-21.31,10.54-33s-7.19-23.22-4.76-34.74c1.55-7.34,6.57-13.39,9.64-20.22,8.75-19.52,1.94-45.79,17.32-60.65,6.92-6.68,17-9.21,26.63-8.89,12.28.41,24.85,4.24,37,6.11C555.09,547.48,569.79,548.88,585.47,546Z" transform="translate(-79.34 -172.91)" fill="#ff6584"/>
|
||||
<path id="Path_319" data-name="Path 319" d="M716.37,657.17l-.1,1.43v.1l-.17,2.3-1.33,18.51-1.61,22.3-.46,6.28-1,13.44v.17l-107,1-175.59,1.9v.84h-.14v-1.12l.45-14.36.86-28.06.74-23.79.07-2.37a10.53,10.53,0,0,1,11.42-10.17c4.72.4,10.85.89,18.18,1.41l3,.22c42.33,2.94,120.56,6.74,199.5,2,1.66-.09,3.33-.19,5-.31,12.24-.77,24.47-1.76,36.58-3a10.53,10.53,0,0,1,11.6,11.23Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_320" data-name="Path 320" d="M429.08,725.44v-.84l175.62-1.91,107-1h.3v-.17l1-13.44.43-6,1.64-22.61,1.29-17.9v-.44a10.617,10.617,0,0,0-.11-2.47.3.3,0,0,0,0-.1,10.391,10.391,0,0,0-2-4.64,10.54,10.54,0,0,0-9.42-4c-12.11,1.24-24.34,2.23-36.58,3-1.67.12-3.34.22-5,.31-78.94,4.69-157.17.89-199.5-2l-3-.22c-7.33-.52-13.46-1-18.18-1.41a10.54,10.54,0,0,0-11.24,8.53,11,11,0,0,0-.18,1.64l-.68,22.16L429.54,710l-.44,14.36v1.12Z" transform="translate(-79.34 -172.91)" fill="#3f3d56"/>
|
||||
<path id="Path_321" data-name="Path 321" d="M716.67,664.18l-1.23,15.33-1.83,22.85-.46,5.72-1,12.81-.06.64v.17h0l-.15,1.48.11-1.48h-.29l-107,1-175.65,1.9v-.28l.49-14.36,1-28.06.64-18.65A6.36,6.36,0,0,1,434.3,658a6.25,6.25,0,0,1,3.78-.9c2.1.17,4.68.37,7.69.59,4.89.36,10.92.78,17.94,1.22,13,.82,29.31,1.7,48,2.42,52,2,122.2,2.67,188.88-3.17,3-.26,6.1-.55,9.13-.84a6.26,6.26,0,0,1,3.48.66,5.159,5.159,0,0,1,.86.54,6.14,6.14,0,0,1,2,2.46,3.564,3.564,0,0,1,.25.61A6.279,6.279,0,0,1,716.67,664.18Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_322" data-name="Path 322" d="M377.44,677.87v3.19a6.13,6.13,0,0,1-3.5,5.54l-40.1.77a6.12,6.12,0,0,1-3.57-5.57v-3Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_323" data-name="Path 323" d="M298.59,515.57l-52.25,1V507.9l52.25-1Z" fill="#3f3d56"/>
|
||||
<path id="Path_324" data-name="Path 324" d="M298.59,515.57l-52.25,1V507.9l52.25-1Z" opacity="0.1"/>
|
||||
<path id="Path_325" data-name="Path 325" d="M300.59,515.57l-52.25,1V507.9l52.25-1Z" fill="#3f3d56"/>
|
||||
<path id="Path_326" data-name="Path 326" d="M758.56,679.87v3.19a6.13,6.13,0,0,0,3.5,5.54l40.1.77a6.12,6.12,0,0,0,3.57-5.57v-3Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_327" data-name="Path 327" d="M678.72,517.57l52.25,1V509.9l-52.25-1Z" opacity="0.1"/>
|
||||
<path id="Path_328" data-name="Path 328" d="M676.72,517.57l52.25,1V509.9l-52.25-1Z" fill="#3f3d56"/>
|
||||
<path id="Path_329" data-name="Path 329" d="M534.13,486.79c.08,7-3.16,13.6-5.91,20.07a163.491,163.491,0,0,0-12.66,74.71c.73,11,2.58,22,.73,32.9s-8.43,21.77-19,24.9c17.53,10.45,41.26,9.35,57.76-2.66,8.79-6.4,15.34-15.33,21.75-24.11a97.86,97.86,0,0,1-13.31,44.75A103.43,103.43,0,0,0,637,616.53c4.31-5.81,8.06-12.19,9.72-19.23,3.09-13-1.22-26.51-4.51-39.5a266.055,266.055,0,0,1-6.17-33c-.43-3.56-.78-7.22.1-10.7,1-4.07,3.67-7.51,5.64-11.22,5.6-10.54,5.73-23.3,2.86-34.88s-8.49-22.26-14.06-32.81c-4.46-8.46-9.3-17.31-17.46-22.28-5.1-3.1-11-4.39-16.88-5.64l-25.37-5.43c-5.55-1.19-11.26-2.38-16.87-1.51-9.47,1.48-16.14,8.32-22,15.34-4.59,5.46-15.81,15.71-16.6,22.86-.72,6.59,5.1,17.63,6.09,24.58,1.3,9,2.22,6,7.3,11.52C532,478.05,534.07,482,534.13,486.79Z" transform="translate(-79.34 -172.91)" fill="#3f3d56"/>
|
||||
</g>
|
||||
<g id="docusaurus_keytar" transform="translate(670.271 615.768)">
|
||||
<path id="Path_40" data-name="Path 40" d="M99,52h43.635V69.662H99Z" transform="translate(-49.132 -33.936)" fill="#fff" fill-rule="evenodd"/>
|
||||
<path id="Path_41" data-name="Path 41" d="M13.389,158.195A10.377,10.377,0,0,1,4.4,153a10.377,10.377,0,0,0,8.988,15.584H23.779V158.195Z" transform="translate(-3 -82.47)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_42" data-name="Path 42" d="M66.967,38.083l36.373-2.273V30.615A10.389,10.389,0,0,0,92.95,20.226H46.2l-1.3-2.249a1.5,1.5,0,0,0-2.6,0L41,20.226l-1.3-2.249a1.5,1.5,0,0,0-2.6,0l-1.3,2.249-1.3-2.249a1.5,1.5,0,0,0-2.6,0l-1.3,2.249-.034,0-2.152-2.151a1.5,1.5,0,0,0-2.508.672L25.21,21.4l-2.7-.723a1.5,1.5,0,0,0-1.836,1.837l.722,2.7-2.65.71a1.5,1.5,0,0,0-.673,2.509l2.152,2.152c0,.011,0,.022,0,.033l-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6L20.226,41l-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3A10.389,10.389,0,0,0,30.615,103.34H92.95A10.389,10.389,0,0,0,103.34,92.95V51.393L66.967,49.12a5.53,5.53,0,0,1,0-11.038" transform="translate(-9.836 -17.226)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_43" data-name="Path 43" d="M143,163.779h15.584V143H143Z" transform="translate(-70.275 -77.665)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_44" data-name="Path 44" d="M173.779,148.389a2.582,2.582,0,0,0-.332.033c-.02-.078-.038-.156-.06-.234a2.594,2.594,0,1,0-2.567-4.455q-.086-.088-.174-.175a2.593,2.593,0,1,0-4.461-2.569c-.077-.022-.154-.04-.231-.06a2.6,2.6,0,1,0-5.128,0c-.077.02-.154.038-.231.06a2.594,2.594,0,1,0-4.461,2.569,10.384,10.384,0,1,0,17.314,9.992,2.592,2.592,0,1,0,.332-5.161" transform="translate(-75.08 -75.262)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_45" data-name="Path 45" d="M153,113.389h15.584V103H153Z" transform="translate(-75.08 -58.444)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_46" data-name="Path 46" d="M183.389,108.944a1.3,1.3,0,1,0,0-2.6,1.336,1.336,0,0,0-.166.017c-.01-.039-.019-.078-.03-.117a1.3,1.3,0,0,0-.5-2.5,1.285,1.285,0,0,0-.783.269q-.043-.044-.087-.087a1.285,1.285,0,0,0,.263-.776,1.3,1.3,0,0,0-2.493-.509,5.195,5.195,0,1,0,0,10,1.3,1.3,0,0,0,2.493-.509,1.285,1.285,0,0,0-.263-.776q.044-.043.087-.087a1.285,1.285,0,0,0,.783.269,1.3,1.3,0,0,0,.5-2.5c.011-.038.02-.078.03-.117a1.337,1.337,0,0,0,.166.017" transform="translate(-84.691 -57.894)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_47" data-name="Path 47" d="M52.188,48.292a1.3,1.3,0,0,1-1.3-1.3,3.9,3.9,0,0,0-7.792,0,1.3,1.3,0,1,1-2.6,0,6.493,6.493,0,0,1,12.987,0,1.3,1.3,0,0,1-1.3,1.3" transform="translate(-21.02 -28.41)" fill-rule="evenodd"/>
|
||||
<path id="Path_48" data-name="Path 48" d="M103,139.752h31.168a10.389,10.389,0,0,0,10.389-10.389V93H113.389A10.389,10.389,0,0,0,103,103.389Z" transform="translate(-51.054 -53.638)" fill="#ffff50" fill-rule="evenodd"/>
|
||||
<path id="Path_49" data-name="Path 49" d="M141.1,94.017H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0,10.389H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0,10.389H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0-25.877H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0,10.293H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0,10.389H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m7.782-47.993c-.006,0-.011,0-.018,0-1.605.055-2.365,1.66-3.035,3.077-.7,1.48-1.24,2.443-2.126,2.414-.981-.035-1.542-1.144-2.137-2.317-.683-1.347-1.462-2.876-3.1-2.819-1.582.054-2.344,1.451-3.017,2.684-.715,1.313-1.2,2.112-2.141,2.075-1-.036-1.533-.938-2.149-1.981-.686-1.162-1.479-2.467-3.084-2.423-1.555.053-2.319,1.239-2.994,2.286-.713,1.106-1.213,1.781-2.164,1.741-1.025-.036-1.554-.784-2.167-1.65-.688-.973-1.463-2.074-3.062-2.021a3.815,3.815,0,0,0-2.959,1.879c-.64.812-1.14,1.456-2.2,1.415a.52.52,0,0,0-.037,1.039,3.588,3.588,0,0,0,3.05-1.811c.611-.777,1.139-1.448,2.178-1.483,1-.043,1.47.579,2.179,1.582.674.953,1.438,2.033,2.977,2.089,1.612.054,2.387-1.151,3.074-2.217.614-.953,1.144-1.775,2.156-1.81.931-.035,1.438.7,2.153,1.912.674,1.141,1.437,2.434,3.006,2.491,1.623.056,2.407-1.361,3.09-2.616.592-1.085,1.15-2.109,2.14-2.143.931-.022,1.417.829,2.135,2.249.671,1.326,1.432,2.828,3.026,2.886l.088,0c1.592,0,2.347-1.6,3.015-3.01.592-1.252,1.152-2.431,2.113-2.479Z" transform="translate(-55.378 -38.552)" fill-rule="evenodd"/>
|
||||
<path id="Path_50" data-name="Path 50" d="M83,163.779h20.779V143H83Z" transform="translate(-41.443 -77.665)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<g id="Group_8" data-name="Group 8" transform="matrix(0.966, -0.259, 0.259, 0.966, 51.971, 43.3)">
|
||||
<rect id="Rectangle_3" data-name="Rectangle 3" width="43.906" height="17.333" rx="2" transform="translate(0 0)" fill="#d8d8d8"/>
|
||||
<g id="Group_2" data-name="Group 2" transform="translate(0.728 10.948)">
|
||||
<rect id="Rectangle_4" data-name="Rectangle 4" width="2.537" height="2.537" rx="1" transform="translate(7.985 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_5" data-name="Rectangle 5" width="2.537" height="2.537" rx="1" transform="translate(10.991 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_6" data-name="Rectangle 6" width="2.537" height="2.537" rx="1" transform="translate(13.997 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_7" data-name="Rectangle 7" width="2.537" height="2.537" rx="1" transform="translate(17.003 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_8" data-name="Rectangle 8" width="2.537" height="2.537" rx="1" transform="translate(20.009 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_9" data-name="Rectangle 9" width="2.537" height="2.537" rx="1" transform="translate(23.015 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_10" data-name="Rectangle 10" width="2.537" height="2.537" rx="1" transform="translate(26.021 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_11" data-name="Rectangle 11" width="2.537" height="2.537" rx="1" transform="translate(29.028 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_12" data-name="Rectangle 12" width="2.537" height="2.537" rx="1" transform="translate(32.034 0)" fill="#4a4a4a"/>
|
||||
<path id="Path_51" data-name="Path 51" d="M.519,0H6.9A.519.519,0,0,1,7.421.52v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.519A.519.519,0,0,1,.519,0ZM35.653,0h6.383a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H35.652a.519.519,0,0,1-.519-.519V.519A.519.519,0,0,1,35.652,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g id="Group_3" data-name="Group 3" transform="translate(0.728 4.878)">
|
||||
<path id="Path_52" data-name="Path 52" d="M.519,0H2.956a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.519A.519.519,0,0,1,.519,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<rect id="Rectangle_13" data-name="Rectangle 13" width="2.537" height="2.537" rx="1" transform="translate(3.945 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_14" data-name="Rectangle 14" width="2.537" height="2.537" rx="1" transform="translate(6.951 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_15" data-name="Rectangle 15" width="2.537" height="2.537" rx="1" transform="translate(9.958 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_16" data-name="Rectangle 16" width="2.537" height="2.537" rx="1" transform="translate(12.964 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_17" data-name="Rectangle 17" width="2.537" height="2.537" rx="1" transform="translate(15.97 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_18" data-name="Rectangle 18" width="2.537" height="2.537" rx="1" transform="translate(18.976 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_19" data-name="Rectangle 19" width="2.537" height="2.537" rx="1" transform="translate(21.982 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_20" data-name="Rectangle 20" width="2.537" height="2.537" rx="1" transform="translate(24.988 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_21" data-name="Rectangle 21" width="2.537" height="2.537" rx="1" transform="translate(27.994 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_22" data-name="Rectangle 22" width="2.537" height="2.537" rx="1" transform="translate(31 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_23" data-name="Rectangle 23" width="2.537" height="2.537" rx="1" transform="translate(34.006 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_24" data-name="Rectangle 24" width="2.537" height="2.537" rx="1" transform="translate(37.012 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_25" data-name="Rectangle 25" width="2.537" height="2.537" rx="1" transform="translate(40.018 0)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<g id="Group_4" data-name="Group 4" transform="translate(43.283 4.538) rotate(180)">
|
||||
<path id="Path_53" data-name="Path 53" d="M.519,0H2.956a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.519A.519.519,0,0,1,.519,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<rect id="Rectangle_26" data-name="Rectangle 26" width="2.537" height="2.537" rx="1" transform="translate(3.945 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_27" data-name="Rectangle 27" width="2.537" height="2.537" rx="1" transform="translate(6.951 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_28" data-name="Rectangle 28" width="2.537" height="2.537" rx="1" transform="translate(9.958 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_29" data-name="Rectangle 29" width="2.537" height="2.537" rx="1" transform="translate(12.964 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_30" data-name="Rectangle 30" width="2.537" height="2.537" rx="1" transform="translate(15.97 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_31" data-name="Rectangle 31" width="2.537" height="2.537" rx="1" transform="translate(18.976 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_32" data-name="Rectangle 32" width="2.537" height="2.537" rx="1" transform="translate(21.982 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_33" data-name="Rectangle 33" width="2.537" height="2.537" rx="1" transform="translate(24.988 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_34" data-name="Rectangle 34" width="2.537" height="2.537" rx="1" transform="translate(27.994 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_35" data-name="Rectangle 35" width="2.537" height="2.537" rx="1" transform="translate(31.001 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_36" data-name="Rectangle 36" width="2.537" height="2.537" rx="1" transform="translate(34.007 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_37" data-name="Rectangle 37" width="2.537" height="2.537" rx="1" transform="translate(37.013 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_38" data-name="Rectangle 38" width="2.537" height="2.537" rx="1" transform="translate(40.018 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_39" data-name="Rectangle 39" width="2.537" height="2.537" rx="1" transform="translate(3.945 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_40" data-name="Rectangle 40" width="2.537" height="2.537" rx="1" transform="translate(6.951 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_41" data-name="Rectangle 41" width="2.537" height="2.537" rx="1" transform="translate(9.958 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_42" data-name="Rectangle 42" width="2.537" height="2.537" rx="1" transform="translate(12.964 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_43" data-name="Rectangle 43" width="2.537" height="2.537" rx="1" transform="translate(15.97 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_44" data-name="Rectangle 44" width="2.537" height="2.537" rx="1" transform="translate(18.976 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_45" data-name="Rectangle 45" width="2.537" height="2.537" rx="1" transform="translate(21.982 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_46" data-name="Rectangle 46" width="2.537" height="2.537" rx="1" transform="translate(24.988 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_47" data-name="Rectangle 47" width="2.537" height="2.537" rx="1" transform="translate(27.994 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_48" data-name="Rectangle 48" width="2.537" height="2.537" rx="1" transform="translate(31.001 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_49" data-name="Rectangle 49" width="2.537" height="2.537" rx="1" transform="translate(34.007 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_50" data-name="Rectangle 50" width="2.537" height="2.537" rx="1" transform="translate(37.013 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_51" data-name="Rectangle 51" width="2.537" height="2.537" rx="1" transform="translate(40.018 0)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<g id="Group_6" data-name="Group 6" transform="translate(0.728 7.883)">
|
||||
<path id="Path_54" data-name="Path 54" d="M.519,0h3.47a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.52A.519.519,0,0,1,.519,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<g id="Group_5" data-name="Group 5" transform="translate(5.073 0)">
|
||||
<rect id="Rectangle_52" data-name="Rectangle 52" width="2.537" height="2.537" rx="1" transform="translate(0 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_53" data-name="Rectangle 53" width="2.537" height="2.537" rx="1" transform="translate(3.006 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_54" data-name="Rectangle 54" width="2.537" height="2.537" rx="1" transform="translate(6.012 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_55" data-name="Rectangle 55" width="2.537" height="2.537" rx="1" transform="translate(9.018 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_56" data-name="Rectangle 56" width="2.537" height="2.537" rx="1" transform="translate(12.025 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_57" data-name="Rectangle 57" width="2.537" height="2.537" rx="1" transform="translate(15.031 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_58" data-name="Rectangle 58" width="2.537" height="2.537" rx="1" transform="translate(18.037 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_59" data-name="Rectangle 59" width="2.537" height="2.537" rx="1" transform="translate(21.042 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_60" data-name="Rectangle 60" width="2.537" height="2.537" rx="1" transform="translate(24.049 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_61" data-name="Rectangle 61" width="2.537" height="2.537" rx="1" transform="translate(27.055 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_62" data-name="Rectangle 62" width="2.537" height="2.537" rx="1" transform="translate(30.061 0)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<path id="Path_55" data-name="Path 55" d="M.52,0H3.8a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.52A.519.519,0,0,1,.519,0Z" transform="translate(38.234 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g id="Group_7" data-name="Group 7" transform="translate(0.728 14.084)">
|
||||
<rect id="Rectangle_63" data-name="Rectangle 63" width="2.537" height="2.537" rx="1" transform="translate(0 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_64" data-name="Rectangle 64" width="2.537" height="2.537" rx="1" transform="translate(3.006 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_65" data-name="Rectangle 65" width="2.537" height="2.537" rx="1" transform="translate(6.012 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_66" data-name="Rectangle 66" width="2.537" height="2.537" rx="1" transform="translate(9.018 0)" fill="#4a4a4a"/>
|
||||
<path id="Path_56" data-name="Path 56" d="M.519,0H14.981A.519.519,0,0,1,15.5.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.018V.519A.519.519,0,0,1,.519,0Zm15.97,0h1.874a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H16.489a.519.519,0,0,1-.519-.519V.519A.519.519,0,0,1,16.489,0Z" transform="translate(12.024 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<rect id="Rectangle_67" data-name="Rectangle 67" width="2.537" height="2.537" rx="1" transform="translate(31.376 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_68" data-name="Rectangle 68" width="2.537" height="2.537" rx="1" transform="translate(34.382 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_69" data-name="Rectangle 69" width="2.537" height="2.537" rx="1" transform="translate(40.018 0)" fill="#4a4a4a"/>
|
||||
<path id="Path_57" data-name="Path 57" d="M2.537,0V.561a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,.561V0Z" transform="translate(39.736 1.08) rotate(180)" fill="#4a4a4a"/>
|
||||
<path id="Path_58" data-name="Path 58" d="M2.537,0V.561a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,.561V0Z" transform="translate(37.2 1.456)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<rect id="Rectangle_70" data-name="Rectangle 70" width="42.273" height="1.127" rx="0.564" transform="translate(0.915 0.556)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_71" data-name="Rectangle 71" width="2.37" height="0.752" rx="0.376" transform="translate(1.949 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_72" data-name="Rectangle 72" width="2.37" height="0.752" rx="0.376" transform="translate(5.193 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_73" data-name="Rectangle 73" width="2.37" height="0.752" rx="0.376" transform="translate(7.688 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_74" data-name="Rectangle 74" width="2.37" height="0.752" rx="0.376" transform="translate(10.183 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_75" data-name="Rectangle 75" width="2.37" height="0.752" rx="0.376" transform="translate(12.679 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_76" data-name="Rectangle 76" width="2.37" height="0.752" rx="0.376" transform="translate(15.797 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_77" data-name="Rectangle 77" width="2.37" height="0.752" rx="0.376" transform="translate(18.292 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_78" data-name="Rectangle 78" width="2.37" height="0.752" rx="0.376" transform="translate(20.788 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_79" data-name="Rectangle 79" width="2.37" height="0.752" rx="0.376" transform="translate(23.283 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_80" data-name="Rectangle 80" width="2.37" height="0.752" rx="0.376" transform="translate(26.402 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_81" data-name="Rectangle 81" width="2.37" height="0.752" rx="0.376" transform="translate(28.897 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_82" data-name="Rectangle 82" width="2.37" height="0.752" rx="0.376" transform="translate(31.393 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_83" data-name="Rectangle 83" width="2.37" height="0.752" rx="0.376" transform="translate(34.512 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_84" data-name="Rectangle 84" width="2.37" height="0.752" rx="0.376" transform="translate(37.007 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_85" data-name="Rectangle 85" width="2.37" height="0.752" rx="0.376" transform="translate(39.502 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
</g>
|
||||
<path id="Path_59" data-name="Path 59" d="M123.779,148.389a2.583,2.583,0,0,0-.332.033c-.02-.078-.038-.156-.06-.234a2.594,2.594,0,1,0-2.567-4.455q-.086-.088-.174-.175a2.593,2.593,0,1,0-4.461-2.569c-.077-.022-.154-.04-.231-.06a2.6,2.6,0,1,0-5.128,0c-.077.02-.154.038-.231.06a2.594,2.594,0,1,0-4.461,2.569,10.384,10.384,0,1,0,17.314,9.992,2.592,2.592,0,1,0,.332-5.161" transform="translate(-51.054 -75.262)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_60" data-name="Path 60" d="M83,113.389h20.779V103H83Z" transform="translate(-41.443 -58.444)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_61" data-name="Path 61" d="M123.389,108.944a1.3,1.3,0,1,0,0-2.6,1.338,1.338,0,0,0-.166.017c-.01-.039-.019-.078-.03-.117a1.3,1.3,0,0,0-.5-2.5,1.285,1.285,0,0,0-.783.269q-.043-.044-.087-.087a1.285,1.285,0,0,0,.263-.776,1.3,1.3,0,0,0-2.493-.509,5.195,5.195,0,1,0,0,10,1.3,1.3,0,0,0,2.493-.509,1.285,1.285,0,0,0-.263-.776q.044-.043.087-.087a1.285,1.285,0,0,0,.783.269,1.3,1.3,0,0,0,.5-2.5c.011-.038.02-.078.03-.117a1.335,1.335,0,0,0,.166.017" transform="translate(-55.859 -57.894)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_62" data-name="Path 62" d="M141.8,38.745a1.41,1.41,0,0,1-.255-.026,1.309,1.309,0,0,1-.244-.073,1.349,1.349,0,0,1-.224-.119,1.967,1.967,0,0,1-.2-.161,1.52,1.52,0,0,1-.161-.2,1.282,1.282,0,0,1-.218-.722,1.41,1.41,0,0,1,.026-.255,1.5,1.5,0,0,1,.072-.244,1.364,1.364,0,0,1,.12-.223,1.252,1.252,0,0,1,.358-.358,1.349,1.349,0,0,1,.224-.119,1.309,1.309,0,0,1,.244-.073,1.2,1.2,0,0,1,.509,0,1.262,1.262,0,0,1,.468.192,1.968,1.968,0,0,1,.2.161,1.908,1.908,0,0,1,.161.2,1.322,1.322,0,0,1,.12.223,1.361,1.361,0,0,1,.1.5,1.317,1.317,0,0,1-.379.919,1.968,1.968,0,0,1-.2.161,1.346,1.346,0,0,1-.223.119,1.332,1.332,0,0,1-.5.1m10.389-.649a1.326,1.326,0,0,1-.92-.379,1.979,1.979,0,0,1-.161-.2,1.282,1.282,0,0,1-.218-.722,1.326,1.326,0,0,1,.379-.919,1.967,1.967,0,0,1,.2-.161,1.351,1.351,0,0,1,.224-.119,1.308,1.308,0,0,1,.244-.073,1.2,1.2,0,0,1,.509,0,1.262,1.262,0,0,1,.468.192,1.967,1.967,0,0,1,.2.161,1.326,1.326,0,0,1,.379.919,1.461,1.461,0,0,1-.026.255,1.323,1.323,0,0,1-.073.244,1.847,1.847,0,0,1-.119.223,1.911,1.911,0,0,1-.161.2,1.967,1.967,0,0,1-.2.161,1.294,1.294,0,0,1-.722.218" transform="translate(-69.074 -26.006)" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g id="React-icon" transform="translate(906.3 541.56)">
|
||||
<path id="Path_330" data-name="Path 330" d="M263.668,117.179c0-5.827-7.3-11.35-18.487-14.775,2.582-11.4,1.434-20.477-3.622-23.382a7.861,7.861,0,0,0-4.016-1v4a4.152,4.152,0,0,1,2.044.466c2.439,1.4,3.5,6.724,2.672,13.574-.2,1.685-.52,3.461-.914,5.272a86.9,86.9,0,0,0-11.386-1.954,87.469,87.469,0,0,0-7.459-8.965c5.845-5.433,11.332-8.41,15.062-8.41V78h0c-4.931,0-11.386,3.514-17.913,9.611-6.527-6.061-12.982-9.539-17.913-9.539v4c3.712,0,9.216,2.959,15.062,8.356a84.687,84.687,0,0,0-7.405,8.947,83.732,83.732,0,0,0-11.4,1.972c-.412-1.793-.717-3.532-.932-5.2-.843-6.85.2-12.175,2.618-13.592a3.991,3.991,0,0,1,2.062-.466v-4h0a8,8,0,0,0-4.052,1c-5.039,2.9-6.168,11.96-3.568,23.328-11.153,3.443-18.415,8.947-18.415,14.757,0,5.828,7.3,11.35,18.487,14.775-2.582,11.4-1.434,20.477,3.622,23.382a7.882,7.882,0,0,0,4.034,1c4.931,0,11.386-3.514,17.913-9.611,6.527,6.061,12.982,9.539,17.913,9.539a8,8,0,0,0,4.052-1c5.039-2.9,6.168-11.96,3.568-23.328C256.406,128.511,263.668,122.988,263.668,117.179Zm-23.346-11.96c-.663,2.313-1.488,4.7-2.421,7.083-.735-1.434-1.506-2.869-2.349-4.3-.825-1.434-1.7-2.833-2.582-4.2C235.517,104.179,237.974,104.645,240.323,105.219Zm-8.212,19.1c-1.4,2.421-2.833,4.716-4.321,6.85-2.672.233-5.379.359-8.1.359-2.708,0-5.415-.126-8.069-.341q-2.232-3.2-4.339-6.814-2.044-3.523-3.73-7.136c1.112-2.4,2.367-4.805,3.712-7.154,1.4-2.421,2.833-4.716,4.321-6.85,2.672-.233,5.379-.359,8.1-.359,2.708,0,5.415.126,8.069.341q2.232,3.2,4.339,6.814,2.044,3.523,3.73,7.136C234.692,119.564,233.455,121.966,232.11,124.315Zm5.792-2.331c.968,2.4,1.793,4.805,2.474,7.136-2.349.574-4.823,1.058-7.387,1.434.879-1.381,1.757-2.8,2.582-4.25C236.4,124.871,237.167,123.419,237.9,121.984ZM219.72,141.116a73.921,73.921,0,0,1-4.985-5.738c1.614.072,3.263.126,4.931.126,1.685,0,3.353-.036,4.985-.126A69.993,69.993,0,0,1,219.72,141.116ZM206.38,130.555c-2.546-.377-5-.843-7.352-1.417.663-2.313,1.488-4.7,2.421-7.083.735,1.434,1.506,2.869,2.349,4.3S205.5,129.192,206.38,130.555ZM219.63,93.241a73.924,73.924,0,0,1,4.985,5.738c-1.614-.072-3.263-.126-4.931-.126-1.686,0-3.353.036-4.985.126A69.993,69.993,0,0,1,219.63,93.241ZM206.362,103.8c-.879,1.381-1.757,2.8-2.582,4.25-.825,1.434-1.6,2.869-2.331,4.3-.968-2.4-1.793-4.805-2.474-7.136C201.323,104.663,203.8,104.179,206.362,103.8Zm-16.227,22.449c-6.348-2.708-10.454-6.258-10.454-9.073s4.106-6.383,10.454-9.073c1.542-.663,3.228-1.255,4.967-1.811a86.122,86.122,0,0,0,4.034,10.92,84.9,84.9,0,0,0-3.981,10.866C193.38,127.525,191.694,126.915,190.134,126.252Zm9.647,25.623c-2.439-1.4-3.5-6.724-2.672-13.574.2-1.686.52-3.461.914-5.272a86.9,86.9,0,0,0,11.386,1.954,87.465,87.465,0,0,0,7.459,8.965c-5.845,5.433-11.332,8.41-15.062,8.41A4.279,4.279,0,0,1,199.781,151.875Zm42.532-13.663c.843,6.85-.2,12.175-2.618,13.592a3.99,3.99,0,0,1-2.062.466c-3.712,0-9.216-2.959-15.062-8.356a84.689,84.689,0,0,0,7.405-8.947,83.731,83.731,0,0,0,11.4-1.972A50.194,50.194,0,0,1,242.313,138.212Zm6.9-11.96c-1.542.663-3.228,1.255-4.967,1.811a86.12,86.12,0,0,0-4.034-10.92,84.9,84.9,0,0,0,3.981-10.866c1.775.556,3.461,1.165,5.039,1.829,6.348,2.708,10.454,6.258,10.454,9.073C259.67,119.994,255.564,123.562,249.216,126.252Z" fill="#61dafb"/>
|
||||
<path id="Path_331" data-name="Path 331" d="M320.8,78.4Z" transform="translate(-119.082 -0.328)" fill="#61dafb"/>
|
||||
<circle id="Ellipse_112" data-name="Ellipse 112" cx="8.194" cy="8.194" r="8.194" transform="translate(211.472 108.984)" fill="#61dafb"/>
|
||||
<path id="Path_332" data-name="Path 332" d="M520.5,78.1Z" transform="translate(-282.975 -0.082)" fill="#61dafb"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 35 KiB |
|
@ -0,0 +1,40 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="1129" height="663" viewBox="0 0 1129 663">
|
||||
<title>Focus on What Matters</title>
|
||||
<circle cx="321" cy="321" r="321" fill="#f2f2f2" />
|
||||
<ellipse cx="559" cy="635.49998" rx="514" ry="27.50002" fill="#3f3d56" />
|
||||
<ellipse cx="558" cy="627" rx="460" ry="22" opacity="0.2" />
|
||||
<rect x="131" y="152.5" width="840" height="50" fill="#3f3d56" />
|
||||
<path d="M166.5,727.3299A21.67009,21.67009,0,0,0,188.1701,749H984.8299A21.67009,21.67009,0,0,0,1006.5,727.3299V296h-840Z" transform="translate(-35.5 -118.5)" fill="#3f3d56" />
|
||||
<path d="M984.8299,236H188.1701A21.67009,21.67009,0,0,0,166.5,257.6701V296h840V257.6701A21.67009,21.67009,0,0,0,984.8299,236Z" transform="translate(-35.5 -118.5)" fill="#3f3d56" />
|
||||
<path d="M984.8299,236H188.1701A21.67009,21.67009,0,0,0,166.5,257.6701V296h840V257.6701A21.67009,21.67009,0,0,0,984.8299,236Z" transform="translate(-35.5 -118.5)" opacity="0.2" />
|
||||
<circle cx="181" cy="147.5" r="13" fill="#3f3d56" />
|
||||
<circle cx="217" cy="147.5" r="13" fill="#3f3d56" />
|
||||
<circle cx="253" cy="147.5" r="13" fill="#3f3d56" />
|
||||
<rect x="168" y="213.5" width="337" height="386" rx="5.33505" fill="#606060" />
|
||||
<rect x="603" y="272.5" width="284" height="22" rx="5.47638" fill="#2e8555" />
|
||||
<rect x="537" y="352.5" width="416" height="15" rx="5.47638" fill="#2e8555" />
|
||||
<rect x="537" y="396.5" width="416" height="15" rx="5.47638" fill="#2e8555" />
|
||||
<rect x="537" y="440.5" width="416" height="15" rx="5.47638" fill="#2e8555" />
|
||||
<rect x="537" y="484.5" width="416" height="15" rx="5.47638" fill="#2e8555" />
|
||||
<rect x="865" y="552.5" width="88" height="26" rx="7.02756" fill="#3ecc5f" />
|
||||
<path d="M1088.60287,624.61594a30.11371,30.11371,0,0,0,3.98291-15.266c0-13.79652-8.54358-24.98081-19.08256-24.98081s-19.08256,11.18429-19.08256,24.98081a30.11411,30.11411,0,0,0,3.98291,15.266,31.248,31.248,0,0,0,0,30.53213,31.248,31.248,0,0,0,0,30.53208,31.248,31.248,0,0,0,0,30.53208,30.11408,30.11408,0,0,0-3.98291,15.266c0,13.79652,8.54353,24.98081,19.08256,24.98081s19.08256-11.18429,19.08256-24.98081a30.11368,30.11368,0,0,0-3.98291-15.266,31.248,31.248,0,0,0,0-30.53208,31.248,31.248,0,0,0,0-30.53208,31.248,31.248,0,0,0,0-30.53213Z" transform="translate(-35.5 -118.5)" fill="#3f3d56" />
|
||||
<ellipse cx="1038.00321" cy="460.31783" rx="19.08256" ry="24.9808" fill="#3f3d56" />
|
||||
<ellipse cx="1038.00321" cy="429.78574" rx="19.08256" ry="24.9808" fill="#3f3d56" />
|
||||
<path d="M1144.93871,339.34489a91.61081,91.61081,0,0,0,7.10658-10.46092l-50.141-8.23491,54.22885.4033a91.566,91.566,0,0,0,1.74556-72.42605l-72.75449,37.74139,67.09658-49.32086a91.41255,91.41255,0,1,0-150.971,102.29805,91.45842,91.45842,0,0,0-10.42451,16.66946l65.0866,33.81447-69.40046-23.292a91.46011,91.46011,0,0,0,14.73837,85.83669,91.40575,91.40575,0,1,0,143.68892,0,91.41808,91.41808,0,0,0,0-113.02862Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
|
||||
<path d="M981.6885,395.8592a91.01343,91.01343,0,0,0,19.56129,56.51431,91.40575,91.40575,0,1,0,143.68892,0C1157.18982,436.82067,981.6885,385.60008,981.6885,395.8592Z" transform="translate(-35.5 -118.5)" opacity="0.1" />
|
||||
<path d="M365.62,461.43628H477.094v45.12043H365.62Z" transform="translate(-35.5 -118.5)" fill="#fff" fill-rule="evenodd" />
|
||||
<path d="M264.76252,608.74122a26.50931,26.50931,0,0,1-22.96231-13.27072,26.50976,26.50976,0,0,0,22.96231,39.81215H291.304V608.74122Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
|
||||
<path d="M384.17242,468.57061l92.92155-5.80726V449.49263a26.54091,26.54091,0,0,0-26.54143-26.54143H331.1161l-3.31768-5.74622a3.83043,3.83043,0,0,0-6.63536,0l-3.31768,5.74622-3.31767-5.74622a3.83043,3.83043,0,0,0-6.63536,0l-3.31768,5.74622L301.257,417.205a3.83043,3.83043,0,0,0-6.63536,0L291.304,422.9512c-.02919,0-.05573.004-.08625.004l-5.49674-5.49541a3.8293,3.8293,0,0,0-6.4071,1.71723l-1.81676,6.77338L270.607,424.1031a3.82993,3.82993,0,0,0-4.6912,4.69253l1.84463,6.89148-6.77072,1.81411a3.8315,3.8315,0,0,0-1.71988,6.40975l5.49673,5.49673c0,.02787-.004.05574-.004.08493l-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74621,3.31768L259.0163,466.081a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31767a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31767a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31768a3.83042,3.83042,0,0,0,0,6.63535l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768L259.0163,558.976a3.83042,3.83042,0,0,0,0,6.63535l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31768a3.83042,3.83042,0,0,0,0,6.63535l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768A26.54091,26.54091,0,0,0,291.304,635.28265H450.55254A26.5409,26.5409,0,0,0,477.094,608.74122V502.5755l-92.92155-5.80727a14.12639,14.12639,0,0,1,0-28.19762" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
|
||||
<path d="M424.01111,635.28265h39.81214V582.19979H424.01111Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
|
||||
<path d="M490.36468,602.10586a6.60242,6.60242,0,0,0-.848.08493c-.05042-.19906-.09821-.39945-.15393-.59852A6.62668,6.62668,0,1,0,482.80568,590.21q-.2203-.22491-.44457-.44589a6.62391,6.62391,0,1,0-11.39689-6.56369c-.1964-.05575-.39414-.10218-.59056-.15262a6.63957,6.63957,0,1,0-13.10086,0c-.1964.05042-.39414.09687-.59056.15262a6.62767,6.62767,0,1,0-11.39688,6.56369,26.52754,26.52754,0,1,0,44.23127,25.52756,6.6211,6.6211,0,1,0,.848-13.18579" transform="translate(-35.5 -118.5)" fill="#44d860" fill-rule="evenodd" />
|
||||
<path d="M437.28182,555.65836H477.094V529.11693H437.28182Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
|
||||
<path d="M490.36468,545.70532a3.31768,3.31768,0,0,0,0-6.63536,3.41133,3.41133,0,0,0-.42333.04247c-.02655-.09953-.04911-.19907-.077-.29859a3.319,3.319,0,0,0-1.278-6.37923,3.28174,3.28174,0,0,0-2.00122.68742q-.10947-.11346-.22294-.22295a3.282,3.282,0,0,0,.67149-1.98265,3.31768,3.31768,0,0,0-6.37-1.2992,13.27078,13.27078,0,1,0,0,25.54082,3.31768,3.31768,0,0,0,6.37-1.2992,3.282,3.282,0,0,0-.67149-1.98265q.11347-.10947.22294-.22294a3.28174,3.28174,0,0,0,2.00122.68742,3.31768,3.31768,0,0,0,1.278-6.37923c.02786-.0982.05042-.19907.077-.29859a3.41325,3.41325,0,0,0,.42333.04246" transform="translate(-35.5 -118.5)" fill="#44d860" fill-rule="evenodd" />
|
||||
<path d="M317.84538,466.081a3.31768,3.31768,0,0,1-3.31767-3.31768,9.953,9.953,0,1,0-19.90608,0,3.31768,3.31768,0,1,1-6.63535,0,16.58839,16.58839,0,1,1,33.17678,0,3.31768,3.31768,0,0,1-3.31768,3.31768" transform="translate(-35.5 -118.5)" fill-rule="evenodd" />
|
||||
<path d="M370.92825,635.28265h79.62429A26.5409,26.5409,0,0,0,477.094,608.74122v-92.895H397.46968a26.54091,26.54091,0,0,0-26.54143,26.54143Z" transform="translate(-35.5 -118.5)" fill="#ffff50" fill-rule="evenodd" />
|
||||
<path d="M457.21444,556.98543H390.80778a1.32707,1.32707,0,0,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0,26.54143H390.80778a1.32707,1.32707,0,1,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0,26.54143H390.80778a1.32707,1.32707,0,1,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0-66.10674H390.80778a1.32707,1.32707,0,0,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0,26.29459H390.80778a1.32707,1.32707,0,0,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0,26.54143H390.80778a1.32707,1.32707,0,0,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414M477.094,474.19076c-.01592,0-.0292-.008-.04512-.00663-4.10064.13934-6.04083,4.24132-7.75274,7.86024-1.78623,3.78215-3.16771,6.24122-5.43171,6.16691-2.50685-.09024-3.94007-2.92222-5.45825-5.91874-1.74377-3.44243-3.73438-7.34667-7.91333-7.20069-4.04227.138-5.98907,3.70784-7.70631,6.857-1.82738,3.35484-3.07084,5.39455-5.46887,5.30033-2.55727-.09289-3.91619-2.39536-5.48877-5.06013-1.75306-2.96733-3.77951-6.30359-7.8775-6.18946-3.97326.13669-5.92537,3.16507-7.64791,5.83912-1.82207,2.82666-3.09872,4.5492-5.52725,4.447-2.61832-.09289-3.9706-2.00388-5.53522-4.21611-1.757-2.4856-3.737-5.299-7.82308-5.16231-3.88567.13271-5.83779,2.61434-7.559,4.80135-1.635,2.07555-2.9116,3.71846-5.61218,3.615a1.32793,1.32793,0,1,0-.09555,2.65414c4.00377.134,6.03154-2.38873,7.79257-4.6275,1.562-1.9853,2.91027-3.69855,5.56441-3.78879,2.55594-.10882,3.75429,1.47968,5.56707,4.04093,1.7212,2.43385,3.67465,5.19416,7.60545,5.33616,4.11789.138,6.09921-2.93946,7.8536-5.66261,1.56861-2.43385,2.92221-4.53461,5.50734-4.62352,2.37944-.08892,3.67466,1.79154,5.50072,4.885,1.72121,2.91557,3.67069,6.21865,7.67977,6.36463,4.14709.14332,6.14965-3.47693,7.89475-6.68181,1.51155-2.77092,2.93814-5.38791,5.46621-5.4755,2.37944-.05573,3.62025,2.11668,5.45558,5.74622,1.71459,3.388,3.65875,7.22591,7.73019,7.37321l.22429.004c4.06614,0,5.99571-4.08074,7.70364-7.68905,1.51154-3.19825,2.94211-6.21069,5.3972-6.33411Z" transform="translate(-35.5 -118.5)" fill-rule="evenodd" />
|
||||
<path d="M344.38682,635.28265h53.08286V582.19979H344.38682Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
|
||||
<path d="M424.01111,602.10586a6.60242,6.60242,0,0,0-.848.08493c-.05042-.19906-.09821-.39945-.15394-.59852A6.62667,6.62667,0,1,0,416.45211,590.21q-.2203-.22491-.44458-.44589a6.62391,6.62391,0,1,0-11.39689-6.56369c-.1964-.05575-.39413-.10218-.59054-.15262a6.63957,6.63957,0,1,0-13.10084,0c-.19641.05042-.39414.09687-.59055.15262a6.62767,6.62767,0,1,0-11.39689,6.56369,26.52755,26.52755,0,1,0,44.2313,25.52756,6.6211,6.6211,0,1,0,.848-13.18579" transform="translate(-35.5 -118.5)" fill="#44d860" fill-rule="evenodd" />
|
||||
<path d="M344.38682,555.65836h53.08286V529.11693H344.38682Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
|
||||
<path d="M410.74039,545.70532a3.31768,3.31768,0,1,0,0-6.63536,3.41133,3.41133,0,0,0-.42333.04247c-.02655-.09953-.04911-.19907-.077-.29859a3.319,3.319,0,0,0-1.278-6.37923,3.28174,3.28174,0,0,0-2.00122.68742q-.10947-.11346-.22294-.22295a3.282,3.282,0,0,0,.67149-1.98265,3.31768,3.31768,0,0,0-6.37-1.2992,13.27078,13.27078,0,1,0,0,25.54082,3.31768,3.31768,0,0,0,6.37-1.2992,3.282,3.282,0,0,0-.67149-1.98265q.11347-.10947.22294-.22294a3.28174,3.28174,0,0,0,2.00122.68742,3.31768,3.31768,0,0,0,1.278-6.37923c.02786-.0982.05042-.19907.077-.29859a3.41325,3.41325,0,0,0,.42333.04246" transform="translate(-35.5 -118.5)" fill="#44d860" fill-rule="evenodd" />
|
||||
<path d="M424.01111,447.8338a3.60349,3.60349,0,0,1-.65028-.06636,3.34415,3.34415,0,0,1-.62372-.18579,3.44679,3.44679,0,0,1-.572-.30522,5.02708,5.02708,0,0,1-.50429-.4114,3.88726,3.88726,0,0,1-.41007-.50428,3.27532,3.27532,0,0,1-.55737-1.84463,3.60248,3.60248,0,0,1,.06636-.65027,3.82638,3.82638,0,0,1,.18447-.62373,3.48858,3.48858,0,0,1,.30656-.57064,3.197,3.197,0,0,1,.91436-.91568,3.44685,3.44685,0,0,1,.572-.30523,3.344,3.344,0,0,1,.62372-.18578,3.06907,3.06907,0,0,1,1.30053,0,3.22332,3.22332,0,0,1,1.19436.491,5.02835,5.02835,0,0,1,.50429.41139,4.8801,4.8801,0,0,1,.41139.50429,3.38246,3.38246,0,0,1,.30522.57064,3.47806,3.47806,0,0,1,.25215,1.274A3.36394,3.36394,0,0,1,426.36,446.865a5.02708,5.02708,0,0,1-.50429.4114,3.3057,3.3057,0,0,1-1.84463.55737m26.54143-1.65884a3.38754,3.38754,0,0,1-2.35024-.96877,5.04185,5.04185,0,0,1-.41007-.50428,3.27532,3.27532,0,0,1-.55737-1.84463,3.38659,3.38659,0,0,1,.96744-2.34892,5.02559,5.02559,0,0,1,.50429-.41139,3.44685,3.44685,0,0,1,.572-.30523,3.3432,3.3432,0,0,1,.62373-.18579,3.06952,3.06952,0,0,1,1.30052,0,3.22356,3.22356,0,0,1,1.19436.491,5.02559,5.02559,0,0,1,.50429.41139,3.38792,3.38792,0,0,1,.96876,2.34892,3.72635,3.72635,0,0,1-.06636.65026,3.37387,3.37387,0,0,1-.18579.62373,4.71469,4.71469,0,0,1-.30522.57064,4.8801,4.8801,0,0,1-.41139.50429,5.02559,5.02559,0,0,1-.50429.41139,3.30547,3.30547,0,0,1-1.84463.55737" transform="translate(-35.5 -118.5)" fill-rule="evenodd" />
|
||||
</svg>
|
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 8.4 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 12 KiB |
|
@ -1,91 +0,0 @@
|
|||
# Getting Started Guide - tfcli
|
||||
|
||||
This guide will walk you through the process of setting up a new `trifid-api` organization and enrolling your first host, from scratch, using the `trifid` stack and a `trifid-api` server.
|
||||
|
||||
This guide assumes you already have a `trifid-api` server set up, but you have *not* created a user account or organization yet. If you have, the [Quick Reference Handbook](docs/tfcli/qrh.md) may be of more use to you.
|
||||
|
||||
If you don't have a `trifid-api` server set up, or need help configuring it, consider checking out the [`trifid-api` Getting Started Guide](docs/trifid-api/getting_started.md) or the [`trifid-api` Quick Reference Handbook](docs/trifid-api/qrh.md).
|
||||
|
||||
## Installing `tfcli`
|
||||
|
||||
The first step to using `tfcli` is installing it. We recommend you do this via `cargo`, rust's package manager, as it is the most fool-proof way to quickly ensure that the program is installed correctly.
|
||||
|
||||
Run the following command:
|
||||
|
||||
```shell
|
||||
cargo install tfcli
|
||||
```
|
||||
|
||||
This will install the `tfcli` binary to your Cargo `bin/` directory. You'll need to ensure that this directory is on your `PATH` - doing so is outside the scope of this guide.
|
||||
|
||||
## Creating your account
|
||||
|
||||
The first step in setting up your `trifid-api` account is creating it! This, like all other tasks, can be done via the `tfcli` program. You'll need the following on hand:
|
||||
|
||||
- An email address (you don't need access to the mailbox though)
|
||||
- Access to the `trifid-api` server logs to get the login token
|
||||
- `tfcli` installed
|
||||
|
||||
In order to create an account, use the 'create account' tfcli command:
|
||||
|
||||
```shell
|
||||
tfcli account create --email [INSERT_YOUR_EMAIL_HERE]
|
||||
```
|
||||
|
||||
At this point, you'll need to check your `trifid-api` server logs. Look for a log message that looks like `sent magic link [long-text-here that starts with 'ml-']`.
|
||||
You'll need to grab the long string of characters starting with `ml-` and going to the end of the line. It'll look something like `ml-NrrnaEm7N-6XqbDUweoNuwchI7SBCZwJQVPUDSS7T1g`.
|
||||
|
||||
This token only remains valid for 10 minutes, so you'll need to move relatively quickly. If the token expires, don't worry - use the `login` command as described at the end of this section to get a new token.
|
||||
|
||||
Once you have your magic-link token, authenticate and create your session token:
|
||||
|
||||
```shell
|
||||
tfcli account magic-link --magic-link-token [insert-long-string-of-characters-you-got-earlier]
|
||||
```
|
||||
|
||||
This will get a special token from `trifid-api` that allows you to modify only your 2fa settings, but not any hosts, networks, or roles. `tfcli` automatically saves this token to your computer - you don't need to worry about it.
|
||||
|
||||
After this, you'll need to set up 2fa before you can do any other management tasks.
|
||||
|
||||
In addition, approximately once every year, your session token will expire. You might also want to use multiple computers. To do this, use the `login` feature instead of `signup`:
|
||||
|
||||
```shell
|
||||
tfcli account login --email [INSERT_YOUR_EMAIL_HERE]
|
||||
```
|
||||
|
||||
You can then use the `magic-link` command exactly as above to renew your session token or log in on a new PC.
|
||||
|
||||
## Setting up 2FA
|
||||
|
||||
`trifid-api` enforces two-factor authentication on all accounts. You will be unable to perform any management tasks until you complete 2fa setup.
|
||||
You'll need:
|
||||
|
||||
- `tfcli` installed
|
||||
- A valid account and session token as created in the previous step
|
||||
- A TOTP-compatible authenticator like Authy or Google Authenticator
|
||||
|
||||
After you've logged in, run the following command to get your TOTP setup code:
|
||||
|
||||
```shell
|
||||
tfcli account mfa-setup
|
||||
```
|
||||
|
||||
This command will give you instructions on how to complete TOTP setup. Follow the directions given. Afterwards, an auth token will be issued by trifid-api
|
||||
and saved to your computer that gives you full control over your `trifid-api` resources such as networks, hosts, and roles.
|
||||
|
||||
This token expires after about 10 minutes. When it expires, you'll need to generate a new one by entering the code on your TOTP authenticator that you set up earlier into the following command:
|
||||
|
||||
```shell
|
||||
tfcli account mfa --code [CODE_IN_AUTHENTICATOR_APP]
|
||||
```
|
||||
|
||||
This will issue another token that is valid for another 10 minutes.
|
||||
|
||||
### Troubleshooting 'Unauthorized' messages
|
||||
|
||||
If you ever see error messages about being 'unauthorized', it most likely means your authentication token has expired, and you need to run `tfcli account mfa` again. If you try that and it is successful, but you still see errors, or if `tfcli account mfa` *itself* gives you an "Unauthorized error", it means your session token has expired. Refer to the end of 'Creating your Account' above to learn how to log in again.
|
||||
After getting a new session token you will always need to get a new TOTP token.
|
||||
|
||||
If, even after renewing your session and authentication tokens, you are still getting 'Unauthorized', it is likely an issue with your server setup. Check the trifid-api server logs or the logs of your proxy and ensure that there are no additional setup issues.
|
||||
|
||||
If you're still having issues, shoot a message to our mailing list on the [homepage](index.md) of this documentation and we would be glad to help you out.
|
|
@ -1,17 +0,0 @@
|
|||
# tfcli
|
||||
|
||||
`tfcli` is a command-line interface for managing trifid-api compatible API servers.
|
||||
|
||||
<div class="alert alert-warning">
|
||||
<strong>Notice</strong>: `tfcli` does not implement a DNClient-compatible VPN client. It only allows management. For a VPN client, check out tfclient instead.
|
||||
</div>
|
||||
|
||||
`tfcli` is a feature-complete comand-line client and supports all features that `trifid-api` does, including some feature additions not available on the normal Defined Networking client.
|
||||
|
||||
## Getting Started
|
||||
|
||||
Please check out the [Getting Started Guide](docs/tfcli/getting_started.md) to learn how to create a organization from scratch and enroll your first host using the `tfcli` program.
|
||||
|
||||
## Quick Reference Handbook
|
||||
|
||||
Check out the [quick reference handbook](docs/tfcli/qrh.md) with a listing of all commands available on `tfcli`.
|
|
@ -1,89 +0,0 @@
|
|||
# `tfcli` Quick Reference Handbook
|
||||
|
||||
## Configuring the Server URL
|
||||
|
||||
`tfcli` needs a server URL to be able to contact the API server. This can be configured in three ways, from most optimal to least optimal:
|
||||
|
||||
1. The file in `$CONFIG/tfcli-server-url.conf` can have it's contents set to the base URL of the server you would like to use
|
||||
2. You can set the environment variable `TFCLI_SERVER` to the base URL
|
||||
3. You can provide the `-s/--server` argument immediately after `tfcli`, before your management command. For example: `tfcli --server https://your-server.your-domain.com network list`
|
||||
|
||||
## Account Management
|
||||
|
||||
These commands provide a means of managing your account and credentials on the `trifid-api` server.
|
||||
|
||||
### Create Account
|
||||
|
||||
Create a new account on the designated server.
|
||||
|
||||
**Usage:** `tfcli account create --email <EMAIL>`
|
||||
|
||||
### Log Into Existing Account
|
||||
|
||||
Log into an existing account on the designated server.
|
||||
|
||||
**Usage:** `tfcli account login --email <EMAIL>`
|
||||
|
||||
### Authenticate with Magic Link Token
|
||||
|
||||
Log into your account with a magic-link token acquired via email or the trifid-api logs
|
||||
|
||||
**Usage:** `tfcli account magic-link --magic-link-token <MAGIC_LINK_TOKEN>`
|
||||
|
||||
### Setup TOTP
|
||||
|
||||
Create a new TOTP authenticator on this account to enable authorizing with 2fa and performing all management tasks
|
||||
|
||||
**Usage:** `tfcli account mfa-setup`
|
||||
|
||||
### Finish setting up TOTP
|
||||
|
||||
Finish creating a new TOTP authenticator by inputting the code shown on your authenticator app
|
||||
|
||||
**Usage:** `tfcli account mfa-setup-finish --code <CODE> --token <TOKEN>`
|
||||
|
||||
### Authenticate with TOTP
|
||||
|
||||
Create a new short-lived authentication token by inputting the code shown on your authenticator app
|
||||
|
||||
**Usage:** `tfcli account mfa --code <CODE>`
|
||||
|
||||
Re-run this command if you get an "Unauthorized" error.
|
||||
|
||||
## Network Management
|
||||
|
||||
### List Networks
|
||||
|
||||
### Lookup Network
|
||||
|
||||
## Organization Management
|
||||
|
||||
### Create organization
|
||||
|
||||
## Role Management
|
||||
|
||||
### Create role
|
||||
|
||||
### List roles
|
||||
|
||||
### Lookup role
|
||||
|
||||
### Delete role
|
||||
|
||||
### Update role
|
||||
|
||||
## Host Management
|
||||
|
||||
### Create host
|
||||
|
||||
### List hosts
|
||||
|
||||
### Lookup hosts
|
||||
|
||||
### Delete host
|
||||
|
||||
### Update host
|
||||
|
||||
### Block host
|
||||
|
||||
### Enroll/re-enroll host
|
|
@ -1,18 +0,0 @@
|
|||
# tfclient - a Rust DNClient alternative
|
||||
|
||||
tfclient is an open-source Rust client for the Defined Networking "Managed Nebula" product. It is compatible with third-party servers and can be used in all the ways that normal dnclient can be used.
|
||||
|
||||
## Platform support
|
||||
|
||||
tfclient is supported on [most platforms](https://hub.e3t.cc/~core/trifid/#supported-platforms). tfclient is broken up into two "support tiers":
|
||||
|
||||
- 'Tier 1' platforms have full support, including linking to and managing the nebula binary. No extra work is required on these platforms - just install tfclient and run!
|
||||
- 'Tier 2' platforms cannot link to the nebula-ffi CGo binary due to platform limitations. On these platforms, tfclient must be compiled in [Tier 2 mode](docs/tfclient/tier-2-building.md), and the user is responsible for managing the Nebula binary and ensuring it points to the tfclient-managed config file. Documentation on how to use tfclient on Tier 2 platforms can be found [here](docs/tfclient/tier-2-building.md)
|
||||
|
||||
On platforms marked 'untested', the trifid maintainers were unable to test tfclient on that platform. Help is wanted to test tfclient on as many platforms as possible!
|
||||
|
||||
tfclient [should work on most platforms](docs/tfclient/why_not_this_os.md), but the authors of tfclient don't have every device and OS combo in the world.
|
||||
|
||||
If you are willing to run untested software on your machine to contribute to trifid, consider [testing tfclient on your device](docs/tfclient/untested_os.md) and [reporting your findings back to us](https://lists.e3t.cc/~core/trifid-devel). This is super helpful to us and helps us maintain trifid for more platforms when we have users willing to test the latest versions and report bugs to us. If you are interested, please see [this page](docs/tfclient/untested_os.md).
|
||||
|
||||
Unfortunately, [tfclient won't work everywhere](docs/tfclient/why_not_this_os.md). See [here](docs/tfclient/why_not_this_os.md) for details.
|
|
@ -1,11 +0,0 @@
|
|||
# Why can't trifid work on mobile devices?
|
||||
|
||||
Mobile devices are tricky to support. Defined Networking maintains an app known as [Mobile Nebula](https://github.com/DefinedNet/mobile_nebula) to bring support for Defined Networking networks and Nebula to Android and iOS. Why can't we just fork this and add trifid support?
|
||||
|
||||
Well, [we did](https://github.com/c0repwn3r/trifid_mobile). This fork is known internally as trifid_mobile, and adds trifid support to the mobile_nebula app. Unfortunately the Defined Networking team is not willing to upstream these changes, which is a major roadblock due to the expensive licencing and publishing cost for mobile apps.
|
||||
|
||||
That is to say, mobile support is currently stalled due to lack of funding to make it work. While we'd love to introduce support on mobile platforms it is too complicated and expensive to dedicate team time to work on.
|
||||
|
||||
If you are a third-party developer with an Apple Developer account and are willing to lend it to publish a trifid_mobile fork, *or* you're a Defined Networking team member that would like to work with us to merge custom URL support into upstream mobile_nebula, please [get in touch directly](mailto:core@e3t.cc) and we can work something out.
|
||||
|
||||
For now, trifid cannot support mobile devices :(
|
|
@ -1,13 +0,0 @@
|
|||
# Help us out - test tfclient on new platforms
|
||||
|
||||
There are [lots](index.md#where-does-trifid-work) of operating systems in which `tfclient` *should* work, but due to a lack of devices, it cannot be tested. If you have a system running one of these devices and want to help out the project, please test tfclient for functionality on your device!
|
||||
|
||||
<div class="alert alert-warning">
|
||||
<strong>Notice</strong>: While tfclient is almost always perfectly safe, there are always risks to running untested software on production machines. Be careful out there!
|
||||
</div>
|
||||
|
||||
If you aren't able to get tfclient to compile with nebula-ffi, consider trying it as a [Tier 2 platform](docs/tfclient/tier-2-building.md). Documentation on how to do this can be found [here](docs/tfclient/tier-2-building.md).
|
||||
|
||||
Any findings, positive or negative, can be posted straight to [trifid-devel](https://lists.e3t.cc/~core/trifid-devel).
|
||||
|
||||
Thanks! We really appreciate it.
|
|
@ -1,11 +0,0 @@
|
|||
# Why cant tfclient support XXXXX?
|
||||
|
||||
There are limits to what operating systems and architectures tfclient can support. As you may know, tfclient is based upon the [Nebula](https://github.com/slackhq/nebula) project, maintained by Slack and Defined Networking. tfclient can only support architectures and operating systems that [Nebula itself supports](https://github.com/slackhq/nebula/releases/).
|
||||
|
||||
In addition, tfclient, being written in Rust, can only function in environments [where Rust compiles well](https://doc.rust-lang.org/nightly/rustc/platform-support.html). For example, this rules out MIPS - `rustc` currently does not function correctly on that architecture, and thus tfclient cannot, and likely never will support that architecture.
|
||||
|
||||
Finally, tfclient generally requires a functioning CGo compiler, in order to properly link to Nebula. If this is not available, but tfclient itself compiles fine, this is known as a 'Tier 2' platform - you must compile and run Nebula separately, and tfclient will be unable to manage it other than providing it's config.
|
||||
|
||||
Did Nebula add a new architecture, and we missed it? Rust supports a new architecture in a new release? [Let us know!](https://lists.e3t.cc/~core/trifid-devel) We love adding support for new systems whenever we can.
|
||||
|
||||
Did we miss an architecture? If your architecture is supported by Nebula, Rust, and CGo, but you still get linking errors or segfaults when trying to build tfclient, we might have missed you - [get in touch](https://lists.e3t.cc/~core/trifid-devel) and we will work with you to get your system supported :D
|
61
index.md
|
@ -1,61 +0,0 @@
|
|||
# trifid
|
||||
|
||||
trifid is an open-souce reimplementation of the [Defined Networking](https://defined.net) management protocol for [Nebula](https://github.com/slackhq/nebula) networks.
|
||||
|
||||
It includes a reimplementation of the [API Server](https://api.defined.net), the [Web UI](https://admin.defined.net), `dnclient`, `nebula-cert` and `dnapi` - all fully API-compatible with the original versions.
|
||||
|
||||
We also include a Rust library for interacting with keys and certificates in the Nebula PKI. Find it in `trifid-pki/`, or on crates.rs as `trifid-pki`.
|
||||
|
||||
In addition, a command-line interface for the Defined Networking management API is included, `tfcli`.
|
||||
|
||||
Want to make your own Defined Networking client? Check out `dnapi-rs`! `dnapi-rs` is a Rust port of the official `dnapi` Go library, to allow for easy interactions with Defined Networking-compatible API servers. Find it in `dnapi-rs/`, or on crates.rs as `dnapi-rs`.
|
||||
|
||||
The API implementation is tested with the official dnclient implementation, and the dnclient implementation is tested with the official API server, to ensure complete feature parity between the two.
|
||||
|
||||
# Links
|
||||
|
||||
- [tfcli documentation](./docs/tfcli/index.md)
|
||||
- [tfclient documentation](./docs/tfclient/index.md)
|
||||
- [trifid-api documentation](./docs/trifid-api/index.md)
|
||||
|
||||
|
||||
- [dnapi-rs documentation](https://docs.rs/dnapi-rs)
|
||||
- [dnapi-rs on crates.io](https://crates.io/crates/dnapi-rs)
|
||||
|
||||
|
||||
- [trifid-pki documentation](https://docs.rs/trifid-pki)
|
||||
- [trifid-pki on crates.io](https://crates.io/crates/trifid-pki)
|
||||
|
||||
|
||||
- [trifid git repository](https://git.e3t.cc/~core/trifid)
|
||||
|
||||
|
||||
- [trifid announcements mailing list](https://lists.e3t.cc/~core/trifid-announce)
|
||||
- [trifid patch mailing list](https://lists.e3t.cc/~core/trifid-devel)
|
||||
- [trifid discussion mailing list](https://lists.e3t.cc/~core/trifid-discuss)
|
||||
|
||||
# Where does trifid work?
|
||||
|
||||
See the [main trifid project page](https://hub.e3t.cc/~core/trifid) for an up-to-date platform support table.
|
||||
|
||||
## Why don't mobile devices work?
|
||||
|
||||
See the [page on this topic](docs/tfclient/mobile.md).
|
||||
|
||||
# Get in touch
|
||||
|
||||
Have a question about trifid? Check out the [discussion mailing list](https://lists.e3t.cc/~core/trifid-discuss)! `trifid-discuss` is a mailing list for end-user discussion and questions related to the trifid project.
|
||||
|
||||
Run a trifid-api server or otherwise just want to hear news about trifid? Subscribe to our [announcements list](https://lists.e3t.cc/~core/trifid-announce)! `trifid-announce` is a low-volume mailing list for announcements related to the trifid project.
|
||||
|
||||
# Contributing
|
||||
|
||||
trifid is open source at its heart and we are happy to take your contribution. Send in your patches to the [development mailing list](https://lists.e3t.cc/~core/trifid-devel) and we will get back to you as fast as we can and work on getting your changes merged. Need help sending patches to this list? Check out the handy guide at https://git-send-email.io - or just shoot an email to `trifid-discuss` and we would be happy to help.
|
||||
|
||||
# Report a bug
|
||||
|
||||
<div class="alert alert-warning">
|
||||
<strong>Notice</strong>: Do not use this list for security-related issues. Shoot an email to core@e3t.cc if you have a security-related issue and we can have a chat about how to properly report and fix it. We are dedicated to building a secure project, and are glad to work with you to responsibly fix your issue.
|
||||
</div>
|
||||
|
||||
Found a bug in any of the components of trifid? Submit it to [our issue tracker](https://todo.e3t.cc/~core/trifid) to let us know!
|
|
@ -0,0 +1,15 @@
|
|||
[package]
|
||||
name = "nebula-config"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
description = "A rust client for the Defined Networking API"
|
||||
license = "AGPL-3.0-or-later"
|
||||
documentation = "https://docs.rs/nebula-config"
|
||||
homepage = "https://git.e3t.cc/core/trifid"
|
||||
repository = "https://git.e3t.cc/core/trifid"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
ipnet = { version = "2.9", features = ["serde"] }
|
|
@ -0,0 +1,532 @@
|
|||
use std::collections::HashMap;
|
||||
use std::net::{Ipv4Addr, SocketAddrV4};
|
||||
use ipnet::{IpNet, Ipv4Net};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct NebulaConfig {
|
||||
pub pki: NebulaConfigPki,
|
||||
#[serde(default = "empty_hashmap")]
|
||||
#[serde(skip_serializing_if = "is_empty_hashmap")]
|
||||
pub static_host_map: HashMap<Ipv4Addr, Vec<SocketAddrV4>>,
|
||||
#[serde(skip_serializing_if = "is_none")]
|
||||
pub lighthouse: Option<NebulaConfigLighthouse>,
|
||||
#[serde(skip_serializing_if = "is_none")]
|
||||
pub listen: Option<NebulaConfigListen>,
|
||||
#[serde(skip_serializing_if = "is_none")]
|
||||
pub punchy: Option<NebulaConfigPunchy>,
|
||||
#[serde(default = "cipher_aes")]
|
||||
#[serde(skip_serializing_if = "is_cipher_aes")]
|
||||
pub cipher: NebulaConfigCipher,
|
||||
#[serde(default = "empty_vec")]
|
||||
#[serde(skip_serializing_if = "is_empty_vec")]
|
||||
pub preferred_ranges: Vec<IpNet>,
|
||||
#[serde(skip_serializing_if = "is_none")]
|
||||
pub relay: Option<NebulaConfigRelay>,
|
||||
#[serde(skip_serializing_if = "is_none")]
|
||||
pub tun: Option<NebulaConfigTun>,
|
||||
#[serde(skip_serializing_if = "is_none")]
|
||||
pub logging: Option<NebulaConfigLogging>,
|
||||
#[serde(skip_serializing_if = "is_none")]
|
||||
pub sshd: Option<NebulaConfigSshd>,
|
||||
|
||||
#[serde(skip_serializing_if = "is_none")]
|
||||
pub firewall: Option<NebulaConfigFirewall>,
|
||||
|
||||
#[serde(default = "u64_1")]
|
||||
#[serde(skip_serializing_if = "is_u64_1")]
|
||||
pub routines: u64,
|
||||
|
||||
#[serde(default = "none")]
|
||||
#[serde(skip_serializing_if = "is_none")]
|
||||
pub stats: Option<NebulaConfigStats>,
|
||||
|
||||
#[serde(default = "none")]
|
||||
#[serde(skip_serializing_if = "is_none")]
|
||||
pub local_range: Option<Ipv4Net>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct NebulaConfigPki {
|
||||
pub ca: String,
|
||||
pub cert: String,
|
||||
#[serde(default = "none")]
|
||||
#[serde(skip_serializing_if = "is_none")]
|
||||
pub key: Option<String>,
|
||||
#[serde(default = "empty_vec")]
|
||||
#[serde(skip_serializing_if = "is_empty_vec")]
|
||||
pub blocklist: Vec<String>,
|
||||
#[serde(default = "bool_false")]
|
||||
#[serde(skip_serializing_if = "is_bool_false")]
|
||||
pub disconnect_invalid: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct NebulaConfigLighthouse {
|
||||
#[serde(default = "bool_false")]
|
||||
#[serde(skip_serializing_if = "is_bool_false")]
|
||||
pub am_lighthouse: bool,
|
||||
#[serde(default = "bool_false")]
|
||||
#[serde(skip_serializing_if = "is_bool_false")]
|
||||
pub serve_dns: bool,
|
||||
#[serde(skip_serializing_if = "is_none")]
|
||||
pub dns: Option<NebulaConfigLighthouseDns>,
|
||||
#[serde(default = "u32_10")]
|
||||
#[serde(skip_serializing_if = "is_u32_10")]
|
||||
pub interval: u32,
|
||||
#[serde(default = "empty_vec")]
|
||||
#[serde(skip_serializing_if = "is_empty_vec")]
|
||||
pub hosts: Vec<Ipv4Addr>,
|
||||
#[serde(default = "empty_hashmap")]
|
||||
#[serde(skip_serializing_if = "is_empty_hashmap")]
|
||||
pub remote_allow_list: HashMap<Ipv4Net, bool>,
|
||||
#[serde(default = "empty_hashmap")]
|
||||
#[serde(skip_serializing_if = "is_empty_hashmap")]
|
||||
pub local_allow_list: HashMap<Ipv4Net, bool>, // `interfaces` is not supported
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct NebulaConfigLighthouseDns {
|
||||
#[serde(default = "string_empty")]
|
||||
#[serde(skip_serializing_if = "is_string_empty")]
|
||||
pub host: String,
|
||||
#[serde(default = "u16_53")]
|
||||
#[serde(skip_serializing_if = "is_u16_53")]
|
||||
pub port: u16,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct NebulaConfigListen {
|
||||
#[serde(default = "string_empty")]
|
||||
#[serde(skip_serializing_if = "is_string_empty")]
|
||||
pub host: String,
|
||||
#[serde(default = "u16_0")]
|
||||
#[serde(skip_serializing_if = "is_u16_0")]
|
||||
pub port: u16,
|
||||
#[serde(default = "u32_64")]
|
||||
#[serde(skip_serializing_if = "is_u32_64")]
|
||||
pub batch: u32,
|
||||
#[serde(skip_serializing_if = "is_none")]
|
||||
pub read_buffer: Option<u32>,
|
||||
#[serde(skip_serializing_if = "is_none")]
|
||||
pub write_buffer: Option<u32>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct NebulaConfigPunchy {
|
||||
#[serde(default = "bool_false")]
|
||||
#[serde(skip_serializing_if = "is_bool_false")]
|
||||
pub punch: bool,
|
||||
#[serde(default = "bool_false")]
|
||||
#[serde(skip_serializing_if = "is_bool_false")]
|
||||
pub respond: bool,
|
||||
#[serde(default = "string_1s")]
|
||||
#[serde(skip_serializing_if = "is_string_1s")]
|
||||
pub delay: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub enum NebulaConfigCipher {
|
||||
#[serde(rename = "aes")]
|
||||
Aes,
|
||||
#[serde(rename = "chachapoly")]
|
||||
ChaChaPoly,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct NebulaConfigRelay {
|
||||
#[serde(default = "empty_vec")]
|
||||
#[serde(skip_serializing_if = "is_empty_vec")]
|
||||
pub relays: Vec<Ipv4Addr>,
|
||||
#[serde(default = "bool_false")]
|
||||
#[serde(skip_serializing_if = "is_bool_false")]
|
||||
pub am_relay: bool,
|
||||
#[serde(default = "bool_true")]
|
||||
#[serde(skip_serializing_if = "is_bool_true")]
|
||||
pub use_relays: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct NebulaConfigTun {
|
||||
#[serde(default = "bool_false")]
|
||||
#[serde(skip_serializing_if = "is_bool_false")]
|
||||
pub disabled: bool,
|
||||
#[serde(skip_serializing_if = "is_none")]
|
||||
pub dev: Option<String>,
|
||||
#[serde(default = "bool_false")]
|
||||
#[serde(skip_serializing_if = "is_bool_false")]
|
||||
pub drop_local_broadcast: bool,
|
||||
#[serde(default = "bool_false")]
|
||||
#[serde(skip_serializing_if = "is_bool_false")]
|
||||
pub drop_multicast: bool,
|
||||
#[serde(default = "u64_500")]
|
||||
#[serde(skip_serializing_if = "is_u64_500")]
|
||||
pub tx_queue: u64,
|
||||
#[serde(default = "u64_1300")]
|
||||
#[serde(skip_serializing_if = "is_u64_1300")]
|
||||
pub mtu: u64,
|
||||
#[serde(default = "empty_vec")]
|
||||
#[serde(skip_serializing_if = "is_empty_vec")]
|
||||
pub routes: Vec<NebulaConfigTunRouteOverride>,
|
||||
#[serde(default = "empty_vec")]
|
||||
#[serde(skip_serializing_if = "is_empty_vec")]
|
||||
pub unsafe_routes: Vec<NebulaConfigTunUnsafeRoute>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct NebulaConfigTunRouteOverride {
|
||||
pub mtu: u64,
|
||||
pub route: Ipv4Net,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct NebulaConfigTunUnsafeRoute {
|
||||
pub route: Ipv4Net,
|
||||
pub via: Ipv4Addr,
|
||||
#[serde(default = "u64_1300")]
|
||||
#[serde(skip_serializing_if = "is_u64_1300")]
|
||||
pub mtu: u64,
|
||||
#[serde(default = "i64_100")]
|
||||
#[serde(skip_serializing_if = "is_i64_100")]
|
||||
pub metric: i64,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct NebulaConfigLogging {
|
||||
#[serde(default = "loglevel_info")]
|
||||
#[serde(skip_serializing_if = "is_loglevel_info")]
|
||||
pub level: NebulaConfigLoggingLevel,
|
||||
#[serde(default = "format_text")]
|
||||
#[serde(skip_serializing_if = "is_format_text")]
|
||||
pub format: NebulaConfigLoggingFormat,
|
||||
#[serde(default = "bool_false")]
|
||||
#[serde(skip_serializing_if = "is_bool_false")]
|
||||
pub disable_timestamp: bool,
|
||||
#[serde(default = "timestamp")]
|
||||
#[serde(skip_serializing_if = "is_timestamp")]
|
||||
pub timestamp_format: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub enum NebulaConfigLoggingLevel {
|
||||
#[serde(rename = "panic")]
|
||||
Panic,
|
||||
#[serde(rename = "fatal")]
|
||||
Fatal,
|
||||
#[serde(rename = "error")]
|
||||
Error,
|
||||
#[serde(rename = "warning")]
|
||||
Warning,
|
||||
#[serde(rename = "info")]
|
||||
Info,
|
||||
#[serde(rename = "debug")]
|
||||
Debug,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub enum NebulaConfigLoggingFormat {
|
||||
#[serde(rename = "json")]
|
||||
Json,
|
||||
#[serde(rename = "text")]
|
||||
Text,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct NebulaConfigSshd {
|
||||
#[serde(default = "bool_false")]
|
||||
#[serde(skip_serializing_if = "is_bool_false")]
|
||||
pub enabled: bool,
|
||||
pub listen: SocketAddrV4,
|
||||
pub host_key: String,
|
||||
#[serde(default = "empty_vec")]
|
||||
#[serde(skip_serializing_if = "is_empty_vec")]
|
||||
pub authorized_users: Vec<NebulaConfigSshdAuthorizedUser>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct NebulaConfigSshdAuthorizedUser {
|
||||
pub user: String,
|
||||
#[serde(default = "empty_vec")]
|
||||
#[serde(skip_serializing_if = "is_empty_vec")]
|
||||
pub keys: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(tag = "type")]
|
||||
pub enum NebulaConfigStats {
|
||||
#[serde(rename = "graphite")]
|
||||
Graphite(NebulaConfigStatsGraphite),
|
||||
#[serde(rename = "prometheus")]
|
||||
Prometheus(NebulaConfigStatsPrometheus),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct NebulaConfigStatsGraphite {
|
||||
#[serde(default = "string_nebula")]
|
||||
#[serde(skip_serializing_if = "is_string_nebula")]
|
||||
pub prefix: String,
|
||||
#[serde(default = "protocol_tcp")]
|
||||
#[serde(skip_serializing_if = "is_protocol_tcp")]
|
||||
pub protocol: NebulaConfigStatsGraphiteProtocol,
|
||||
pub host: SocketAddrV4,
|
||||
pub interval: String,
|
||||
#[serde(default = "bool_false")]
|
||||
#[serde(skip_serializing_if = "is_bool_false")]
|
||||
pub message_metrics: bool,
|
||||
#[serde(default = "bool_false")]
|
||||
#[serde(skip_serializing_if = "is_bool_false")]
|
||||
pub lighthouse_metrics: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub enum NebulaConfigStatsGraphiteProtocol {
|
||||
#[serde(rename = "tcp")]
|
||||
Tcp,
|
||||
#[serde(rename = "udp")]
|
||||
Udp,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct NebulaConfigStatsPrometheus {
|
||||
pub listen: String,
|
||||
pub path: String,
|
||||
#[serde(default = "string_nebula")]
|
||||
#[serde(skip_serializing_if = "is_string_nebula")]
|
||||
pub namespace: String,
|
||||
#[serde(default = "string_nebula")]
|
||||
#[serde(skip_serializing_if = "is_string_nebula")]
|
||||
pub subsystem: String,
|
||||
pub interval: String,
|
||||
#[serde(default = "bool_false")]
|
||||
#[serde(skip_serializing_if = "is_bool_false")]
|
||||
pub message_metrics: bool,
|
||||
#[serde(default = "bool_false")]
|
||||
#[serde(skip_serializing_if = "is_bool_false")]
|
||||
pub lighthouse_metrics: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct NebulaConfigFirewall {
|
||||
#[serde(default = "none")]
|
||||
#[serde(skip_serializing_if = "is_none")]
|
||||
pub conntrack: Option<NebulaConfigFirewallConntrack>,
|
||||
|
||||
#[serde(default = "none")]
|
||||
#[serde(skip_serializing_if = "is_none")]
|
||||
pub inbound: Option<Vec<NebulaConfigFirewallRule>>,
|
||||
|
||||
#[serde(default = "none")]
|
||||
#[serde(skip_serializing_if = "is_none")]
|
||||
pub outbound: Option<Vec<NebulaConfigFirewallRule>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct NebulaConfigFirewallConntrack {
|
||||
#[serde(default = "string_12m")]
|
||||
#[serde(skip_serializing_if = "is_string_12m")]
|
||||
pub tcp_timeout: String,
|
||||
#[serde(default = "string_3m")]
|
||||
#[serde(skip_serializing_if = "is_string_3m")]
|
||||
pub udp_timeout: String,
|
||||
#[serde(default = "string_10m")]
|
||||
#[serde(skip_serializing_if = "is_string_10m")]
|
||||
pub default_timeout: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct NebulaConfigFirewallRule {
|
||||
#[serde(default = "none")]
|
||||
#[serde(skip_serializing_if = "is_none")]
|
||||
pub port: Option<String>,
|
||||
#[serde(default = "none")]
|
||||
#[serde(skip_serializing_if = "is_none")]
|
||||
pub proto: Option<String>,
|
||||
#[serde(default = "none")]
|
||||
#[serde(skip_serializing_if = "is_none")]
|
||||
pub ca_name: Option<String>,
|
||||
#[serde(default = "none")]
|
||||
#[serde(skip_serializing_if = "is_none")]
|
||||
pub ca_sha: Option<String>,
|
||||
#[serde(default = "none")]
|
||||
#[serde(skip_serializing_if = "is_none")]
|
||||
pub host: Option<String>,
|
||||
#[serde(default = "none")]
|
||||
#[serde(skip_serializing_if = "is_none")]
|
||||
pub group: Option<String>,
|
||||
#[serde(default = "none")]
|
||||
#[serde(skip_serializing_if = "is_none")]
|
||||
pub groups: Option<Vec<String>>,
|
||||
#[serde(default = "none")]
|
||||
#[serde(skip_serializing_if = "is_none")]
|
||||
pub cidr: Option<String>,
|
||||
}
|
||||
|
||||
// Default values for serde
|
||||
|
||||
fn string_12m() -> String {
|
||||
"12m".to_string()
|
||||
}
|
||||
fn is_string_12m(s: &str) -> bool {
|
||||
s == "12m"
|
||||
}
|
||||
|
||||
fn string_3m() -> String {
|
||||
"3m".to_string()
|
||||
}
|
||||
fn is_string_3m(s: &str) -> bool {
|
||||
s == "3m"
|
||||
}
|
||||
|
||||
fn string_10m() -> String {
|
||||
"10m".to_string()
|
||||
}
|
||||
fn is_string_10m(s: &str) -> bool {
|
||||
s == "10m"
|
||||
}
|
||||
|
||||
fn empty_vec<T>() -> Vec<T> {
|
||||
vec![]
|
||||
}
|
||||
fn is_empty_vec<T>(v: &Vec<T>) -> bool {
|
||||
v.is_empty()
|
||||
}
|
||||
|
||||
fn empty_hashmap<A, B>() -> HashMap<A, B> {
|
||||
HashMap::new()
|
||||
}
|
||||
fn is_empty_hashmap<A, B>(h: &HashMap<A, B>) -> bool {
|
||||
h.is_empty()
|
||||
}
|
||||
|
||||
fn bool_false() -> bool {
|
||||
false
|
||||
}
|
||||
fn is_bool_false(b: &bool) -> bool {
|
||||
!*b
|
||||
}
|
||||
|
||||
fn bool_true() -> bool {
|
||||
true
|
||||
}
|
||||
fn is_bool_true(b: &bool) -> bool {
|
||||
*b
|
||||
}
|
||||
|
||||
fn u16_53() -> u16 {
|
||||
53
|
||||
}
|
||||
fn is_u16_53(u: &u16) -> bool {
|
||||
*u == 53
|
||||
}
|
||||
|
||||
fn u32_10() -> u32 {
|
||||
10
|
||||
}
|
||||
fn is_u32_10(u: &u32) -> bool {
|
||||
*u == 10
|
||||
}
|
||||
|
||||
fn u16_0() -> u16 {
|
||||
0
|
||||
}
|
||||
fn is_u16_0(u: &u16) -> bool {
|
||||
*u == 0
|
||||
}
|
||||
|
||||
fn u32_64() -> u32 {
|
||||
64
|
||||
}
|
||||
fn is_u32_64(u: &u32) -> bool {
|
||||
*u == 64
|
||||
}
|
||||
|
||||
fn string_1s() -> String {
|
||||
"1s".to_string()
|
||||
}
|
||||
fn is_string_1s(s: &str) -> bool {
|
||||
s == "1s"
|
||||
}
|
||||
|
||||
fn cipher_aes() -> NebulaConfigCipher {
|
||||
NebulaConfigCipher::Aes
|
||||
}
|
||||
fn is_cipher_aes(c: &NebulaConfigCipher) -> bool {
|
||||
matches!(c, NebulaConfigCipher::Aes)
|
||||
}
|
||||
|
||||
fn u64_500() -> u64 {
|
||||
500
|
||||
}
|
||||
fn is_u64_500(u: &u64) -> bool {
|
||||
*u == 500
|
||||
}
|
||||
|
||||
fn u64_1300() -> u64 {
|
||||
1300
|
||||
}
|
||||
fn is_u64_1300(u: &u64) -> bool {
|
||||
*u == 1300
|
||||
}
|
||||
|
||||
fn i64_100() -> i64 {
|
||||
100
|
||||
}
|
||||
fn is_i64_100(i: &i64) -> bool {
|
||||
*i == 100
|
||||
}
|
||||
|
||||
fn loglevel_info() -> NebulaConfigLoggingLevel {
|
||||
NebulaConfigLoggingLevel::Info
|
||||
}
|
||||
fn is_loglevel_info(l: &NebulaConfigLoggingLevel) -> bool {
|
||||
matches!(l, NebulaConfigLoggingLevel::Info)
|
||||
}
|
||||
|
||||
fn format_text() -> NebulaConfigLoggingFormat {
|
||||
NebulaConfigLoggingFormat::Text
|
||||
}
|
||||
fn is_format_text(f: &NebulaConfigLoggingFormat) -> bool {
|
||||
matches!(f, NebulaConfigLoggingFormat::Text)
|
||||
}
|
||||
|
||||
fn timestamp() -> String {
|
||||
"2006-01-02T15:04:05Z07:00".to_string()
|
||||
}
|
||||
fn is_timestamp(s: &str) -> bool {
|
||||
s == "2006-01-02T15:04:05Z07:00"
|
||||
}
|
||||
|
||||
fn u64_1() -> u64 {
|
||||
1
|
||||
}
|
||||
fn is_u64_1(u: &u64) -> bool {
|
||||
*u == 1
|
||||
}
|
||||
|
||||
fn string_nebula() -> String {
|
||||
"nebula".to_string()
|
||||
}
|
||||
fn is_string_nebula(s: &str) -> bool {
|
||||
s == "nebula"
|
||||
}
|
||||
|
||||
fn string_empty() -> String {
|
||||
String::new()
|
||||
}
|
||||
fn is_string_empty(s: &str) -> bool {
|
||||
s.is_empty()
|
||||
}
|
||||
|
||||
fn protocol_tcp() -> NebulaConfigStatsGraphiteProtocol {
|
||||
NebulaConfigStatsGraphiteProtocol::Tcp
|
||||
}
|
||||
fn is_protocol_tcp(p: &NebulaConfigStatsGraphiteProtocol) -> bool {
|
||||
matches!(p, NebulaConfigStatsGraphiteProtocol::Tcp)
|
||||
}
|
||||
|
||||
fn none<T>() -> Option<T> {
|
||||
None
|
||||
}
|
||||
fn is_none<T>(o: &Option<T>) -> bool {
|
||||
o.is_none()
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "nebula-ffi"
|
||||
version = "0.2.0"
|
||||
version = "1.8.1"
|
||||
edition = "2021"
|
||||
description = "A Rust wrapper crate for communicating with Nebula via a CGO FFI."
|
||||
license = "GPL-3.0-or-later"
|
||||
|
@ -12,5 +12,5 @@ repository = "https://git.e3t.cc/~core/trifid"
|
|||
|
||||
|
||||
[build-dependencies]
|
||||
gobuild = "0.1.0-alpha.2"
|
||||
bindgen = "0.68.1"
|
||||
bindgen = "0.69"
|
||||
cc = "1"
|
||||
|
|
|
@ -1,27 +1,86 @@
|
|||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
use bindgen::CargoCallbacks;
|
||||
use gobuild::BuildMode;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::{env, process};
|
||||
|
||||
fn get_cargo_target_dir() -> Result<std::path::PathBuf, Box<dyn std::error::Error>> {
|
||||
let skip_triple = std::env::var("TARGET")? == std::env::var("HOST")?;
|
||||
let skip_parent_dirs = if skip_triple { 4 } else { 5 };
|
||||
|
||||
let out_dir = std::path::PathBuf::from(std::env::var("OUT_DIR")?);
|
||||
let mut current = out_dir.as_path();
|
||||
for _ in 0..skip_parent_dirs {
|
||||
current = current.parent().ok_or("not found")?;
|
||||
}
|
||||
|
||||
Ok(std::path::PathBuf::from(current))
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Find compiler: if /usr/local/go/bin/go exists, use that
|
||||
// otherwise, rely on PATH
|
||||
let compiler = if Path::new("/usr/local/go/bin/go").exists() {
|
||||
println!("Using /usr/local/go/bin/go");
|
||||
"/usr/local/go/bin/go"
|
||||
// Find compiler:
|
||||
// 1. GOC
|
||||
// 2. /usr/local/go/bin/go
|
||||
// 3. system "go"
|
||||
|
||||
let compiler = match env::var("GOC") {
|
||||
Ok(c) => c,
|
||||
Err(_) => {
|
||||
if Path::new("/usr/local/go/bin/go").exists() {
|
||||
"/usr/local/go/bin/go".to_string()
|
||||
} else {
|
||||
"go"
|
||||
"go".to_string()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
gobuild::Build::new().compiler(compiler).buildmode(BuildMode::CArchive).file("main.go").compile("nebulaffi");
|
||||
println!("using go compiler {}", compiler);
|
||||
|
||||
let c_compiler = cc::Build::new().try_get_compiler().unwrap();
|
||||
|
||||
let compile_config = get_compile_config();
|
||||
|
||||
let out_dir = env::var("OUT_DIR").unwrap();
|
||||
let out_path = PathBuf::from(out_dir);
|
||||
let out_file = compile_config.lib_filename.clone();
|
||||
let out = out_path.join(out_file);
|
||||
|
||||
let mut command = process::Command::new(compiler);
|
||||
command.args([
|
||||
"build",
|
||||
"-buildmode",
|
||||
compile_config.link_type.as_str(),
|
||||
"-o",
|
||||
out.display().to_string().as_str(),
|
||||
"main.go",
|
||||
]);
|
||||
command.env("CGO_ENABLED", "1");
|
||||
command.env("CC", c_compiler.path());
|
||||
command.env("GOARCH", compile_config.goarch.clone());
|
||||
command.env("GOOS", compile_config.goos.clone());
|
||||
println!("running go compile command: {:?}", command);
|
||||
|
||||
let mut child = command.spawn().unwrap();
|
||||
let status = child.wait().unwrap();
|
||||
println!("{}", status);
|
||||
|
||||
if !status.success() {
|
||||
panic!("`{:?}` exited with status code {}", command, status);
|
||||
}
|
||||
|
||||
println!("Go compile success");
|
||||
|
||||
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||
println!("cargo:rustc-link-search={}", env::var("OUT_DIR").unwrap());
|
||||
|
||||
println!("cargo:rustc-link-search={}", out_path.display());
|
||||
println!("cargo:rustc-link-lib=dylib=nebulaffi");
|
||||
if compile_config.link_type == "c-shared" {
|
||||
copy_shared_lib(&compile_config);
|
||||
println!("cargo:rustc-link-lib=dylib=nebula");
|
||||
} else {
|
||||
println!("cargo:rustc-link-lib=static=nebula");
|
||||
}
|
||||
|
||||
//let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||
|
||||
//println!("cargo:rustc-link-search={}", out_path.display());
|
||||
println!("cargo:rerun-if-changed=go.mod");
|
||||
println!("cargo:rerun-if-changed=go.sum");
|
||||
println!("cargo:rerun-if-changed=main.go");
|
||||
|
@ -29,13 +88,113 @@ fn main() {
|
|||
println!("Generating bindings");
|
||||
|
||||
let bindings = bindgen::Builder::default()
|
||||
.header(out_path.join("libnebulaffi.h").display().to_string())
|
||||
.parse_callbacks(Box::new(CargoCallbacks))
|
||||
.header(
|
||||
out_path
|
||||
.join(compile_config.header_filename)
|
||||
.display()
|
||||
.to_string(),
|
||||
)
|
||||
.parse_callbacks(Box::new(CargoCallbacks::new()))
|
||||
.generate()
|
||||
.expect("Error generating CFFI bindings");
|
||||
|
||||
|
||||
bindings
|
||||
.write_to_file(out_path.join("bindings.rs"))
|
||||
.expect("Couldn't write bindings!");
|
||||
}
|
||||
|
||||
fn copy_shared_lib(go_compile_config: &GoCompileConfig) {
|
||||
let target_dir = get_cargo_target_dir().unwrap();
|
||||
let target_file = target_dir.join(go_compile_config.lib_filename.clone());
|
||||
let out_dir = env::var("OUT_DIR").unwrap();
|
||||
let out_path = PathBuf::from(out_dir);
|
||||
let out_file = go_compile_config.lib_filename.clone();
|
||||
let out = out_path.join(out_file);
|
||||
std::fs::copy(out, target_file).unwrap();
|
||||
}
|
||||
|
||||
// Go build supported modes.
|
||||
// Pulled from golang/go/src/internal/platform/supported.go
|
||||
// c-archive:
|
||||
// aix, darwin, ios, windows
|
||||
// linux/386, linux/amd64, linux/arm, linux/armbe, linux/arm64, linux/arm64be, linux/loong64, linux/ppc64le, linux/riscv64, linux/s390x
|
||||
// freebsd/amd64
|
||||
|
||||
// c-shared:
|
||||
// linux/amd64, linux/arm, linux/arm64, linux/loong64, linux/386, linux/ppc64le, linux/riscv64, linux/s390x
|
||||
// android/amd64, android/arm, android/arm64, android/386
|
||||
// freebsd/amd64
|
||||
// darwin/amd64, darwin/arm64
|
||||
// windows/amd64, windows/386, windows/arm64
|
||||
|
||||
struct GoCompileConfig {
|
||||
goarch: String,
|
||||
goos: String,
|
||||
link_type: String,
|
||||
lib_filename: String,
|
||||
header_filename: String,
|
||||
}
|
||||
|
||||
fn get_compile_config() -> GoCompileConfig {
|
||||
let goarch = goarch();
|
||||
let goos = goos();
|
||||
let platform_value = format!("{}/{}", goos, goarch);
|
||||
let (preferred_link_type, lib_filename, header_filename) =
|
||||
match (goos.as_str(), goarch.as_str()) {
|
||||
("darwin", _) => ("c-archive", "libnebula.a", "libnebula.h"),
|
||||
("windows", _) => ("c-archive", "libnebula.a", "libnebula.h"),
|
||||
("linux", "386")
|
||||
| ("linux", "amd64")
|
||||
| ("linux", "arm")
|
||||
| ("linux", "armbe")
|
||||
| ("linux", "arm64")
|
||||
| ("linux", "arm64be")
|
||||
| ("linux", "loong64")
|
||||
| ("linux", "ppc64le")
|
||||
| ("linux", "riscv64")
|
||||
| ("linux", "s390x") => ("c-archive", "libnebula.a", "libnebula.h"),
|
||||
("freebsd", "amd64") => ("c-archive", "libnebula.a", "libnebula.h"),
|
||||
_ => panic!(
|
||||
"unsupported platform {} / {}",
|
||||
env::var("TARGET").unwrap(),
|
||||
platform_value
|
||||
),
|
||||
};
|
||||
|
||||
GoCompileConfig {
|
||||
goarch,
|
||||
goos,
|
||||
link_type: preferred_link_type.to_string(),
|
||||
lib_filename: lib_filename.to_string(),
|
||||
header_filename: header_filename.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn goarch() -> String {
|
||||
match env::var("CARGO_CFG_TARGET_ARCH").unwrap().as_str() {
|
||||
"x86" => "386",
|
||||
"x86_64" => "amd64",
|
||||
"mips" => "mips",
|
||||
"powerpc" => "ppc",
|
||||
"powerpc64" => "ppc64",
|
||||
"arm" => "arm",
|
||||
"aarch64" => "arm64",
|
||||
arch => panic!("unsupported architecture {arch}"),
|
||||
}
|
||||
.to_string()
|
||||
}
|
||||
fn goos() -> String {
|
||||
match env::var("CARGO_CFG_TARGET_OS").unwrap().as_str() {
|
||||
"windows" => "windows",
|
||||
"macos" => "darwin",
|
||||
"ios" => "darwin",
|
||||
"linux" => "linux",
|
||||
"android" => "android",
|
||||
"freebsd" => "freebsd",
|
||||
"dragonfly" => "dragonfly",
|
||||
"openbsd" => "openbsd",
|
||||
"netbsd" => "netbsd",
|
||||
os => panic!("unsupported operating system {os}"),
|
||||
}
|
||||
.to_string()
|
||||
}
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
module main
|
||||
module git.e3t.cc/core/trifid/nebula-ffi
|
||||
|
||||
go 1.20
|
||||
go 1.21
|
||||
|
||||
require (
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/slackhq/nebula v1.8.1
|
||||
)
|
||||
|
||||
require (
|
||||
dario.cat/mergo v1.0.0 // indirect
|
||||
|
@ -13,26 +18,23 @@ require (
|
|||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/gopacket v1.1.19 // indirect
|
||||
github.com/imdario/mergo v0.3.15 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/miekg/dns v1.1.55 // indirect
|
||||
github.com/miekg/dns v1.1.56 // indirect
|
||||
github.com/nbrownus/go-metrics-prometheus v0.0.0-20210712211119-974a6260965f // indirect
|
||||
github.com/prometheus/client_golang v1.16.0 // indirect
|
||||
github.com/prometheus/client_model v0.4.0 // indirect
|
||||
github.com/prometheus/common v0.42.0 // indirect
|
||||
github.com/prometheus/procfs v0.10.1 // indirect
|
||||
github.com/prometheus/client_golang v1.17.0 // indirect
|
||||
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect
|
||||
github.com/prometheus/common v0.44.0 // indirect
|
||||
github.com/prometheus/procfs v0.11.1 // indirect
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/slackhq/nebula v1.7.2 // indirect
|
||||
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 // indirect
|
||||
github.com/vishvananda/netlink v1.1.0 // indirect
|
||||
github.com/vishvananda/netlink v1.1.1-0.20211118161826-650dca95af54 // indirect
|
||||
github.com/vishvananda/netns v0.0.4 // indirect
|
||||
golang.org/x/crypto v0.11.0 // indirect
|
||||
golang.org/x/mod v0.10.0 // indirect
|
||||
golang.org/x/net v0.13.0 // indirect
|
||||
golang.org/x/sys v0.10.0 // indirect
|
||||
golang.org/x/term v0.10.0 // indirect
|
||||
golang.org/x/tools v0.8.0 // indirect
|
||||
golang.org/x/crypto v0.17.0 // indirect
|
||||
golang.org/x/mod v0.12.0 // indirect
|
||||
golang.org/x/net v0.19.0 // indirect
|
||||
golang.org/x/sys v0.15.0 // indirect
|
||||
golang.org/x/term v0.15.0 // indirect
|
||||
golang.org/x/tools v0.13.0 // indirect
|
||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||
golang.zx2c4.com/wireguard v0.0.0-20230325221338-052af4a8072b // indirect
|
||||
golang.zx2c4.com/wireguard/windows v0.5.3 // indirect
|
||||
|
|
|
@ -20,6 +20,7 @@ github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
|
|||
github.com/cyberdelia/go-metrics-graphite v0.0.0-20161219230853-39f87cc3b432 h1:M5QgkYacWj0Xs8MhpIK/5uwU02icXpEoSo9sM2aRCps=
|
||||
github.com/cyberdelia/go-metrics-graphite v0.0.0-20161219230853-39f87cc3b432/go.mod h1:xwIwAxMvYnVrGJPe2FKx5prTrnAjGOD8zvDOnxnrrkM=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ=
|
||||
github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
|
||||
|
@ -29,7 +30,6 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb
|
|||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
|
@ -52,16 +52,15 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
|||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
|
||||
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
|
||||
github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM=
|
||||
github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
|
@ -71,20 +70,20 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxv
|
|||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||
github.com/miekg/dns v1.1.54 h1:5jon9mWcb0sFJGpnI99tOMhCPyJ+RPVz5b63MQG0VWI=
|
||||
github.com/miekg/dns v1.1.54/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
|
||||
github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo=
|
||||
github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
|
||||
github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE=
|
||||
github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nbrownus/go-metrics-prometheus v0.0.0-20210712211119-974a6260965f h1:8dM0ilqKL0Uzl42GABzzC4Oqlc3kGRILz0vgoff7nwg=
|
||||
|
@ -92,46 +91,41 @@ github.com/nbrownus/go-metrics-prometheus v0.0.0-20210712211119-974a6260965f/go.
|
|||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
||||
github.com/prometheus/client_golang v1.15.1 h1:8tXpTmJbyH5lydzFPoxSIJ0J46jdh3tylbvM1xCv0LI=
|
||||
github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk=
|
||||
github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8=
|
||||
github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc=
|
||||
github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q=
|
||||
github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY=
|
||||
github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
|
||||
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM=
|
||||
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
||||
github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM=
|
||||
github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
|
||||
github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
|
||||
github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI=
|
||||
github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
|
||||
github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg=
|
||||
github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
|
||||
github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI=
|
||||
github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/slackhq/nebula v1.7.2 h1:Rko1Mlksz/nC0c919xjGpB8uOSrTJ5e6KPgZx+lVfYw=
|
||||
github.com/slackhq/nebula v1.7.2/go.mod h1:cnaoahkUipDs1vrNoIszyp0QPRIQN9Pm68ppQEW1Fhg=
|
||||
github.com/slackhq/nebula v1.7.3-0.20230802182832-83b6dc7b16e5 h1:NWU3xgmHAWA10Io2a20RFOVC0raucO+ZBohow3Am3H0=
|
||||
github.com/slackhq/nebula v1.7.3-0.20230802182832-83b6dc7b16e5/go.mod h1:gpXidU9u3Nf0nfkwmM4nnjxhEiV/Z+8MEumGo4wVuyI=
|
||||
github.com/slackhq/nebula v1.8.1 h1:ZksG1misr1ongDnP8FUUIaalkCJyXD4jL93DCWyM4zE=
|
||||
github.com/slackhq/nebula v1.8.1/go.mod h1:KFJPfI2wzLBlnCmB5R5hzeDc9ltlzPROqPvpnC9KYCU=
|
||||
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 h1:TG/diQgUe0pntT/2D9tmUCz4VNwm9MfrtPr0SU2qSX8=
|
||||
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8/go.mod h1:P5HUIBuIWKbyjl083/loAegFkfbFNx5i2qEP4CNbm7E=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
|
@ -140,9 +134,11 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
|||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
|
||||
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/vishvananda/netlink v1.1.1-0.20211118161826-650dca95af54 h1:8mhqcHPqTMhSPoslhGYihEgSfc77+7La1P6kiB6+9So=
|
||||
github.com/vishvananda/netlink v1.1.1-0.20211118161826-650dca95af54/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
|
||||
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
|
||||
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
|
@ -152,16 +148,14 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
|||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
|
||||
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
|
||||
golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
|
||||
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
|
||||
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
|
||||
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
@ -172,10 +166,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/net v0.13.0 h1:Nvo8UFsZ8X3BhAC9699Z1j7XQ3rsZnUUm7jfBEk1ueY=
|
||||
golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
|
||||
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
|
||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -183,41 +175,39 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
|
||||
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
|
||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c=
|
||||
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
|
||||
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
|
||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y=
|
||||
golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
|
||||
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@ -237,13 +227,12 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
|
|||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
@ -253,4 +242,5 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#![deny(clippy::missing_panics_doc)]
|
||||
#![deny(clippy::missing_safety_doc)]
|
||||
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[allow(non_snake_case)]
|
||||
|
@ -36,12 +35,11 @@ pub mod generated {
|
|||
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
|
||||
}
|
||||
|
||||
use generated::GoString;
|
||||
use std::error::Error;
|
||||
use std::ffi::{c_char, CString};
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::path::{Path};
|
||||
use generated::GoString;
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
impl From<&str> for GoString {
|
||||
#[allow(clippy::cast_possible_wrap)]
|
||||
|
@ -51,7 +49,7 @@ impl From<&str> for GoString {
|
|||
let ptr = c_str.as_ptr();
|
||||
let go_string = GoString {
|
||||
p: ptr,
|
||||
n: c_str.as_bytes().len() as isize
|
||||
n: c_str.as_bytes().len() as isize,
|
||||
};
|
||||
go_string
|
||||
}
|
||||
|
@ -73,14 +71,18 @@ impl NebulaInstance {
|
|||
/// # Panics
|
||||
/// This function will panic if memory is corrupted while communicating with Go.
|
||||
pub fn new(config_path: &Path, config_test: bool) -> Result<Self, Box<dyn Error>> {
|
||||
let mut config_path_bytes = unsafe { config_path.display().to_string().as_bytes_mut().to_vec() };
|
||||
let mut config_path_bytes =
|
||||
unsafe { config_path.display().to_string().as_bytes_mut().to_vec() };
|
||||
config_path_bytes.push(0u8);
|
||||
let config_test_u8 = u8::from(config_test);
|
||||
|
||||
let res;
|
||||
|
||||
unsafe {
|
||||
res = generated::NebulaSetup(config_path_bytes.as_mut_ptr().cast::<c_char>(), config_test_u8);
|
||||
res = generated::NebulaSetup(
|
||||
config_path_bytes.as_mut_ptr().cast::<c_char>(),
|
||||
config_test_u8,
|
||||
);
|
||||
}
|
||||
|
||||
let res = cstring_to_string(res);
|
||||
|
@ -194,18 +196,18 @@ pub enum NebulaError {
|
|||
/// Returned by nebula when the TUN/TAP device already exists
|
||||
DeviceOrResourceBusy {
|
||||
/// The complete error string returned by the Nebula wrapper
|
||||
error_str: String
|
||||
error_str: String,
|
||||
},
|
||||
/// An unknown error that the error parser couldn't figure out how to parse.
|
||||
Unknown {
|
||||
/// The complete error string returned by the Nebula wrapper
|
||||
error_str: String
|
||||
error_str: String,
|
||||
},
|
||||
/// Occurs if you call a function before NebulaSetup has been called
|
||||
NebulaNotSetup {
|
||||
/// The complete error string returned by the Nebula wrapper
|
||||
error_str: String
|
||||
}
|
||||
error_str: String,
|
||||
},
|
||||
}
|
||||
impl Display for NebulaError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
|
@ -223,11 +225,17 @@ impl NebulaError {
|
|||
#[must_use]
|
||||
pub fn from_string(string: &str) -> Self {
|
||||
if string.starts_with("device or resource busy") {
|
||||
Self::DeviceOrResourceBusy { error_str: string.to_string() }
|
||||
Self::DeviceOrResourceBusy {
|
||||
error_str: string.to_string(),
|
||||
}
|
||||
} else if string.starts_with("NebulaSetup has not yet been called") {
|
||||
Self::NebulaNotSetup { error_str: string.to_string() }
|
||||
Self::NebulaNotSetup {
|
||||
error_str: string.to_string(),
|
||||
}
|
||||
} else {
|
||||
Self::Unknown { error_str: string.to_string() }
|
||||
Self::Unknown {
|
||||
error_str: string.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|