Compare commits

..

47 Commits

Author SHA1 Message Date
core 2120ec06f9
upd lock
/ build (push) Successful in 1m32s Details
/ build_x64 (push) Failing after 49m13s Details
/ build_arm64 (push) Has been cancelled Details
/ build_win64 (push) Has been cancelled Details
2024-01-23 19:38:05 -05:00
core 12a24b135a
work, api alpha3
/ build_arm64 (push) Waiting to run Details
/ build_win64 (push) Waiting to run Details
/ build (push) Successful in 1m32s Details
/ build_x64 (push) Has been cancelled Details
2024-01-23 19:34:46 -05:00
core 0b807b351d
0.3.0-alpha2: fix edge case where trifid would issue certs that outlive the CA sometimes
/ build (push) Successful in 42s Details
/ build_x64 (push) Successful in 3m14s Details
/ build_win64 (push) Successful in 3m52s Details
/ build_arm64 (push) Failing after 49m48s Details
2024-01-02 20:21:16 -05:00
core 51bb540ab4
remove that thing
/ build (push) Successful in 1m30s Details
/ build_x64 (push) Successful in 8m55s Details
/ build_arm64 (push) Failing after 19m55s Details
/ build_win64 (push) Successful in 11m34s Details
2023-12-29 21:25:04 -05:00
core ec8cc4f1ca
minor bugfix
/ build (push) Successful in 1m36s Details
/ build_arm64 (push) Failing after 39s Details
/ build_win64 (push) Failing after 53s Details
/ build_x64 (push) Has been cancelled Details
2023-12-29 21:14:01 -05:00
core 30a8d59ba8
trifid-api 0.3.0-alpha1.1
/ build (push) Successful in 1m50s Details
/ build_x64 (push) Failing after 27m6s Details
/ build_arm64 (push) Successful in 12m40s Details
/ build_win64 (push) Failing after 12m56s Details
2023-12-29 16:22:25 -05:00
core 47a3199336
nebula-config 0.1.0 2023-12-29 16:12:31 -05:00
core 3ed98c8d8a
tfclient 0.4, nebula-ffi 1.8.1. nebula 1.7.3 -> 1.8.1 2023-12-29 16:10:32 -05:00
core 8ed4d1768e
tfapi exe file correctness
/ build (push) Successful in 1m33s Details
/ build_x64 (push) Successful in 10m5s Details
/ build_win64 (push) Successful in 12m54s Details
/ build_arm64 (push) Has been cancelled Details
2023-12-28 01:52:18 -05:00
core c9d37f41ac
trifidapi CI builds
/ build (push) Successful in 1m36s Details
/ build_x64 (push) Failing after 35m0s Details
/ build_arm64 (push) Failing after 37m35s Details
/ build_win64 (push) Successful in 55m37s Details
2023-12-28 00:41:08 -05:00
core 057e9e3ce3
bugfix alpha1 2023-12-27 01:57:17 -05:00
core a5fb79288b
dnclient endpoint speedrun: 14 minutes 2023-12-27 00:03:40 -05:00
core d8888e8f6e
enrollment 2023-12-26 22:06:48 -05:00
core 13dec2963c
some work on config generation 2023-12-25 23:23:57 -05:00
core f7de7ff592
add server private signing keys to HostKey 2023-12-25 18:50:42 -05:00
core c1762169b7
models for new db changes, update dnapi-rs, add debug to enroll messages for compat with JsonAPIResponse 2023-12-25 18:45:02 -05:00
core bda0ac2a52
v bump to 0.3.0-alpha1, database structure 2023-12-24 17:35:19 -05:00
core 011737c527
frontend magic link, make tokens always end in 'tf' 2023-12-18 12:33:34 -05:00
core 026d00b9cb
tfweb restart again 2023-12-17 22:07:55 -05:00
core 71604380a1
start the tfweb rewrite 2023-12-16 21:49:03 -05:00
core 908e1b845c
network create request, remove old tfweb pending rewrite 2023-12-16 21:14:12 -05:00
core e4ab3769ba
update platform support doc
/ build (push) Successful in 1m33s Details
/ build_x64 (push) Successful in 2m16s Details
/ build_arm64 (push) Successful in 5m56s Details
/ build_win64 (push) Successful in 3m33s Details
2023-12-16 12:01:40 -05:00
core 420d7f9788
update the windows buildscript to produce static nebula-ffi builds, massively increase nebula-ffi platform support
/ build (push) Successful in 43s Details
/ build_x64 (push) Successful in 5m48s Details
/ build_arm64 (push) Successful in 2m35s Details
/ build_win64 (push) Successful in 3m28s Details
2023-12-16 11:53:06 -05:00
core 80d9bdff92
Update build_windows.sh
/ build (push) Successful in 43s Details
/ build_x64 (push) Successful in 5m50s Details
/ build_arm64 (push) Successful in 2m39s Details
/ build_win64 (push) Failing after 3m40s Details
2023-12-15 23:27:26 -05:00
core 7cb2dc86e2
Update build_windows.sh
/ build (push) Successful in 43s Details
/ build_x64 (push) Successful in 5m47s Details
/ build_arm64 (push) Successful in 2m37s Details
/ build_win64 (push) Failing after 2m46s Details
Signed-off-by: e3team Git Services <git@e3t.cc>
2023-12-15 23:20:35 -05:00
core 5f6b3fde83
Update .forgejo/workflows/tfclient.yml
/ build_x64 (push) Successful in 5m46s Details
/ build_arm64 (push) Successful in 2m49s Details
/ build_win64 (push) Failing after 3m58s Details
/ build (push) Successful in 1m29s Details
Signed-off-by: e3team Git Services <git@e3t.cc>
2023-12-15 23:08:08 -05:00
core 7fcb20a823
fix nebula-ffi buildscript
/ build (push) Successful in 1m36s Details
/ build_x64 (push) Failing after 2m15s Details
/ build_arm64 (push) Failing after 5m58s Details
/ build_win64 (push) Failing after 3m51s Details
2023-12-15 22:59:20 -05:00
core 1a2ad44d58
fix workspace resolver and CI failure
/ build (push) Successful in 43s Details
/ build_x64 (push) Failing after 3m33s Details
/ build_arm64 (push) Failing after 2m1s Details
/ build_win64 (push) Failing after 2m2s Details
2023-12-15 22:47:46 -05:00
core c0ceed09fb
enable stricter optimization for CI builds
/ build (push) Successful in 44s Details
/ build_x64 (push) Failing after 46s Details
/ build_arm64 (push) Failing after 1m7s Details
/ build_win64 (push) Failing after 1m5s Details
2023-12-15 22:40:04 -05:00
core d44a6c1166
work
/ build (push) Successful in 1m45s Details
/ build_x64 (push) Successful in 5m42s Details
/ build_arm64 (push) Successful in 2m33s Details
/ build_win64 (push) Successful in 6m6s Details
2023-12-15 15:16:59 -05:00
core 2045d7b636
actually display hosts table
/ build (push) Successful in 49s Details
/ build_x64 (push) Successful in 2m12s Details
/ build_arm64 (push) Successful in 2m40s Details
/ build_win64 (push) Successful in 2m36s Details
2023-11-25 15:24:58 -05:00
core 74f045ed62
merge tfcli 0.3.0
/ build (push) Successful in 49s Details
/ build_x64 (push) Successful in 2m11s Details
/ build_arm64 (push) Successful in 2m38s Details
/ build_win64 (push) Successful in 2m39s Details
2023-11-25 15:12:23 -05:00
core 5813aef8de
Merge branch 'feat-compact-list-views-2'
# Conflicts:
#	Cargo.lock
#	tfcli/src/main.rs
#	tfcli/src/network.rs
#	tfcli/src/role.rs
2023-11-25 15:10:32 -05:00
core f108db3f23
lots of work
/ build (push) Successful in 48s Details
/ build_x64 (push) Successful in 2m6s Details
/ build_arm64 (push) Successful in 2m35s Details
/ build_win64 (push) Successful in 2m32s Details
2023-11-25 15:08:57 -05:00
core 646340b637
0.3 error fixes, refmt
/ build (push) Successful in 49s Details
/ build_x64 (push) Successful in 2m6s Details
/ build_arm64 (push) Successful in 2m40s Details
/ build_win64 (push) Successful in 2m36s Details
2023-11-23 15:23:52 -05:00
core 2a5a2bb910
totp auth work pt2
/ build (push) Successful in 47s Details
/ build_x64 (push) Successful in 2m6s Details
/ build_arm64 (push) Successful in 2m32s Details
/ build_win64 (push) Successful in 2m35s Details
2023-11-22 22:50:20 -05:00
core 19332e519b
totp auth work
/ build (push) Successful in 47s Details
/ build_x64 (push) Successful in 2m6s Details
/ build_arm64 (push) Successful in 2m32s Details
/ build_win64 (push) Successful in 2m38s Details
2023-11-22 10:59:21 -05:00
core a1ae83fa5f
new api work
/ build (push) Successful in 47s Details
/ build_x64 (push) Successful in 2m6s Details
/ build_arm64 (push) Successful in 2m36s Details
/ build_win64 (push) Successful in 2m40s Details
2023-11-21 22:54:21 -05:00
core 4180bdd162
create totp authenticator
/ build (push) Successful in 46s Details
/ build_x64 (push) Successful in 2m7s Details
/ build_arm64 (push) Successful in 2m34s Details
/ build_win64 (push) Successful in 2m40s Details
2023-11-21 11:26:25 -05:00
core 68627b0c92
worktm
/ build (push) Successful in 46s Details
/ build_x64 (push) Successful in 2m26s Details
/ build_arm64 (push) Successful in 2m36s Details
/ build_win64 (push) Successful in 2m34s Details
2023-11-20 20:07:02 -05:00
core e7e49f9255
login req
/ build (push) Successful in 47s Details
/ build_x64 (push) Successful in 2m6s Details
/ build_arm64 (push) Successful in 2m33s Details
/ build_win64 (push) Successful in 2m31s Details
2023-11-19 21:32:12 -05:00
core 51b6d3a85a
verify magic link
/ build (push) Successful in 46s Details
/ build_x64 (push) Successful in 2m7s Details
/ build_arm64 (push) Successful in 2m37s Details
/ build_win64 (push) Successful in 2m34s Details
2023-11-19 20:58:46 -05:00
core cd07ff5310
email sending & magic links (that work)
/ build_x64 (push) Successful in 2m9s Details
/ build_arm64 (push) Successful in 2m37s Details
/ build_win64 (push) Successful in 2m38s Details
/ build (push) Successful in 50s Details
2023-11-19 11:36:06 -05:00
core 5204994769
email sending & magic links
/ build (push) Successful in 49s Details
/ build_x64 (push) Successful in 2m6s Details
/ build_arm64 (push) Successful in 2m34s Details
/ build_win64 (push) Successful in 2m33s Details
2023-11-19 11:31:30 -05:00
core 79b1765ed5
some signup work on new api
/ build (push) Successful in 48s Details
/ build_x64 (push) Successful in 2m12s Details
/ build_arm64 (push) Successful in 2m35s Details
/ build_win64 (push) Successful in 2m35s Details
2023-11-19 10:49:08 -05:00
core 53c6fb18fd
new work
/ build (push) Failing after 49s Details
/ build_x64 (push) Successful in 2m26s Details
/ build_arm64 (push) Successful in 2m33s Details
/ build_win64 (push) Successful in 2m32s Details
2023-11-18 22:51:45 -05:00
core c1a1113d8a
initial work on compact listing views 2023-09-30 17:48:29 -04:00
515 changed files with 14399 additions and 25537 deletions

View File

@ -26,12 +26,9 @@ jobs:
uses: https://github.com/actions-rs/cargo@v1 uses: https://github.com/actions-rs/cargo@v1
with: with:
command: build command: build
args: --release --bin tfclient args: --bin tfclient --profile release-ci
- name: Upload binary - 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: build_arm64:
runs_on: docker-arm64 runs_on: docker-arm64
steps: steps:
@ -57,12 +54,9 @@ jobs:
RUSTFLAGS: "-C linker=aarch64-linux-gnu-gcc" RUSTFLAGS: "-C linker=aarch64-linux-gnu-gcc"
with: with:
command: build command: build
args: --release --bin tfclient --target aarch64-unknown-linux-gnu args: --bin tfclient --target aarch64-unknown-linux-gnu --profile release-ci
- name: Upload binary - 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/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/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: build_win64:
runs_on: docker runs_on: docker
steps: steps:
@ -86,8 +80,8 @@ jobs:
uses: https://github.com/actions-rs/cargo@v1 uses: https://github.com/actions-rs/cargo@v1
with: with:
command: build command: build
args: --release --bin tfclient --target x86_64-pc-windows-gnu args: --bin tfclient --target x86_64-pc-windows-gnu --profile release-ci
- name: Compile release bundle - name: Compile release bundle
run: ./build_windows.sh run: ./build_windows.sh
- name: Upload binary - 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/tfclient.zip ${{ secrets.TRIFID_DLCDN_USER }}@${{ secrets.TRIFID_DLCDN_IP }}:${{ secrets.TRIFID_DLCDN_PATH }}/tfclient/win64/$GITHUB_SHA/tfclient.zip 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

View File

@ -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

View File

@ -1,15 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<module type="CPP_MODULE" version="4"> <module type="CPP_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager"> <component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/tfclient/src" isTestSource="false" /> <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-api/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/trifid-pki/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$/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$/tfcli/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/nebula-ffi/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" /> <excludeFolder url="file://$MODULE_DIR$/target" />
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />

2921
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,18 @@
[workspace] [workspace]
members = [ members = [
"trifid-api",
"trifid-api/trifid_api_migration",
"trifid-api/trifid_api_entities",
"tfclient", "tfclient",
"trifid-pki", "trifid-pki",
"dnapi-rs", "dnapi-rs",
"tfcli", "tfcli",
"nebula-ffi" "nebula-ffi",
"nebula-config",
"trifid-api",
"trifid-api-derive",
"trifid_mobile_bridge"
] ]
resolver = "2" resolver = "2"
[profile.release-ci]
inherits = "release"
lto = true

View File

@ -2,8 +2,8 @@ FROM rust:latest
COPY trifid-pki /trifid-pki COPY trifid-pki /trifid-pki
COPY dnapi-rs /dnapi-rs 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"] CMD ["/bin/trifid-api"]

View File

@ -24,11 +24,11 @@ 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. 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? | | Operating System / Architecture | tfclient support tier | trifid-api compatible? |
|---------------------------------|-----------------------------------|-------------------------------------| |---------------------------------|-----------------------|-------------------------------------|
| Windows (all architectures) | Tier 2 - external nebula required | Yes (tfclient/dnclient) | | Windows (all architectures) | Tier 1 | Yes (tfclient/dnclient) |
| Darwin (OSX, MacOS) | Tier 2 - untested, maybe T1 | Yes (tfclient/dnclient) | | Darwin (OSX, MacOS) | Tier 1 | Yes (tfclient/dnclient) |
| FreeBSD (amd64) | Tier 1 - untested | Yes (tfclient/dnclient) | | FreeBSD (amd64) | Tier 1 | Yes (tfclient/dnclient) |
| Linux (most architectures) | Tier 1 | Yes (tfclient/dnclient) | | Linux (most architectures) | Tier 1 | Yes (tfclient/dnclient) |
| Android | Unsupported | No (almost - help wanted! see docs) | | Android | Unsupported | No (almost - help wanted! see docs) |
| iOS | Unsupported | No (almost - help wanted! see docs) | | iOS | Unsupported | No (almost - help wanted! see docs) |

View File

@ -1,18 +1,16 @@
#!/bin/bash #!/bin/bash
set -e set -e
cargo build --target x86_64-pc-windows-gnu --release --bin tfclient cargo build --target x86_64-pc-windows-gnu --profile release-ci --bin tfclient
rm -rf target/x86_64-pc-windows-gnu/release/tfclient_dist/ rm -rf target/x86_64-pc-windows-gnu/release-ci/tfclient_dist/
mkdir -p target/x86_64-pc-windows-gnu/release/tfclient_dist/ mkdir -p target/x86_64-pc-windows-gnu/release-ci/tfclient_dist/
cp target/x86_64-pc-windows-gnu/release/tfclient.exe target/x86_64-pc-windows-gnu/release/tfclient_dist/tfclient.exe 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" echo "[*] Downloading WinTun"
mkdir -p target/x86_64-pc-windows-gnu/release/tfclient_dist/dist/windows/ 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 wget https://www.wintun.net/builds/wintun-0.14.1.zip -O /tmp/wintun.zip
echo "[*] Unzipping WinTun" echo "[*] Unzipping WinTun"
unzip -d target/x86_64-pc-windows-gnu/release/tfclient_dist/dist/windows/ /tmp/wintun.zip unzip -d target/x86_64-pc-windows-gnu/release-ci/tfclient_dist/dist/windows/ /tmp/wintun.zip
echo "[*] Copying nebula.dll"
cp target/x86_64-pc-windows-gnu/release/nebula.dll target/x86_64-pc-windows-gnu/release/tfclient_dist/nebula.dll
echo "[*] Building zip bundle" echo "[*] Building zip bundle"
cd target/x86_64-pc-windows-gnu/release cd target/x86_64-pc-windows-gnu/release-ci
zip -r tfclient.zip tfclient_dist/* zip -r tfclient.zip tfclient_dist/*
cd ../../../ cd ../../../
echo "[*] Windows production build success!" echo "[*] Windows production build success!"

2
database_structure Normal file
View File

@ -0,0 +1,2 @@
Users
\-

View File

@ -1,6 +1,6 @@
[package] [package]
name = "dnapi-rs" name = "dnapi-rs"
version = "0.2.1" version = "0.2.3"
edition = "2021" edition = "2021"
description = "A rust client for the Defined Networking API" description = "A rust client for the Defined Networking API"
license = "AGPL-3.0-or-later" license = "AGPL-3.0-or-later"

View File

@ -13,6 +13,7 @@ use log::{debug, error};
use reqwest::StatusCode; use reqwest::StatusCode;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::error::Error; use std::error::Error;
use reqwest::header::HeaderValue;
use trifid_pki::cert::serialize_ed25519_public; use trifid_pki::cert::serialize_ed25519_public;
use trifid_pki::ed25519_dalek::{Signature, Signer, SigningKey, Verifier}; use trifid_pki::ed25519_dalek::{Signature, Signer, SigningKey, Verifier};
use url::Url; use url::Url;
@ -89,10 +90,15 @@ impl Client {
.send() .send()
.await?; .await?;
let empty_hval;
#[allow(clippy::unwrap_used)] {
empty_hval = HeaderValue::from_str("").unwrap();
};
let req_id = resp let req_id = resp
.headers() .headers()
.get("X-Request-ID") .get("X-Request-ID")
.ok_or("Response missing X-Request-ID")? .unwrap_or(&empty_hval)
.to_str()?; .to_str()?;
debug!("enrollment request complete {{req_id: {}}}", req_id); debug!("enrollment request complete {{req_id: {}}}", req_id);

View File

@ -13,6 +13,7 @@ use log::{debug, error, trace};
use reqwest::StatusCode; use reqwest::StatusCode;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::error::Error; use std::error::Error;
use reqwest::header::HeaderValue;
use trifid_pki::cert::serialize_ed25519_public; use trifid_pki::cert::serialize_ed25519_public;
use trifid_pki::ed25519_dalek::{Signature, Signer, SigningKey, Verifier}; use trifid_pki::ed25519_dalek::{Signature, Signer, SigningKey, Verifier};
use url::Url; use url::Url;
@ -90,10 +91,15 @@ impl Client {
.body(req_json) .body(req_json)
.send()?; .send()?;
let empty_hval;
#[allow(clippy::unwrap_used)] {
empty_hval = HeaderValue::from_str("").unwrap();
};
let req_id = resp let req_id = resp
.headers() .headers()
.get("X-Request-ID") .get("X-Request-ID")
.ok_or("Response missing X-Request-ID")? .unwrap_or(&empty_hval)
.to_str()?; .to_str()?;
debug!("enrollment request complete {{req_id: {}}}", req_id); debug!("enrollment request complete {{req_id: {}}}", req_id);
@ -254,7 +260,10 @@ impl Client {
ed_privkey.verify(b64_msg_bytes, &Signature::from_slice(&signature)?)?; ed_privkey.verify(b64_msg_bytes, &Signature::from_slice(&signature)?)?;
debug!("signature valid via clientside check"); 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 { let body = RequestV1 {
version: 1, version: 1,

View File

@ -13,7 +13,7 @@ pub const DO_UPDATE: &str = "DoUpdate";
base64_serde_type!(Base64Standard, base64::engine::general_purpose::STANDARD); base64_serde_type!(Base64Standard, base64::engine::general_purpose::STANDARD);
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize, Debug)]
/// `RequestV1` is the version 1 `DNClient` request message. /// `RequestV1` is the version 1 `DNClient` request message.
pub struct RequestV1 { pub struct RequestV1 {
/// Version is always 1 /// Version is always 1
@ -30,7 +30,7 @@ pub struct RequestV1 {
pub signature: Vec<u8>, pub signature: Vec<u8>,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize, Debug)]
/// `RequestWrapper` wraps a `DNClient` request message. It consists of a /// `RequestWrapper` wraps a `DNClient` request message. It consists of a
/// type and value, with the type string indicating how to interpret the value blob. /// type and value, with the type string indicating how to interpret the value blob.
pub struct RequestWrapper { pub struct RequestWrapper {
@ -48,14 +48,14 @@ pub struct RequestWrapper {
pub timestamp: String, pub timestamp: String,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize, Debug)]
/// `SignedResponseWrapper` contains a response message and a signature to validate inside `data`. /// `SignedResponseWrapper` contains a response message and a signature to validate inside `data`.
pub struct SignedResponseWrapper { pub struct SignedResponseWrapper {
/// The response data contained in this message /// The response data contained in this message
pub data: SignedResponse, pub data: SignedResponse,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize, Debug)]
/// `SignedResponse` contains a response message and a signature to validate. /// `SignedResponse` contains a response message and a signature to validate.
pub struct SignedResponse { pub struct SignedResponse {
/// The API version - always 1 /// The API version - always 1
@ -68,14 +68,14 @@ pub struct SignedResponse {
pub signature: Vec<u8>, pub signature: Vec<u8>,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize, Debug)]
/// `CheckForUpdateResponseWrapper` contains a response to `CheckForUpdate` inside "data." /// `CheckForUpdateResponseWrapper` contains a response to `CheckForUpdate` inside "data."
pub struct CheckForUpdateResponseWrapper { pub struct CheckForUpdateResponseWrapper {
/// The response data contained in this message /// The response data contained in this message
pub data: CheckForUpdateResponse, pub data: CheckForUpdateResponse,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize, Debug)]
/// `CheckForUpdateResponse` is the response generated for a `CheckForUpdate` request. /// `CheckForUpdateResponse` is the response generated for a `CheckForUpdate` request.
pub struct CheckForUpdateResponse { pub struct CheckForUpdateResponse {
#[serde(rename = "updateAvailable")] #[serde(rename = "updateAvailable")]
@ -83,7 +83,7 @@ pub struct CheckForUpdateResponse {
pub update_available: bool, pub update_available: bool,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize, Debug)]
/// `DoUpdateRequest` is the request sent for a `DoUpdate` request. /// `DoUpdateRequest` is the request sent for a `DoUpdate` request.
pub struct DoUpdateRequest { pub struct DoUpdateRequest {
#[serde(rename = "edPubkeyPEM")] #[serde(rename = "edPubkeyPEM")]
@ -100,7 +100,7 @@ pub struct DoUpdateRequest {
pub nonce: Vec<u8>, pub nonce: Vec<u8>,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize, Debug)]
/// A server response to a `DoUpdateRequest`, with the updated config and key information /// A server response to a `DoUpdateRequest`, with the updated config and key information
pub struct DoUpdateResponse { pub struct DoUpdateResponse {
#[serde(with = "Base64Standard")] #[serde(with = "Base64Standard")]
@ -141,7 +141,7 @@ pub struct EnrollRequest {
pub timestamp: String, pub timestamp: String,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize, Debug)]
#[serde(untagged)] #[serde(untagged)]
/// The response to an `EnrollRequest` /// The response to an `EnrollRequest`
pub enum EnrollResponse { pub enum EnrollResponse {
@ -157,7 +157,7 @@ pub enum EnrollResponse {
}, },
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize, Debug)]
/// The data included in an successful enrollment. /// The data included in an successful enrollment.
pub struct EnrollResponseData { pub struct EnrollResponseData {
#[serde(with = "Base64Standard")] #[serde(with = "Base64Standard")]
@ -176,7 +176,7 @@ pub struct EnrollResponseData {
pub organization: EnrollResponseDataOrg, pub organization: EnrollResponseDataOrg,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize, Debug)]
/// The organization data that this node is now a part of /// The organization data that this node is now a part of
pub struct EnrollResponseDataOrg { pub struct EnrollResponseDataOrg {
/// The organization ID that this node is now a part of /// The organization ID that this node is now a part of
@ -185,7 +185,7 @@ pub struct EnrollResponseDataOrg {
pub name: String, pub name: String,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize, Debug)]
/// `APIError` represents a single error returned in an API error response. /// `APIError` represents a single error returned in an API error response.
pub struct APIError { pub struct APIError {
/// The error code /// The error code

View File

@ -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 |

15
nebula-config/Cargo.toml Normal file
View File

@ -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"] }

532
nebula-config/src/lib.rs Normal file
View File

@ -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()
}

View File

@ -1,6 +1,6 @@
[package] [package]
name = "nebula-ffi" name = "nebula-ffi"
version = "1.7.2" version = "1.8.1"
edition = "2021" edition = "2021"
description = "A Rust wrapper crate for communicating with Nebula via a CGO FFI." description = "A Rust wrapper crate for communicating with Nebula via a CGO FFI."
license = "GPL-3.0-or-later" license = "GPL-3.0-or-later"
@ -12,5 +12,5 @@ repository = "https://git.e3t.cc/~core/trifid"
[build-dependencies] [build-dependencies]
bindgen = "0.68.1" bindgen = "0.69"
cc = "1" cc = "1"

View File

@ -1,26 +1,22 @@
use std::{env, process};
use std::path::PathBuf;
use bindgen::CargoCallbacks; use bindgen::CargoCallbacks;
use std::path::Path; 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>> { 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 out_dir = std::path::PathBuf::from(std::env::var("OUT_DIR")?);
let profile = std::env::var("PROFILE")?; let mut current = out_dir.as_path();
let mut target_dir = None; for _ in 0..skip_parent_dirs {
let mut sub_path = out_dir.as_path(); current = current.parent().ok_or("not found")?;
while let Some(parent) = sub_path.parent() {
if parent.ends_with(&profile) {
target_dir = Some(parent);
break;
}
sub_path = parent;
} }
let target_dir = target_dir.ok_or("not found")?;
Ok(target_dir.to_path_buf()) Ok(std::path::PathBuf::from(current))
} }
fn main() { fn main() {
// Find compiler: // Find compiler:
// 1. GOC // 1. GOC
// 2. /usr/local/go/bin/go // 2. /usr/local/go/bin/go
@ -39,21 +35,28 @@ fn main() {
println!("using go compiler {}", compiler); println!("using go compiler {}", compiler);
//gobuild::Build::new().compiler(compiler).buildmode(BuildMode::CArchive).file("main.go").compile("nebulaffi");
let c_compiler = cc::Build::new().try_get_compiler().unwrap(); 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_dir = env::var("OUT_DIR").unwrap();
let out_path = PathBuf::from(out_dir); let out_path = PathBuf::from(out_dir);
let out_file = lib_name(); let out_file = compile_config.lib_filename.clone();
let out = out_path.join(out_file); let out = out_path.join(out_file);
let mut command = process::Command::new(compiler); let mut command = process::Command::new(compiler);
command.args(["build", "-buildmode", link_type().as_str(), "-o", out.display().to_string().as_str(), "main.go"]); 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("CGO_ENABLED", "1");
command.env("CC", c_compiler.path()); command.env("CC", c_compiler.path());
command.env("GOARCH", goarch()); command.env("GOARCH", compile_config.goarch.clone());
command.env("GOOS", goos()); command.env("GOOS", compile_config.goos.clone());
println!("running go compile command: {:?}", command); println!("running go compile command: {:?}", command);
let mut child = command.spawn().unwrap(); let mut child = command.spawn().unwrap();
@ -65,10 +68,15 @@ fn main() {
} }
println!("Go compile success"); println!("Go compile success");
copy_if_windows();
print_link(); println!("cargo:rustc-link-search={}", env::var("OUT_DIR").unwrap());
println!("cargo:rustc-link-search=native={}", env::var("OUT_DIR").unwrap());
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()); //let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
@ -80,42 +88,88 @@ fn main() {
println!("Generating bindings"); println!("Generating bindings");
let bindings = bindgen::Builder::default() let bindings = bindgen::Builder::default()
.header(out_path.join(header_name()).display().to_string()) .header(
.parse_callbacks(Box::new(CargoCallbacks)) out_path
.join(compile_config.header_filename)
.display()
.to_string(),
)
.parse_callbacks(Box::new(CargoCallbacks::new()))
.generate() .generate()
.expect("Error generating CFFI bindings"); .expect("Error generating CFFI bindings");
bindings bindings
.write_to_file(out_path.join("bindings.rs")) .write_to_file(out_path.join("bindings.rs"))
.expect("Couldn't write bindings!"); .expect("Couldn't write bindings!");
} }
fn lib_name() -> String { fn copy_shared_lib(go_compile_config: &GoCompileConfig) {
if env::var("CARGO_CFG_TARGET_FAMILY").unwrap() == "windows" {
"nebula.dll".to_string()
} else {
"libnebula.a".to_string()
}
}
fn header_name() -> String {
if env::var("CARGO_CFG_TARGET_FAMILY").unwrap() == "windows" {
"nebula.h".to_string()
} else {
"libnebula.h".to_string()
}
}
fn copy_if_windows() {
let target_dir = get_cargo_target_dir().unwrap(); let target_dir = get_cargo_target_dir().unwrap();
let target_file = target_dir.join(lib_name()); let target_file = target_dir.join(go_compile_config.lib_filename.clone());
let out_dir = env::var("OUT_DIR").unwrap(); let out_dir = env::var("OUT_DIR").unwrap();
let out_path = PathBuf::from(out_dir); let out_path = PathBuf::from(out_dir);
let out_file = lib_name(); let out_file = go_compile_config.lib_filename.clone();
let out = out_path.join(out_file); let out = out_path.join(out_file);
std::fs::copy(out, target_file).unwrap(); 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 { fn goarch() -> String {
match env::var("CARGO_CFG_TARGET_ARCH").unwrap().as_str() { match env::var("CARGO_CFG_TARGET_ARCH").unwrap().as_str() {
"x86" => "386", "x86" => "386",
@ -125,8 +179,9 @@ fn goarch() -> String {
"powerpc64" => "ppc64", "powerpc64" => "ppc64",
"arm" => "arm", "arm" => "arm",
"aarch64" => "arm64", "aarch64" => "arm64",
arch => panic!("unsupported architecture {arch}") arch => panic!("unsupported architecture {arch}"),
}.to_string() }
.to_string()
} }
fn goos() -> String { fn goos() -> String {
match env::var("CARGO_CFG_TARGET_OS").unwrap().as_str() { match env::var("CARGO_CFG_TARGET_OS").unwrap().as_str() {
@ -139,22 +194,7 @@ fn goos() -> String {
"dragonfly" => "dragonfly", "dragonfly" => "dragonfly",
"openbsd" => "openbsd", "openbsd" => "openbsd",
"netbsd" => "netbsd", "netbsd" => "netbsd",
os => panic!("unsupported operating system {os}") os => panic!("unsupported operating system {os}"),
}.to_string()
}
fn print_link() {
if env::var("CARGO_CFG_TARGET_FAMILY").unwrap() == "windows" {
println!("cargo:rustc-link-lib=dylib=nebula");
} else {
println!("cargo:rustc-link-lib=static=nebula");
}
}
fn link_type() -> String {
if env::var("CARGO_CFG_TARGET_FAMILY").unwrap() == "windows" {
"c-shared".to_string()
} else {
"c-archive".to_string()
} }
.to_string()
} }

View File

@ -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 ( require (
dario.cat/mergo v1.0.0 // indirect dario.cat/mergo v1.0.0 // indirect
@ -13,26 +18,23 @@ require (
github.com/gogo/protobuf v1.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect github.com/golang/protobuf v1.5.3 // indirect
github.com/google/gopacket v1.1.19 // 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/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/nbrownus/go-metrics-prometheus v0.0.0-20210712211119-974a6260965f // indirect
github.com/prometheus/client_golang v1.16.0 // indirect github.com/prometheus/client_golang v1.17.0 // indirect
github.com/prometheus/client_model v0.4.0 // indirect github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect
github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/common v0.44.0 // indirect
github.com/prometheus/procfs v0.10.1 // indirect github.com/prometheus/procfs v0.11.1 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // 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/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 github.com/vishvananda/netns v0.0.4 // indirect
golang.org/x/crypto v0.11.0 // indirect golang.org/x/crypto v0.17.0 // indirect
golang.org/x/mod v0.10.0 // indirect golang.org/x/mod v0.12.0 // indirect
golang.org/x/net v0.13.0 // indirect golang.org/x/net v0.19.0 // indirect
golang.org/x/sys v0.10.0 // indirect golang.org/x/sys v0.15.0 // indirect
golang.org/x/term v0.10.0 // indirect golang.org/x/term v0.15.0 // indirect
golang.org/x/tools v0.8.0 // indirect golang.org/x/tools v0.13.0 // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // 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 v0.0.0-20230325221338-052af4a8072b // indirect
golang.zx2c4.com/wireguard/windows v0.5.3 // indirect golang.zx2c4.com/wireguard/windows v0.5.3 // indirect

View File

@ -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 h1:M5QgkYacWj0Xs8MhpIK/5uwU02icXpEoSo9sM2aRCps=
github.com/cyberdelia/go-metrics-graphite v0.0.0-20161219230853-39f87cc3b432/go.mod h1:xwIwAxMvYnVrGJPe2FKx5prTrnAjGOD8zvDOnxnrrkM= 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.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/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 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ=
github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= 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.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.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.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/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.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= 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.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.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.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/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 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= 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/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.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.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.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.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= 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/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.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 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/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/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.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 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= 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.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE=
github.com/miekg/dns v1.1.54/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY=
github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo=
github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 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/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 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.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-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/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= 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.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/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/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/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 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.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.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.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_golang v1.15.1 h1:8tXpTmJbyH5lydzFPoxSIJ0J46jdh3tylbvM1xCv0LI= github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q=
github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY=
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_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 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.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.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM=
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/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 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.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= 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.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= 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.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.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.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.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI=
github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY=
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/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= 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/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.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 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.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 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= 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.8.1 h1:ZksG1misr1ongDnP8FUUIaalkCJyXD4jL93DCWyM4zE=
github.com/slackhq/nebula v1.7.2/go.mod h1:cnaoahkUipDs1vrNoIszyp0QPRIQN9Pm68ppQEW1Fhg= github.com/slackhq/nebula v1.8.1/go.mod h1:KFJPfI2wzLBlnCmB5R5hzeDc9ltlzPROqPvpnC9KYCU=
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/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 h1:TG/diQgUe0pntT/2D9tmUCz4VNwm9MfrtPr0SU2qSX8= 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/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= 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.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 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/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= 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 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 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-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-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= 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.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 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.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.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.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.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 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-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-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/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-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-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.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/net v0.13.0 h1:Nvo8UFsZ8X3BhAC9699Z1j7XQ3rsZnUUm7jfBEk1ueY=
golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 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-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/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-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-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.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-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-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-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-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-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-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-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-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-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-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-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-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-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.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
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/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 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.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
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/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 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.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 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-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-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-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-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.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y= golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= 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-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-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/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.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-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.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 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 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/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 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-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/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.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/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 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 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.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= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -25,7 +25,6 @@
#![deny(clippy::missing_panics_doc)] #![deny(clippy::missing_panics_doc)]
#![deny(clippy::missing_safety_doc)] #![deny(clippy::missing_safety_doc)]
#[allow(non_upper_case_globals)] #[allow(non_upper_case_globals)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[allow(non_snake_case)] #[allow(non_snake_case)]
@ -36,12 +35,11 @@ pub mod generated {
include!(concat!(env!("OUT_DIR"), "/bindings.rs")); include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
} }
use generated::GoString;
use std::error::Error; use std::error::Error;
use std::ffi::{c_char, CString}; use std::ffi::{c_char, CString};
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
use std::path::{Path}; use std::path::Path;
use generated::GoString;
impl From<&str> for GoString { impl From<&str> for GoString {
#[allow(clippy::cast_possible_wrap)] #[allow(clippy::cast_possible_wrap)]
@ -51,7 +49,7 @@ impl From<&str> for GoString {
let ptr = c_str.as_ptr(); let ptr = c_str.as_ptr();
let go_string = GoString { let go_string = GoString {
p: ptr, p: ptr,
n: c_str.as_bytes().len() as isize n: c_str.as_bytes().len() as isize,
}; };
go_string go_string
} }
@ -73,14 +71,18 @@ impl NebulaInstance {
/// # Panics /// # Panics
/// This function will panic if memory is corrupted while communicating with Go. /// 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>> { 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); config_path_bytes.push(0u8);
let config_test_u8 = u8::from(config_test); let config_test_u8 = u8::from(config_test);
let res; let res;
unsafe { 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); let res = cstring_to_string(res);
@ -194,18 +196,18 @@ pub enum NebulaError {
/// Returned by nebula when the TUN/TAP device already exists /// Returned by nebula when the TUN/TAP device already exists
DeviceOrResourceBusy { DeviceOrResourceBusy {
/// The complete error string returned by the Nebula wrapper /// 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. /// An unknown error that the error parser couldn't figure out how to parse.
Unknown { Unknown {
/// The complete error string returned by the Nebula wrapper /// 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 /// Occurs if you call a function before NebulaSetup has been called
NebulaNotSetup { NebulaNotSetup {
/// The complete error string returned by the Nebula wrapper /// The complete error string returned by the Nebula wrapper
error_str: String error_str: String,
} },
} }
impl Display for NebulaError { impl Display for NebulaError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
@ -223,11 +225,17 @@ impl NebulaError {
#[must_use] #[must_use]
pub fn from_string(string: &str) -> Self { pub fn from_string(string: &str) -> Self {
if string.starts_with("device or resource busy") { 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") { } 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 { } else {
Self::Unknown { error_str: string.to_string() } Self::Unknown {
error_str: string.to_string(),
}
} }
} }
} }

View File

@ -1,6 +1,6 @@
[package] [package]
name = "tfcli" name = "tfcli"
version = "0.2.0" version = "0.3.1"
edition = "2021" edition = "2021"
description = "Command-line client for managing trifid-api" description = "Command-line client for managing trifid-api"
license = "GPL-3.0-or-later" license = "GPL-3.0-or-later"
@ -20,3 +20,4 @@ dirs = "5"
qr2term = "0.3" qr2term = "0.3"
ipnet = "2.7" ipnet = "2.7"
serde_json = "1" serde_json = "1"
comfy-table = "7"

View File

@ -1,38 +1,48 @@
use crate::api::APIErrorResponse;
use crate::AccountCommands;
use serde::{Deserialize, Serialize};
use std::error::Error; use std::error::Error;
use std::fs; use std::fs;
use serde::{Deserialize, Serialize};
use url::Url; use url::Url;
use crate::AccountCommands;
use crate::api::APIErrorResponse;
pub async fn account_main(command: AccountCommands, server: Url) -> Result<(), Box<dyn Error>> { pub async fn account_main(command: AccountCommands, server: Url) -> Result<(), Box<dyn Error>> {
match command { match command {
AccountCommands::Create { email } => create_account(email, server).await, AccountCommands::Create { email } => create_account(email, server).await,
AccountCommands::MagicLink { magic_link_token } => auth_magic_link(magic_link_token, server).await, AccountCommands::MagicLink { magic_link_token } => {
auth_magic_link(magic_link_token, server).await
}
AccountCommands::MfaSetup {} => create_mfa_authenticator(server).await, AccountCommands::MfaSetup {} => create_mfa_authenticator(server).await,
AccountCommands::MfaSetupFinish {code, token} => finish_mfa_authenticator(token, code, server).await, AccountCommands::MfaSetupFinish { code, token } => {
AccountCommands::Mfa {code} => mfa_auth(code, server).await, finish_mfa_authenticator(token, code, server).await
AccountCommands::Login { email } => login_account(email, server).await }
AccountCommands::Mfa { code } => mfa_auth(code, server).await,
AccountCommands::Login { email } => login_account(email, server).await,
} }
} }
#[derive(Serialize)] #[derive(Serialize)]
pub struct CreateAccountBody { pub struct CreateAccountBody {
pub email: String pub email: String,
} }
pub async fn create_account(email: String, server: Url) -> Result<(), Box<dyn Error>> { pub async fn create_account(email: String, server: Url) -> Result<(), Box<dyn Error>> {
let client = reqwest::Client::new(); let client = reqwest::Client::new();
let res = client.post(server.join("/v1/signup")?).json(&CreateAccountBody { email }).send().await?; let res = client
.post(server.join("/v1/signup")?)
.json(&CreateAccountBody { email })
.send()
.await?;
if res.status().is_success() { if res.status().is_success() {
println!("Account created successfully, check your email."); println!("Account created successfully, check your email.");
println!("Finish creating your account with 'tfcli account magic-link --magic-link-token [magic-link-token]'."); println!("Finish creating your account with 'tfcli account magic-link --magic-link-token [magic-link-token]'.");
} else { } else {
let resp: APIErrorResponse = res.json().await?; let resp: APIErrorResponse = res.json().await?;
eprintln!("[error] Error creating account: {} {}", resp.errors[0].code, resp.errors[0].message); eprintln!(
"[error] Error creating account: {} {}",
resp.errors[0].code, resp.errors[0].message
);
std::process::exit(1); std::process::exit(1);
} }
@ -42,21 +52,27 @@ pub async fn create_account(email: String, server: Url) -> Result<(), Box<dyn Er
#[derive(Serialize)] #[derive(Serialize)]
pub struct LoginAccountBody { pub struct LoginAccountBody {
pub email: String pub email: String,
} }
pub async fn login_account(email: String, server: Url) -> Result<(), Box<dyn Error>> { pub async fn login_account(email: String, server: Url) -> Result<(), Box<dyn Error>> {
let client = reqwest::Client::new(); let client = reqwest::Client::new();
let res = client.post(server.join("/v1/auth/magic-link")?).json(&LoginAccountBody { email }).send().await?; let res = client
.post(server.join("/v1/auth/magic-link")?)
.json(&LoginAccountBody { email })
.send()
.await?;
if res.status().is_success() { if res.status().is_success() {
println!("Magic link sent, check your email."); println!("Magic link sent, check your email.");
println!("Finish creating your account with 'tfcli account magic-link --magic-link-token [magic-link-token]'."); println!("Finish creating your account with 'tfcli account magic-link --magic-link-token [magic-link-token]'.");
} else { } else {
let resp: APIErrorResponse = res.json().await?; let resp: APIErrorResponse = res.json().await?;
eprintln!("[error] Error logging in: {} {}", resp.errors[0].code, resp.errors[0].message); eprintln!(
"[error] Error logging in: {} {}",
resp.errors[0].code, resp.errors[0].message
);
std::process::exit(1); std::process::exit(1);
} }
@ -64,26 +80,31 @@ pub async fn login_account(email: String, server: Url) -> Result<(), Box<dyn Err
Ok(()) Ok(())
} }
#[derive(Serialize)] #[derive(Serialize)]
pub struct MagicLinkBody { pub struct MagicLinkBody {
#[serde(rename = "magicLinkToken")] #[serde(rename = "magicLinkToken")]
pub magic_link_token: String pub magic_link_token: String,
} }
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct MagicLinkSuccess { pub struct MagicLinkSuccess {
pub data: MagicLinkSuccessBody pub data: MagicLinkSuccessBody,
} }
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct MagicLinkSuccessBody { pub struct MagicLinkSuccessBody {
#[serde(rename = "sessionToken")] #[serde(rename = "sessionToken")]
pub session_token: String pub session_token: String,
} }
pub async fn auth_magic_link(magic_token: String, server: Url) -> Result<(), Box<dyn Error>> { pub async fn auth_magic_link(magic_token: String, server: Url) -> Result<(), Box<dyn Error>> {
let client = reqwest::Client::new(); let client = reqwest::Client::new();
let res = client.post(server.join("/v1/auth/verify-magic-link")?).json(&MagicLinkBody { magic_link_token: magic_token }).send().await?; let res = client
.post(server.join("/v1/auth/verify-magic-link")?)
.json(&MagicLinkBody {
magic_link_token: magic_token,
})
.send()
.await?;
if res.status().is_success() { if res.status().is_success() {
let resp: MagicLinkSuccess = res.json().await?; let resp: MagicLinkSuccess = res.json().await?;
@ -97,7 +118,10 @@ pub async fn auth_magic_link(magic_token: String, server: Url) -> Result<(), Box
} else { } else {
let resp: APIErrorResponse = res.json().await?; let resp: APIErrorResponse = res.json().await?;
eprintln!("[error] Error getting session token: {} {}", resp.errors[0].code, resp.errors[0].message); eprintln!(
"[error] Error getting session token: {} {}",
resp.errors[0].code, resp.errors[0].message
);
std::process::exit(1); std::process::exit(1);
} }
@ -135,14 +159,14 @@ pub struct WhoamiResponseMetadata {}
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct CreateMfaResponse { pub struct CreateMfaResponse {
pub data: CreateMfaResponseData pub data: CreateMfaResponseData,
} }
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct CreateMfaResponseData { pub struct CreateMfaResponseData {
#[serde(rename = "totpToken")] #[serde(rename = "totpToken")]
pub totp_token: String, pub totp_token: String,
pub secret: String, pub secret: String,
pub url: String pub url: String,
} }
pub async fn create_mfa_authenticator(server: Url) -> Result<(), Box<dyn Error>> { pub async fn create_mfa_authenticator(server: Url) -> Result<(), Box<dyn Error>> {
@ -153,14 +177,25 @@ pub async fn create_mfa_authenticator(server: Url) -> Result<(), Box<dyn Error>>
let session_token = fs::read_to_string(&token_store)?; let session_token = fs::read_to_string(&token_store)?;
// do we have mfa already? // do we have mfa already?
let whoami: WhoamiResponse = client.get(server.join("/v2/whoami")?).bearer_auth(&session_token).send().await?.json().await?; let whoami: WhoamiResponse = client
.get(server.join("/v2/whoami")?)
.bearer_auth(&session_token)
.send()
.await?
.json()
.await?;
if whoami.data.actor.has_totp_authenticator { if whoami.data.actor.has_totp_authenticator {
eprintln!("[error] user already has a totp authenticator, cannot add another one"); eprintln!("[error] user already has a totp authenticator, cannot add another one");
std::process::exit(1); std::process::exit(1);
} }
let res = client.post(server.join("/v1/totp-authenticators")?).bearer_auth(&session_token).body("{}").send().await?; let res = client
.post(server.join("/v1/totp-authenticators")?)
.bearer_auth(&session_token)
.body("{}")
.send()
.await?;
if res.status().is_success() { if res.status().is_success() {
let resp: CreateMfaResponse = res.json().await?; let resp: CreateMfaResponse = res.json().await?;
@ -169,14 +204,23 @@ pub async fn create_mfa_authenticator(server: Url) -> Result<(), Box<dyn Error>>
println!("To complete setup, you'll need a TOTP-compatible app, such as Google Authenticator or Authy."); println!("To complete setup, you'll need a TOTP-compatible app, such as Google Authenticator or Authy.");
println!("Scan the following code with your authenticator app:"); println!("Scan the following code with your authenticator app:");
qr2term::print_qr(resp.data.url)?; qr2term::print_qr(resp.data.url)?;
println!("Alternatively, enter the following secret into your authenticator app: '{}'", resp.data.secret); println!(
"Alternatively, enter the following secret into your authenticator app: '{}'",
resp.data.secret
);
println!("Once done, enable TOTP by running the following command with the code shown on your authenticator app:"); println!("Once done, enable TOTP by running the following command with the code shown on your authenticator app:");
println!("tfcli account mfa-setup-finish --token {} --code [CODE IN AUTHENTICATOR]", resp.data.totp_token); println!(
"tfcli account mfa-setup-finish --token {} --code [CODE IN AUTHENTICATOR]",
resp.data.totp_token
);
println!("This code will expire in 10 minutes."); println!("This code will expire in 10 minutes.");
} else { } else {
let resp: APIErrorResponse = res.json().await?; let resp: APIErrorResponse = res.json().await?;
eprintln!("[error] Error adding MFA to account: {} {}", resp.errors[0].code, resp.errors[0].message); eprintln!(
"[error] Error adding MFA to account: {} {}",
resp.errors[0].code, resp.errors[0].message
);
std::process::exit(1); std::process::exit(1);
} }
@ -188,27 +232,39 @@ pub async fn create_mfa_authenticator(server: Url) -> Result<(), Box<dyn Error>>
pub struct MfaVerifyBody { pub struct MfaVerifyBody {
#[serde(rename = "totpToken")] #[serde(rename = "totpToken")]
pub totp_token: String, pub totp_token: String,
pub code: String pub code: String,
} }
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct MFASuccess { pub struct MFASuccess {
pub data: MFASuccessBody pub data: MFASuccessBody,
} }
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct MFASuccessBody { pub struct MFASuccessBody {
#[serde(rename = "authToken")] #[serde(rename = "authToken")]
pub auth_token: String pub auth_token: String,
} }
pub async fn finish_mfa_authenticator(token: String, code: String, server: Url) -> Result<(), Box<dyn Error>> { pub async fn finish_mfa_authenticator(
token: String,
code: String,
server: Url,
) -> Result<(), Box<dyn Error>> {
let client = reqwest::Client::new(); let client = reqwest::Client::new();
// load session token // load session token
let token_store = dirs::config_dir().unwrap().join("tfcli-session.token"); let token_store = dirs::config_dir().unwrap().join("tfcli-session.token");
let session_token = fs::read_to_string(&token_store)?; let session_token = fs::read_to_string(&token_store)?;
let res = client.post(server.join("/v1/verify-totp-authenticators")?).json(&MfaVerifyBody {totp_token: token, code }).bearer_auth(session_token).send().await?; let res = client
.post(server.join("/v1/verify-totp-authenticators")?)
.json(&MfaVerifyBody {
totp_token: token,
code,
})
.bearer_auth(session_token)
.send()
.await?;
if res.status().is_success() { if res.status().is_success() {
let resp: MFASuccess = res.json().await?; let resp: MFASuccess = res.json().await?;
@ -222,7 +278,10 @@ pub async fn finish_mfa_authenticator(token: String, code: String, server: Url)
} else { } else {
let resp: APIErrorResponse = res.json().await?; let resp: APIErrorResponse = res.json().await?;
eprintln!("[error] Error verifying MFA code: {} {}", resp.errors[0].code, resp.errors[0].message); eprintln!(
"[error] Error verifying MFA code: {} {}",
resp.errors[0].code, resp.errors[0].message
);
std::process::exit(1); std::process::exit(1);
} }
@ -232,7 +291,7 @@ pub async fn finish_mfa_authenticator(token: String, code: String, server: Url)
#[derive(Serialize)] #[derive(Serialize)]
pub struct MfaAuthBody { pub struct MfaAuthBody {
pub code: String pub code: String,
} }
pub async fn mfa_auth(code: String, server: Url) -> Result<(), Box<dyn Error>> { pub async fn mfa_auth(code: String, server: Url) -> Result<(), Box<dyn Error>> {
@ -242,7 +301,12 @@ pub async fn mfa_auth(code: String, server: Url) -> Result<(), Box<dyn Error>> {
let token_store = dirs::config_dir().unwrap().join("tfcli-session.token"); let token_store = dirs::config_dir().unwrap().join("tfcli-session.token");
let session_token = fs::read_to_string(&token_store)?; let session_token = fs::read_to_string(&token_store)?;
let res = client.post(server.join("/v1/auth/totp")?).json(&MfaAuthBody { code }).bearer_auth(session_token).send().await?; let res = client
.post(server.join("/v1/auth/totp")?)
.json(&MfaAuthBody { code })
.bearer_auth(session_token)
.send()
.await?;
if res.status().is_success() { if res.status().is_success() {
let resp: MFASuccess = res.json().await?; let resp: MFASuccess = res.json().await?;
@ -256,7 +320,10 @@ pub async fn mfa_auth(code: String, server: Url) -> Result<(), Box<dyn Error>> {
} else { } else {
let resp: APIErrorResponse = res.json().await?; let resp: APIErrorResponse = res.json().await?;
eprintln!("[error] Error verifying MFA code: {} {}", resp.errors[0].code, resp.errors[0].message); eprintln!(
"[error] Error verifying MFA code: {} {}",
resp.errors[0].code, resp.errors[0].message
);
std::process::exit(1); std::process::exit(1);
} }

View File

@ -2,11 +2,11 @@ use serde::Deserialize;
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct APIErrorResponse { pub struct APIErrorResponse {
pub errors: Vec<APIError> pub errors: Vec<APIError>,
} }
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct APIError { pub struct APIError {
pub code: String, pub code: String,
pub message: String, pub message: String,
pub path: Option<String> pub path: Option<String>,
} }

View File

@ -1,34 +1,71 @@
use crate::api::APIErrorResponse;
use crate::{HostCommands, HostOverrideCommands, TableStyle};
use comfy_table::modifiers::UTF8_ROUND_CORNERS;
use comfy_table::presets::UTF8_FULL;
use comfy_table::Table;
use serde::{Deserialize, Serialize};
use std::error::Error; use std::error::Error;
use std::fs; use std::fs;
use std::net::{Ipv4Addr, SocketAddrV4}; use std::net::{Ipv4Addr, SocketAddrV4};
use serde::{Deserialize, Serialize}; use url::Url;
use url::{Url};
use crate::api::APIErrorResponse;
use crate::{HostCommands, HostOverrideCommands};
pub async fn host_main(command: HostCommands, server: Url) -> Result<(), Box<dyn Error>> { pub async fn host_main(command: HostCommands, server: Url) -> Result<(), Box<dyn Error>> {
match command { match command {
HostCommands::List {} => list_hosts(server).await, HostCommands::List { table_style } => list_hosts(server, table_style).await,
HostCommands::Create { name, network_id, role_id, ip_address, listen_port, lighthouse, relay, static_address } => create_host(name, network_id, role_id, ip_address, listen_port, lighthouse, relay, static_address, server).await, HostCommands::Create {
name,
network_id,
role_id,
ip_address,
listen_port,
lighthouse,
relay,
static_address,
} => {
create_host(
name,
network_id,
role_id,
ip_address,
listen_port,
lighthouse,
relay,
static_address,
server,
)
.await
}
HostCommands::Lookup { id } => get_host(id, server).await, HostCommands::Lookup { id } => get_host(id, server).await,
HostCommands::Delete { id } => delete_host(id, server).await, HostCommands::Delete { id } => delete_host(id, server).await,
HostCommands::Update { id, listen_port, static_address, name, ip, role } => update_host(id, listen_port, static_address, name, ip, role, server).await, HostCommands::Update {
id,
listen_port,
static_address,
name,
ip,
role,
} => update_host(id, listen_port, static_address, name, ip, role, server).await,
HostCommands::Block { id } => block_host(id, server).await, HostCommands::Block { id } => block_host(id, server).await,
HostCommands::Enroll { id } => enroll_host(id, server).await, HostCommands::Enroll { id } => enroll_host(id, server).await,
HostCommands::Overrides { command } => match command { HostCommands::Overrides { command } => match command {
HostOverrideCommands::List { id } => list_overrides(id, server).await, HostOverrideCommands::List { id } => list_overrides(id, server).await,
HostOverrideCommands::Set { id, key, boolean, string, numeric } => set_override(id, key, boolean, numeric, string, server).await, HostOverrideCommands::Set {
HostOverrideCommands::Unset { id, key } => unset_override(id, key, server).await id,
} key,
boolean,
string,
numeric,
} => set_override(id, key, boolean, numeric, string, server).await,
HostOverrideCommands::Unset { id, key } => unset_override(id, key, server).await,
},
} }
} }
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct HostListResp { pub struct HostListResp {
pub data: Vec<Host> pub data: Vec<Host>,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct HostMetadata { pub struct HostMetadata {
#[serde(rename = "lastSeenAt")] #[serde(rename = "lastSeenAt")]
@ -66,7 +103,7 @@ pub struct Host {
pub metadata: HostMetadata, pub metadata: HostMetadata,
} }
pub async fn list_hosts(server: Url) -> Result<(), Box<dyn Error>> { pub async fn list_hosts(server: Url, table_style: TableStyle) -> Result<(), Box<dyn Error>> {
let client = reqwest::Client::new(); let client = reqwest::Client::new();
// load session token // load session token
@ -77,36 +114,120 @@ pub async fn list_hosts(server: Url) -> Result<(), Box<dyn Error>> {
let token = format!("{} {}", session_token, auth_token); let token = format!("{} {}", session_token, auth_token);
let res = client.get(server.join("/v1/hosts?pageSize=5000")?).bearer_auth(token).send().await?; let res = client
.get(server.join("/v1/hosts?pageSize=5000")?)
.bearer_auth(token)
.send()
.await?;
if res.status().is_success() { if res.status().is_success() {
let resp: HostListResp = res.json().await?; let resp: HostListResp = res.json().await?;
for host in &resp.data {
println!(" Host: {} ({})", host.name, host.id);
println!(" Organization: {}", host.organization_id);
println!(" Network: {}", host.network_id);
println!(" Role: {}", host.role_id);
println!(" IP Address: {}", host.ip_address);
println!(" Static Addresses: {}", host.static_addresses.iter().map(|u| u.to_string()).collect::<Vec<_>>().join(", "));
println!(" Listen Port: {}", host.listen_port);
println!(" Type: {}", if host.is_lighthouse { "Lighthouse" } else if host.is_relay { "Relay" } else { "Host" } );
println!(" Blocked: {}", host.is_blocked);
println!(" Last Seen: {}", host.metadata.last_seen_at);
println!(" Client Version: {}", host.metadata.version);
println!(" Platform: {}", host.metadata.platform);
println!("Client Update Available: {}", host.metadata.update_available);
println!(" Created: {}", host.created_at);
println!();
}
if resp.data.is_empty() { if resp.data.is_empty() {
println!("No hosts found"); println!("No hosts found");
return Ok(());
} }
if matches!(table_style, TableStyle::List) {
for host in &resp.data {
println!(" Host: {} ({})", host.name, host.id);
println!(" Organization: {}", host.organization_id);
println!(" Network: {}", host.network_id);
println!(" Role: {}", host.role_id);
println!(" IP Address: {}", host.ip_address);
println!(
" Static Addresses: {}",
host.static_addresses
.iter()
.map(|u| u.to_string())
.collect::<Vec<_>>()
.join(", ")
);
println!(" Listen Port: {}", host.listen_port);
println!(
" Type: {}",
if host.is_lighthouse {
"Lighthouse"
} else if host.is_relay {
"Relay"
} else {
"Host"
}
);
println!(" Blocked: {}", host.is_blocked);
println!(" Last Seen: {}", host.metadata.last_seen_at);
println!(" Client Version: {}", host.metadata.version);
println!(" Platform: {}", host.metadata.platform);
println!(
"Client Update Available: {}",
host.metadata.update_available
);
println!(" Created: {}", host.created_at);
println!();
}
return Ok(());
}
let mut table = Table::new();
match table_style {
TableStyle::List => unreachable!(),
TableStyle::Basic => (),
TableStyle::Pretty => {
table
.load_preset(UTF8_FULL)
.apply_modifier(UTF8_ROUND_CORNERS);
}
};
table.set_header(vec![
"ID",
"Name",
"Organization ID",
"Network ID",
"Role ID",
"IP Address",
"Static Addresses",
"Listen Port",
"Type",
"Blocked",
"Last Seen",
]);
for host in &resp.data {
table.add_row(vec![
host.id.as_str(),
&host.name,
&host.organization_id,
&host.network_id,
&host.role_id,
&host.ip_address,
&host
.static_addresses
.iter()
.map(|u| u.to_string())
.collect::<Vec<_>>()
.join(" "),
&host.listen_port.to_string(),
if host.is_lighthouse {
"Lighthouse"
} else if host.is_relay {
"Relay"
} else {
"Host"
},
if host.is_blocked { "true" } else { "false" },
&host.metadata.last_seen_at,
]);
}
println!("{table}");
} else { } else {
let resp: APIErrorResponse = res.json().await?; let resp: APIErrorResponse = res.json().await?;
eprintln!("[error] Error listing hosts: {} {}", resp.errors[0].code, resp.errors[0].message); eprintln!(
"[error] Error listing hosts: {} {}",
resp.errors[0].code, resp.errors[0].message
);
std::process::exit(1); std::process::exit(1);
} }
@ -114,7 +235,6 @@ pub async fn list_hosts(server: Url) -> Result<(), Box<dyn Error>> {
Ok(()) Ok(())
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct HostCreateBody { pub struct HostCreateBody {
pub name: String, pub name: String,
@ -134,11 +254,9 @@ pub struct HostCreateBody {
pub static_addresses: Vec<SocketAddrV4>, pub static_addresses: Vec<SocketAddrV4>,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct HostGetMetadata {} pub struct HostGetMetadata {}
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct HostGetResponse { pub struct HostGetResponse {
pub data: Host, pub data: Host,
@ -146,7 +264,17 @@ pub struct HostGetResponse {
} }
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub async fn create_host(name: String, network_id: String, role_id: String, ip_address: Ipv4Addr, listen_port: Option<u16>, lighthouse: bool, relay: bool, static_address: Option<SocketAddrV4>, server: Url) -> Result<(), Box<dyn Error>> { pub async fn create_host(
name: String,
network_id: String,
role_id: String,
ip_address: Ipv4Addr,
listen_port: Option<u16>,
lighthouse: bool,
relay: bool,
static_address: Option<SocketAddrV4>,
server: Url,
) -> Result<(), Box<dyn Error>> {
if lighthouse && relay { if lighthouse && relay {
eprintln!("[error] Error creating host: a host cannot be both a lighthouse and a relay at the same time"); eprintln!("[error] Error creating host: a host cannot be both a lighthouse and a relay at the same time");
std::process::exit(1); std::process::exit(1);
@ -172,16 +300,21 @@ pub async fn create_host(name: String, network_id: String, role_id: String, ip_a
let token = format!("{} {}", session_token, auth_token); let token = format!("{} {}", session_token, auth_token);
let res = client.post(server.join("/v1/hosts")?).json(&HostCreateBody { let res = client
name, .post(server.join("/v1/hosts")?)
network_id, .json(&HostCreateBody {
role_id, name,
ip_address, network_id,
listen_port: listen_port.unwrap_or(0), role_id,
is_lighthouse: lighthouse, ip_address,
is_relay: relay, listen_port: listen_port.unwrap_or(0),
static_addresses: static_address.map_or(vec![], |u| vec![u]), is_lighthouse: lighthouse,
}).bearer_auth(token).send().await?; is_relay: relay,
static_addresses: static_address.map_or(vec![], |u| vec![u]),
})
.bearer_auth(token)
.send()
.await?;
if res.status().is_success() { if res.status().is_success() {
let host: Host = res.json::<HostGetResponse>().await?.data; let host: Host = res.json::<HostGetResponse>().await?.data;
@ -191,21 +324,42 @@ pub async fn create_host(name: String, network_id: String, role_id: String, ip_a
println!(" Network: {}", host.network_id); println!(" Network: {}", host.network_id);
println!(" Role: {}", host.role_id); println!(" Role: {}", host.role_id);
println!(" IP Address: {}", host.ip_address); println!(" IP Address: {}", host.ip_address);
println!(" Static Addresses: {}", host.static_addresses.iter().map(|u| u.to_string()).collect::<Vec<_>>().join(", ")); println!(
" Static Addresses: {}",
host.static_addresses
.iter()
.map(|u| u.to_string())
.collect::<Vec<_>>()
.join(", ")
);
println!(" Listen Port: {}", host.listen_port); println!(" Listen Port: {}", host.listen_port);
println!(" Type: {}", if host.is_lighthouse { "Lighthouse" } else if host.is_relay { "Relay" } else { "Host" } ); println!(
" Type: {}",
if host.is_lighthouse {
"Lighthouse"
} else if host.is_relay {
"Relay"
} else {
"Host"
}
);
println!(" Blocked: {}", host.is_blocked); println!(" Blocked: {}", host.is_blocked);
println!(" Last Seen: {}", host.metadata.last_seen_at); println!(" Last Seen: {}", host.metadata.last_seen_at);
println!(" Client Version: {}", host.metadata.version); println!(" Client Version: {}", host.metadata.version);
println!(" Platform: {}", host.metadata.platform); println!(" Platform: {}", host.metadata.platform);
println!("Client Update Available: {}", host.metadata.update_available); println!(
"Client Update Available: {}",
host.metadata.update_available
);
println!(" Created: {}", host.created_at); println!(" Created: {}", host.created_at);
println!(); println!();
} else { } else {
let resp: APIErrorResponse = res.json().await?; let resp: APIErrorResponse = res.json().await?;
eprintln!("[error] Error creating host: {} {}", resp.errors[0].code, resp.errors[0].message); eprintln!(
"[error] Error creating host: {} {}",
resp.errors[0].code, resp.errors[0].message
);
std::process::exit(1); std::process::exit(1);
} }
@ -224,7 +378,11 @@ pub async fn get_host(id: String, server: Url) -> Result<(), Box<dyn Error>> {
let token = format!("{} {}", session_token, auth_token); let token = format!("{} {}", session_token, auth_token);
let res = client.get(server.join(&format!("/v1/hosts/{}", id))?).bearer_auth(token).send().await?; let res = client
.get(server.join(&format!("/v1/hosts/{}", id))?)
.bearer_auth(token)
.send()
.await?;
if res.status().is_success() { if res.status().is_success() {
let host: Host = res.json::<HostGetResponse>().await?.data; let host: Host = res.json::<HostGetResponse>().await?.data;
@ -234,21 +392,42 @@ pub async fn get_host(id: String, server: Url) -> Result<(), Box<dyn Error>> {
println!(" Network: {}", host.network_id); println!(" Network: {}", host.network_id);
println!(" Role: {}", host.role_id); println!(" Role: {}", host.role_id);
println!(" IP Address: {}", host.ip_address); println!(" IP Address: {}", host.ip_address);
println!(" Static Addresses: {}", host.static_addresses.iter().map(|u| u.to_string()).collect::<Vec<_>>().join(", ")); println!(
" Static Addresses: {}",
host.static_addresses
.iter()
.map(|u| u.to_string())
.collect::<Vec<_>>()
.join(", ")
);
println!(" Listen Port: {}", host.listen_port); println!(" Listen Port: {}", host.listen_port);
println!(" Type: {}", if host.is_lighthouse { "Lighthouse" } else if host.is_relay { "Relay" } else { "Host" } ); println!(
" Type: {}",
if host.is_lighthouse {
"Lighthouse"
} else if host.is_relay {
"Relay"
} else {
"Host"
}
);
println!(" Blocked: {}", host.is_blocked); println!(" Blocked: {}", host.is_blocked);
println!(" Last Seen: {}", host.metadata.last_seen_at); println!(" Last Seen: {}", host.metadata.last_seen_at);
println!(" Client Version: {}", host.metadata.version); println!(" Client Version: {}", host.metadata.version);
println!(" Platform: {}", host.metadata.platform); println!(" Platform: {}", host.metadata.platform);
println!("Client Update Available: {}", host.metadata.update_available); println!(
"Client Update Available: {}",
host.metadata.update_available
);
println!(" Created: {}", host.created_at); println!(" Created: {}", host.created_at);
println!(); println!();
} else { } else {
let resp: APIErrorResponse = res.json().await?; let resp: APIErrorResponse = res.json().await?;
eprintln!("[error] Error listing hosts: {} {}", resp.errors[0].code, resp.errors[0].message); eprintln!(
"[error] Error listing hosts: {} {}",
resp.errors[0].code, resp.errors[0].message
);
std::process::exit(1); std::process::exit(1);
} }
@ -267,14 +446,21 @@ pub async fn delete_host(id: String, server: Url) -> Result<(), Box<dyn Error>>
let token = format!("{} {}", session_token, auth_token); let token = format!("{} {}", session_token, auth_token);
let res = client.delete(server.join(&format!("/v1/hosts/{}", id))?).bearer_auth(token).send().await?; let res = client
.delete(server.join(&format!("/v1/hosts/{}", id))?)
.bearer_auth(token)
.send()
.await?;
if res.status().is_success() { if res.status().is_success() {
println!("Host removed"); println!("Host removed");
} else { } else {
let resp: APIErrorResponse = res.json().await?; let resp: APIErrorResponse = res.json().await?;
eprintln!("[error] Error removing host: {} {}", resp.errors[0].code, resp.errors[0].message); eprintln!(
"[error] Error removing host: {} {}",
resp.errors[0].code, resp.errors[0].message
);
std::process::exit(1); std::process::exit(1);
} }
@ -290,10 +476,18 @@ pub struct HostUpdateBody {
pub static_addresses: Vec<SocketAddrV4>, pub static_addresses: Vec<SocketAddrV4>,
pub name: Option<String>, pub name: Option<String>,
pub ip: Option<Ipv4Addr>, pub ip: Option<Ipv4Addr>,
pub role: Option<String> pub role: Option<String>,
} }
pub async fn update_host(id: String, listen_port: Option<u16>, static_address: Option<SocketAddrV4>, name: Option<String>, ip: Option<Ipv4Addr>, role: Option<String>, server: Url) -> Result<(), Box<dyn Error>> { pub async fn update_host(
id: String,
listen_port: Option<u16>,
static_address: Option<SocketAddrV4>,
name: Option<String>,
ip: Option<Ipv4Addr>,
role: Option<String>,
server: Url,
) -> Result<(), Box<dyn Error>> {
let client = reqwest::Client::new(); let client = reqwest::Client::new();
// load session token // load session token
@ -304,13 +498,18 @@ pub async fn update_host(id: String, listen_port: Option<u16>, static_address: O
let token = format!("{} {}", session_token, auth_token); let token = format!("{} {}", session_token, auth_token);
let res = client.put(server.join(&format!("/v1/hosts/{}?extension=extended_hosts", id))?).json(&HostUpdateBody { let res = client
listen_port: listen_port.unwrap_or(0), .put(server.join(&format!("/v1/hosts/{}?extension=extended_hosts", id))?)
static_addresses: static_address.map_or_else(Vec::new, |u| vec![u]), .json(&HostUpdateBody {
name, listen_port: listen_port.unwrap_or(0),
ip, static_addresses: static_address.map_or_else(Vec::new, |u| vec![u]),
role name,
}).bearer_auth(token).send().await?; ip,
role,
})
.bearer_auth(token)
.send()
.await?;
if res.status().is_success() { if res.status().is_success() {
let host: Host = res.json::<HostGetResponse>().await?.data; let host: Host = res.json::<HostGetResponse>().await?.data;
@ -320,21 +519,42 @@ pub async fn update_host(id: String, listen_port: Option<u16>, static_address: O
println!(" Network: {}", host.network_id); println!(" Network: {}", host.network_id);
println!(" Role: {}", host.role_id); println!(" Role: {}", host.role_id);
println!(" IP Address: {}", host.ip_address); println!(" IP Address: {}", host.ip_address);
println!(" Static Addresses: {}", host.static_addresses.iter().map(|u| u.to_string()).collect::<Vec<_>>().join(", ")); println!(
" Static Addresses: {}",
host.static_addresses
.iter()
.map(|u| u.to_string())
.collect::<Vec<_>>()
.join(", ")
);
println!(" Listen Port: {}", host.listen_port); println!(" Listen Port: {}", host.listen_port);
println!(" Type: {}", if host.is_lighthouse { "Lighthouse" } else if host.is_relay { "Relay" } else { "Host" } ); println!(
" Type: {}",
if host.is_lighthouse {
"Lighthouse"
} else if host.is_relay {
"Relay"
} else {
"Host"
}
);
println!(" Blocked: {}", host.is_blocked); println!(" Blocked: {}", host.is_blocked);
println!(" Last Seen: {}", host.metadata.last_seen_at); println!(" Last Seen: {}", host.metadata.last_seen_at);
println!(" Client Version: {}", host.metadata.version); println!(" Client Version: {}", host.metadata.version);
println!(" Platform: {}", host.metadata.platform); println!(" Platform: {}", host.metadata.platform);
println!("Client Update Available: {}", host.metadata.update_available); println!(
"Client Update Available: {}",
host.metadata.update_available
);
println!(" Created: {}", host.created_at); println!(" Created: {}", host.created_at);
println!(); println!();
} else { } else {
let resp: APIErrorResponse = res.json().await?; let resp: APIErrorResponse = res.json().await?;
eprintln!("[error] Error updating host: {} {}", resp.errors[0].code, resp.errors[0].message); eprintln!(
"[error] Error updating host: {} {}",
resp.errors[0].code, resp.errors[0].message
);
std::process::exit(1); std::process::exit(1);
} }
@ -342,7 +562,6 @@ pub async fn update_host(id: String, listen_port: Option<u16>, static_address: O
Ok(()) Ok(())
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct EnrollmentCodeResponseMetadata {} pub struct EnrollmentCodeResponseMetadata {}
@ -376,18 +595,29 @@ pub async fn enroll_host(id: String, server: Url) -> Result<(), Box<dyn Error>>
let token = format!("{} {}", session_token, auth_token); let token = format!("{} {}", session_token, auth_token);
let res = client.post(server.join(&format!("/v1/hosts/{}/enrollment-code", id))?).header("content-length", 0).bearer_auth(token).send().await?; let res = client
.post(server.join(&format!("/v1/hosts/{}/enrollment-code", id))?)
.header("content-length", 0)
.bearer_auth(token)
.send()
.await?;
if res.status().is_success() { if res.status().is_success() {
let resp: EnrollmentResponse = res.json().await?; let resp: EnrollmentResponse = res.json().await?;
println!("Enrollment code generated. Enroll the host with the following code: {}", resp.data.enrollment_code.code); println!(
"Enrollment code generated. Enroll the host with the following code: {}",
resp.data.enrollment_code.code
);
println!("This code will be valid for {} seconds, at which point you will need to generate a new code", resp.data.enrollment_code.lifetime_seconds); println!("This code will be valid for {} seconds, at which point you will need to generate a new code", resp.data.enrollment_code.lifetime_seconds);
println!("If this host is blocked, a successful re-enrollment will unblock it."); println!("If this host is blocked, a successful re-enrollment will unblock it.");
} else { } else {
let resp: APIErrorResponse = res.json().await?; let resp: APIErrorResponse = res.json().await?;
eprintln!("[error] Error blocking host: {} {}", resp.errors[0].code, resp.errors[0].message); eprintln!(
"[error] Error blocking host: {} {}",
resp.errors[0].code, resp.errors[0].message
);
std::process::exit(1); std::process::exit(1);
} }
@ -406,14 +636,22 @@ pub async fn block_host(id: String, server: Url) -> Result<(), Box<dyn Error>> {
let token = format!("{} {}", session_token, auth_token); let token = format!("{} {}", session_token, auth_token);
let res = client.post(server.join(&format!("/v1/hosts/{}/block", id))?).header("Content-Length", "0").bearer_auth(token).send().await?; let res = client
.post(server.join(&format!("/v1/hosts/{}/block", id))?)
.header("Content-Length", "0")
.bearer_auth(token)
.send()
.await?;
if res.status().is_success() { if res.status().is_success() {
println!("Host blocked. To unblock it, re-enroll the host."); println!("Host blocked. To unblock it, re-enroll the host.");
} else { } else {
let resp: APIErrorResponse = res.json().await?; let resp: APIErrorResponse = res.json().await?;
eprintln!("[error] Error blocking host: {} {}", resp.errors[0].code, resp.errors[0].message); eprintln!(
"[error] Error blocking host: {} {}",
resp.errors[0].code, resp.errors[0].message
);
std::process::exit(1); std::process::exit(1);
} }
@ -423,18 +661,18 @@ pub async fn block_host(id: String, server: Url) -> Result<(), Box<dyn Error>> {
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct HostConfigOverrideResponse { pub struct HostConfigOverrideResponse {
pub data: HostConfigOverrideData pub data: HostConfigOverrideData,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct HostConfigOverrideData { pub struct HostConfigOverrideData {
pub overrides: Vec<HostConfigOverrideDataOverride> pub overrides: Vec<HostConfigOverrideDataOverride>,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct HostConfigOverrideDataOverride { pub struct HostConfigOverrideDataOverride {
pub key: String, pub key: String,
pub value: HostConfigOverrideDataOverrideValue pub value: HostConfigOverrideDataOverrideValue,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
@ -442,7 +680,7 @@ pub struct HostConfigOverrideDataOverride {
pub enum HostConfigOverrideDataOverrideValue { pub enum HostConfigOverrideDataOverrideValue {
Boolean(bool), Boolean(bool),
Numeric(i64), Numeric(i64),
Other(String) Other(String),
} }
pub async fn list_overrides(id: String, server: Url) -> Result<(), Box<dyn Error>> { pub async fn list_overrides(id: String, server: Url) -> Result<(), Box<dyn Error>> {
@ -456,18 +694,25 @@ pub async fn list_overrides(id: String, server: Url) -> Result<(), Box<dyn Error
let token = format!("{} {}", session_token, auth_token); let token = format!("{} {}", session_token, auth_token);
let res = client.get(server.join(&format!("/v1/hosts/{}/config-overrides", id))?).bearer_auth(token).send().await?; let res = client
.get(server.join(&format!("/v1/hosts/{}/config-overrides", id))?)
.bearer_auth(token)
.send()
.await?;
if res.status().is_success() { if res.status().is_success() {
let resp: HostConfigOverrideResponse = res.json().await?; let resp: HostConfigOverrideResponse = res.json().await?;
for c_override in &resp.data.overrides { for c_override in &resp.data.overrides {
println!(" Key: {}", c_override.key); println!(" Key: {}", c_override.key);
println!("Value: {}", match &c_override.value { println!(
HostConfigOverrideDataOverrideValue::Boolean(v) => format!("bool:{}", v), "Value: {}",
HostConfigOverrideDataOverrideValue::Numeric(v) => format!("numeric:{}", v), match &c_override.value {
HostConfigOverrideDataOverrideValue::Other(v) => format!("string:{}", v) HostConfigOverrideDataOverrideValue::Boolean(v) => format!("bool:{}", v),
}); HostConfigOverrideDataOverrideValue::Numeric(v) => format!("numeric:{}", v),
HostConfigOverrideDataOverrideValue::Other(v) => format!("string:{}", v),
}
);
} }
if resp.data.overrides.is_empty() { if resp.data.overrides.is_empty() {
@ -476,7 +721,10 @@ pub async fn list_overrides(id: String, server: Url) -> Result<(), Box<dyn Error
} else { } else {
let resp: APIErrorResponse = res.json().await?; let resp: APIErrorResponse = res.json().await?;
eprintln!("[error] Error looking up config overrides: {} {}", resp.errors[0].code, resp.errors[0].message); eprintln!(
"[error] Error looking up config overrides: {} {}",
resp.errors[0].code, resp.errors[0].message
);
std::process::exit(1); std::process::exit(1);
} }
@ -486,14 +734,24 @@ pub async fn list_overrides(id: String, server: Url) -> Result<(), Box<dyn Error
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct SetOverrideRequest { pub struct SetOverrideRequest {
pub overrides: Vec<HostConfigOverrideDataOverride> pub overrides: Vec<HostConfigOverrideDataOverride>,
} }
pub async fn set_override(id: String, key: String, boolean: Option<bool>, numeric: Option<i64>, other: Option<String>, server: Url) -> Result<(), Box<dyn Error>> { pub async fn set_override(
id: String,
key: String,
boolean: Option<bool>,
numeric: Option<i64>,
other: Option<String>,
server: Url,
) -> Result<(), Box<dyn Error>> {
if boolean.is_none() && numeric.is_none() && other.is_none() { if boolean.is_none() && numeric.is_none() && other.is_none() {
eprintln!("[error] no value provided: you must provide at least --boolean, --numeric, or --string"); eprintln!("[error] no value provided: you must provide at least --boolean, --numeric, or --string");
std::process::exit(1); std::process::exit(1);
} else if boolean.is_some() && numeric.is_some() || boolean.is_some() && other.is_some() || numeric.is_some() && other.is_some() { } else if boolean.is_some() && numeric.is_some()
|| boolean.is_some() && other.is_some()
|| numeric.is_some() && other.is_some()
{
eprintln!("[error] multiple values provided: you must provide only one of --boolean, --numeric, or --string"); eprintln!("[error] multiple values provided: you must provide only one of --boolean, --numeric, or --string");
std::process::exit(1); std::process::exit(1);
} }
@ -520,7 +778,11 @@ pub async fn set_override(id: String, key: String, boolean: Option<bool>, numeri
let token = format!("{} {}", session_token, auth_token); let token = format!("{} {}", session_token, auth_token);
let res = client.get(server.join(&format!("/v1/hosts/{}/config-overrides", id))?).bearer_auth(token.clone()).send().await?; let res = client
.get(server.join(&format!("/v1/hosts/{}/config-overrides", id))?)
.bearer_auth(token.clone())
.send()
.await?;
if res.status().is_success() { if res.status().is_success() {
let resp: HostConfigOverrideResponse = res.json().await?; let resp: HostConfigOverrideResponse = res.json().await?;
@ -533,25 +795,28 @@ pub async fn set_override(id: String, key: String, boolean: Option<bool>, numeri
} }
} }
others.push(HostConfigOverrideDataOverride { others.push(HostConfigOverrideDataOverride { key, value: val });
key,
value: val,
});
let res = client.put(server.join(&format!("/v1/hosts/{}/config-overrides", id))?).bearer_auth(token.clone()).json(&SetOverrideRequest { let res = client
overrides: others, .put(server.join(&format!("/v1/hosts/{}/config-overrides", id))?)
}).send().await?; .bearer_auth(token.clone())
.json(&SetOverrideRequest { overrides: others })
.send()
.await?;
if res.status().is_success() { if res.status().is_success() {
let resp: HostConfigOverrideResponse = res.json().await?; let resp: HostConfigOverrideResponse = res.json().await?;
for c_override in &resp.data.overrides { for c_override in &resp.data.overrides {
println!(" Key: {}", c_override.key); println!(" Key: {}", c_override.key);
println!("Value: {}", match &c_override.value { println!(
HostConfigOverrideDataOverrideValue::Boolean(v) => format!("bool:{}", v), "Value: {}",
HostConfigOverrideDataOverrideValue::Numeric(v) => format!("numeric:{}", v), match &c_override.value {
HostConfigOverrideDataOverrideValue::Other(v) => format!("string:{}", v) HostConfigOverrideDataOverrideValue::Boolean(v) => format!("bool:{}", v),
}); HostConfigOverrideDataOverrideValue::Numeric(v) => format!("numeric:{}", v),
HostConfigOverrideDataOverrideValue::Other(v) => format!("string:{}", v),
}
);
} }
if resp.data.overrides.is_empty() { if resp.data.overrides.is_empty() {
@ -562,14 +827,20 @@ pub async fn set_override(id: String, key: String, boolean: Option<bool>, numeri
} else { } else {
let resp: APIErrorResponse = res.json().await?; let resp: APIErrorResponse = res.json().await?;
eprintln!("[error] Error setting config overrides: {} {}", resp.errors[0].code, resp.errors[0].message); eprintln!(
"[error] Error setting config overrides: {} {}",
resp.errors[0].code, resp.errors[0].message
);
std::process::exit(1); std::process::exit(1);
} }
} else { } else {
let resp: APIErrorResponse = res.json().await?; let resp: APIErrorResponse = res.json().await?;
eprintln!("[error] Error setting config overrides: {} {}", resp.errors[0].code, resp.errors[0].message); eprintln!(
"[error] Error setting config overrides: {} {}",
resp.errors[0].code, resp.errors[0].message
);
std::process::exit(1); std::process::exit(1);
} }
@ -588,7 +859,11 @@ pub async fn unset_override(id: String, key: String, server: Url) -> Result<(),
let token = format!("{} {}", session_token, auth_token); let token = format!("{} {}", session_token, auth_token);
let res = client.get(server.join(&format!("/v1/hosts/{}/config-overrides", id))?).bearer_auth(token.clone()).send().await?; let res = client
.get(server.join(&format!("/v1/hosts/{}/config-overrides", id))?)
.bearer_auth(token.clone())
.send()
.await?;
if res.status().is_success() { if res.status().is_success() {
let resp: HostConfigOverrideResponse = res.json().await?; let resp: HostConfigOverrideResponse = res.json().await?;
@ -601,20 +876,26 @@ pub async fn unset_override(id: String, key: String, server: Url) -> Result<(),
} }
} }
let res = client.put(server.join(&format!("/v1/hosts/{}/config-overrides", id))?).bearer_auth(token.clone()).json(&SetOverrideRequest { let res = client
overrides: others, .put(server.join(&format!("/v1/hosts/{}/config-overrides", id))?)
}).send().await?; .bearer_auth(token.clone())
.json(&SetOverrideRequest { overrides: others })
.send()
.await?;
if res.status().is_success() { if res.status().is_success() {
let resp: HostConfigOverrideResponse = res.json().await?; let resp: HostConfigOverrideResponse = res.json().await?;
for c_override in &resp.data.overrides { for c_override in &resp.data.overrides {
println!(" Key: {}", c_override.key); println!(" Key: {}", c_override.key);
println!("Value: {}", match &c_override.value { println!(
HostConfigOverrideDataOverrideValue::Boolean(v) => format!("bool:{}", v), "Value: {}",
HostConfigOverrideDataOverrideValue::Numeric(v) => format!("numeric:{}", v), match &c_override.value {
HostConfigOverrideDataOverrideValue::Other(v) => format!("string:{}", v) HostConfigOverrideDataOverrideValue::Boolean(v) => format!("bool:{}", v),
}); HostConfigOverrideDataOverrideValue::Numeric(v) => format!("numeric:{}", v),
HostConfigOverrideDataOverrideValue::Other(v) => format!("string:{}", v),
}
);
} }
if resp.data.overrides.is_empty() { if resp.data.overrides.is_empty() {
@ -625,14 +906,20 @@ pub async fn unset_override(id: String, key: String, server: Url) -> Result<(),
} else { } else {
let resp: APIErrorResponse = res.json().await?; let resp: APIErrorResponse = res.json().await?;
eprintln!("[error] Error unsetting config overrides: {} {}", resp.errors[0].code, resp.errors[0].message); eprintln!(
"[error] Error unsetting config overrides: {} {}",
resp.errors[0].code, resp.errors[0].message
);
std::process::exit(1); std::process::exit(1);
} }
} else { } else {
let resp: APIErrorResponse = res.json().await?; let resp: APIErrorResponse = res.json().await?;
eprintln!("[error] Error unsetting config overrides: {} {}", resp.errors[0].code, resp.errors[0].message); eprintln!(
"[error] Error unsetting config overrides: {} {}",
resp.errors[0].code, resp.errors[0].message
);
std::process::exit(1); std::process::exit(1);
} }

View File

@ -1,21 +1,22 @@
use std::error::Error;
use std::fs;
use std::net::{Ipv4Addr, SocketAddrV4};
use clap::{Parser, Subcommand};
use ipnet::Ipv4Net;
use url::Url;
use crate::account::account_main; use crate::account::account_main;
use crate::host::host_main; use crate::host::host_main;
use crate::network::network_main; use crate::network::network_main;
use crate::org::org_main; use crate::org::org_main;
use crate::role::role_main; use crate::role::role_main;
use clap::{Parser, Subcommand, ValueEnum};
use ipnet::Ipv4Net;
use std::error::Error;
use std::fmt::{Display, Formatter};
use std::fs;
use std::net::{Ipv4Addr, SocketAddrV4};
use url::Url;
pub mod account; pub mod account;
pub mod api; pub mod api;
pub mod host;
pub mod network; pub mod network;
pub mod org; pub mod org;
pub mod role; pub mod role;
pub mod host;
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)] #[command(author, version, about, long_about = None)]
@ -24,8 +25,8 @@ pub struct Args {
#[command(subcommand)] #[command(subcommand)]
command: Commands, command: Commands,
#[clap(short, long, env = "TFCLI_SERVER")] #[clap(short, long, env = "TFCLI_SERVER")]
/// The base URL of your trifid-api instance. Defaults to the value in $XDG_CONFIG_HOME/tfcli-server-url.conf or the TFCLI_SERVER environment variable. /// The base URL of your trifid-api-old instance. Defaults to the value in $XDG_CONFIG_HOME/tfcli-server-url.conf or the TFCLI_SERVER environment variable.
server: Option<Url> server: Option<Url>,
} }
#[derive(Subcommand, Debug)] #[derive(Subcommand, Debug)]
@ -33,28 +34,28 @@ pub enum Commands {
/// Manage your trifid account /// Manage your trifid account
Account { Account {
#[command(subcommand)] #[command(subcommand)]
command: AccountCommands command: AccountCommands,
}, },
/// Manage the networks associated with your trifid account /// Manage the networks associated with your trifid account
Network { Network {
#[command(subcommand)] #[command(subcommand)]
command: NetworkCommands command: NetworkCommands,
}, },
/// Manage the organization associated with your trifid account /// Manage the organization associated with your trifid account
Org { Org {
#[command(subcommand)] #[command(subcommand)]
command: OrgCommands command: OrgCommands,
}, },
/// Manage the roles associated with your trifid organization /// Manage the roles associated with your trifid organization
Role { Role {
#[command(subcommand)] #[command(subcommand)]
command: RoleCommands command: RoleCommands,
}, },
/// Manage the hosts associated with your trifid network /// Manage the hosts associated with your trifid network
Host { Host {
#[command(subcommand)] #[command(subcommand)]
command: HostCommands command: HostCommands,
} },
} }
#[derive(Subcommand, Debug)] #[derive(Subcommand, Debug)]
@ -62,17 +63,17 @@ pub enum AccountCommands {
/// Create a new trifid account on the designated server /// Create a new trifid account on the designated server
Create { Create {
#[clap(short, long)] #[clap(short, long)]
email: String email: String,
}, },
/// Log into an existing account on the designated server /// Log into an existing account on the designated server
Login { Login {
#[clap(short, long)] #[clap(short, long)]
email: String email: String,
}, },
/// Log in to your account with a magic-link token acquired via email or the trifid-api logs. /// Log in to your account with a magic-link token acquired via email or the trifid-api-old logs.
MagicLink { MagicLink {
#[clap(short, long)] #[clap(short, long)]
magic_link_token: String magic_link_token: String,
}, },
/// Create a new TOTP authenticator on this account to enable authorizing with 2fa and performing all management tasks. /// Create a new TOTP authenticator on this account to enable authorizing with 2fa and performing all management tasks.
MfaSetup {}, MfaSetup {},
@ -81,33 +82,36 @@ pub enum AccountCommands {
#[clap(short, long)] #[clap(short, long)]
code: String, code: String,
#[clap(short, long)] #[clap(short, long)]
token: String token: String,
}, },
/// Create a new short-lived authentication token by inputting the code shown on your authenticator app. /// Create a new short-lived authentication token by inputting the code shown on your authenticator app.
Mfa { Mfa {
#[clap(short, long)] #[clap(short, long)]
code: String code: String,
} },
} }
#[derive(Subcommand, Debug)] #[derive(Subcommand, Debug)]
pub enum NetworkCommands { pub enum NetworkCommands {
/// List all networks associated with your trifid account. /// List all networks associated with your trifid account.
List {}, List {
#[clap(short = 'T', long, default_value_t = TableStyle::Basic)]
table_style: TableStyle,
},
/// Lookup a specific network by ID. /// Lookup a specific network by ID.
Lookup { Lookup {
#[clap(short, long)] #[clap(short, long)]
id: String id: String,
} },
} }
#[derive(Subcommand, Debug)] #[derive(Subcommand, Debug)]
pub enum OrgCommands { pub enum OrgCommands {
/// Create an organization on your trifid-api server. NOTE: This command ONLY works on trifid-api servers. It will NOT work on original DN servers. /// Create an organization on your trifid-api-old server. NOTE: This command ONLY works on trifid-api-old servers. It will NOT work on original DN servers.
Create { Create {
#[clap(short, long)] #[clap(short, long)]
cidr: Ipv4Net cidr: Ipv4Net,
} },
} }
#[derive(Subcommand, Debug)] #[derive(Subcommand, Debug)]
@ -120,19 +124,22 @@ pub enum RoleCommands {
description: String, description: String,
/// A JSON string containing the firewall rules to add to this host /// A JSON string containing the firewall rules to add to this host
#[clap(short, long)] #[clap(short, long)]
rules_json: String rules_json: String,
}, },
/// List all roles attached to your organization /// List all roles attached to your organization
List {}, List {
#[clap(short = 'T', long, default_value_t = TableStyle::Basic)]
table_style: TableStyle,
},
/// Lookup a specific role by it's ID /// Lookup a specific role by it's ID
Lookup { Lookup {
#[clap(short, long)] #[clap(short, long)]
id: String id: String,
}, },
/// Delete a specific role by it's ID /// Delete a specific role by it's ID
Delete { Delete {
#[clap(short, long)] #[clap(short, long)]
id: String id: String,
}, },
/// Update a specific role by it's ID. Warning: any data not provided in this update will be removed - include all data you wish to remain /// Update a specific role by it's ID. Warning: any data not provided in this update will be removed - include all data you wish to remain
Update { Update {
@ -142,8 +149,8 @@ pub enum RoleCommands {
description: String, description: String,
/// A JSON string containing the firewall rules to add to this host /// A JSON string containing the firewall rules to add to this host
#[clap(short, long)] #[clap(short, long)]
rules_json: String rules_json: String,
} },
} }
#[derive(Subcommand, Debug)] #[derive(Subcommand, Debug)]
@ -165,21 +172,24 @@ pub enum HostCommands {
#[clap(short = 'R', long)] #[clap(short = 'R', long)]
relay: bool, relay: bool,
#[clap(short, long)] #[clap(short, long)]
static_address: Option<SocketAddrV4> static_address: Option<SocketAddrV4>,
}, },
/// List all hosts on your network /// List all hosts on your network
List {}, List {
#[clap(short = 'T', long, default_value_t = TableStyle::Basic)]
table_style: TableStyle,
},
/// Lookup a specific host by it's ID /// Lookup a specific host by it's ID
Lookup { Lookup {
#[clap(short, long)] #[clap(short, long)]
id: String id: String,
}, },
/// Delete a specific host by it's ID /// Delete a specific host by it's ID
Delete { Delete {
#[clap(short, long)] #[clap(short, long)]
id: String id: String,
}, },
/// Update a specific host by it's ID, changing the listen port and static addresses, as well as the name, ip and role. The name, ip and role updates will only work on trifid-api compatible servers. /// Update a specific host by it's ID, changing the listen port and static addresses, as well as the name, ip and role. The name, ip and role updates will only work on trifid-api-old compatible servers.
Update { Update {
#[clap(short, long)] #[clap(short, long)]
id: String, id: String,
@ -192,23 +202,23 @@ pub enum HostCommands {
#[clap(short, long)] #[clap(short, long)]
role: Option<String>, role: Option<String>,
#[clap(short = 'I', long)] #[clap(short = 'I', long)]
ip: Option<Ipv4Addr> ip: Option<Ipv4Addr>,
}, },
/// Blocks the specified host from the network /// Blocks the specified host from the network
Block { Block {
#[clap(short, long)] #[clap(short, long)]
id: String id: String,
}, },
/// Enroll or re-enroll the host by generating an enrollment code /// Enroll or re-enroll the host by generating an enrollment code
Enroll { Enroll {
#[clap(short, long)] #[clap(short, long)]
id: String id: String,
}, },
/// Manage config overrides set on the host /// Manage config overrides set on the host
Overrides { Overrides {
#[command(subcommand)] #[command(subcommand)]
command: HostOverrideCommands command: HostOverrideCommands,
} },
} }
#[derive(Subcommand, Debug)] #[derive(Subcommand, Debug)]
@ -216,7 +226,7 @@ pub enum HostOverrideCommands {
/// List the config overrides set on the host /// List the config overrides set on the host
List { List {
#[clap(short, long)] #[clap(short, long)]
id: String id: String,
}, },
/// Set a config override on the host /// Set a config override on the host
Set { Set {
@ -229,14 +239,35 @@ pub enum HostOverrideCommands {
#[clap(short, long)] #[clap(short, long)]
numeric: Option<i64>, numeric: Option<i64>,
#[clap(short, long)] #[clap(short, long)]
string: Option<String> string: Option<String>,
}, },
/// Unset a config override on the host /// Unset a config override on the host
Unset { Unset {
#[clap(short, long)] #[clap(short, long)]
id: String, id: String,
#[clap(short, long)] #[clap(short, long)]
key: String key: String,
},
}
#[derive(Debug, Clone, ValueEnum)]
pub enum TableStyle {
List,
Basic,
Pretty,
}
impl Default for TableStyle {
fn default() -> Self {
Self::Basic
}
}
impl Display for TableStyle {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::List => write!(f, "list"),
Self::Basic => write!(f, "basic"),
Self::Pretty => write!(f, "pretty"),
}
} }
} }
@ -270,7 +301,10 @@ async fn main2() -> Result<(), Box<dyn Error>> {
let url = match Url::parse(&url_s) { let url = match Url::parse(&url_s) {
Ok(u) => u, Ok(u) => u,
Err(e) => { Err(e) => {
eprintln!("[error] unable to parse the URL in {}", srv_url_file.display()); eprintln!(
"[error] unable to parse the URL in {}",
srv_url_file.display()
);
eprintln!("[error] urlparse returned error '{}'", e); eprintln!("[error] urlparse returned error '{}'", e);
eprintln!("[error] please correct the error and try again"); eprintln!("[error] please correct the error and try again");
std::process::exit(1); std::process::exit(1);
@ -284,6 +318,6 @@ async fn main2() -> Result<(), Box<dyn Error>> {
Commands::Network { command } => network_main(command, server).await, Commands::Network { command } => network_main(command, server).await,
Commands::Org { command } => org_main(command, server).await, Commands::Org { command } => org_main(command, server).await,
Commands::Role { command } => role_main(command, server).await, Commands::Role { command } => role_main(command, server).await,
Commands::Host { command } => host_main(command, server).await Commands::Host { command } => host_main(command, server).await,
} }
} }

View File

@ -1,20 +1,23 @@
use crate::api::APIErrorResponse;
use crate::{NetworkCommands, TableStyle};
use comfy_table::modifiers::UTF8_ROUND_CORNERS;
use comfy_table::presets::UTF8_FULL;
use comfy_table::Table;
use serde::Deserialize;
use std::error::Error; use std::error::Error;
use std::fs; use std::fs;
use serde::Deserialize;
use url::Url; use url::Url;
use crate::api::APIErrorResponse;
use crate::NetworkCommands;
pub async fn network_main(command: NetworkCommands, server: Url) -> Result<(), Box<dyn Error>> { pub async fn network_main(command: NetworkCommands, server: Url) -> Result<(), Box<dyn Error>> {
match command { match command {
NetworkCommands::List {} => list_networks(server).await, NetworkCommands::List { table_style } => list_networks(server, table_style).await,
NetworkCommands::Lookup {id} => get_network(id, server).await NetworkCommands::Lookup { id } => get_network(id, server).await,
} }
} }
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct NetworkListResp { pub struct NetworkListResp {
pub data: Vec<Network> pub data: Vec<Network>,
} }
#[derive(Deserialize)] #[derive(Deserialize)]
@ -29,10 +32,10 @@ pub struct Network {
pub created_at: String, pub created_at: String,
#[serde(rename = "lighthousesAsRelays")] #[serde(rename = "lighthousesAsRelays")]
pub lighthouses_as_relays: bool, pub lighthouses_as_relays: bool,
pub name: String pub name: String,
} }
pub async fn list_networks(server: Url) -> Result<(), Box<dyn Error>> { pub async fn list_networks(server: Url, table_style: TableStyle) -> Result<(), Box<dyn Error>> {
let client = reqwest::Client::new(); let client = reqwest::Client::new();
// load session token // load session token
@ -43,29 +46,75 @@ pub async fn list_networks(server: Url) -> Result<(), Box<dyn Error>> {
let token = format!("{} {}", session_token, auth_token); let token = format!("{} {}", session_token, auth_token);
let res = client.get(server.join("/v1/networks")?).bearer_auth(token).send().await?; let res = client
.get(server.join("/v1/networks")?)
.bearer_auth(token)
.send()
.await?;
if res.status().is_success() { if res.status().is_success() {
let resp: NetworkListResp = res.json().await?; let resp: NetworkListResp = res.json().await?;
for network in &resp.data {
println!(" Network: {}", network.id);
println!(" CIDR: {}", network.cidr);
println!(" Organization: {}", network.organization_id);
println!(" Signing CA: {}", network.signing_ca_id);
println!("Dedicated Relays: {}", !network.lighthouses_as_relays);
println!(" Name: {}", network.name);
println!(" Created At: {}", network.created_at);
println!();
}
if resp.data.is_empty() { if resp.data.is_empty() {
println!("No networks found"); println!("No networks found");
return Ok(());
} }
if matches!(table_style, TableStyle::List) {
for network in &resp.data {
println!(" Network: {}", network.id);
println!(" CIDR: {}", network.cidr);
println!(" Organization: {}", network.organization_id);
println!(" Signing CA: {}", network.signing_ca_id);
println!("Dedicated Relays: {}", !network.lighthouses_as_relays);
println!(" Name: {}", network.name);
println!(" Created At: {}", network.created_at);
println!();
}
return Ok(());
}
let mut table = Table::new();
match table_style {
TableStyle::List => unreachable!(),
TableStyle::Basic => (),
TableStyle::Pretty => {
table
.load_preset(UTF8_FULL)
.apply_modifier(UTF8_ROUND_CORNERS);
}
};
table.set_header(vec![
"ID",
"Name",
"CIDR",
"Organization ID",
"Signing CA ID",
"Dedicated Relays",
"Created At",
]);
for network in &resp.data {
table.add_row(vec![
&network.id,
&network.name,
&network.cidr,
&network.organization_id,
&network.signing_ca_id,
(!network.lighthouses_as_relays).to_string().as_str(),
&network.created_at,
]);
}
println!("{table}");
} else { } else {
let resp: APIErrorResponse = res.json().await?; let resp: APIErrorResponse = res.json().await?;
eprintln!("[error] Error listing networks: {} {}", resp.errors[0].code, resp.errors[0].message); eprintln!(
"[error] Error listing networks: {} {}",
resp.errors[0].code, resp.errors[0].message
);
std::process::exit(1); std::process::exit(1);
} }
@ -75,7 +124,7 @@ pub async fn list_networks(server: Url) -> Result<(), Box<dyn Error>> {
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct NetworkGetResponse { pub struct NetworkGetResponse {
pub data: Network pub data: Network,
} }
pub async fn get_network(id: String, server: Url) -> Result<(), Box<dyn Error>> { pub async fn get_network(id: String, server: Url) -> Result<(), Box<dyn Error>> {
@ -89,7 +138,11 @@ pub async fn get_network(id: String, server: Url) -> Result<(), Box<dyn Error>>
let token = format!("{} {}", session_token, auth_token); let token = format!("{} {}", session_token, auth_token);
let res = client.get(server.join(&format!("/v1/networks/{}", id))?).bearer_auth(token).send().await?; let res = client
.get(server.join(&format!("/v1/networks/{}", id))?)
.bearer_auth(token)
.send()
.await?;
if res.status().is_success() { if res.status().is_success() {
let network: Network = res.json::<NetworkGetResponse>().await?.data; let network: Network = res.json::<NetworkGetResponse>().await?.data;
@ -101,11 +154,13 @@ pub async fn get_network(id: String, server: Url) -> Result<(), Box<dyn Error>>
println!("Dedicated Relays: {}", !network.lighthouses_as_relays); println!("Dedicated Relays: {}", !network.lighthouses_as_relays);
println!(" Name: {}", network.name); println!(" Name: {}", network.name);
println!(" Created At: {}", network.created_at); println!(" Created At: {}", network.created_at);
} else { } else {
let resp: APIErrorResponse = res.json().await?; let resp: APIErrorResponse = res.json().await?;
eprintln!("[error] Error listing networks: {} {}", resp.errors[0].code, resp.errors[0].message); eprintln!(
"[error] Error listing networks: {} {}",
resp.errors[0].code, resp.errors[0].message
);
std::process::exit(1); std::process::exit(1);
} }

View File

@ -1,10 +1,10 @@
use std::error::Error; use crate::api::APIErrorResponse;
use std::fs; use crate::OrgCommands;
use ipnet::Ipv4Net; use ipnet::Ipv4Net;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::error::Error;
use std::fs;
use url::Url; use url::Url;
use crate::OrgCommands;
use crate::api::APIErrorResponse;
pub async fn org_main(command: OrgCommands, server: Url) -> Result<(), Box<dyn Error>> { pub async fn org_main(command: OrgCommands, server: Url) -> Result<(), Box<dyn Error>> {
match command { match command {
@ -14,14 +14,14 @@ pub async fn org_main(command: OrgCommands, server: Url) -> Result<(), Box<dyn E
#[derive(Serialize)] #[derive(Serialize)]
pub struct CreateOrgBody { pub struct CreateOrgBody {
pub cidr: String pub cidr: String,
} }
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct OrgCreateResponse { pub struct OrgCreateResponse {
pub organization: String, pub organization: String,
pub ca: String, pub ca: String,
pub network: String pub network: String,
} }
pub async fn create_org(cidr: Ipv4Net, server: Url) -> Result<(), Box<dyn Error>> { pub async fn create_org(cidr: Ipv4Net, server: Url) -> Result<(), Box<dyn Error>> {
@ -34,7 +34,14 @@ pub async fn create_org(cidr: Ipv4Net, server: Url) -> Result<(), Box<dyn Error>
let token = format!("{} {}", session_token, auth_token); let token = format!("{} {}", session_token, auth_token);
let res = client.post(server.join("/v1/organization")?).json(&CreateOrgBody { cidr: cidr.to_string() }).bearer_auth(token).send().await?; let res = client
.post(server.join("/v1/organization")?)
.json(&CreateOrgBody {
cidr: cidr.to_string(),
})
.bearer_auth(token)
.send()
.await?;
if res.status().is_success() { if res.status().is_success() {
let resp: OrgCreateResponse = res.json().await?; let resp: OrgCreateResponse = res.json().await?;
@ -45,7 +52,10 @@ pub async fn create_org(cidr: Ipv4Net, server: Url) -> Result<(), Box<dyn Error>
} else { } else {
let resp: APIErrorResponse = res.json().await?; let resp: APIErrorResponse = res.json().await?;
eprintln!("[error] Error creating org: {} {}", resp.errors[0].code, resp.errors[0].message); eprintln!(
"[error] Error creating org: {} {}",
resp.errors[0].code, resp.errors[0].message
);
std::process::exit(1); std::process::exit(1);
} }

View File

@ -1,23 +1,34 @@
use crate::api::APIErrorResponse;
use crate::{RoleCommands, TableStyle};
use comfy_table::modifiers::UTF8_ROUND_CORNERS;
use comfy_table::presets::UTF8_FULL;
use comfy_table::Table;
use serde::{Deserialize, Serialize};
use std::error::Error; use std::error::Error;
use std::fs; use std::fs;
use serde::{Deserialize, Serialize};
use url::Url; use url::Url;
use crate::api::APIErrorResponse;
use crate::{RoleCommands};
pub async fn role_main(command: RoleCommands, server: Url) -> Result<(), Box<dyn Error>> { pub async fn role_main(command: RoleCommands, server: Url) -> Result<(), Box<dyn Error>> {
match command { match command {
RoleCommands::List {} => list_roles(server).await, RoleCommands::List { table_style } => list_roles(server, table_style).await,
RoleCommands::Lookup {id} => get_role(id, server).await, RoleCommands::Lookup { id } => get_role(id, server).await,
RoleCommands::Create { name, description, rules_json } => create_role(name, description, rules_json, server).await, RoleCommands::Create {
name,
description,
rules_json,
} => create_role(name, description, rules_json, server).await,
RoleCommands::Delete { id } => delete_role(id, server).await, RoleCommands::Delete { id } => delete_role(id, server).await,
RoleCommands::Update { id, description, rules_json } => update_role(id, description, rules_json, server).await RoleCommands::Update {
id,
description,
rules_json,
} => update_role(id, description, rules_json, server).await,
} }
} }
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct RoleListResp { pub struct RoleListResp {
pub data: Vec<Role> pub data: Vec<Role>,
} }
#[derive(Deserialize)] #[derive(Deserialize)]
@ -30,7 +41,7 @@ pub struct Role {
#[serde(rename = "createdAt")] #[serde(rename = "createdAt")]
pub created_at: String, pub created_at: String,
#[serde(rename = "modifiedAt")] #[serde(rename = "modifiedAt")]
pub modified_at: String pub modified_at: String,
} }
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
pub struct RoleFirewallRule { pub struct RoleFirewallRule {
@ -39,15 +50,15 @@ pub struct RoleFirewallRule {
#[serde(rename = "allowedRoleID")] #[serde(rename = "allowedRoleID")]
pub allowed_role_id: Option<String>, pub allowed_role_id: Option<String>,
#[serde(rename = "portRange")] #[serde(rename = "portRange")]
pub port_range: Option<RoleFirewallRulePortRange> pub port_range: Option<RoleFirewallRulePortRange>,
} }
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
pub struct RoleFirewallRulePortRange { pub struct RoleFirewallRulePortRange {
pub from: u16, pub from: u16,
pub to: u16 pub to: u16,
} }
pub async fn list_roles(server: Url) -> Result<(), Box<dyn Error>> { pub async fn list_roles(server: Url, table_style: TableStyle) -> Result<(), Box<dyn Error>> {
let client = reqwest::Client::new(); let client = reqwest::Client::new();
// load session token // load session token
@ -58,31 +69,86 @@ pub async fn list_roles(server: Url) -> Result<(), Box<dyn Error>> {
let token = format!("{} {}", session_token, auth_token); let token = format!("{} {}", session_token, auth_token);
let res = client.get(server.join("/v1/roles")?).bearer_auth(token).send().await?; let res = client
.get(server.join("/v1/roles")?)
.bearer_auth(token)
.send()
.await?;
if res.status().is_success() { if res.status().is_success() {
let resp: RoleListResp = res.json().await?; let resp: RoleListResp = res.json().await?;
for role in &resp.data {
println!(" Role: {} ({})", role.name, role.id);
println!(" Description: {}", role.description);
for rule in &role.firewall_rules {
println!("Rule Description: {}", rule.description);
println!(" Allowed Role: {}", rule.allowed_role_id.as_ref().unwrap_or(&"All roles".to_string()));
println!(" Protocol: {}", rule.protocol);
println!(" Port Range: {}", if let Some(pr) = rule.port_range.as_ref() { format!("{}-{}", pr.from, pr.to) } else { "Any".to_string() });
}
println!(" Created: {}", role.created_at);
println!(" Updated: {}", role.modified_at);
}
if resp.data.is_empty() { if resp.data.is_empty() {
println!("No roles found"); println!("No roles found");
return Ok(());
} }
if matches!(table_style, TableStyle::List) {
for role in &resp.data {
println!(" Role: {} ({})", role.name, role.id);
println!(" Description: {}", role.description);
for rule in &role.firewall_rules {
println!("Rule Description: {}", rule.description);
println!(
" Allowed Role: {}",
rule.allowed_role_id
.as_ref()
.unwrap_or(&"All roles".to_string())
);
println!(" Protocol: {}", rule.protocol);
println!(
" Port Range: {}",
if let Some(pr) = rule.port_range.as_ref() {
format!("{}-{}", pr.from, pr.to)
} else {
"Any".to_string()
}
);
}
println!(" Created: {}", role.created_at);
println!(" Updated: {}", role.modified_at);
}
return Ok(());
}
let mut table = Table::new();
match table_style {
TableStyle::List => unreachable!(),
TableStyle::Basic => (),
TableStyle::Pretty => {
table
.load_preset(UTF8_FULL)
.apply_modifier(UTF8_ROUND_CORNERS);
}
};
table.set_header(vec![
"ID",
"Name",
"Description",
"Rule Count",
"Created",
"Updated",
]);
for role in &resp.data {
table.add_row(vec![
&role.id,
&role.name,
&role.description,
role.firewall_rules.len().to_string().as_str(),
&role.created_at,
&role.modified_at,
]);
}
println!("{table}");
} else { } else {
let resp: APIErrorResponse = res.json().await?; let resp: APIErrorResponse = res.json().await?;
eprintln!("[error] Error listing roles: {} {}", resp.errors[0].code, resp.errors[0].message); eprintln!(
"[error] Error listing roles: {} {}",
resp.errors[0].code, resp.errors[0].message
);
std::process::exit(1); std::process::exit(1);
} }
@ -92,7 +158,7 @@ pub async fn list_roles(server: Url) -> Result<(), Box<dyn Error>> {
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct RoleGetResponse { pub struct RoleGetResponse {
pub data: Role pub data: Role,
} }
pub async fn get_role(id: String, server: Url) -> Result<(), Box<dyn Error>> { pub async fn get_role(id: String, server: Url) -> Result<(), Box<dyn Error>> {
@ -106,7 +172,11 @@ pub async fn get_role(id: String, server: Url) -> Result<(), Box<dyn Error>> {
let token = format!("{} {}", session_token, auth_token); let token = format!("{} {}", session_token, auth_token);
let res = client.get(server.join(&format!("/v1/roles/{}", id))?).bearer_auth(token).send().await?; let res = client
.get(server.join(&format!("/v1/roles/{}", id))?)
.bearer_auth(token)
.send()
.await?;
if res.status().is_success() { if res.status().is_success() {
let role: Role = res.json::<RoleGetResponse>().await?.data; let role: Role = res.json::<RoleGetResponse>().await?.data;
@ -115,17 +185,31 @@ pub async fn get_role(id: String, server: Url) -> Result<(), Box<dyn Error>> {
println!(" Description: {}", role.description); println!(" Description: {}", role.description);
for rule in &role.firewall_rules { for rule in &role.firewall_rules {
println!("Rule Description: {}", rule.description); println!("Rule Description: {}", rule.description);
println!(" Allowed Role: {}", rule.allowed_role_id.as_ref().unwrap_or(&"All roles".to_string())); println!(
" Allowed Role: {}",
rule.allowed_role_id
.as_ref()
.unwrap_or(&"All roles".to_string())
);
println!(" Protocol: {}", rule.protocol); println!(" Protocol: {}", rule.protocol);
println!(" Port Range: {}", if let Some(pr) = rule.port_range.as_ref() { format!("{}-{}", pr.from, pr.to) } else { "Any".to_string() }); println!(
" Port Range: {}",
if let Some(pr) = rule.port_range.as_ref() {
format!("{}-{}", pr.from, pr.to)
} else {
"Any".to_string()
}
);
} }
println!(" Created: {}", role.created_at); println!(" Created: {}", role.created_at);
println!(" Updated: {}", role.modified_at); println!(" Updated: {}", role.modified_at);
} else { } else {
let resp: APIErrorResponse = res.json().await?; let resp: APIErrorResponse = res.json().await?;
eprintln!("[error] Error listing roles: {} {}", resp.errors[0].code, resp.errors[0].message); eprintln!(
"[error] Error listing roles: {} {}",
resp.errors[0].code, resp.errors[0].message
);
std::process::exit(1); std::process::exit(1);
} }
@ -138,10 +222,15 @@ pub struct RoleCreateBody {
pub name: String, pub name: String,
pub description: String, pub description: String,
#[serde(rename = "firewallRules")] #[serde(rename = "firewallRules")]
pub firewall_rules: Vec<RoleFirewallRule> pub firewall_rules: Vec<RoleFirewallRule>,
} }
pub async fn create_role(name: String, description: String, rules_json: String, server: Url) -> Result<(), Box<dyn Error>> { pub async fn create_role(
name: String,
description: String,
rules_json: String,
server: Url,
) -> Result<(), Box<dyn Error>> {
let client = reqwest::Client::new(); let client = reqwest::Client::new();
let rules: Vec<RoleFirewallRule> = match serde_json::from_str(&rules_json) { let rules: Vec<RoleFirewallRule> = match serde_json::from_str(&rules_json) {
@ -160,11 +249,16 @@ pub async fn create_role(name: String, description: String, rules_json: String,
let token = format!("{} {}", session_token, auth_token); let token = format!("{} {}", session_token, auth_token);
let res = client.post(server.join("/v1/roles")?).json(&RoleCreateBody { let res = client
name, .post(server.join("/v1/roles")?)
description, .json(&RoleCreateBody {
firewall_rules: rules, name,
}).bearer_auth(token).send().await?; description,
firewall_rules: rules,
})
.bearer_auth(token)
.send()
.await?;
if res.status().is_success() { if res.status().is_success() {
let role: Role = res.json::<RoleGetResponse>().await?.data; let role: Role = res.json::<RoleGetResponse>().await?.data;
@ -173,17 +267,31 @@ pub async fn create_role(name: String, description: String, rules_json: String,
println!(" Description: {}", role.description); println!(" Description: {}", role.description);
for rule in &role.firewall_rules { for rule in &role.firewall_rules {
println!("Rule Description: {}", rule.description); println!("Rule Description: {}", rule.description);
println!(" Allowed Role: {}", rule.allowed_role_id.as_ref().unwrap_or(&"All roles".to_string())); println!(
" Allowed Role: {}",
rule.allowed_role_id
.as_ref()
.unwrap_or(&"All roles".to_string())
);
println!(" Protocol: {}", rule.protocol); println!(" Protocol: {}", rule.protocol);
println!(" Port Range: {}", if let Some(pr) = rule.port_range.as_ref() { format!("{}-{}", pr.from, pr.to) } else { "Any".to_string() }); println!(
" Port Range: {}",
if let Some(pr) = rule.port_range.as_ref() {
format!("{}-{}", pr.from, pr.to)
} else {
"Any".to_string()
}
);
} }
println!(" Created: {}", role.created_at); println!(" Created: {}", role.created_at);
println!(" Updated: {}", role.modified_at); println!(" Updated: {}", role.modified_at);
} else { } else {
let resp: APIErrorResponse = res.json().await?; let resp: APIErrorResponse = res.json().await?;
eprintln!("[error] Error creating role: {} {}", resp.errors[0].code, resp.errors[0].message); eprintln!(
"[error] Error creating role: {} {}",
resp.errors[0].code, resp.errors[0].message
);
std::process::exit(1); std::process::exit(1);
} }
@ -195,10 +303,15 @@ pub async fn create_role(name: String, description: String, rules_json: String,
pub struct RoleUpdateBody { pub struct RoleUpdateBody {
pub description: String, pub description: String,
#[serde(rename = "firewallRules")] #[serde(rename = "firewallRules")]
pub firewall_rules: Vec<RoleFirewallRule> pub firewall_rules: Vec<RoleFirewallRule>,
} }
pub async fn update_role(id: String, description: String, rules_json: String, server: Url) -> Result<(), Box<dyn Error>> { pub async fn update_role(
id: String,
description: String,
rules_json: String,
server: Url,
) -> Result<(), Box<dyn Error>> {
let client = reqwest::Client::new(); let client = reqwest::Client::new();
let rules: Vec<RoleFirewallRule> = match serde_json::from_str(&rules_json) { let rules: Vec<RoleFirewallRule> = match serde_json::from_str(&rules_json) {
@ -217,10 +330,15 @@ pub async fn update_role(id: String, description: String, rules_json: String, se
let token = format!("{} {}", session_token, auth_token); let token = format!("{} {}", session_token, auth_token);
let res = client.put(server.join(&format!("/v1/roles/{}", id))?).json(&RoleUpdateBody { let res = client
description, .put(server.join(&format!("/v1/roles/{}", id))?)
firewall_rules: rules, .json(&RoleUpdateBody {
}).bearer_auth(token).send().await?; description,
firewall_rules: rules,
})
.bearer_auth(token)
.send()
.await?;
if res.status().is_success() { if res.status().is_success() {
let role: Role = res.json::<RoleGetResponse>().await?.data; let role: Role = res.json::<RoleGetResponse>().await?.data;
@ -229,17 +347,31 @@ pub async fn update_role(id: String, description: String, rules_json: String, se
println!(" Description: {}", role.description); println!(" Description: {}", role.description);
for rule in &role.firewall_rules { for rule in &role.firewall_rules {
println!("Rule Description: {}", rule.description); println!("Rule Description: {}", rule.description);
println!(" Allowed Role: {}", rule.allowed_role_id.as_ref().unwrap_or(&"All roles".to_string())); println!(
" Allowed Role: {}",
rule.allowed_role_id
.as_ref()
.unwrap_or(&"All roles".to_string())
);
println!(" Protocol: {}", rule.protocol); println!(" Protocol: {}", rule.protocol);
println!(" Port Range: {}", if let Some(pr) = rule.port_range.as_ref() { format!("{}-{}", pr.from, pr.to) } else { "Any".to_string() }); println!(
" Port Range: {}",
if let Some(pr) = rule.port_range.as_ref() {
format!("{}-{}", pr.from, pr.to)
} else {
"Any".to_string()
}
);
} }
println!(" Created: {}", role.created_at); println!(" Created: {}", role.created_at);
println!(" Updated: {}", role.modified_at); println!(" Updated: {}", role.modified_at);
} else { } else {
let resp: APIErrorResponse = res.json().await?; let resp: APIErrorResponse = res.json().await?;
eprintln!("[error] Error updating role: {} {}", resp.errors[0].code, resp.errors[0].message); eprintln!(
"[error] Error updating role: {} {}",
resp.errors[0].code, resp.errors[0].message
);
std::process::exit(1); std::process::exit(1);
} }
@ -258,14 +390,21 @@ pub async fn delete_role(id: String, server: Url) -> Result<(), Box<dyn Error>>
let token = format!("{} {}", session_token, auth_token); let token = format!("{} {}", session_token, auth_token);
let res = client.delete(server.join(&format!("/v1/roles/{}", id))?).bearer_auth(token).send().await?; let res = client
.delete(server.join(&format!("/v1/roles/{}", id))?)
.bearer_auth(token)
.send()
.await?;
if res.status().is_success() { if res.status().is_success() {
println!("Role removed"); println!("Role removed");
} else { } else {
let resp: APIErrorResponse = res.json().await?; let resp: APIErrorResponse = res.json().await?;
eprintln!("[error] Error removing role: {} {}", resp.errors[0].code, resp.errors[0].message); eprintln!(
"[error] Error removing role: {} {}",
resp.errors[0].code, resp.errors[0].message
);
std::process::exit(1); std::process::exit(1);
} }

View File

@ -0,0 +1,5 @@
package main
func main() {
}

24
tfclient-go/config.go Normal file
View File

@ -0,0 +1,24 @@
package tfclient
import (
"crypto/ed25519"
"runtime"
)
type TfConfig struct {
HostKey struct {
HostID string `yaml:"host_id"`
PrivateKey ed25519.PrivateKey `yaml:"private_key"`
Counter uint `yaml:"counter"`
TrustedKeys []ed25519.PublicKey `yaml:"trusted_keys"`
}
}
func ConfigPath() string {
switch runtime.GOOS {
case "windows":
return "C:\\ProgramData\\tfclient"
default:
return "/etc/tfclient"
}
}

10
tfclient-go/go.mod Normal file
View File

@ -0,0 +1,10 @@
module git.e3t.cc/core/trifid/tfclient-go
go 1.20
require (
github.com/sirupsen/logrus v1.9.3
github.com/slackhq/nebula v1.8.2
)
require gopkg.in/yaml.v3 v3.0.1 // indirect

12
tfclient-go/go.sum Normal file
View File

@ -0,0 +1,12 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/slackhq/nebula v1.8.2/go.mod h1:SVVwnlGdmLg387U0XQMOSHRrD3VlJeXqd2/x/w/vxPs=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
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=

12
tfclient-go/socket.go Normal file
View File

@ -0,0 +1,12 @@
package tfclient
import "runtime"
func SocketPath(Name string) string {
switch runtime.GOOS {
case "windows":
return "C:\\ProgramData\\tfclient\\" + Name + ".sock"
default:
return "/tmp/tfclient-" + Name + ".sock"
}
}

View File

@ -1,6 +1,6 @@
[package] [package]
name = "tfclient" name = "tfclient"
version = "0.3.0" version = "0.4.0"
edition = "2021" edition = "2021"
description = "An open-source reimplementation of a Defined Networking-compatible client" description = "An open-source reimplementation of a Defined Networking-compatible client"
license = "GPL-3.0-or-later" license = "GPL-3.0-or-later"
@ -30,7 +30,7 @@ ipnet = "2.7"
base64-serde = "0.7" base64-serde = "0.7"
dnapi-rs = { version = "0.2", path = "../dnapi-rs" } dnapi-rs = { version = "0.2", path = "../dnapi-rs" }
serde_yaml = "0.9" serde_yaml = "0.9"
nebula-ffi = { version = "1.7.2", path = "../nebula-ffi", optional = true } nebula-ffi = { version = "1.8.1", path = "../nebula-ffi", optional = true }
[package.metadata.deb] [package.metadata.deb]

View File

@ -112,10 +112,7 @@ pub fn apiworker_main(
cdata.creds = Some(creds); cdata.creds = Some(creds);
cdata.dh_privkey = Some(dh_privkey); cdata.dh_privkey = Some(dh_privkey);
match fs::write( match fs::write(nebula_yml(&instance), config) {
nebula_yml(&instance),
config,
) {
Ok(_) => (), Ok(_) => (),
Err(e) => { Err(e) => {
error!("unable to save nebula config: {}", e); error!("unable to save nebula config: {}", e);
@ -175,10 +172,7 @@ pub fn apiworker_main(
} }
}; };
match fs::write( match fs::write(nebula_yml(&instance), config) {
nebula_yml(&instance),
config,
) {
Ok(_) => (), Ok(_) => (),
Err(e) => { Err(e) => {
error!("unable to save nebula config: {}", e); error!("unable to save nebula config: {}", e);

View File

@ -4,11 +4,11 @@ use std::error::Error;
use std::fs; use std::fs;
use std::net::{Ipv4Addr, SocketAddrV4}; use std::net::{Ipv4Addr, SocketAddrV4};
use crate::dirs::{config_dir, tfclient_toml, tfdata_toml};
use dnapi_rs::client_blocking::EnrollMeta; use dnapi_rs::client_blocking::EnrollMeta;
use dnapi_rs::credentials::Credentials; use dnapi_rs::credentials::Credentials;
use log::{debug, info}; use log::{debug, info};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::dirs::{config_dir, tfclient_toml, tfdata_toml};
pub const DEFAULT_PORT: u16 = 8157; pub const DEFAULT_PORT: u16 = 8157;
fn default_port() -> u16 { fn default_port() -> u16 {
@ -39,10 +39,7 @@ pub fn create_config(instance: &str) -> Result<(), Box<dyn Error>> {
disable_automatic_config_updates: false, disable_automatic_config_updates: false,
}; };
let config_str = toml::to_string(&config)?; let config_str = toml::to_string(&config)?;
fs::write( fs::write(tfclient_toml(instance), config_str)?;
tfclient_toml(instance),
config_str,
)?;
Ok(()) Ok(())
} }
@ -72,10 +69,7 @@ pub fn create_cdata(instance: &str) -> Result<(), Box<dyn Error>> {
meta: None, meta: None,
}; };
let config_str = toml::to_string(&config)?; let config_str = toml::to_string(&config)?;
fs::write( fs::write(tfdata_toml(instance), config_str)?;
tfdata_toml(instance),
config_str,
)?;
Ok(()) Ok(())
} }

View File

@ -6,7 +6,7 @@ use std::thread;
use crate::apiworker::{apiworker_main, APIWorkerMessage}; use crate::apiworker::{apiworker_main, APIWorkerMessage};
use crate::config::load_config; use crate::config::load_config;
use crate::nebulaworker::{NebulaWorkerMessage, nebulaworker_main}; use crate::nebulaworker::{nebulaworker_main, NebulaWorkerMessage};
use crate::socketworker::{socketworker_main, SocketWorkerMessage}; use crate::socketworker::{socketworker_main, SocketWorkerMessage};
use crate::timerworker::{timer_main, TimerWorkerMessage}; use crate::timerworker::{timer_main, TimerWorkerMessage};
use crate::util::{check_server_url, shutdown}; use crate::util::{check_server_url, shutdown};
@ -83,7 +83,11 @@ pub fn daemon_main(name: String, server: String) {
let timer_transmitter = transmitter; let timer_transmitter = transmitter;
let timer_thread = thread::spawn(move || { let timer_thread = thread::spawn(move || {
timer_main(timer_transmitter, rx_timer, config.disable_automatic_config_updates); timer_main(
timer_transmitter,
rx_timer,
config.disable_automatic_config_updates,
);
}); });
info!("Waiting for timer thread to exit..."); info!("Waiting for timer thread to exit...");
match timer_thread.join() { match timer_thread.join() {
@ -95,7 +99,6 @@ pub fn daemon_main(name: String, server: String) {
} }
info!("Timer thread exited"); info!("Timer thread exited");
info!("Waiting for socket thread to exit..."); info!("Waiting for socket thread to exit...");
match socket_thread.join() { match socket_thread.join() {
Ok(_) => (), Ok(_) => (),

View File

@ -31,13 +31,19 @@ pub fn config_dir(instance: &str) -> PathBuf {
} }
pub fn tfclient_toml(instance: &str) -> PathBuf { pub fn tfclient_toml(instance: &str) -> PathBuf {
config_base().join(format!("{}/", instance)).join("tfclient.toml") config_base()
.join(format!("{}/", instance))
.join("tfclient.toml")
} }
pub fn tfdata_toml(instance: &str) -> PathBuf { pub fn tfdata_toml(instance: &str) -> PathBuf {
config_base().join(format!("{}/", instance)).join("tfdata.toml") config_base()
.join(format!("{}/", instance))
.join("tfdata.toml")
} }
pub fn nebula_yml(instance: &str) -> PathBuf { pub fn nebula_yml(instance: &str) -> PathBuf {
config_base().join(format!("{}/", instance)).join("nebula.yml") config_base()
.join(format!("{}/", instance))
.join("nebula.yml")
} }

View File

@ -44,7 +44,6 @@ struct Cli {
#[derive(Subcommand)] #[derive(Subcommand)]
enum Commands { enum Commands {
/// Run the tfclient daemon in the foreground /// Run the tfclient daemon in the foreground
Run { Run {
#[clap(short, long, default_value = "tfclient")] #[clap(short, long, default_value = "tfclient")]
@ -55,7 +54,7 @@ enum Commands {
server: String, server: String,
}, },
/// Enroll this host using a trifid-api enrollment code /// Enroll this host using a trifid-api-old enrollment code
Enroll { Enroll {
#[clap(short, long, default_value = "tfclient")] #[clap(short, long, default_value = "tfclient")]
/// Service name specified on install /// Service name specified on install

View File

@ -2,13 +2,13 @@
use crate::config::{load_cdata, NebulaConfig, TFClientConfig}; use crate::config::{load_cdata, NebulaConfig, TFClientConfig};
use crate::daemon::ThreadMessageSender; use crate::daemon::ThreadMessageSender;
use crate::dirs::{nebula_yml}; use crate::dirs::nebula_yml;
use crate::util::shutdown;
use log::{debug, error, info}; use log::{debug, error, info};
use nebula_ffi::NebulaInstance;
use std::error::Error; use std::error::Error;
use std::fs; use std::fs;
use std::sync::mpsc::Receiver; use std::sync::mpsc::Receiver;
use nebula_ffi::NebulaInstance;
use crate::util::shutdown;
pub enum NebulaWorkerMessage { pub enum NebulaWorkerMessage {
Shutdown, Shutdown,
@ -23,20 +23,15 @@ fn insert_private_key(instance: &str) -> Result<(), Box<dyn Error>> {
let cdata = load_cdata(instance)?; let cdata = load_cdata(instance)?;
let key = cdata.dh_privkey.ok_or("Missing private key")?; let key = cdata.dh_privkey.ok_or("Missing private key")?;
let config_str = fs::read_to_string( let config_str = fs::read_to_string(nebula_yml(instance))?;
nebula_yml(instance),
)?;
let mut config: NebulaConfig = serde_yaml::from_str(&config_str)?; let mut config: NebulaConfig = serde_yaml::from_str(&config_str)?;
config.pki.key = Some(String::from_utf8(key)?); config.pki.key = Some(String::from_utf8(key)?);
debug!("inserted private key into config: {:?}", config); debug!("inserted private key into config");
let config_str = serde_yaml::to_string(&config)?; let config_str = serde_yaml::to_string(&config)?;
fs::write( fs::write(nebula_yml(instance), config_str)?;
nebula_yml(instance),
config_str,
)?;
Ok(()) Ok(())
} }
@ -74,30 +69,31 @@ pub fn nebulaworker_main(
error!("not enrolled, cannot start nebula"); error!("not enrolled, cannot start nebula");
} else { } else {
info!("setting up nebula..."); info!("setting up nebula...");
nebula = Some(match NebulaInstance::new(nebula_yml(&instance).as_path(), false) { nebula = Some(
Ok(i) => { match NebulaInstance::new(nebula_yml(&instance).as_path(), false) {
info!("nebula setup"); Ok(i) => {
info!("starting nebula..."); info!("nebula setup");
match i.start() { info!("starting nebula...");
Ok(_) => (), match i.start() {
Err(e) => { Ok(_) => (),
error!("error starting Nebula: {}", e); Err(e) => {
error!("nebula thread exiting with error"); error!("error starting Nebula: {}", e);
shutdown(&transmitter); error!("nebula thread exiting with error");
return; shutdown(&transmitter);
return;
}
} }
i
}
Err(e) => {
error!("error setting up Nebula: {}", e);
error!("nebula thread exiting with error");
shutdown(&transmitter);
return;
} }
i
}, },
Err(e) => { );
error!("error setting up Nebula: {}", e);
error!("nebula thread exiting with error");
shutdown(&transmitter);
return;
}
});
info!("nebula process started"); info!("nebula process started");
} }
@ -157,30 +153,31 @@ pub fn nebulaworker_main(
} else { } else {
debug!("detected enrollment, starting nebula for the first time"); debug!("detected enrollment, starting nebula for the first time");
info!("setting up nebula..."); info!("setting up nebula...");
nebula = Some(match NebulaInstance::new(nebula_yml(&instance).as_path(), false) { nebula = Some(
Ok(i) => { match NebulaInstance::new(nebula_yml(&instance).as_path(), false) {
info!("nebula setup"); Ok(i) => {
info!("starting nebula..."); info!("nebula setup");
match i.start() { info!("starting nebula...");
Ok(_) => (), match i.start() {
Err(e) => { Ok(_) => (),
error!("error starting Nebula: {}", e); Err(e) => {
error!("nebula thread exiting with error"); error!("error starting Nebula: {}", e);
shutdown(&transmitter); error!("nebula thread exiting with error");
return; shutdown(&transmitter);
return;
}
} }
i
}
Err(e) => {
error!("error setting up Nebula: {}", e);
error!("nebula thread exiting with error");
shutdown(&transmitter);
return;
} }
i
}, },
Err(e) => { );
error!("error setting up Nebula: {}", e);
error!("nebula thread exiting with error");
shutdown(&transmitter);
return;
}
});
info!("nebula process started"); info!("nebula process started");
} }

View File

@ -4,7 +4,7 @@
use crate::config::{load_cdata, NebulaConfig, TFClientConfig}; use crate::config::{load_cdata, NebulaConfig, TFClientConfig};
use crate::daemon::ThreadMessageSender; use crate::daemon::ThreadMessageSender;
use crate::dirs::{nebula_yml}; use crate::dirs::nebula_yml;
use log::{debug, error, info}; use log::{debug, error, info};
use std::error::Error; use std::error::Error;
use std::fs; use std::fs;
@ -23,9 +23,7 @@ fn insert_private_key(instance: &str) -> Result<(), Box<dyn Error>> {
let cdata = load_cdata(instance)?; let cdata = load_cdata(instance)?;
let key = cdata.dh_privkey.ok_or("Missing private key")?; let key = cdata.dh_privkey.ok_or("Missing private key")?;
let config_str = fs::read_to_string( let config_str = fs::read_to_string(nebula_yml(instance))?;
nebula_yml(instance),
)?;
let mut config: NebulaConfig = serde_yaml::from_str(&config_str)?; let mut config: NebulaConfig = serde_yaml::from_str(&config_str)?;
config.pki.key = Some(String::from_utf8(key)?); config.pki.key = Some(String::from_utf8(key)?);
@ -33,25 +31,26 @@ fn insert_private_key(instance: &str) -> Result<(), Box<dyn Error>> {
debug!("inserted private key into config: {:?}", config); debug!("inserted private key into config: {:?}", config);
let config_str = serde_yaml::to_string(&config)?; let config_str = serde_yaml::to_string(&config)?;
fs::write( fs::write(nebula_yml(instance), config_str)?;
nebula_yml(instance),
config_str,
)?;
Ok(()) Ok(())
} }
pub fn nebulaworker_main(
pub fn nebulaworker_main(_config: TFClientConfig, instance: String, _transmitter: ThreadMessageSender, rx: Receiver<NebulaWorkerMessage>) { _config: TFClientConfig,
instance: String,
_transmitter: ThreadMessageSender,
rx: Receiver<NebulaWorkerMessage>,
) {
loop { loop {
match rx.recv() { match rx.recv() {
Ok(msg) => match msg { Ok(msg) => match msg {
NebulaWorkerMessage::WakeUp => { NebulaWorkerMessage::WakeUp => {
continue; continue;
}, }
NebulaWorkerMessage::Shutdown => { NebulaWorkerMessage::Shutdown => {
break; break;
}, }
NebulaWorkerMessage::ConfigUpdated => { NebulaWorkerMessage::ConfigUpdated => {
info!("our configuration has been updated - reloading"); info!("our configuration has been updated - reloading");

View File

@ -12,7 +12,11 @@ pub enum TimerWorkerMessage {
Shutdown, Shutdown,
} }
pub fn timer_main(tx: ThreadMessageSender, rx: Receiver<TimerWorkerMessage>, disable_config_updates: bool) { pub fn timer_main(
tx: ThreadMessageSender,
rx: Receiver<TimerWorkerMessage>,
disable_config_updates: bool,
) {
let mut api_reload_timer = SystemTime::now().add(Duration::from_secs(60)); let mut api_reload_timer = SystemTime::now().add(Duration::from_secs(60));
loop { loop {

View File

@ -1,12 +1,12 @@
use log::{error, warn};
use sha2::Digest;
use sha2::Sha256;
use url::Url;
use crate::apiworker::APIWorkerMessage; use crate::apiworker::APIWorkerMessage;
use crate::daemon::ThreadMessageSender; use crate::daemon::ThreadMessageSender;
use crate::nebulaworker::NebulaWorkerMessage; use crate::nebulaworker::NebulaWorkerMessage;
use crate::socketworker::SocketWorkerMessage; use crate::socketworker::SocketWorkerMessage;
use crate::timerworker::TimerWorkerMessage; use crate::timerworker::TimerWorkerMessage;
use log::{error, warn};
use sha2::Digest;
use sha2::Sha256;
use url::Url;
pub fn sha256(bytes: &[u8]) -> String { pub fn sha256(bytes: &[u8]) -> String {
let mut hasher = Sha256::new(); let mut hasher = Sha256::new();
@ -46,15 +46,12 @@ pub fn shutdown(transmitter: &ThreadMessageSender) {
Ok(_) => (), Ok(_) => (),
Err(e) => { Err(e) => {
error!( error!(
"Error sending shutdown message to nebula worker thread: {}", "Error sending shutdown message to nebula worker thread: {}",
e e
); );
} }
} }
match transmitter match transmitter.api_thread.send(APIWorkerMessage::Shutdown) {
.api_thread
.send(APIWorkerMessage::Shutdown)
{
Ok(_) => (), Ok(_) => (),
Err(e) => { Err(e) => {
error!("Error sending shutdown message to api worker thread: {}", e); error!("Error sending shutdown message to api worker thread: {}", e);
@ -67,21 +64,18 @@ pub fn shutdown(transmitter: &ThreadMessageSender) {
Ok(_) => (), Ok(_) => (),
Err(e) => { Err(e) => {
error!( error!(
"Error sending shutdown message to socket worker thread: {}", "Error sending shutdown message to socket worker thread: {}",
e e
); );
} }
} }
match transmitter match transmitter.timer_thread.send(TimerWorkerMessage::Shutdown) {
.timer_thread
.send(TimerWorkerMessage::Shutdown)
{
Ok(_) => (), Ok(_) => (),
Err(e) => { Err(e) => {
error!( error!(
"Error sending shutdown message to timer worker thread: {}", "Error sending shutdown message to timer worker thread: {}",
e e
); );
} }
} }
} }

View File

@ -1,9 +1,11 @@
/** @type { import("eslint").Linter.FlatConfig } */
module.exports = { module.exports = {
root: true, root: true,
extends: [ extends: [
'eslint:recommended', 'eslint:recommended',
'plugin:@typescript-eslint/recommended', 'plugin:@typescript-eslint/recommended',
'plugin:svelte/recommended' 'plugin:svelte/recommended',
'prettier'
], ],
parser: '@typescript-eslint/parser', parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'], plugins: ['@typescript-eslint'],

1
tfweb/.gitignore vendored
View File

@ -8,4 +8,3 @@ node_modules
!.env.example !.env.example
vite.config.js.timestamp-* vite.config.js.timestamp-*
vite.config.ts.timestamp-* vite.config.ts.timestamp-*
.idea

View File

@ -1,2 +1 @@
engine-strict=true engine-strict=true
resolution-mode=highest

4
tfweb/.prettierignore Normal file
View File

@ -0,0 +1,4 @@
# Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml
package-lock.json
yarn.lock

18
tfweb/.prettierrc Normal file
View File

@ -0,0 +1,18 @@
{
"useTabs": true,
"singleQuote": true,
"trailingComma": "none",
"printWidth": 100,
"plugins": [
"prettier-plugin-svelte",
"prettier-plugin-tailwindcss"
],
"overrides": [
{
"files": "*.svelte",
"options": {
"parser": "svelte"
}
}
]
}

13
tfweb/components.json Normal file
View File

@ -0,0 +1,13 @@
{
"$schema": "https://shadcn-svelte.com/schema.json",
"style": "default",
"tailwind": {
"config": "tailwind.config.js",
"css": "src/app.pcss",
"baseColor": "zinc"
},
"aliases": {
"components": "$lib/components",
"utils": "$lib/utils"
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +0,0 @@
{
"$schema": "./node_modules/@openapitools/openapi-generator-cli/config.schema.json",
"spaces": 2,
"generator-cli": {
"version": "6.6.0"
}
}

View File

@ -8,30 +8,41 @@
"preview": "vite preview", "preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "eslint ." "lint": "prettier --check . && eslint .",
"format": "prettier --write ."
}, },
"devDependencies": { "devDependencies": {
"@sveltejs/adapter-auto": "^2.0.0", "@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/adapter-node": "^1.3.1", "@sveltejs/kit": "^2.0.0",
"@sveltejs/kit": "^1.5.0", "@sveltejs/vite-plugin-svelte": "^3.0.0",
"@typescript-eslint/eslint-plugin": "^5.45.0", "@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^5.45.0", "@typescript-eslint/parser": "^6.0.0",
"autoprefixer": "^10.4.16",
"eslint": "^8.28.0", "eslint": "^8.28.0",
"eslint-plugin-svelte": "^2.26.0", "eslint-config-prettier": "^9.1.0",
"svelte": "^3.54.0", "eslint-plugin-svelte": "^2.30.0",
"svelte-check": "^3.0.1", "postcss": "^8.4.32",
"postcss-load-config": "^5.0.2",
"prettier": "^3.1.1",
"prettier-plugin-svelte": "^3.1.2",
"prettier-plugin-tailwindcss": "^0.5.9",
"svelte": "^4.2.7",
"svelte-check": "^3.6.0",
"tailwindcss": "^3.3.6",
"tslib": "^2.4.1", "tslib": "^2.4.1",
"typescript": "^5.0.0", "typescript": "^5.0.0",
"vite": "^4.3.0" "vite": "^5.0.3"
}, },
"type": "module", "type": "module",
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-free": "^6.4.2", "bits-ui": "^0.11.8",
"@popperjs/core": "^2.11.8", "clsx": "^2.0.0",
"@types/qrcode": "^1.5.0", "formsnap": "^0.4.1",
"bootstrap": "^5.3.2", "lucide-svelte": "^0.298.0",
"bootswatch": "^5.3.2", "mode-watcher": "^0.1.2",
"qrcode": "^1.5.3", "sveltekit-superforms": "^1.12.0",
"sveltekit-i18n": "^2.4.2" "tailwind-merge": "^2.1.0",
"tailwind-variants": "^0.1.19",
"zod": "^3.22.4"
} }
} }

2468
tfweb/pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff

13
tfweb/postcss.config.cjs Normal file
View File

@ -0,0 +1,13 @@
const tailwindcss = require("tailwindcss");
const autoprefixer = require("autoprefixer");
const config = {
plugins: [
//Some plugins, like tailwindcss/nesting, need to run before Tailwind,
tailwindcss(),
//But others, like autoprefixer, need to run after,
autoprefixer
]
};
module.exports = config;

1
tfweb/src/app.d.ts vendored
View File

@ -5,6 +5,7 @@ declare global {
// interface Error {} // interface Error {}
// interface Locals {} // interface Locals {}
// interface PageData {} // interface PageData {}
// interface PageState {}
// interface Platform {} // interface Platform {}
} }
} }

View File

@ -1,12 +1,12 @@
<!DOCTYPE html> <!doctype html>
<html lang="en" style="height: 100%;"> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" /> <link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head% %sveltekit.head%
</head> </head>
<body data-sveltekit-preload-data="hover" style="height: 100%;"> <body data-sveltekit-preload-data="hover">
%sveltekit.body% <div style="display: contents">%sveltekit.body%</div>
</body> </body>
</html> </html>

78
tfweb/src/app.pcss Normal file
View File

@ -0,0 +1,78 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
--muted: 240 4.8% 95.9%;
--muted-foreground: 240 3.8% 46.1%;
--popover: 0 0% 100%;
--popover-foreground: 240 10% 3.9%;
--card: 0 0% 100%;
--card-foreground: 240 10% 3.9%;
--border: 240 5.9% 90%;
--input: 240 5.9% 90%;
--primary: 240 5.9% 10%;
--primary-foreground: 0 0% 98%;
--secondary: 240 4.8% 95.9%;
--secondary-foreground: 240 5.9% 10%;
--accent: 240 4.8% 95.9%;
--accent-foreground: 240 5.9% 10%;
--destructive: 0 72.2% 50.6%;
--destructive-foreground: 0 0% 98%;
--ring: 240 10% 3.9%;
--radius: 0.5rem;
}
.dark {
--background: 240 10% 3.9%;
--foreground: 0 0% 98%;
--muted: 240 3.7% 15.9%;
--muted-foreground: 240 5% 64.9%;
--popover: 240 10% 3.9%;
--popover-foreground: 0 0% 98%;
--card: 240 10% 3.9%;
--card-foreground: 0 0% 98%;
--border: 240 3.7% 15.9%;
--input: 240 3.7% 15.9%;
--primary: 0 0% 98%;
--primary-foreground: 240 5.9% 10%;
--secondary: 240 3.7% 15.9%;
--secondary-foreground: 0 0% 98%;
--accent: 240 3.7% 15.9%;
--accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--ring: 240 4.9% 83.9%;
}
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}

View File

@ -1,16 +0,0 @@
<script lang="ts">
import Sidebar from "$components/Sidebar.svelte";
export let selected;
</script>
<div class="container-fluid g-0">
<div class="row">
<div class="col-sm-3 col-md-3 col-lg-3 col-xl-2">
<Sidebar bind:selected={selected} />
</div>
<div class="col me-3 mt-2">
<slot></slot>
</div>
</div>
</div>

View File

@ -1,42 +0,0 @@
<script lang="ts">
import {logDeltaReset, Logger, logSetup} from "$lib/logger";
import {t} from "$lib/i18n/translations";
export let isLoading;
export let isError;
export let error;
logSetup();
let logger = new Logger("LoadingWrapper.svelte");
function loadingproclog() {
if (!isLoading) {
logger.info("page loaded - content paint");
logDeltaReset();
}
}
$: isLoading, loadingproclog();
</script>
{#if isLoading}
<div class="h-100 d-flex align-items-center justify-content-center">
<div class="card">
<div class="card-body text-center">
<h4 class="card-title mb-0">{$t("common.loading")} <i class="fas fa-gear fa-spin"></i></h4>
</div>
</div>
</div>
{:else}
{#if isError}
<div class="h-100 d-flex align-items-center justify-content-center">
<div class="card w-25">
<div class="card-body text-center">
<h4 class="card-title mb-0 text-danger">{error}</h4>
</div>
</div>
</div>
{:else}
<slot></slot>
{/if}
{/if}

View File

@ -1,35 +0,0 @@
<script lang="ts">
import {Logger, logSetup} from "$lib/logger";
import QRCode from "qrcode";
import {onMount} from "svelte";
export let value;
let canvas;
logSetup();
let logger = new Logger("QrCode.svelte");
function updateQrCode() {
if (canvas === undefined) {
logger.warn(`component has not yet mounted, delaying 500ms and trying again`);
setTimeout(() => {
updateQrCode();
}, 500);
return;
}
logger.info(`updating qrcode to ${value}`);
QRCode.toCanvas(canvas, value, (err) => {
if (err) {
logger.error(`error updating qrcode: ${err}`);
} else {
logger.info(`qrcode updated successfully`);
}
})
}
$: value, updateQrCode();
</script>
<canvas bind:this={canvas} id="canvas"></canvas>

View File

@ -1,48 +0,0 @@
<script lang="ts">
import {t} from "$lib/i18n/translations";
export let selected;
</script>
<div class="sticky-top d-flex flex-column flex-shrink-0 p-3 vh-100 bg-dark">
<p class="d-flex align-items-center mb-3 mb-md-0 me-md-auto text-white text-decoration-none ml-5 fs-4">
<i class="fas fa-satellite fa-fw bi me-2"></i>
Trifid
</p>
<hr>
<ul class="nav nav-pills flex-column mb-auto">
<li class="nav-item">
<a class="nav-link py-2 px-4" class:active={selected === 'hosts'} href="/hosts">
<i class="bi me-2 fas fa-computer fa-fw"></i>
{$t("common.page.hosts")}
</a>
</li>
<li class="nav-item">
<a class="nav-link py-2 px-4" class:active={selected === 'lighthouses'} href="/lighthouses">
<i class="bi me-2 fas fa-server fa-fw"></i>
{$t("common.page.lighthouses")}
</a>
</li>
<li class="nav-item">
<a class="nav-link py-2 px-4" class:active={selected === 'relays'} href="/relays">
<i class="bi me-2 fas fa-network-wired fa=fw"></i>
{$t("common.page.relays")}
</a>
</li>
<li class="nav-item">
<a class="nav-link py-2 px-4" class:active={selected === 'roles'} href="/roles">
<i class="bi me-2 fas fa-address-book fa-fw"></i>
{$t("common.page.roles")}
</a>
</li>
</ul>
<hr>
<div class="nav-item">
<button class="nav-link py-2 px-4" on:click={() => {window.localStorage.setItem("mfa", ""); window.location.href = "/2fa"}}>
<i class="me-2 fas fa-right-from-bracket fa-fw"></i>
{$t("common.logout")}
</button>
</div>
</div>

View File

@ -1,11 +0,0 @@
import { writable } from "svelte/store";
import { browser } from "$app/environment";
export function persist(name, def_val = "") {
const store = writable(browser && localStorage.getItem(name) || def_val);
store.subscribe((value) => {
if (browser)
return (localStorage.setItem(name, value));
});
return store;
}
//# sourceMappingURL=PersistentStore.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"PersistentStore.js","sourceRoot":"","sources":["PersistentStore.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,QAAQ,EAAC,MAAM,cAAc,CAAC;AACtC,OAAO,EAAC,OAAO,EAAC,MAAM,kBAAkB,CAAC;AAEzC,MAAM,UAAU,OAAO,CAAC,IAAY,EAAE,OAAO,GAAG,EAAE;IAC9C,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,CAAC;IACzE,KAAK,CAAC,SAAS,CAAC,CAAC,KAAU,EAAE,EAAE;QAC3B,IAAI,OAAO;YAAE,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IACH,OAAO,KAAK,CAAC;AACjB,CAAC"}

View File

@ -1,11 +0,0 @@
import type { Writable } from "svelte/store";
import {writable} from "svelte/store";
import {browser} from "$app/environment";
export function persist(name: string, def_val = ""): Writable<any> {
const store = writable(browser && localStorage.getItem(name) || def_val);
store.subscribe((value: any) => {
if (browser) return (localStorage.setItem(name, value));
});
return store;
}

View File

@ -1,17 +0,0 @@
import {browser} from "$app/environment";
export function updateTooltips() {
if (browser) {
setTimeout(() => {
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]')
const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => {
let tooltip = new document.B.Tooltip(tooltipTriggerEl, {trigger: 'hover'})
tooltipTriggerEl.addEventListener('click', () => {
tooltip.hide();
tooltip.dispose();
})
});
console.log(tooltipList);
});
}
}

View File

@ -1,23 +0,0 @@
# OpenAPI Generator Ignore
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
# Use this file to prevent files from being overwritten by the generator.
# The patterns follow closely to .gitignore or .dockerignore.
# As an example, the C# client generator defines ApiClient.cs.
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
#ApiClient.cs
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
#foo/*/qux
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
#foo/**/qux
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
# You can also negate patterns with an exclamation (!).
# For example, you can ignore all files in a docs folder with the file extension .md:
#docs/*.md
# Then explicitly reverse the ignore rule for a single file:
#!docs/README.md

View File

@ -1,61 +0,0 @@
.openapi-generator-ignore
apis/AuditLogsApi.ts
apis/DownloadsApi.ts
apis/HostsApi.ts
apis/NetworksApi.ts
apis/RolesApi.ts
apis/index.ts
index.ts
models/Actor.ts
models/ActorAPIKey.ts
models/ActorHost.ts
models/ActorOIDCUser.ts
models/ActorSupport.ts
models/ActorSystem.ts
models/ActorUser.ts
models/AuditLog.ts
models/AuditLogsList200Response.ts
models/Downloads.ts
models/DownloadsDNClientLinks.ts
models/DownloadsDnclient.ts
models/DownloadsList200Response.ts
models/DownloadsMobile.ts
models/DownloadsVersionInfo.ts
models/DownloadsVersionInfoDnclientValue.ts
models/DownloadsVersionInfoLatest.ts
models/Event.ts
models/FirewallRule.ts
models/FirewallRulePortRange.ts
models/Host.ts
models/HostAndEnrollCodeCreate200Response.ts
models/HostAndEnrollCodeCreate200ResponseData.ts
models/HostAndEnrollCodeCreate200ResponseDataEnrollmentCode.ts
models/HostAndEnrollCodeCreate400Response.ts
models/HostBlock200Response.ts
models/HostBlock200ResponseData.ts
models/HostCreate200Response.ts
models/HostCreate400Response.ts
models/HostCreateRequest.ts
models/HostDelete200Response.ts
models/HostEdit200Response.ts
models/HostEditRequest.ts
models/HostEnrollCodeCreate200Response.ts
models/HostEnrollCodeCreate200ResponseData.ts
models/HostEnrollCodeCreate200ResponseDataEnrollmentCode.ts
models/HostGet200Response.ts
models/HostMetadata.ts
models/HostsList200Response.ts
models/ModelError.ts
models/Network.ts
models/NetworkGet200Response.ts
models/NetworksList200Response.ts
models/PaginationMetadata.ts
models/PaginationMetadataPage.ts
models/Role.ts
models/RoleCreate200Response.ts
models/RoleCreateRequest.ts
models/RoleEditRequest.ts
models/RolesList200Response.ts
models/Target.ts
models/index.ts
runtime.ts

View File

@ -1 +0,0 @@
6.6.0

View File

@ -1,78 +0,0 @@
/* tslint:disable */
/* eslint-disable */
/**
* Defined Networking API
* <br/> <br/> This API enables automated administration of Defined Networking hosts, roles, logs, and more. To authenticate, obtain an api key to use as a bearer token from your Defined Networking admin panel [API Keys page](https://admin.defined.net/settings/api-keys). API keys must be given the appropriate permission scopes for every method and endpoint, as specified throughout this documentation. Please [contact us](https://www.defined.net/contact?reason=support) for any questions or issues. In the event of a token leak, please take care to [rotate the key](/guides/rotating-api-keys). <div className=\'introduction-end\'></div>
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import * as runtime from '../runtime';
import { AuditLogsList200ResponseFromJSON, AuditLogsList200ResponseToJSON, } from '../models';
/**
*
*/
export class AuditLogsApi extends runtime.BaseAPI {
/**
* Get a paginated list of audit logs. Token scope required: `audit-logs:list` ### Request
* List audit logs
*/
async auditLogsListRaw(requestParameters, initOverrides) {
const queryParameters = {};
if (requestParameters.includeCounts !== undefined) {
queryParameters['includeCounts'] = requestParameters.includeCounts;
}
if (requestParameters.cursor !== undefined) {
queryParameters['cursor'] = requestParameters.cursor;
}
if (requestParameters.pageSize !== undefined) {
queryParameters['pageSize'] = requestParameters.pageSize;
}
if (requestParameters.filterTargetID !== undefined) {
queryParameters['filter.targetID'] = requestParameters.filterTargetID;
}
if (requestParameters.filterTargetType !== undefined) {
queryParameters['filter.targetType'] = requestParameters.filterTargetType;
}
const headerParameters = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/audit-logs`,
method: 'GET',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => AuditLogsList200ResponseFromJSON(jsonValue));
}
/**
* Get a paginated list of audit logs. Token scope required: `audit-logs:list` ### Request
* List audit logs
*/
async auditLogsList(requestParameters = {}, initOverrides) {
const response = await this.auditLogsListRaw(requestParameters, initOverrides);
return await response.value();
}
}
/**
* @export
*/
export const AuditLogsListFilterTargetTypeEnum = {
ApiKey: 'apiKey',
Host: 'host',
Network: 'network',
Role: 'role',
User: 'user',
Ca: 'ca',
OidcProvider: 'oidcProvider'
};
//# sourceMappingURL=AuditLogsApi.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"AuditLogsApi.js","sourceRoot":"","sources":["AuditLogsApi.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,oBAAoB;AACpB;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,OAAO,MAAM,YAAY,CAAC;AAItC,OAAO,EACH,gCAAgC,EAChC,8BAA8B,GACjC,MAAM,WAAW,CAAC;AAUnB;;GAEG;AACH,MAAM,OAAO,YAAa,SAAQ,OAAO,CAAC,OAAO;IAE7C;;;OAGG;IACH,KAAK,CAAC,gBAAgB,CAAC,iBAAuC,EAAE,aAA0D;QACtH,MAAM,eAAe,GAAQ,EAAE,CAAC;QAEhC,IAAI,iBAAiB,CAAC,aAAa,KAAK,SAAS,EAAE;YAC/C,eAAe,CAAC,eAAe,CAAC,GAAG,iBAAiB,CAAC,aAAa,CAAC;SACtE;QAED,IAAI,iBAAiB,CAAC,MAAM,KAAK,SAAS,EAAE;YACxC,eAAe,CAAC,QAAQ,CAAC,GAAG,iBAAiB,CAAC,MAAM,CAAC;SACxD;QAED,IAAI,iBAAiB,CAAC,QAAQ,KAAK,SAAS,EAAE;YAC1C,eAAe,CAAC,UAAU,CAAC,GAAG,iBAAiB,CAAC,QAAQ,CAAC;SAC5D;QAED,IAAI,iBAAiB,CAAC,cAAc,KAAK,SAAS,EAAE;YAChD,eAAe,CAAC,iBAAiB,CAAC,GAAG,iBAAiB,CAAC,cAAc,CAAC;SACzE;QAED,IAAI,iBAAiB,CAAC,gBAAgB,KAAK,SAAS,EAAE;YAClD,eAAe,CAAC,mBAAmB,CAAC,GAAG,iBAAiB,CAAC,gBAAgB,CAAC;SAC7E;QAED,MAAM,gBAAgB,GAAwB,EAAE,CAAC;QAEjD,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,aAAa,CAAC,WAAW,EAAE;YACtD,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC;YAC7C,MAAM,WAAW,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;YAEhD,IAAI,WAAW,EAAE;gBACb,gBAAgB,CAAC,eAAe,CAAC,GAAG,UAAU,WAAW,EAAE,CAAC;aAC/D;SACJ;QACD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC;YAChC,IAAI,EAAE,gBAAgB;YACtB,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,gBAAgB;YACzB,KAAK,EAAE,eAAe;SACzB,EAAE,aAAa,CAAC,CAAC;QAElB,OAAO,IAAI,OAAO,CAAC,eAAe,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,gCAAgC,CAAC,SAAS,CAAC,CAAC,CAAC;IAC7G,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,aAAa,CAAC,oBAA0C,EAAE,EAAE,aAA0D;QACxH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,iBAAiB,EAAE,aAAa,CAAC,CAAC;QAC/E,OAAO,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC;IAClC,CAAC;CAEJ;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,iCAAiC,GAAG;IAC7C,MAAM,EAAE,QAAQ;IAChB,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,MAAM;IACZ,EAAE,EAAE,IAAI;IACR,YAAY,EAAE,cAAc;CACtB,CAAC"}

View File

@ -1,108 +0,0 @@
/* tslint:disable */
/* eslint-disable */
/**
* Defined Networking API
* <br/> <br/> This API enables automated administration of Defined Networking hosts, roles, logs, and more. To authenticate, obtain an api key to use as a bearer token from your Defined Networking admin panel [API Keys page](https://admin.defined.net/settings/api-keys). API keys must be given the appropriate permission scopes for every method and endpoint, as specified throughout this documentation. Please [contact us](https://www.defined.net/contact?reason=support) for any questions or issues. In the event of a token leak, please take care to [rotate the key](/guides/rotating-api-keys). <div className=\'introduction-end\'></div>
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import * as runtime from '../runtime';
import type {
AuditLogsList200Response,
} from '../models';
import {
AuditLogsList200ResponseFromJSON,
AuditLogsList200ResponseToJSON,
} from '../models';
export interface AuditLogsListRequest {
includeCounts?: boolean;
cursor?: string;
pageSize?: number;
filterTargetID?: string;
filterTargetType?: AuditLogsListFilterTargetTypeEnum;
}
/**
*
*/
export class AuditLogsApi extends runtime.BaseAPI {
/**
* Get a paginated list of audit logs. Token scope required: `audit-logs:list` ### Request
* List audit logs
*/
async auditLogsListRaw(requestParameters: AuditLogsListRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<AuditLogsList200Response>> {
const queryParameters: any = {};
if (requestParameters.includeCounts !== undefined) {
queryParameters['includeCounts'] = requestParameters.includeCounts;
}
if (requestParameters.cursor !== undefined) {
queryParameters['cursor'] = requestParameters.cursor;
}
if (requestParameters.pageSize !== undefined) {
queryParameters['pageSize'] = requestParameters.pageSize;
}
if (requestParameters.filterTargetID !== undefined) {
queryParameters['filter.targetID'] = requestParameters.filterTargetID;
}
if (requestParameters.filterTargetType !== undefined) {
queryParameters['filter.targetType'] = requestParameters.filterTargetType;
}
const headerParameters: runtime.HTTPHeaders = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/audit-logs`,
method: 'GET',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => AuditLogsList200ResponseFromJSON(jsonValue));
}
/**
* Get a paginated list of audit logs. Token scope required: `audit-logs:list` ### Request
* List audit logs
*/
async auditLogsList(requestParameters: AuditLogsListRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<AuditLogsList200Response> {
const response = await this.auditLogsListRaw(requestParameters, initOverrides);
return await response.value();
}
}
/**
* @export
*/
export const AuditLogsListFilterTargetTypeEnum = {
ApiKey: 'apiKey',
Host: 'host',
Network: 'network',
Role: 'role',
User: 'user',
Ca: 'ca',
OidcProvider: 'oidcProvider'
} as const;
export type AuditLogsListFilterTargetTypeEnum = typeof AuditLogsListFilterTargetTypeEnum[keyof typeof AuditLogsListFilterTargetTypeEnum];

View File

@ -1,51 +0,0 @@
/* tslint:disable */
/* eslint-disable */
/**
* Defined Networking API
* <br/> <br/> This API enables automated administration of Defined Networking hosts, roles, logs, and more. To authenticate, obtain an api key to use as a bearer token from your Defined Networking admin panel [API Keys page](https://admin.defined.net/settings/api-keys). API keys must be given the appropriate permission scopes for every method and endpoint, as specified throughout this documentation. Please [contact us](https://www.defined.net/contact?reason=support) for any questions or issues. In the event of a token leak, please take care to [rotate the key](/guides/rotating-api-keys). <div className=\'introduction-end\'></div>
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import * as runtime from '../runtime';
import { DownloadsList200ResponseFromJSON, DownloadsList200ResponseToJSON, } from '../models';
/**
*
*/
export class DownloadsApi extends runtime.BaseAPI {
/**
* Get a list of recently released software download links and basic info. This endpoint is unauthenticated. ### Request
* List software downloads
*/
async downloadsListRaw(initOverrides) {
const queryParameters = {};
const headerParameters = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/downloads`,
method: 'GET',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => DownloadsList200ResponseFromJSON(jsonValue));
}
/**
* Get a list of recently released software download links and basic info. This endpoint is unauthenticated. ### Request
* List software downloads
*/
async downloadsList(initOverrides) {
const response = await this.downloadsListRaw(initOverrides);
return await response.value();
}
}
//# sourceMappingURL=DownloadsApi.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"DownloadsApi.js","sourceRoot":"","sources":["DownloadsApi.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,oBAAoB;AACpB;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,OAAO,MAAM,YAAY,CAAC;AAItC,OAAO,EACH,gCAAgC,EAChC,8BAA8B,GACjC,MAAM,WAAW,CAAC;AAEnB;;GAEG;AACH,MAAM,OAAO,YAAa,SAAQ,OAAO,CAAC,OAAO;IAE7C;;;OAGG;IACH,KAAK,CAAC,gBAAgB,CAAC,aAA0D;QAC7E,MAAM,eAAe,GAAQ,EAAE,CAAC;QAEhC,MAAM,gBAAgB,GAAwB,EAAE,CAAC;QAEjD,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,aAAa,CAAC,WAAW,EAAE;YACtD,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC;YAC7C,MAAM,WAAW,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;YAEhD,IAAI,WAAW,EAAE;gBACb,gBAAgB,CAAC,eAAe,CAAC,GAAG,UAAU,WAAW,EAAE,CAAC;aAC/D;SACJ;QACD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC;YAChC,IAAI,EAAE,eAAe;YACrB,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,gBAAgB;YACzB,KAAK,EAAE,eAAe;SACzB,EAAE,aAAa,CAAC,CAAC;QAElB,OAAO,IAAI,OAAO,CAAC,eAAe,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,gCAAgC,CAAC,SAAS,CAAC,CAAC,CAAC;IAC7G,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,aAAa,CAAC,aAA0D;QAC1E,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC;QAC5D,OAAO,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC;IAClC,CAAC;CAEJ"}

View File

@ -1,66 +0,0 @@
/* tslint:disable */
/* eslint-disable */
/**
* Defined Networking API
* <br/> <br/> This API enables automated administration of Defined Networking hosts, roles, logs, and more. To authenticate, obtain an api key to use as a bearer token from your Defined Networking admin panel [API Keys page](https://admin.defined.net/settings/api-keys). API keys must be given the appropriate permission scopes for every method and endpoint, as specified throughout this documentation. Please [contact us](https://www.defined.net/contact?reason=support) for any questions or issues. In the event of a token leak, please take care to [rotate the key](/guides/rotating-api-keys). <div className=\'introduction-end\'></div>
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import * as runtime from '../runtime';
import type {
DownloadsList200Response,
} from '../models';
import {
DownloadsList200ResponseFromJSON,
DownloadsList200ResponseToJSON,
} from '../models';
/**
*
*/
export class DownloadsApi extends runtime.BaseAPI {
/**
* Get a list of recently released software download links and basic info. This endpoint is unauthenticated. ### Request
* List software downloads
*/
async downloadsListRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<DownloadsList200Response>> {
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/downloads`,
method: 'GET',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => DownloadsList200ResponseFromJSON(jsonValue));
}
/**
* Get a list of recently released software download links and basic info. This endpoint is unauthenticated. ### Request
* List software downloads
*/
async downloadsList(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<DownloadsList200Response> {
const response = await this.downloadsListRaw(initOverrides);
return await response.value();
}
}

View File

@ -1,332 +0,0 @@
/* tslint:disable */
/* eslint-disable */
/**
* Defined Networking API
* <br/> <br/> This API enables automated administration of Defined Networking hosts, roles, logs, and more. To authenticate, obtain an api key to use as a bearer token from your Defined Networking admin panel [API Keys page](https://admin.defined.net/settings/api-keys). API keys must be given the appropriate permission scopes for every method and endpoint, as specified throughout this documentation. Please [contact us](https://www.defined.net/contact?reason=support) for any questions or issues. In the event of a token leak, please take care to [rotate the key](/guides/rotating-api-keys). <div className=\'introduction-end\'></div>
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import * as runtime from '../runtime';
import { HostAndEnrollCodeCreate200ResponseFromJSON, HostAndEnrollCodeCreate200ResponseToJSON, HostAndEnrollCodeCreate400ResponseFromJSON, HostAndEnrollCodeCreate400ResponseToJSON, HostBlock200ResponseFromJSON, HostBlock200ResponseToJSON, HostCreate200ResponseFromJSON, HostCreate200ResponseToJSON, HostCreate400ResponseFromJSON, HostCreate400ResponseToJSON, HostCreateRequestFromJSON, HostCreateRequestToJSON, HostDelete200ResponseFromJSON, HostDelete200ResponseToJSON, HostEdit200ResponseFromJSON, HostEdit200ResponseToJSON, HostEditRequestFromJSON, HostEditRequestToJSON, HostEnrollCodeCreate200ResponseFromJSON, HostEnrollCodeCreate200ResponseToJSON, HostGet200ResponseFromJSON, HostGet200ResponseToJSON, HostsList200ResponseFromJSON, HostsList200ResponseToJSON, } from '../models';
/**
*
*/
export class HostsApi extends runtime.BaseAPI {
/**
* Token scopes required: `hosts:create`, `hosts:enroll` ### Request
* Create host & enrollment code
*/
async hostAndEnrollCodeCreateRaw(requestParameters, initOverrides) {
if (requestParameters.hostCreateRequest === null || requestParameters.hostCreateRequest === undefined) {
throw new runtime.RequiredError('hostCreateRequest', 'Required parameter requestParameters.hostCreateRequest was null or undefined when calling hostAndEnrollCodeCreate.');
}
const queryParameters = {};
const headerParameters = {};
headerParameters['Content-Type'] = 'application/json';
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/host-and-enrollment-code`,
method: 'POST',
headers: headerParameters,
query: queryParameters,
body: HostCreateRequestToJSON(requestParameters.hostCreateRequest),
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => HostAndEnrollCodeCreate200ResponseFromJSON(jsonValue));
}
/**
* Token scopes required: `hosts:create`, `hosts:enroll` ### Request
* Create host & enrollment code
*/
async hostAndEnrollCodeCreate(requestParameters, initOverrides) {
const response = await this.hostAndEnrollCodeCreateRaw(requestParameters, initOverrides);
return await response.value();
}
/**
* Prevent a host from being able to interact with other nodes on your network. See https://www.defined.net/blog/blocklisting/ for more details. To unblock, re-enroll the host. Token scope required: `hosts:block` ### Request
* Block host
*/
async hostBlockRaw(requestParameters, initOverrides) {
if (requestParameters.hostID === null || requestParameters.hostID === undefined) {
throw new runtime.RequiredError('hostID', 'Required parameter requestParameters.hostID was null or undefined when calling hostBlock.');
}
const queryParameters = {};
const headerParameters = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/hosts/{hostID}/block`.replace(`{${"hostID"}}`, encodeURIComponent(String(requestParameters.hostID))),
method: 'POST',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => HostBlock200ResponseFromJSON(jsonValue));
}
/**
* Prevent a host from being able to interact with other nodes on your network. See https://www.defined.net/blog/blocklisting/ for more details. To unblock, re-enroll the host. Token scope required: `hosts:block` ### Request
* Block host
*/
async hostBlock(requestParameters, initOverrides) {
const response = await this.hostBlockRaw(requestParameters, initOverrides);
return await response.value();
}
/**
* Create a new host, lighthouse, or relay. Token scope required: `hosts:create` ### Request
* Create host
*/
async hostCreateRaw(requestParameters, initOverrides) {
if (requestParameters.hostCreateRequest === null || requestParameters.hostCreateRequest === undefined) {
throw new runtime.RequiredError('hostCreateRequest', 'Required parameter requestParameters.hostCreateRequest was null or undefined when calling hostCreate.');
}
const queryParameters = {};
const headerParameters = {};
headerParameters['Content-Type'] = 'application/json';
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/hosts`,
method: 'POST',
headers: headerParameters,
query: queryParameters,
body: HostCreateRequestToJSON(requestParameters.hostCreateRequest),
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => HostCreate200ResponseFromJSON(jsonValue));
}
/**
* Create a new host, lighthouse, or relay. Token scope required: `hosts:create` ### Request
* Create host
*/
async hostCreate(requestParameters, initOverrides) {
const response = await this.hostCreateRaw(requestParameters, initOverrides);
return await response.value();
}
/**
* Token scope required: `hosts:delete` ### Request
* Delete host
*/
async hostDeleteRaw(requestParameters, initOverrides) {
if (requestParameters.hostID === null || requestParameters.hostID === undefined) {
throw new runtime.RequiredError('hostID', 'Required parameter requestParameters.hostID was null or undefined when calling hostDelete.');
}
const queryParameters = {};
const headerParameters = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/hosts/{hostID}`.replace(`{${"hostID"}}`, encodeURIComponent(String(requestParameters.hostID))),
method: 'DELETE',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => HostDelete200ResponseFromJSON(jsonValue));
}
/**
* Token scope required: `hosts:delete` ### Request
* Delete host
*/
async hostDelete(requestParameters, initOverrides) {
const response = await this.hostDeleteRaw(requestParameters, initOverrides);
return await response.value();
}
/**
* Token scope required: `hosts:update` :::caution Any properties not provided in the request will be reset to their default values. ::: ### Request
* Edit host
*/
async hostEditRaw(requestParameters, initOverrides) {
if (requestParameters.hostID === null || requestParameters.hostID === undefined) {
throw new runtime.RequiredError('hostID', 'Required parameter requestParameters.hostID was null or undefined when calling hostEdit.');
}
if (requestParameters.hostEditRequest === null || requestParameters.hostEditRequest === undefined) {
throw new runtime.RequiredError('hostEditRequest', 'Required parameter requestParameters.hostEditRequest was null or undefined when calling hostEdit.');
}
const queryParameters = {};
const headerParameters = {};
headerParameters['Content-Type'] = 'application/json';
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/hosts/{hostID}`.replace(`{${"hostID"}}`, encodeURIComponent(String(requestParameters.hostID))),
method: 'PUT',
headers: headerParameters,
query: queryParameters,
body: HostEditRequestToJSON(requestParameters.hostEditRequest),
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => HostEdit200ResponseFromJSON(jsonValue));
}
/**
* Token scope required: `hosts:update` :::caution Any properties not provided in the request will be reset to their default values. ::: ### Request
* Edit host
*/
async hostEdit(requestParameters, initOverrides) {
const response = await this.hostEditRaw(requestParameters, initOverrides);
return await response.value();
}
/**
* Obtain a code that can be used with the `dnclient enroll` command on a host, lighthouse, or relay to enroll it into your Managed Nebula network. Token scope required: `hosts:enroll` ### Request
* Create enrollment code
*/
async hostEnrollCodeCreateRaw(requestParameters, initOverrides) {
if (requestParameters.hostID === null || requestParameters.hostID === undefined) {
throw new runtime.RequiredError('hostID', 'Required parameter requestParameters.hostID was null or undefined when calling hostEnrollCodeCreate.');
}
const queryParameters = {};
const headerParameters = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/hosts/{hostID}/enrollment-code`.replace(`{${"hostID"}}`, encodeURIComponent(String(requestParameters.hostID))),
method: 'POST',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => HostEnrollCodeCreate200ResponseFromJSON(jsonValue));
}
/**
* Obtain a code that can be used with the `dnclient enroll` command on a host, lighthouse, or relay to enroll it into your Managed Nebula network. Token scope required: `hosts:enroll` ### Request
* Create enrollment code
*/
async hostEnrollCodeCreate(requestParameters, initOverrides) {
const response = await this.hostEnrollCodeCreateRaw(requestParameters, initOverrides);
return await response.value();
}
/**
* Fetch information about a particular host, lighthouse, or relay. Token scope required: `hosts:read` ### Request
* Get host
*/
async hostGetRaw(requestParameters, initOverrides) {
if (requestParameters.hostID === null || requestParameters.hostID === undefined) {
throw new runtime.RequiredError('hostID', 'Required parameter requestParameters.hostID was null or undefined when calling hostGet.');
}
const queryParameters = {};
const headerParameters = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/hosts/{hostID}`.replace(`{${"hostID"}}`, encodeURIComponent(String(requestParameters.hostID))),
method: 'GET',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => HostGet200ResponseFromJSON(jsonValue));
}
/**
* Fetch information about a particular host, lighthouse, or relay. Token scope required: `hosts:read` ### Request
* Get host
*/
async hostGet(requestParameters, initOverrides) {
const response = await this.hostGetRaw(requestParameters, initOverrides);
return await response.value();
}
/**
* Get a paginated list of hosts, lighthouses, and relays. Token scope required: `hosts:list` ### Request
* List hosts
*/
async hostsListRaw(requestParameters, initOverrides) {
const queryParameters = {};
if (requestParameters.includeCounts !== undefined) {
queryParameters['includeCounts'] = requestParameters.includeCounts;
}
if (requestParameters.cursor !== undefined) {
queryParameters['cursor'] = requestParameters.cursor;
}
if (requestParameters.pageSize !== undefined) {
queryParameters['pageSize'] = requestParameters.pageSize;
}
if (requestParameters.filterIsBlocked !== undefined) {
queryParameters['filter.isBlocked'] = requestParameters.filterIsBlocked;
}
if (requestParameters.filterIsLighthouse !== undefined) {
queryParameters['filter.isLighthouse'] = requestParameters.filterIsLighthouse;
}
if (requestParameters.filterIsRelay !== undefined) {
queryParameters['filter.isRelay'] = requestParameters.filterIsRelay;
}
if (requestParameters.filterMetadataLastSeenAt !== undefined) {
queryParameters['filter.metadata.lastSeenAt'] = requestParameters.filterMetadataLastSeenAt;
}
if (requestParameters.filterMetadataPlatform !== undefined) {
queryParameters['filter.metadata.platform'] = requestParameters.filterMetadataPlatform;
}
if (requestParameters.filterMetadataUpdateAvailable !== undefined) {
queryParameters['filter.metadata.updateAvailable'] = requestParameters.filterMetadataUpdateAvailable;
}
const headerParameters = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/hosts`,
method: 'GET',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => HostsList200ResponseFromJSON(jsonValue));
}
/**
* Get a paginated list of hosts, lighthouses, and relays. Token scope required: `hosts:list` ### Request
* List hosts
*/
async hostsList(requestParameters = {}, initOverrides) {
const response = await this.hostsListRaw(requestParameters, initOverrides);
return await response.value();
}
}
/**
* @export
*/
export const HostsListFilterMetadataLastSeenAtEnum = {
Null: 'null'
};
/**
* @export
*/
export const HostsListFilterMetadataPlatformEnum = {
Mobile: 'mobile',
Dnclient: 'dnclient',
Null: 'null'
};
//# sourceMappingURL=HostsApi.js.map

File diff suppressed because one or more lines are too long

View File

@ -1,486 +0,0 @@
/* tslint:disable */
/* eslint-disable */
/**
* Defined Networking API
* <br/> <br/> This API enables automated administration of Defined Networking hosts, roles, logs, and more. To authenticate, obtain an api key to use as a bearer token from your Defined Networking admin panel [API Keys page](https://admin.defined.net/settings/api-keys). API keys must be given the appropriate permission scopes for every method and endpoint, as specified throughout this documentation. Please [contact us](https://www.defined.net/contact?reason=support) for any questions or issues. In the event of a token leak, please take care to [rotate the key](/guides/rotating-api-keys). <div className=\'introduction-end\'></div>
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import * as runtime from '../runtime';
import type {
HostAndEnrollCodeCreate200Response,
HostAndEnrollCodeCreate400Response,
HostBlock200Response,
HostCreate200Response,
HostCreate400Response,
HostCreateRequest,
HostDelete200Response,
HostEdit200Response,
HostEditRequest,
HostEnrollCodeCreate200Response,
HostGet200Response,
HostsList200Response,
} from '../models';
import {
HostAndEnrollCodeCreate200ResponseFromJSON,
HostAndEnrollCodeCreate200ResponseToJSON,
HostAndEnrollCodeCreate400ResponseFromJSON,
HostAndEnrollCodeCreate400ResponseToJSON,
HostBlock200ResponseFromJSON,
HostBlock200ResponseToJSON,
HostCreate200ResponseFromJSON,
HostCreate200ResponseToJSON,
HostCreate400ResponseFromJSON,
HostCreate400ResponseToJSON,
HostCreateRequestFromJSON,
HostCreateRequestToJSON,
HostDelete200ResponseFromJSON,
HostDelete200ResponseToJSON,
HostEdit200ResponseFromJSON,
HostEdit200ResponseToJSON,
HostEditRequestFromJSON,
HostEditRequestToJSON,
HostEnrollCodeCreate200ResponseFromJSON,
HostEnrollCodeCreate200ResponseToJSON,
HostGet200ResponseFromJSON,
HostGet200ResponseToJSON,
HostsList200ResponseFromJSON,
HostsList200ResponseToJSON,
} from '../models';
export interface HostAndEnrollCodeCreateRequest {
hostCreateRequest: HostCreateRequest;
}
export interface HostBlockRequest {
hostID: string;
}
export interface HostCreateOperationRequest {
hostCreateRequest: HostCreateRequest;
}
export interface HostDeleteRequest {
hostID: string;
}
export interface HostEditOperationRequest {
hostID: string;
hostEditRequest: HostEditRequest;
}
export interface HostEnrollCodeCreateRequest {
hostID: string;
}
export interface HostGetRequest {
hostID: string;
}
export interface HostsListRequest {
includeCounts?: boolean;
cursor?: string;
pageSize?: number;
filterIsBlocked?: boolean;
filterIsLighthouse?: boolean;
filterIsRelay?: boolean;
filterMetadataLastSeenAt?: HostsListFilterMetadataLastSeenAtEnum;
filterMetadataPlatform?: HostsListFilterMetadataPlatformEnum;
filterMetadataUpdateAvailable?: boolean;
}
/**
*
*/
export class HostsApi extends runtime.BaseAPI {
/**
* Token scopes required: `hosts:create`, `hosts:enroll` ### Request
* Create host & enrollment code
*/
async hostAndEnrollCodeCreateRaw(requestParameters: HostAndEnrollCodeCreateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<HostAndEnrollCodeCreate200Response>> {
if (requestParameters.hostCreateRequest === null || requestParameters.hostCreateRequest === undefined) {
throw new runtime.RequiredError('hostCreateRequest','Required parameter requestParameters.hostCreateRequest was null or undefined when calling hostAndEnrollCodeCreate.');
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
headerParameters['Content-Type'] = 'application/json';
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/host-and-enrollment-code`,
method: 'POST',
headers: headerParameters,
query: queryParameters,
body: HostCreateRequestToJSON(requestParameters.hostCreateRequest),
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => HostAndEnrollCodeCreate200ResponseFromJSON(jsonValue));
}
/**
* Token scopes required: `hosts:create`, `hosts:enroll` ### Request
* Create host & enrollment code
*/
async hostAndEnrollCodeCreate(requestParameters: HostAndEnrollCodeCreateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<HostAndEnrollCodeCreate200Response> {
const response = await this.hostAndEnrollCodeCreateRaw(requestParameters, initOverrides);
return await response.value();
}
/**
* Prevent a host from being able to interact with other nodes on your network. See https://www.defined.net/blog/blocklisting/ for more details. To unblock, re-enroll the host. Token scope required: `hosts:block` ### Request
* Block host
*/
async hostBlockRaw(requestParameters: HostBlockRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<HostBlock200Response>> {
if (requestParameters.hostID === null || requestParameters.hostID === undefined) {
throw new runtime.RequiredError('hostID','Required parameter requestParameters.hostID was null or undefined when calling hostBlock.');
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/hosts/{hostID}/block`.replace(`{${"hostID"}}`, encodeURIComponent(String(requestParameters.hostID))),
method: 'POST',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => HostBlock200ResponseFromJSON(jsonValue));
}
/**
* Prevent a host from being able to interact with other nodes on your network. See https://www.defined.net/blog/blocklisting/ for more details. To unblock, re-enroll the host. Token scope required: `hosts:block` ### Request
* Block host
*/
async hostBlock(requestParameters: HostBlockRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<HostBlock200Response> {
const response = await this.hostBlockRaw(requestParameters, initOverrides);
return await response.value();
}
/**
* Create a new host, lighthouse, or relay. Token scope required: `hosts:create` ### Request
* Create host
*/
async hostCreateRaw(requestParameters: HostCreateOperationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<HostCreate200Response>> {
if (requestParameters.hostCreateRequest === null || requestParameters.hostCreateRequest === undefined) {
throw new runtime.RequiredError('hostCreateRequest','Required parameter requestParameters.hostCreateRequest was null or undefined when calling hostCreate.');
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
headerParameters['Content-Type'] = 'application/json';
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/hosts`,
method: 'POST',
headers: headerParameters,
query: queryParameters,
body: HostCreateRequestToJSON(requestParameters.hostCreateRequest),
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => HostCreate200ResponseFromJSON(jsonValue));
}
/**
* Create a new host, lighthouse, or relay. Token scope required: `hosts:create` ### Request
* Create host
*/
async hostCreate(requestParameters: HostCreateOperationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<HostCreate200Response> {
const response = await this.hostCreateRaw(requestParameters, initOverrides);
return await response.value();
}
/**
* Token scope required: `hosts:delete` ### Request
* Delete host
*/
async hostDeleteRaw(requestParameters: HostDeleteRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<HostDelete200Response>> {
if (requestParameters.hostID === null || requestParameters.hostID === undefined) {
throw new runtime.RequiredError('hostID','Required parameter requestParameters.hostID was null or undefined when calling hostDelete.');
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/hosts/{hostID}`.replace(`{${"hostID"}}`, encodeURIComponent(String(requestParameters.hostID))),
method: 'DELETE',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => HostDelete200ResponseFromJSON(jsonValue));
}
/**
* Token scope required: `hosts:delete` ### Request
* Delete host
*/
async hostDelete(requestParameters: HostDeleteRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<HostDelete200Response> {
const response = await this.hostDeleteRaw(requestParameters, initOverrides);
return await response.value();
}
/**
* Token scope required: `hosts:update` :::caution Any properties not provided in the request will be reset to their default values. ::: ### Request
* Edit host
*/
async hostEditRaw(requestParameters: HostEditOperationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<HostEdit200Response>> {
if (requestParameters.hostID === null || requestParameters.hostID === undefined) {
throw new runtime.RequiredError('hostID','Required parameter requestParameters.hostID was null or undefined when calling hostEdit.');
}
if (requestParameters.hostEditRequest === null || requestParameters.hostEditRequest === undefined) {
throw new runtime.RequiredError('hostEditRequest','Required parameter requestParameters.hostEditRequest was null or undefined when calling hostEdit.');
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
headerParameters['Content-Type'] = 'application/json';
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/hosts/{hostID}`.replace(`{${"hostID"}}`, encodeURIComponent(String(requestParameters.hostID))),
method: 'PUT',
headers: headerParameters,
query: queryParameters,
body: HostEditRequestToJSON(requestParameters.hostEditRequest),
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => HostEdit200ResponseFromJSON(jsonValue));
}
/**
* Token scope required: `hosts:update` :::caution Any properties not provided in the request will be reset to their default values. ::: ### Request
* Edit host
*/
async hostEdit(requestParameters: HostEditOperationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<HostEdit200Response> {
const response = await this.hostEditRaw(requestParameters, initOverrides);
return await response.value();
}
/**
* Obtain a code that can be used with the `dnclient enroll` command on a host, lighthouse, or relay to enroll it into your Managed Nebula network. Token scope required: `hosts:enroll` ### Request
* Create enrollment code
*/
async hostEnrollCodeCreateRaw(requestParameters: HostEnrollCodeCreateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<HostEnrollCodeCreate200Response>> {
if (requestParameters.hostID === null || requestParameters.hostID === undefined) {
throw new runtime.RequiredError('hostID','Required parameter requestParameters.hostID was null or undefined when calling hostEnrollCodeCreate.');
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/hosts/{hostID}/enrollment-code`.replace(`{${"hostID"}}`, encodeURIComponent(String(requestParameters.hostID))),
method: 'POST',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => HostEnrollCodeCreate200ResponseFromJSON(jsonValue));
}
/**
* Obtain a code that can be used with the `dnclient enroll` command on a host, lighthouse, or relay to enroll it into your Managed Nebula network. Token scope required: `hosts:enroll` ### Request
* Create enrollment code
*/
async hostEnrollCodeCreate(requestParameters: HostEnrollCodeCreateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<HostEnrollCodeCreate200Response> {
const response = await this.hostEnrollCodeCreateRaw(requestParameters, initOverrides);
return await response.value();
}
/**
* Fetch information about a particular host, lighthouse, or relay. Token scope required: `hosts:read` ### Request
* Get host
*/
async hostGetRaw(requestParameters: HostGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<HostGet200Response>> {
if (requestParameters.hostID === null || requestParameters.hostID === undefined) {
throw new runtime.RequiredError('hostID','Required parameter requestParameters.hostID was null or undefined when calling hostGet.');
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/hosts/{hostID}`.replace(`{${"hostID"}}`, encodeURIComponent(String(requestParameters.hostID))),
method: 'GET',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => HostGet200ResponseFromJSON(jsonValue));
}
/**
* Fetch information about a particular host, lighthouse, or relay. Token scope required: `hosts:read` ### Request
* Get host
*/
async hostGet(requestParameters: HostGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<HostGet200Response> {
const response = await this.hostGetRaw(requestParameters, initOverrides);
return await response.value();
}
/**
* Get a paginated list of hosts, lighthouses, and relays. Token scope required: `hosts:list` ### Request
* List hosts
*/
async hostsListRaw(requestParameters: HostsListRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<HostsList200Response>> {
const queryParameters: any = {};
if (requestParameters.includeCounts !== undefined) {
queryParameters['includeCounts'] = requestParameters.includeCounts;
}
if (requestParameters.cursor !== undefined) {
queryParameters['cursor'] = requestParameters.cursor;
}
if (requestParameters.pageSize !== undefined) {
queryParameters['pageSize'] = requestParameters.pageSize;
}
if (requestParameters.filterIsBlocked !== undefined) {
queryParameters['filter.isBlocked'] = requestParameters.filterIsBlocked;
}
if (requestParameters.filterIsLighthouse !== undefined) {
queryParameters['filter.isLighthouse'] = requestParameters.filterIsLighthouse;
}
if (requestParameters.filterIsRelay !== undefined) {
queryParameters['filter.isRelay'] = requestParameters.filterIsRelay;
}
if (requestParameters.filterMetadataLastSeenAt !== undefined) {
queryParameters['filter.metadata.lastSeenAt'] = requestParameters.filterMetadataLastSeenAt;
}
if (requestParameters.filterMetadataPlatform !== undefined) {
queryParameters['filter.metadata.platform'] = requestParameters.filterMetadataPlatform;
}
if (requestParameters.filterMetadataUpdateAvailable !== undefined) {
queryParameters['filter.metadata.updateAvailable'] = requestParameters.filterMetadataUpdateAvailable;
}
const headerParameters: runtime.HTTPHeaders = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/hosts`,
method: 'GET',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => HostsList200ResponseFromJSON(jsonValue));
}
/**
* Get a paginated list of hosts, lighthouses, and relays. Token scope required: `hosts:list` ### Request
* List hosts
*/
async hostsList(requestParameters: HostsListRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<HostsList200Response> {
const response = await this.hostsListRaw(requestParameters, initOverrides);
return await response.value();
}
}
/**
* @export
*/
export const HostsListFilterMetadataLastSeenAtEnum = {
Null: 'null'
} as const;
export type HostsListFilterMetadataLastSeenAtEnum = typeof HostsListFilterMetadataLastSeenAtEnum[keyof typeof HostsListFilterMetadataLastSeenAtEnum];
/**
* @export
*/
export const HostsListFilterMetadataPlatformEnum = {
Mobile: 'mobile',
Dnclient: 'dnclient',
Null: 'null'
} as const;
export type HostsListFilterMetadataPlatformEnum = typeof HostsListFilterMetadataPlatformEnum[keyof typeof HostsListFilterMetadataPlatformEnum];

View File

@ -1,93 +0,0 @@
/* tslint:disable */
/* eslint-disable */
/**
* Defined Networking API
* <br/> <br/> This API enables automated administration of Defined Networking hosts, roles, logs, and more. To authenticate, obtain an api key to use as a bearer token from your Defined Networking admin panel [API Keys page](https://admin.defined.net/settings/api-keys). API keys must be given the appropriate permission scopes for every method and endpoint, as specified throughout this documentation. Please [contact us](https://www.defined.net/contact?reason=support) for any questions or issues. In the event of a token leak, please take care to [rotate the key](/guides/rotating-api-keys). <div className=\'introduction-end\'></div>
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import * as runtime from '../runtime';
import { NetworkGet200ResponseFromJSON, NetworkGet200ResponseToJSON, NetworksList200ResponseFromJSON, NetworksList200ResponseToJSON, } from '../models';
/**
*
*/
export class NetworksApi extends runtime.BaseAPI {
/**
* Fetch information about a particular network. Token scope required: `networks:read` ### Request
* Get network
*/
async networkGetRaw(requestParameters, initOverrides) {
if (requestParameters.networkID === null || requestParameters.networkID === undefined) {
throw new runtime.RequiredError('networkID', 'Required parameter requestParameters.networkID was null or undefined when calling networkGet.');
}
const queryParameters = {};
const headerParameters = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/networks/{networkID}`.replace(`{${"networkID"}}`, encodeURIComponent(String(requestParameters.networkID))),
method: 'GET',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => NetworkGet200ResponseFromJSON(jsonValue));
}
/**
* Fetch information about a particular network. Token scope required: `networks:read` ### Request
* Get network
*/
async networkGet(requestParameters, initOverrides) {
const response = await this.networkGetRaw(requestParameters, initOverrides);
return await response.value();
}
/**
* Get a paginated list of networks. :::note Currently, there is a limit of one network per Defined Networking account. ::: Token scope required: `networks:list` ### Request
* List networks
*/
async networksListRaw(requestParameters, initOverrides) {
const queryParameters = {};
if (requestParameters.includeCounts !== undefined) {
queryParameters['includeCounts'] = requestParameters.includeCounts;
}
if (requestParameters.cursor !== undefined) {
queryParameters['cursor'] = requestParameters.cursor;
}
if (requestParameters.pageSize !== undefined) {
queryParameters['pageSize'] = requestParameters.pageSize;
}
const headerParameters = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/networks`,
method: 'GET',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => NetworksList200ResponseFromJSON(jsonValue));
}
/**
* Get a paginated list of networks. :::note Currently, there is a limit of one network per Defined Networking account. ::: Token scope required: `networks:list` ### Request
* List networks
*/
async networksList(requestParameters = {}, initOverrides) {
const response = await this.networksListRaw(requestParameters, initOverrides);
return await response.value();
}
}
//# sourceMappingURL=NetworksApi.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"NetworksApi.js","sourceRoot":"","sources":["NetworksApi.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,oBAAoB;AACpB;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,OAAO,MAAM,YAAY,CAAC;AAKtC,OAAO,EACH,6BAA6B,EAC7B,2BAA2B,EAC3B,+BAA+B,EAC/B,6BAA6B,GAChC,MAAM,WAAW,CAAC;AAYnB;;GAEG;AACH,MAAM,OAAO,WAAY,SAAQ,OAAO,CAAC,OAAO;IAE5C;;;OAGG;IACH,KAAK,CAAC,aAAa,CAAC,iBAAoC,EAAE,aAA0D;QAChH,IAAI,iBAAiB,CAAC,SAAS,KAAK,IAAI,IAAI,iBAAiB,CAAC,SAAS,KAAK,SAAS,EAAE;YACnF,MAAM,IAAI,OAAO,CAAC,aAAa,CAAC,WAAW,EAAC,+FAA+F,CAAC,CAAC;SAChJ;QAED,MAAM,eAAe,GAAQ,EAAE,CAAC;QAEhC,MAAM,gBAAgB,GAAwB,EAAE,CAAC;QAEjD,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,aAAa,CAAC,WAAW,EAAE;YACtD,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC;YAC7C,MAAM,WAAW,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;YAEhD,IAAI,WAAW,EAAE;gBACb,gBAAgB,CAAC,eAAe,CAAC,GAAG,UAAU,WAAW,EAAE,CAAC;aAC/D;SACJ;QACD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC;YAChC,IAAI,EAAE,0BAA0B,CAAC,OAAO,CAAC,IAAI,WAAW,GAAG,EAAE,kBAAkB,CAAC,MAAM,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC,CAAC;YACrH,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,gBAAgB;YACzB,KAAK,EAAE,eAAe;SACzB,EAAE,aAAa,CAAC,CAAC;QAElB,OAAO,IAAI,OAAO,CAAC,eAAe,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,6BAA6B,CAAC,SAAS,CAAC,CAAC,CAAC;IAC1G,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,UAAU,CAAC,iBAAoC,EAAE,aAA0D;QAC7G,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,iBAAiB,EAAE,aAAa,CAAC,CAAC;QAC5E,OAAO,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC;IAClC,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,eAAe,CAAC,iBAAsC,EAAE,aAA0D;QACpH,MAAM,eAAe,GAAQ,EAAE,CAAC;QAEhC,IAAI,iBAAiB,CAAC,aAAa,KAAK,SAAS,EAAE;YAC/C,eAAe,CAAC,eAAe,CAAC,GAAG,iBAAiB,CAAC,aAAa,CAAC;SACtE;QAED,IAAI,iBAAiB,CAAC,MAAM,KAAK,SAAS,EAAE;YACxC,eAAe,CAAC,QAAQ,CAAC,GAAG,iBAAiB,CAAC,MAAM,CAAC;SACxD;QAED,IAAI,iBAAiB,CAAC,QAAQ,KAAK,SAAS,EAAE;YAC1C,eAAe,CAAC,UAAU,CAAC,GAAG,iBAAiB,CAAC,QAAQ,CAAC;SAC5D;QAED,MAAM,gBAAgB,GAAwB,EAAE,CAAC;QAEjD,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,aAAa,CAAC,WAAW,EAAE;YACtD,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC;YAC7C,MAAM,WAAW,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;YAEhD,IAAI,WAAW,EAAE;gBACb,gBAAgB,CAAC,eAAe,CAAC,GAAG,UAAU,WAAW,EAAE,CAAC;aAC/D;SACJ;QACD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC;YAChC,IAAI,EAAE,cAAc;YACpB,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,gBAAgB;YACzB,KAAK,EAAE,eAAe;SACzB,EAAE,aAAa,CAAC,CAAC;QAElB,OAAO,IAAI,OAAO,CAAC,eAAe,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,+BAA+B,CAAC,SAAS,CAAC,CAAC,CAAC;IAC5G,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,YAAY,CAAC,oBAAyC,EAAE,EAAE,aAA0D;QACtH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,iBAAiB,EAAE,aAAa,CAAC,CAAC;QAC9E,OAAO,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC;IAClC,CAAC;CAEJ"}

View File

@ -1,131 +0,0 @@
/* tslint:disable */
/* eslint-disable */
/**
* Defined Networking API
* <br/> <br/> This API enables automated administration of Defined Networking hosts, roles, logs, and more. To authenticate, obtain an api key to use as a bearer token from your Defined Networking admin panel [API Keys page](https://admin.defined.net/settings/api-keys). API keys must be given the appropriate permission scopes for every method and endpoint, as specified throughout this documentation. Please [contact us](https://www.defined.net/contact?reason=support) for any questions or issues. In the event of a token leak, please take care to [rotate the key](/guides/rotating-api-keys). <div className=\'introduction-end\'></div>
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import * as runtime from '../runtime';
import type {
NetworkGet200Response,
NetworksList200Response,
} from '../models';
import {
NetworkGet200ResponseFromJSON,
NetworkGet200ResponseToJSON,
NetworksList200ResponseFromJSON,
NetworksList200ResponseToJSON,
} from '../models';
export interface NetworkGetRequest {
networkID: string;
}
export interface NetworksListRequest {
includeCounts?: boolean;
cursor?: string;
pageSize?: number;
}
/**
*
*/
export class NetworksApi extends runtime.BaseAPI {
/**
* Fetch information about a particular network. Token scope required: `networks:read` ### Request
* Get network
*/
async networkGetRaw(requestParameters: NetworkGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<NetworkGet200Response>> {
if (requestParameters.networkID === null || requestParameters.networkID === undefined) {
throw new runtime.RequiredError('networkID','Required parameter requestParameters.networkID was null or undefined when calling networkGet.');
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/networks/{networkID}`.replace(`{${"networkID"}}`, encodeURIComponent(String(requestParameters.networkID))),
method: 'GET',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => NetworkGet200ResponseFromJSON(jsonValue));
}
/**
* Fetch information about a particular network. Token scope required: `networks:read` ### Request
* Get network
*/
async networkGet(requestParameters: NetworkGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<NetworkGet200Response> {
const response = await this.networkGetRaw(requestParameters, initOverrides);
return await response.value();
}
/**
* Get a paginated list of networks. :::note Currently, there is a limit of one network per Defined Networking account. ::: Token scope required: `networks:list` ### Request
* List networks
*/
async networksListRaw(requestParameters: NetworksListRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<NetworksList200Response>> {
const queryParameters: any = {};
if (requestParameters.includeCounts !== undefined) {
queryParameters['includeCounts'] = requestParameters.includeCounts;
}
if (requestParameters.cursor !== undefined) {
queryParameters['cursor'] = requestParameters.cursor;
}
if (requestParameters.pageSize !== undefined) {
queryParameters['pageSize'] = requestParameters.pageSize;
}
const headerParameters: runtime.HTTPHeaders = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/networks`,
method: 'GET',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => NetworksList200ResponseFromJSON(jsonValue));
}
/**
* Get a paginated list of networks. :::note Currently, there is a limit of one network per Defined Networking account. ::: Token scope required: `networks:list` ### Request
* List networks
*/
async networksList(requestParameters: NetworksListRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<NetworksList200Response> {
const response = await this.networksListRaw(requestParameters, initOverrides);
return await response.value();
}
}

View File

@ -1,199 +0,0 @@
/* tslint:disable */
/* eslint-disable */
/**
* Defined Networking API
* <br/> <br/> This API enables automated administration of Defined Networking hosts, roles, logs, and more. To authenticate, obtain an api key to use as a bearer token from your Defined Networking admin panel [API Keys page](https://admin.defined.net/settings/api-keys). API keys must be given the appropriate permission scopes for every method and endpoint, as specified throughout this documentation. Please [contact us](https://www.defined.net/contact?reason=support) for any questions or issues. In the event of a token leak, please take care to [rotate the key](/guides/rotating-api-keys). <div className=\'introduction-end\'></div>
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import * as runtime from '../runtime';
import { HostAndEnrollCodeCreate400ResponseFromJSON, HostAndEnrollCodeCreate400ResponseToJSON, HostDelete200ResponseFromJSON, HostDelete200ResponseToJSON, RoleCreate200ResponseFromJSON, RoleCreate200ResponseToJSON, RoleCreateRequestFromJSON, RoleCreateRequestToJSON, RoleEditRequestFromJSON, RoleEditRequestToJSON, RolesList200ResponseFromJSON, RolesList200ResponseToJSON, } from '../models';
/**
*
*/
export class RolesApi extends runtime.BaseAPI {
/**
* Create a new role. Token scope required: `roles:create` ### Request
* Create role
*/
async roleCreateRaw(requestParameters, initOverrides) {
if (requestParameters.roleCreateRequest === null || requestParameters.roleCreateRequest === undefined) {
throw new runtime.RequiredError('roleCreateRequest', 'Required parameter requestParameters.roleCreateRequest was null or undefined when calling roleCreate.');
}
const queryParameters = {};
const headerParameters = {};
headerParameters['Content-Type'] = 'application/json';
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/roles`,
method: 'POST',
headers: headerParameters,
query: queryParameters,
body: RoleCreateRequestToJSON(requestParameters.roleCreateRequest),
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => RoleCreate200ResponseFromJSON(jsonValue));
}
/**
* Create a new role. Token scope required: `roles:create` ### Request
* Create role
*/
async roleCreate(requestParameters, initOverrides) {
const response = await this.roleCreateRaw(requestParameters, initOverrides);
return await response.value();
}
/**
* Token scope required: `roles:delete` ### Request
* Delete role
*/
async roleDeleteRaw(requestParameters, initOverrides) {
if (requestParameters.roleID === null || requestParameters.roleID === undefined) {
throw new runtime.RequiredError('roleID', 'Required parameter requestParameters.roleID was null or undefined when calling roleDelete.');
}
const queryParameters = {};
const headerParameters = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/roles/{roleID}`.replace(`{${"roleID"}}`, encodeURIComponent(String(requestParameters.roleID))),
method: 'DELETE',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => HostDelete200ResponseFromJSON(jsonValue));
}
/**
* Token scope required: `roles:delete` ### Request
* Delete role
*/
async roleDelete(requestParameters, initOverrides) {
const response = await this.roleDeleteRaw(requestParameters, initOverrides);
return await response.value();
}
/**
* Token scope required: `roles:update` :::caution Any properties not provided in the request will be reset to their default values. If only changing one firewall rule, be sure to include the others as well, otherwise they will be removed. ::: ### Request
* Edit role
*/
async roleEditRaw(requestParameters, initOverrides) {
if (requestParameters.roleID === null || requestParameters.roleID === undefined) {
throw new runtime.RequiredError('roleID', 'Required parameter requestParameters.roleID was null or undefined when calling roleEdit.');
}
if (requestParameters.roleEditRequest === null || requestParameters.roleEditRequest === undefined) {
throw new runtime.RequiredError('roleEditRequest', 'Required parameter requestParameters.roleEditRequest was null or undefined when calling roleEdit.');
}
const queryParameters = {};
const headerParameters = {};
headerParameters['Content-Type'] = 'application/json';
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/roles/{roleID}`.replace(`{${"roleID"}}`, encodeURIComponent(String(requestParameters.roleID))),
method: 'PUT',
headers: headerParameters,
query: queryParameters,
body: RoleEditRequestToJSON(requestParameters.roleEditRequest),
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => RoleCreate200ResponseFromJSON(jsonValue));
}
/**
* Token scope required: `roles:update` :::caution Any properties not provided in the request will be reset to their default values. If only changing one firewall rule, be sure to include the others as well, otherwise they will be removed. ::: ### Request
* Edit role
*/
async roleEdit(requestParameters, initOverrides) {
const response = await this.roleEditRaw(requestParameters, initOverrides);
return await response.value();
}
/**
* Fetch information about a particular role. Token scope required: `roles:read` ### Request
* Get role
*/
async roleGetRaw(requestParameters, initOverrides) {
if (requestParameters.roleID === null || requestParameters.roleID === undefined) {
throw new runtime.RequiredError('roleID', 'Required parameter requestParameters.roleID was null or undefined when calling roleGet.');
}
const queryParameters = {};
const headerParameters = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/roles/{roleID}`.replace(`{${"roleID"}}`, encodeURIComponent(String(requestParameters.roleID))),
method: 'GET',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => RoleCreate200ResponseFromJSON(jsonValue));
}
/**
* Fetch information about a particular role. Token scope required: `roles:read` ### Request
* Get role
*/
async roleGet(requestParameters, initOverrides) {
const response = await this.roleGetRaw(requestParameters, initOverrides);
return await response.value();
}
/**
* Get a paginated list of roles. Token scope required: `roles:list` ### Request
* List roles
*/
async rolesListRaw(requestParameters, initOverrides) {
const queryParameters = {};
if (requestParameters.includeCounts !== undefined) {
queryParameters['includeCounts'] = requestParameters.includeCounts;
}
if (requestParameters.cursor !== undefined) {
queryParameters['cursor'] = requestParameters.cursor;
}
if (requestParameters.pageSize !== undefined) {
queryParameters['pageSize'] = requestParameters.pageSize;
}
const headerParameters = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/roles`,
method: 'GET',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => RolesList200ResponseFromJSON(jsonValue));
}
/**
* Get a paginated list of roles. Token scope required: `roles:list` ### Request
* List roles
*/
async rolesList(requestParameters = {}, initOverrides) {
const response = await this.rolesListRaw(requestParameters, initOverrides);
return await response.value();
}
}
//# sourceMappingURL=RolesApi.js.map

File diff suppressed because one or more lines are too long

View File

@ -1,286 +0,0 @@
/* tslint:disable */
/* eslint-disable */
/**
* Defined Networking API
* <br/> <br/> This API enables automated administration of Defined Networking hosts, roles, logs, and more. To authenticate, obtain an api key to use as a bearer token from your Defined Networking admin panel [API Keys page](https://admin.defined.net/settings/api-keys). API keys must be given the appropriate permission scopes for every method and endpoint, as specified throughout this documentation. Please [contact us](https://www.defined.net/contact?reason=support) for any questions or issues. In the event of a token leak, please take care to [rotate the key](/guides/rotating-api-keys). <div className=\'introduction-end\'></div>
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import * as runtime from '../runtime';
import type {
HostAndEnrollCodeCreate400Response,
HostDelete200Response,
RoleCreate200Response,
RoleCreateRequest,
RoleEditRequest,
RolesList200Response,
} from '../models';
import {
HostAndEnrollCodeCreate400ResponseFromJSON,
HostAndEnrollCodeCreate400ResponseToJSON,
HostDelete200ResponseFromJSON,
HostDelete200ResponseToJSON,
RoleCreate200ResponseFromJSON,
RoleCreate200ResponseToJSON,
RoleCreateRequestFromJSON,
RoleCreateRequestToJSON,
RoleEditRequestFromJSON,
RoleEditRequestToJSON,
RolesList200ResponseFromJSON,
RolesList200ResponseToJSON,
} from '../models';
export interface RoleCreateOperationRequest {
roleCreateRequest: RoleCreateRequest;
}
export interface RoleDeleteRequest {
roleID: string;
}
export interface RoleEditOperationRequest {
roleID: string;
roleEditRequest: RoleEditRequest;
}
export interface RoleGetRequest {
roleID: string;
}
export interface RolesListRequest {
includeCounts?: boolean;
cursor?: string;
pageSize?: number;
}
/**
*
*/
export class RolesApi extends runtime.BaseAPI {
/**
* Create a new role. Token scope required: `roles:create` ### Request
* Create role
*/
async roleCreateRaw(requestParameters: RoleCreateOperationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<RoleCreate200Response>> {
if (requestParameters.roleCreateRequest === null || requestParameters.roleCreateRequest === undefined) {
throw new runtime.RequiredError('roleCreateRequest','Required parameter requestParameters.roleCreateRequest was null or undefined when calling roleCreate.');
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
headerParameters['Content-Type'] = 'application/json';
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/roles`,
method: 'POST',
headers: headerParameters,
query: queryParameters,
body: RoleCreateRequestToJSON(requestParameters.roleCreateRequest),
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => RoleCreate200ResponseFromJSON(jsonValue));
}
/**
* Create a new role. Token scope required: `roles:create` ### Request
* Create role
*/
async roleCreate(requestParameters: RoleCreateOperationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<RoleCreate200Response> {
const response = await this.roleCreateRaw(requestParameters, initOverrides);
return await response.value();
}
/**
* Token scope required: `roles:delete` ### Request
* Delete role
*/
async roleDeleteRaw(requestParameters: RoleDeleteRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<HostDelete200Response>> {
if (requestParameters.roleID === null || requestParameters.roleID === undefined) {
throw new runtime.RequiredError('roleID','Required parameter requestParameters.roleID was null or undefined when calling roleDelete.');
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/roles/{roleID}`.replace(`{${"roleID"}}`, encodeURIComponent(String(requestParameters.roleID))),
method: 'DELETE',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => HostDelete200ResponseFromJSON(jsonValue));
}
/**
* Token scope required: `roles:delete` ### Request
* Delete role
*/
async roleDelete(requestParameters: RoleDeleteRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<HostDelete200Response> {
const response = await this.roleDeleteRaw(requestParameters, initOverrides);
return await response.value();
}
/**
* Token scope required: `roles:update` :::caution Any properties not provided in the request will be reset to their default values. If only changing one firewall rule, be sure to include the others as well, otherwise they will be removed. ::: ### Request
* Edit role
*/
async roleEditRaw(requestParameters: RoleEditOperationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<RoleCreate200Response>> {
if (requestParameters.roleID === null || requestParameters.roleID === undefined) {
throw new runtime.RequiredError('roleID','Required parameter requestParameters.roleID was null or undefined when calling roleEdit.');
}
if (requestParameters.roleEditRequest === null || requestParameters.roleEditRequest === undefined) {
throw new runtime.RequiredError('roleEditRequest','Required parameter requestParameters.roleEditRequest was null or undefined when calling roleEdit.');
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
headerParameters['Content-Type'] = 'application/json';
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/roles/{roleID}`.replace(`{${"roleID"}}`, encodeURIComponent(String(requestParameters.roleID))),
method: 'PUT',
headers: headerParameters,
query: queryParameters,
body: RoleEditRequestToJSON(requestParameters.roleEditRequest),
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => RoleCreate200ResponseFromJSON(jsonValue));
}
/**
* Token scope required: `roles:update` :::caution Any properties not provided in the request will be reset to their default values. If only changing one firewall rule, be sure to include the others as well, otherwise they will be removed. ::: ### Request
* Edit role
*/
async roleEdit(requestParameters: RoleEditOperationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<RoleCreate200Response> {
const response = await this.roleEditRaw(requestParameters, initOverrides);
return await response.value();
}
/**
* Fetch information about a particular role. Token scope required: `roles:read` ### Request
* Get role
*/
async roleGetRaw(requestParameters: RoleGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<RoleCreate200Response>> {
if (requestParameters.roleID === null || requestParameters.roleID === undefined) {
throw new runtime.RequiredError('roleID','Required parameter requestParameters.roleID was null or undefined when calling roleGet.');
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/roles/{roleID}`.replace(`{${"roleID"}}`, encodeURIComponent(String(requestParameters.roleID))),
method: 'GET',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => RoleCreate200ResponseFromJSON(jsonValue));
}
/**
* Fetch information about a particular role. Token scope required: `roles:read` ### Request
* Get role
*/
async roleGet(requestParameters: RoleGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<RoleCreate200Response> {
const response = await this.roleGetRaw(requestParameters, initOverrides);
return await response.value();
}
/**
* Get a paginated list of roles. Token scope required: `roles:list` ### Request
* List roles
*/
async rolesListRaw(requestParameters: RolesListRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<RolesList200Response>> {
const queryParameters: any = {};
if (requestParameters.includeCounts !== undefined) {
queryParameters['includeCounts'] = requestParameters.includeCounts;
}
if (requestParameters.cursor !== undefined) {
queryParameters['cursor'] = requestParameters.cursor;
}
if (requestParameters.pageSize !== undefined) {
queryParameters['pageSize'] = requestParameters.pageSize;
}
const headerParameters: runtime.HTTPHeaders = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("ApiToken", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const response = await this.request({
path: `/v1/roles`,
method: 'GET',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => RolesList200ResponseFromJSON(jsonValue));
}
/**
* Get a paginated list of roles. Token scope required: `roles:list` ### Request
* List roles
*/
async rolesList(requestParameters: RolesListRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<RolesList200Response> {
const response = await this.rolesListRaw(requestParameters, initOverrides);
return await response.value();
}
}

View File

@ -1,8 +0,0 @@
/* tslint:disable */
/* eslint-disable */
export * from './AuditLogsApi';
export * from './DownloadsApi';
export * from './HostsApi';
export * from './NetworksApi';
export * from './RolesApi';
//# sourceMappingURL=index.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,oBAAoB;AACpB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC"}

View File

@ -1,7 +0,0 @@
/* tslint:disable */
/* eslint-disable */
export * from './AuditLogsApi';
export * from './DownloadsApi';
export * from './HostsApi';
export * from './NetworksApi';
export * from './RolesApi';

View File

@ -1,6 +0,0 @@
/* tslint:disable */
/* eslint-disable */
export * from './runtime';
export * from './apis';
export * from './models';
//# sourceMappingURL=index.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,oBAAoB;AACpB,cAAc,WAAW,CAAC;AAC1B,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC"}

View File

@ -1,5 +0,0 @@
/* tslint:disable */
/* eslint-disable */
export * from './runtime';
export * from './apis';
export * from './models';

View File

@ -1,56 +0,0 @@
/* tslint:disable */
/* eslint-disable */
/**
* Defined Networking API
* <br/> <br/> This API enables automated administration of Defined Networking hosts, roles, logs, and more. To authenticate, obtain an api key to use as a bearer token from your Defined Networking admin panel [API Keys page](https://admin.defined.net/settings/api-keys). API keys must be given the appropriate permission scopes for every method and endpoint, as specified throughout this documentation. Please [contact us](https://www.defined.net/contact?reason=support) for any questions or issues. In the event of a token leak, please take care to [rotate the key](/guides/rotating-api-keys). <div className=\'introduction-end\'></div>
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { instanceOfActorAPIKey, ActorAPIKeyFromJSON, ActorAPIKeyFromJSONTyped, ActorAPIKeyToJSON, } from './ActorAPIKey';
import { instanceOfActorHost, ActorHostFromJSON, ActorHostFromJSONTyped, ActorHostToJSON, } from './ActorHost';
import { instanceOfActorOIDCUser, ActorOIDCUserFromJSON, ActorOIDCUserFromJSONTyped, ActorOIDCUserToJSON, } from './ActorOIDCUser';
import { instanceOfActorSupport, ActorSupportFromJSON, ActorSupportFromJSONTyped, ActorSupportToJSON, } from './ActorSupport';
import { instanceOfActorSystem, ActorSystemFromJSON, ActorSystemFromJSONTyped, ActorSystemToJSON, } from './ActorSystem';
import { instanceOfActorUser, ActorUserFromJSON, ActorUserFromJSONTyped, ActorUserToJSON, } from './ActorUser';
export function ActorFromJSON(json) {
return ActorFromJSONTyped(json, false);
}
export function ActorFromJSONTyped(json, ignoreDiscriminator) {
if ((json === undefined) || (json === null)) {
return json;
}
return { ...ActorAPIKeyFromJSONTyped(json, true), ...ActorHostFromJSONTyped(json, true), ...ActorOIDCUserFromJSONTyped(json, true), ...ActorSupportFromJSONTyped(json, true), ...ActorSystemFromJSONTyped(json, true), ...ActorUserFromJSONTyped(json, true) };
}
export function ActorToJSON(value) {
if (value === undefined) {
return undefined;
}
if (value === null) {
return null;
}
if (instanceOfActorAPIKey(value)) {
return ActorAPIKeyToJSON(value);
}
if (instanceOfActorHost(value)) {
return ActorHostToJSON(value);
}
if (instanceOfActorOIDCUser(value)) {
return ActorOIDCUserToJSON(value);
}
if (instanceOfActorSupport(value)) {
return ActorSupportToJSON(value);
}
if (instanceOfActorSystem(value)) {
return ActorSystemToJSON(value);
}
if (instanceOfActorUser(value)) {
return ActorUserToJSON(value);
}
return {};
}
//# sourceMappingURL=Actor.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"Actor.js","sourceRoot":"","sources":["Actor.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,oBAAoB;AACpB;;;;;;;;;;GAUG;AAGH,OAAO,EACH,qBAAqB,EACrB,mBAAmB,EACnB,wBAAwB,EACxB,iBAAiB,GACpB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACH,mBAAmB,EACnB,iBAAiB,EACjB,sBAAsB,EACtB,eAAe,GAClB,MAAM,aAAa,CAAC;AAErB,OAAO,EACH,uBAAuB,EACvB,qBAAqB,EACrB,0BAA0B,EAC1B,mBAAmB,GACtB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACH,sBAAsB,EACtB,oBAAoB,EACpB,yBAAyB,EACzB,kBAAkB,GACrB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACH,qBAAqB,EACrB,mBAAmB,EACnB,wBAAwB,EACxB,iBAAiB,GACpB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACH,mBAAmB,EACnB,iBAAiB,EACjB,sBAAsB,EACtB,eAAe,GAClB,MAAM,aAAa,CAAC;AASrB,MAAM,UAAU,aAAa,CAAC,IAAS;IACnC,OAAO,kBAAkB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAS,EAAE,mBAA4B;IACtE,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE;QACzC,OAAO,IAAI,CAAC;KACf;IACD,OAAO,EAAE,GAAG,wBAAwB,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,GAAG,sBAAsB,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,GAAG,0BAA0B,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,GAAG,yBAAyB,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,GAAG,wBAAwB,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,GAAG,sBAAsB,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;AACnQ,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAoB;IAC5C,IAAI,KAAK,KAAK,SAAS,EAAE;QACrB,OAAO,SAAS,CAAC;KACpB;IACD,IAAI,KAAK,KAAK,IAAI,EAAE;QAChB,OAAO,IAAI,CAAC;KACf;IAED,IAAI,qBAAqB,CAAC,KAAK,CAAC,EAAE;QAC9B,OAAO,iBAAiB,CAAC,KAAoB,CAAC,CAAC;KAClD;IACD,IAAI,mBAAmB,CAAC,KAAK,CAAC,EAAE;QAC5B,OAAO,eAAe,CAAC,KAAkB,CAAC,CAAC;KAC9C;IACD,IAAI,uBAAuB,CAAC,KAAK,CAAC,EAAE;QAChC,OAAO,mBAAmB,CAAC,KAAsB,CAAC,CAAC;KACtD;IACD,IAAI,sBAAsB,CAAC,KAAK,CAAC,EAAE;QAC/B,OAAO,kBAAkB,CAAC,KAAqB,CAAC,CAAC;KACpD;IACD,IAAI,qBAAqB,CAAC,KAAK,CAAC,EAAE;QAC9B,OAAO,iBAAiB,CAAC,KAAoB,CAAC,CAAC;KAClD;IACD,IAAI,mBAAmB,CAAC,KAAK,CAAC,EAAE;QAC5B,OAAO,eAAe,CAAC,KAAkB,CAAC,CAAC;KAC9C;IAED,OAAO,EAAE,CAAC;AACd,CAAC"}

View File

@ -1,105 +0,0 @@
/* tslint:disable */
/* eslint-disable */
/**
* Defined Networking API
* <br/> <br/> This API enables automated administration of Defined Networking hosts, roles, logs, and more. To authenticate, obtain an api key to use as a bearer token from your Defined Networking admin panel [API Keys page](https://admin.defined.net/settings/api-keys). API keys must be given the appropriate permission scopes for every method and endpoint, as specified throughout this documentation. Please [contact us](https://www.defined.net/contact?reason=support) for any questions or issues. In the event of a token leak, please take care to [rotate the key](/guides/rotating-api-keys). <div className=\'introduction-end\'></div>
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import type {ActorAPIKey} from './ActorAPIKey';
import {
instanceOfActorAPIKey,
ActorAPIKeyFromJSON,
ActorAPIKeyFromJSONTyped,
ActorAPIKeyToJSON,
} from './ActorAPIKey';
import type {ActorHost} from './ActorHost';
import {
instanceOfActorHost,
ActorHostFromJSON,
ActorHostFromJSONTyped,
ActorHostToJSON,
} from './ActorHost';
import type {ActorOIDCUser} from './ActorOIDCUser';
import {
instanceOfActorOIDCUser,
ActorOIDCUserFromJSON,
ActorOIDCUserFromJSONTyped,
ActorOIDCUserToJSON,
} from './ActorOIDCUser';
import type {ActorSupport} from './ActorSupport';
import {
instanceOfActorSupport,
ActorSupportFromJSON,
ActorSupportFromJSONTyped,
ActorSupportToJSON,
} from './ActorSupport';
import type {ActorSystem} from './ActorSystem';
import {
instanceOfActorSystem,
ActorSystemFromJSON,
ActorSystemFromJSONTyped,
ActorSystemToJSON,
} from './ActorSystem';
import type {ActorUser} from './ActorUser';
import {
instanceOfActorUser,
ActorUserFromJSON,
ActorUserFromJSONTyped,
ActorUserToJSON,
} from './ActorUser';
/**
* @type Actor
* The entity performing the action which caused a change.
* @export
*/
export type Actor = ActorAPIKey | ActorHost | ActorOIDCUser | ActorSupport | ActorSystem | ActorUser;
export function ActorFromJSON(json: any): Actor {
return ActorFromJSONTyped(json, false);
}
export function ActorFromJSONTyped(json: any, ignoreDiscriminator: boolean): Actor {
if ((json === undefined) || (json === null)) {
return json;
}
return { ...ActorAPIKeyFromJSONTyped(json, true), ...ActorHostFromJSONTyped(json, true), ...ActorOIDCUserFromJSONTyped(json, true), ...ActorSupportFromJSONTyped(json, true), ...ActorSystemFromJSONTyped(json, true), ...ActorUserFromJSONTyped(json, true) };
}
export function ActorToJSON(value?: Actor | null): any {
if (value === undefined) {
return undefined;
}
if (value === null) {
return null;
}
if (instanceOfActorAPIKey(value)) {
return ActorAPIKeyToJSON(value as ActorAPIKey);
}
if (instanceOfActorHost(value)) {
return ActorHostToJSON(value as ActorHost);
}
if (instanceOfActorOIDCUser(value)) {
return ActorOIDCUserToJSON(value as ActorOIDCUser);
}
if (instanceOfActorSupport(value)) {
return ActorSupportToJSON(value as ActorSupport);
}
if (instanceOfActorSystem(value)) {
return ActorSystemToJSON(value as ActorSystem);
}
if (instanceOfActorUser(value)) {
return ActorUserToJSON(value as ActorUser);
}
return {};
}

View File

@ -1,54 +0,0 @@
/* tslint:disable */
/* eslint-disable */
/**
* Defined Networking API
* <br/> <br/> This API enables automated administration of Defined Networking hosts, roles, logs, and more. To authenticate, obtain an api key to use as a bearer token from your Defined Networking admin panel [API Keys page](https://admin.defined.net/settings/api-keys). API keys must be given the appropriate permission scopes for every method and endpoint, as specified throughout this documentation. Please [contact us](https://www.defined.net/contact?reason=support) for any questions or issues. In the event of a token leak, please take care to [rotate the key](/guides/rotating-api-keys). <div className=\'introduction-end\'></div>
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { exists, mapValues } from '../runtime';
/**
* @export
*/
export const ActorAPIKeyTypeEnum = {
ApiKey: 'apiKey'
};
/**
* Check if a given object implements the ActorAPIKey interface.
*/
export function instanceOfActorAPIKey(value) {
let isInstance = true;
return isInstance;
}
export function ActorAPIKeyFromJSON(json) {
return ActorAPIKeyFromJSONTyped(json, false);
}
export function ActorAPIKeyFromJSONTyped(json, ignoreDiscriminator) {
if ((json === undefined) || (json === null)) {
return json;
}
return {
'type': !exists(json, 'type') ? undefined : json['type'],
'id': !exists(json, 'id') ? undefined : json['id'],
'name': !exists(json, 'name') ? undefined : json['name'],
};
}
export function ActorAPIKeyToJSON(value) {
if (value === undefined) {
return undefined;
}
if (value === null) {
return null;
}
return {
'type': value.type,
'id': value.id,
'name': value.name,
};
}
//# sourceMappingURL=ActorAPIKey.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"ActorAPIKey.js","sourceRoot":"","sources":["ActorAPIKey.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,oBAAoB;AACpB;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AA4B/C;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG;IAC/B,MAAM,EAAE,QAAQ;CACV,CAAC;AAIX;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAa;IAC/C,IAAI,UAAU,GAAG,IAAI,CAAC;IAEtB,OAAO,UAAU,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,IAAS;IACzC,OAAO,wBAAwB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,IAAS,EAAE,mBAA4B;IAC5E,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE;QACzC,OAAO,IAAI,CAAC;KACf;IACD,OAAO;QAEH,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;QACxD,IAAI,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QAClD,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;KAC3D,CAAC;AACN,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAA0B;IACxD,IAAI,KAAK,KAAK,SAAS,EAAE;QACrB,OAAO,SAAS,CAAC;KACpB;IACD,IAAI,KAAK,KAAK,IAAI,EAAE;QAChB,OAAO,IAAI,CAAC;KACf;IACD,OAAO;QAEH,MAAM,EAAE,KAAK,CAAC,IAAI;QAClB,IAAI,EAAE,KAAK,CAAC,EAAE;QACd,MAAM,EAAE,KAAK,CAAC,IAAI;KACrB,CAAC;AACN,CAAC"}

View File

@ -1,91 +0,0 @@
/* tslint:disable */
/* eslint-disable */
/**
* Defined Networking API
* <br/> <br/> This API enables automated administration of Defined Networking hosts, roles, logs, and more. To authenticate, obtain an api key to use as a bearer token from your Defined Networking admin panel [API Keys page](https://admin.defined.net/settings/api-keys). API keys must be given the appropriate permission scopes for every method and endpoint, as specified throughout this documentation. Please [contact us](https://www.defined.net/contact?reason=support) for any questions or issues. In the event of a token leak, please take care to [rotate the key](/guides/rotating-api-keys). <div className=\'introduction-end\'></div>
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { exists, mapValues } from '../runtime';
/**
*
* @export
* @interface ActorAPIKey
*/
export interface ActorAPIKey {
/**
* An API key which used to perform the action.
* @type {string}
* @memberof ActorAPIKey
*/
type?: ActorAPIKeyTypeEnum;
/**
*
* @type {string}
* @memberof ActorAPIKey
*/
id?: string;
/**
*
* @type {string}
* @memberof ActorAPIKey
*/
name?: string | null;
}
/**
* @export
*/
export const ActorAPIKeyTypeEnum = {
ApiKey: 'apiKey'
} as const;
export type ActorAPIKeyTypeEnum = typeof ActorAPIKeyTypeEnum[keyof typeof ActorAPIKeyTypeEnum];
/**
* Check if a given object implements the ActorAPIKey interface.
*/
export function instanceOfActorAPIKey(value: object): boolean {
let isInstance = true;
return isInstance;
}
export function ActorAPIKeyFromJSON(json: any): ActorAPIKey {
return ActorAPIKeyFromJSONTyped(json, false);
}
export function ActorAPIKeyFromJSONTyped(json: any, ignoreDiscriminator: boolean): ActorAPIKey {
if ((json === undefined) || (json === null)) {
return json;
}
return {
'type': !exists(json, 'type') ? undefined : json['type'],
'id': !exists(json, 'id') ? undefined : json['id'],
'name': !exists(json, 'name') ? undefined : json['name'],
};
}
export function ActorAPIKeyToJSON(value?: ActorAPIKey | null): any {
if (value === undefined) {
return undefined;
}
if (value === null) {
return null;
}
return {
'type': value.type,
'id': value.id,
'name': value.name,
};
}

View File

@ -1,54 +0,0 @@
/* tslint:disable */
/* eslint-disable */
/**
* Defined Networking API
* <br/> <br/> This API enables automated administration of Defined Networking hosts, roles, logs, and more. To authenticate, obtain an api key to use as a bearer token from your Defined Networking admin panel [API Keys page](https://admin.defined.net/settings/api-keys). API keys must be given the appropriate permission scopes for every method and endpoint, as specified throughout this documentation. Please [contact us](https://www.defined.net/contact?reason=support) for any questions or issues. In the event of a token leak, please take care to [rotate the key](/guides/rotating-api-keys). <div className=\'introduction-end\'></div>
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { exists, mapValues } from '../runtime';
/**
* @export
*/
export const ActorHostTypeEnum = {
Host: 'host'
};
/**
* Check if a given object implements the ActorHost interface.
*/
export function instanceOfActorHost(value) {
let isInstance = true;
return isInstance;
}
export function ActorHostFromJSON(json) {
return ActorHostFromJSONTyped(json, false);
}
export function ActorHostFromJSONTyped(json, ignoreDiscriminator) {
if ((json === undefined) || (json === null)) {
return json;
}
return {
'type': !exists(json, 'type') ? undefined : json['type'],
'id': !exists(json, 'id') ? undefined : json['id'],
'name': !exists(json, 'name') ? undefined : json['name'],
};
}
export function ActorHostToJSON(value) {
if (value === undefined) {
return undefined;
}
if (value === null) {
return null;
}
return {
'type': value.type,
'id': value.id,
'name': value.name,
};
}
//# sourceMappingURL=ActorHost.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"ActorHost.js","sourceRoot":"","sources":["ActorHost.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,oBAAoB;AACpB;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AA4B/C;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC7B,IAAI,EAAE,MAAM;CACN,CAAC;AAIX;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC7C,IAAI,UAAU,GAAG,IAAI,CAAC;IAEtB,OAAO,UAAU,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAS;IACvC,OAAO,sBAAsB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,IAAS,EAAE,mBAA4B;IAC1E,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE;QACzC,OAAO,IAAI,CAAC;KACf;IACD,OAAO;QAEH,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;QACxD,IAAI,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QAClD,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;KAC3D,CAAC;AACN,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAwB;IACpD,IAAI,KAAK,KAAK,SAAS,EAAE;QACrB,OAAO,SAAS,CAAC;KACpB;IACD,IAAI,KAAK,KAAK,IAAI,EAAE;QAChB,OAAO,IAAI,CAAC;KACf;IACD,OAAO;QAEH,MAAM,EAAE,KAAK,CAAC,IAAI;QAClB,IAAI,EAAE,KAAK,CAAC,EAAE;QACd,MAAM,EAAE,KAAK,CAAC,IAAI;KACrB,CAAC;AACN,CAAC"}

View File

@ -1,91 +0,0 @@
/* tslint:disable */
/* eslint-disable */
/**
* Defined Networking API
* <br/> <br/> This API enables automated administration of Defined Networking hosts, roles, logs, and more. To authenticate, obtain an api key to use as a bearer token from your Defined Networking admin panel [API Keys page](https://admin.defined.net/settings/api-keys). API keys must be given the appropriate permission scopes for every method and endpoint, as specified throughout this documentation. Please [contact us](https://www.defined.net/contact?reason=support) for any questions or issues. In the event of a token leak, please take care to [rotate the key](/guides/rotating-api-keys). <div className=\'introduction-end\'></div>
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { exists, mapValues } from '../runtime';
/**
*
* @export
* @interface ActorHost
*/
export interface ActorHost {
/**
* A host. Used for example when hosts are enrolled.
* @type {string}
* @memberof ActorHost
*/
type?: ActorHostTypeEnum;
/**
*
* @type {string}
* @memberof ActorHost
*/
id?: string;
/**
*
* @type {string}
* @memberof ActorHost
*/
name?: string | null;
}
/**
* @export
*/
export const ActorHostTypeEnum = {
Host: 'host'
} as const;
export type ActorHostTypeEnum = typeof ActorHostTypeEnum[keyof typeof ActorHostTypeEnum];
/**
* Check if a given object implements the ActorHost interface.
*/
export function instanceOfActorHost(value: object): boolean {
let isInstance = true;
return isInstance;
}
export function ActorHostFromJSON(json: any): ActorHost {
return ActorHostFromJSONTyped(json, false);
}
export function ActorHostFromJSONTyped(json: any, ignoreDiscriminator: boolean): ActorHost {
if ((json === undefined) || (json === null)) {
return json;
}
return {
'type': !exists(json, 'type') ? undefined : json['type'],
'id': !exists(json, 'id') ? undefined : json['id'],
'name': !exists(json, 'name') ? undefined : json['name'],
};
}
export function ActorHostToJSON(value?: ActorHost | null): any {
if (value === undefined) {
return undefined;
}
if (value === null) {
return null;
}
return {
'type': value.type,
'id': value.id,
'name': value.name,
};
}

View File

@ -1,56 +0,0 @@
/* tslint:disable */
/* eslint-disable */
/**
* Defined Networking API
* <br/> <br/> This API enables automated administration of Defined Networking hosts, roles, logs, and more. To authenticate, obtain an api key to use as a bearer token from your Defined Networking admin panel [API Keys page](https://admin.defined.net/settings/api-keys). API keys must be given the appropriate permission scopes for every method and endpoint, as specified throughout this documentation. Please [contact us](https://www.defined.net/contact?reason=support) for any questions or issues. In the event of a token leak, please take care to [rotate the key](/guides/rotating-api-keys). <div className=\'introduction-end\'></div>
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { exists, mapValues } from '../runtime';
/**
* @export
*/
export const ActorOIDCUserTypeEnum = {
OidcUser: 'oidcUser'
};
/**
* Check if a given object implements the ActorOIDCUser interface.
*/
export function instanceOfActorOIDCUser(value) {
let isInstance = true;
return isInstance;
}
export function ActorOIDCUserFromJSON(json) {
return ActorOIDCUserFromJSONTyped(json, false);
}
export function ActorOIDCUserFromJSONTyped(json, ignoreDiscriminator) {
if ((json === undefined) || (json === null)) {
return json;
}
return {
'type': !exists(json, 'type') ? undefined : json['type'],
'email': !exists(json, 'email') ? undefined : json['email'],
'issuer': !exists(json, 'issuer') ? undefined : json['issuer'],
'subject': !exists(json, 'subject') ? undefined : json['subject'],
};
}
export function ActorOIDCUserToJSON(value) {
if (value === undefined) {
return undefined;
}
if (value === null) {
return null;
}
return {
'type': value.type,
'email': value.email,
'issuer': value.issuer,
'subject': value.subject,
};
}
//# sourceMappingURL=ActorOIDCUser.js.map

Some files were not shown because too many files have changed in this diff Show More