Compare commits

...

33 Commits

Author SHA1 Message Date
Johan Siebens 280c626704 fix incorrect dns configuration examples 2025-05-28 21:39:25 +02:00
Johan Siebens 57e8eb3a25 feat: add support for external dns plugins 2025-05-24 11:01:05 +02:00
Johan Siebens f8b0eceae7 fix: add missing tags 2025-05-23 08:25:37 +02:00
Johan Siebens 924ddf1b36 minor updates 2025-05-07 21:44:42 +02:00
Johan Siebens 65e446e126 fix incorrect env variables usage 2025-05-07 21:35:35 +02:00
Johan Siebens 8fe4342571 update docs and install script 2025-05-07 21:31:40 +02:00
Johan Siebens d5a5a924ca update docs 2025-04-29 07:24:54 +02:00
Johan Siebens 442d794189 update docs 2025-04-28 13:38:09 +02:00
Johan Siebens 9483662395 update docs 2025-04-28 13:30:13 +02:00
Johan Siebens 5b9da83c30 update docs 2025-04-28 13:27:08 +02:00
Johan Siebens 776e3de7d8 updates docs 2025-04-28 11:48:45 +02:00
Johan Siebens a0e1fcb4aa add configuration page 2025-04-28 11:47:45 +02:00
Johan Siebens 814335d703 fix: update auto-approved advertised routes when set after registration 2025-04-28 11:14:36 +02:00
Johan Siebens 644b99b70f chore: update docs 2025-04-27 11:00:05 +02:00
Johan Siebens 1ab135aa9a fix typo 2025-04-27 10:40:39 +02:00
Johan Siebens 4c31c71593 chore: update deps 2025-04-27 10:38:23 +02:00
Johan Siebens d5dd7b1c9d chore: upgrade go toolchain 2025-04-27 10:38:23 +02:00
Johan Siebens 2116b38ae5 update docs 2025-04-27 09:21:50 +02:00
Johan Siebens 0127b027f6 updates 2025-04-26 22:02:37 +02:00
Johan Siebens a4ae50f20c updates 2025-04-26 21:58:06 +02:00
Johan Siebens e1f3ad61fb chore: updates docs 2025-04-26 21:54:11 +02:00
Johan Siebens a2fd56be89 fix: nil pointer when sonyflake is not properly configured 2025-04-26 09:48:57 +02:00
Johan Siebens 828e0c920b chore: use yaml-to-json library, giving better support for configuring third-party libs like libdns providers 2025-03-16 11:03:39 +01:00
Johan Siebens 978b0ecf4f feat: add environment variable substition in configuration, remove implicit use of env variables 2025-03-16 11:03:39 +01:00
Johan Siebens c1c708269c fix: improve session management and update channels, avoiding potential deadlocks 2025-03-06 16:35:59 +01:00
Johan Siebens ed3e1eb54a feat: add /machine/update-health handler 2025-02-16 13:32:50 +01:00
Johan Siebens 4a3b5399e6 chore: remove print lines 2025-02-16 11:01:20 +01:00
Johan Siebens 28c5ff2570 feat: add command to set name of a machine 2025-02-15 15:17:37 +01:00
Johan Siebens 48bd29beba chore: bump base image 2025-02-15 07:44:36 +01:00
Johan Siebens eb46fa12ec chore: remove stale issues workflow 2025-02-15 07:42:11 +01:00
Johan Siebens 99aececab2 chore(deps): upgrade tailscale dependency 2025-02-11 16:24:09 +01:00
Johan Siebens 8e0cc33fd4 chore: upgrade go toolchain 2025-02-11 12:02:29 +01:00
Johan Siebens 4394d44cbd fix: add support for autgroup:member when validating node attributes
Signed-off-by: Johan Siebens <johan.siebens@gmail.com>
2024-11-23 08:24:09 +01:00
74 changed files with 6112 additions and 3635 deletions
+8 -8
View File
@@ -13,14 +13,14 @@ jobs:
fail-fast: false
matrix:
ts_version:
- "v1.64"
- "v1.62"
- "v1.60"
- "v1.58"
- "v1.56"
- "v1.54"
- "v1.52"
- "v1.50"
- "v1.80"
- "v1.78"
- "v1.76"
- "v1.74"
- "v1.72"
- "v1.70"
- "v1.68"
- "v1.66"
env:
IONSCALE_TESTS_TS_TARGET_VERSION: ${{ matrix.ts_version }}
steps:
-22
View File
@@ -1,22 +0,0 @@
name: Close inactive issues
on:
schedule:
- cron: "30 1 * * *"
jobs:
close-issues:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v5
with:
days-before-issue-stale: 90
days-before-issue-close: 7
stale-issue-label: "stale"
stale-issue-message: "This issue is stale because it has been open for 90 days with no activity."
close-issue-message: "This issue was closed because it has been inactive for 14 days since being marked as stale."
days-before-pr-stale: -1
days-before-pr-close: -1
repo-token: ${{ secrets.GITHUB_TOKEN }}
+1 -1
View File
@@ -1,4 +1,4 @@
FROM --platform=${BUILDPLATFORM:-linux/amd64} alpine:3.20.0
FROM --platform=${BUILDPLATFORM:-linux/amd64} alpine:3.21.3
COPY ionscale /usr/local/bin/ionscale
+114 -94
View File
@@ -1,71 +1,76 @@
module github.com/jsiebens/ionscale
go 1.22.0
go 1.24.2
require (
github.com/99designs/keyring v1.2.2
github.com/a-h/templ v0.2.663
github.com/a-h/templ v0.3.857
github.com/apparentlymart/go-cidr v1.1.0
github.com/bufbuild/connect-go v1.10.0
github.com/caarlos0/env/v6 v6.10.1
github.com/caddyserver/certmagic v0.20.0
github.com/coreos/go-oidc/v3 v3.10.0
github.com/dustinkirkland/golang-petname v0.0.0-20240422154211-76c06c4bde6b
github.com/coreos/go-oidc/v3 v3.14.1
github.com/dustinkirkland/golang-petname v0.0.0-20240428194347-eebcea082ee0
github.com/glebarez/sqlite v1.11.0
github.com/go-gormigrate/gormigrate/v2 v2.1.2
github.com/go-jose/go-jose/v3 v3.0.3
github.com/golang-jwt/jwt/v4 v4.5.0
github.com/go-gormigrate/gormigrate/v2 v2.1.4
github.com/go-jose/go-jose/v3 v3.0.4
github.com/golang-jwt/jwt/v4 v4.5.2
github.com/hashicorp/go-bexpr v0.1.14
github.com/hashicorp/go-getter v1.7.4
github.com/hashicorp/go-getter v1.7.8
github.com/hashicorp/go-hclog v1.6.3
github.com/hashicorp/go-multierror v1.1.1
github.com/imdario/mergo v0.3.16
github.com/hashicorp/go-plugin v1.6.3
github.com/jsiebens/go-edit v0.1.0
github.com/jsiebens/libdns-plugin v0.1.0
github.com/jsiebens/mockoidc v0.1.0-rc2
github.com/klauspost/compress v1.17.8
github.com/labstack/echo-contrib v0.17.1
github.com/labstack/echo/v4 v4.12.0
github.com/klauspost/compress v1.18.0
github.com/labstack/echo-contrib v0.17.3
github.com/labstack/echo/v4 v4.13.3
github.com/libdns/azure v0.4.0
github.com/libdns/cloudflare v0.1.1
github.com/libdns/digitalocean v0.0.0-20230728223659-4f9064657aea
github.com/libdns/googleclouddns v1.1.0
github.com/libdns/libdns v0.2.2
github.com/libdns/libdns v0.2.3
github.com/libdns/route53 v1.3.3
github.com/mitchellh/go-homedir v1.1.0
github.com/mitchellh/pointerstructure v1.2.1
github.com/mr-tron/base58 v1.2.0
github.com/nleeper/goment v1.4.4
github.com/ory/dockertest/v3 v3.10.0
github.com/prometheus/client_golang v1.19.0
github.com/rodaine/table v1.2.0
github.com/ory/dockertest/v3 v3.12.0
github.com/prometheus/client_golang v1.22.0
github.com/puzpuzpuz/xsync/v3 v3.5.1
github.com/rodaine/table v1.3.0
github.com/sony/sonyflake v1.2.0
github.com/spf13/cobra v1.8.0
github.com/stretchr/testify v1.9.0
github.com/spf13/cobra v1.9.1
github.com/stretchr/testify v1.10.0
github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a
github.com/travisjeffery/certmagic-sqlstorage v1.1.1
github.com/xhit/go-str2duration/v2 v2.1.0
go.uber.org/zap v1.27.0
golang.org/x/crypto v0.22.0
golang.org/x/net v0.24.0
golang.org/x/oauth2 v0.19.0
golang.org/x/sync v0.7.0
google.golang.org/protobuf v1.33.0
golang.org/x/crypto v0.38.0
golang.org/x/net v0.40.0
golang.org/x/oauth2 v0.29.0
golang.org/x/sync v0.14.0
google.golang.org/protobuf v1.36.6
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1
gorm.io/driver/postgres v1.5.7
gorm.io/gorm v1.25.9
gorm.io/driver/postgres v1.5.11
gorm.io/gorm v1.26.0
gorm.io/plugin/prometheus v0.1.0
inet.af/netaddr v0.0.0-20230525184311-b8eac61e914a
tailscale.com v1.64.2
sigs.k8s.io/yaml v1.4.0
tailscale.com v1.80.0
)
require (
cloud.google.com/go v0.112.2 // indirect
cloud.google.com/go/auth v0.3.0 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect
cloud.google.com/go/compute/metadata v0.3.0 // indirect
cloud.google.com/go/iam v1.1.7 // indirect
cloud.google.com/go/storage v1.40.0 // indirect
dario.cat/mergo v1.0.0 // indirect
cel.dev/expr v0.23.1 // indirect
cloud.google.com/go v0.120.1 // indirect
cloud.google.com/go/auth v0.16.1 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
cloud.google.com/go/compute/metadata v0.6.0 // indirect
cloud.google.com/go/iam v1.5.2 // indirect
cloud.google.com/go/monitoring v1.24.2 // indirect
cloud.google.com/go/storage v1.52.0 // indirect
dario.cat/mergo v1.0.1 // indirect
filippo.io/edwards25519 v1.1.0 // indirect
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 // indirect
@@ -74,11 +79,14 @@ require (
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.51.0 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.51.0 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
github.com/akutz/memconn v0.1.0 // indirect
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa // indirect
github.com/aws/aws-sdk-go v1.51.29 // indirect
github.com/aws/aws-sdk-go v1.55.7 // indirect
github.com/aws/aws-sdk-go-v2 v1.26.1 // indirect
github.com/aws/aws-sdk-go-v2/config v1.27.11 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.11 // indirect
@@ -99,54 +107,61 @@ require (
github.com/bits-and-blooms/bitset v1.13.0 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/containerd/continuity v0.4.3 // indirect
github.com/coreos/go-iptables v0.7.0 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/cncf/xds/go v0.0.0-20250326154945-ae57f3c0d45f // indirect
github.com/coder/websocket v1.8.12 // indirect
github.com/containerd/continuity v0.4.5 // indirect
github.com/coreos/go-iptables v0.7.1-0.20240112124308-65c67c9f46e6 // indirect
github.com/danieljoos/wincred v1.2.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dblohm7/wingoes v0.0.0-20240123200102-b75a8a7d7eb0 // indirect
github.com/digitalocean/go-smbios v0.0.0-20180907143718-390a4f403a8e // indirect
github.com/digitalocean/godo v1.113.0 // indirect
github.com/docker/cli v26.1.0+incompatible // indirect
github.com/docker/docker v26.1.0+incompatible // indirect
github.com/docker/cli v27.4.1+incompatible // indirect
github.com/docker/docker v27.4.1+incompatible // indirect
github.com/docker/go-connections v0.5.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/dvsekhvalnov/jose2go v1.7.0 // indirect
github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect
github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect
github.com/fatih/color v1.18.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fxamacker/cbor/v2 v2.6.0 // indirect
github.com/gaissmai/bart v0.4.1 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/gaissmai/bart v0.11.1 // indirect
github.com/glebarez/go-sqlite v1.22.0 // indirect
github.com/go-jose/go-jose/v4 v4.0.1 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-jose/go-jose/v4 v4.1.0 // indirect
github.com/go-json-experiment/json v0.0.0-20250103232110-6a9a0fde9288 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-viper/mapstructure/v2 v2.1.0 // indirect
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/btree v1.1.2 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/nftables v0.2.0 // indirect
github.com/google/s2a-go v0.1.7 // indirect
github.com/google/nftables v0.2.1-0.20240414091927-5e242ec57806 // indirect
github.com/google/s2a-go v0.1.9 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/googleapis/gax-go/v2 v2.12.3 // indirect
github.com/gorilla/csrf v1.7.2 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
github.com/googleapis/gax-go/v2 v2.14.1 // indirect
github.com/gorilla/csrf v1.7.3-0.20250123201450-9dd6af1f6d30 // indirect
github.com/gorilla/securecookie v1.1.2 // indirect
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-retryablehttp v0.7.5 // indirect
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
github.com/hashicorp/go-safetemp v1.0.0 // indirect
github.com/hashicorp/go-version v1.6.0 // indirect
github.com/hashicorp/go-version v1.7.0 // indirect
github.com/hashicorp/yamux v0.1.2 // indirect
github.com/hdevalence/ed25519consensus v0.2.0 // indirect
github.com/illarion/gonotify v1.0.1 // indirect
github.com/illarion/gonotify/v2 v2.0.3 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
@@ -156,17 +171,15 @@ require (
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/josharian/native v1.1.1-0.20230202152459-5c7d0dd6ab86 // indirect
github.com/jsimonetti/rtnetlink v1.4.1 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/labstack/gommon v0.4.2 // indirect
github.com/lib/pq v1.10.6 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mdlayher/genetlink v1.3.2 // indirect
github.com/mdlayher/netlink v1.7.2 // indirect
github.com/mdlayher/netlink v1.7.3-0.20250113171957-fbb4dce95f42 // indirect
github.com/mdlayher/sdnotify v1.0.0 // indirect
github.com/mdlayher/socket v0.5.1 // indirect
github.com/mholt/acmez v1.2.0 // indirect
@@ -175,73 +188,80 @@ require (
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/sys/user v0.3.0 // indirect
github.com/moby/term v0.5.0 // indirect
github.com/mtibben/percent v0.2.1 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/oklog/run v1.1.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0 // indirect
github.com/opencontainers/runc v1.1.12 // indirect
github.com/opencontainers/runc v1.2.3 // indirect
github.com/pierrec/lz4/v4 v4.1.21 // indirect
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus-community/pro-bing v0.4.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.53.0 // indirect
github.com/prometheus/procfs v0.14.0 // indirect
github.com/prometheus/common v0.63.0 // indirect
github.com/prometheus/procfs v0.16.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/safchain/ethtool v0.3.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/pflag v1.0.6 // indirect
github.com/spiffe/go-spiffe/v2 v2.5.0 // indirect
github.com/tailscale/certstore v0.1.1-0.20231202035212-d3fa0460f47e // indirect
github.com/tailscale/go-winio v0.0.0-20231025203758-c4f33415bf55 // indirect
github.com/tailscale/golang-x-crypto v0.0.0-20240108194725-7ce1f622c780 // indirect
github.com/tailscale/golang-x-crypto v0.0.0-20240604161659-3fde5e568aa4 // indirect
github.com/tailscale/goupnp v1.0.1-0.20210804011211-c64d0f06ea05 // indirect
github.com/tailscale/netlink v1.1.1-0.20211101221916-cabfb018fe85 // indirect
github.com/tailscale/peercred v0.0.0-20240214030740-b535050b2aa4 // indirect
github.com/tailscale/web-client-prebuilt v0.0.0-20240226180453-5db17b287bf1 // indirect
github.com/tailscale/wireguard-go v0.0.0-20231121184858-cc193a0b3272 // indirect
github.com/tcnksm/go-httpstat v0.2.0 // indirect
github.com/tailscale/netlink v1.1.1-0.20240822203006-4d49adab4de7 // indirect
github.com/tailscale/peercred v0.0.0-20250107143737-35a0c7bd7edc // indirect
github.com/tailscale/web-client-prebuilt v0.0.0-20250124233751-d4cd19a26976 // indirect
github.com/tailscale/wireguard-go v0.0.0-20250107165329-0b8b35511f19 // indirect
github.com/tkuchiki/go-timezone v0.2.3 // indirect
github.com/u-root/uio v0.0.0-20240118234441-a3c409a6018e // indirect
github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 // indirect
github.com/ulikunitz/xz v0.5.12 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
github.com/vishvananda/netlink v1.2.1-beta.2 // indirect
github.com/vishvananda/netns v0.0.4 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
github.com/zeebo/blake3 v0.2.3 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 // indirect
go.opentelemetry.io/otel v1.26.0 // indirect
go.opentelemetry.io/otel/metric v1.26.0 // indirect
go.opentelemetry.io/otel/trace v1.26.0 // indirect
github.com/zeebo/errs v1.4.0 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/detectors/gcp v1.35.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
go.opentelemetry.io/otel v1.35.0 // indirect
go.opentelemetry.io/otel/metric v1.35.0 // indirect
go.opentelemetry.io/otel/sdk v1.35.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.35.0 // indirect
go.opentelemetry.io/otel/trace v1.35.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go4.org/intern v0.0.0-20230525184215-6c62f75575cb // indirect
go4.org/mem v0.0.0-20220726221520-4f986261bf13 // indirect
go4.org/mem v0.0.0-20240501181205-ae6ca9944745 // indirect
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
go4.org/unsafe/assume-no-moving-gc v0.0.0-20231121144256-b99613f794b6 // indirect
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/term v0.19.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.20.0 // indirect
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 // indirect
golang.org/x/mod v0.22.0 // indirect
golang.org/x/sys v0.33.0 // indirect
golang.org/x/term v0.32.0 // indirect
golang.org/x/text v0.25.0 // indirect
golang.org/x/time v0.11.0 // indirect
golang.org/x/tools v0.29.0 // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
golang.zx2c4.com/wireguard/windows v0.5.3 // indirect
google.golang.org/api v0.176.1 // indirect
google.golang.org/genproto v0.0.0-20240415180920-8c6c420018be // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240415180920-8c6c420018be // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be // indirect
google.golang.org/grpc v1.63.2 // indirect
gvisor.dev/gvisor v0.0.0-20240306221502-ee1e1f6070e3 // indirect
google.golang.org/api v0.230.0 // indirect
google.golang.org/genproto v0.0.0-20250425173222-7b384671a197 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250425173222-7b384671a197 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250512202823-5a2f75b736a9 // indirect
google.golang.org/grpc v1.72.1 // indirect
gvisor.dev/gvisor v0.0.0-20240722211153-64c016c92987 // indirect
modernc.org/libc v1.50.3 // indirect
modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.8.0 // indirect
modernc.org/sqlite v1.29.8 // indirect
nhooyr.io/websocket v1.8.11 // indirect
)
+958 -213
View File
File diff suppressed because it is too large Load Diff
+35
View File
@@ -33,6 +33,7 @@ func machineCommands() *cobra.Command {
command.AddCommand(disableExitNodeCommand())
command.AddCommand(disableMachineKeyExpiryCommand())
command.AddCommand(authorizeMachineCommand())
command.AddCommand(setMachineNameCommand())
return command
}
@@ -168,6 +169,40 @@ func deleteMachineCommand() *cobra.Command {
return command
}
func setMachineNameCommand() *cobra.Command {
command, tc := prepareCommand(false, &cobra.Command{
Use: "set-name",
Short: "Set the name of a given machine",
SilenceUsage: true,
})
var machineID uint64
var useOSHostname bool
var name string
command.Flags().Uint64Var(&machineID, "machine-id", 0, "Machine ID")
command.Flags().StringVar(&name, "name", "", "New name for the machine")
command.Flags().BoolVar(&useOSHostname, "use-os-hostname", false, "Auto-generate from the machine OS hostname")
_ = command.MarkFlagRequired("machine-id")
command.RunE = func(cmd *cobra.Command, args []string) error {
if !useOSHostname && name == "" {
return fmt.Errorf("name is required when not using os hostname")
}
req := api.SetMachineNameRequest{MachineId: machineID, Name: name, UseOsHostname: useOSHostname}
if _, err := tc.Client().SetMachineName(cmd.Context(), connect.NewRequest(&req)); err != nil {
return err
}
fmt.Println("Machine name set.")
return nil
}
return command
}
func expireMachineCommand() *cobra.Command {
command, tc := prepareCommand(false, &cobra.Command{
Use: "expire",
+144 -70
View File
@@ -2,18 +2,19 @@ package config
import (
"encoding/base64"
"encoding/json"
"fmt"
"github.com/caarlos0/env/v6"
"github.com/caddyserver/certmagic"
"github.com/imdario/mergo"
"github.com/jsiebens/ionscale/internal/domain"
"github.com/jsiebens/ionscale/internal/key"
"github.com/jsiebens/ionscale/internal/util"
"github.com/mitchellh/go-homedir"
"gopkg.in/yaml.v3"
"net/url"
"os"
"path/filepath"
"regexp"
"sigs.k8s.io/yaml"
"strings"
"tailscale.com/tailcfg"
tkey "tailscale.com/types/key"
"time"
@@ -61,6 +62,11 @@ func LoadConfig(path string) (*Config, error) {
return nil, err
}
b, err = expandEnvVars(b)
if err != nil {
return nil, err
}
if err := yaml.Unmarshal(b, cfg); err != nil {
return nil, err
}
@@ -73,23 +79,17 @@ func LoadConfig(path string) (*Config, error) {
return nil, err
}
// merge env configuration on top of the default/file configuration
b, err = expandEnvVars(b)
if err != nil {
return nil, err
}
if err := yaml.Unmarshal(b, cfg); err != nil {
return nil, err
}
}
envCfg := &Config{}
if err := env.Parse(envCfg, env.Options{Prefix: "IONSCALE_"}); err != nil {
return nil, err
}
// merge env configuration on top of the default/file configuration
if err := mergo.Merge(cfg, envCfg, mergo.WithOverride); err != nil {
return nil, err
}
keepAliveInterval = cfg.PollNet.KeepAliveInterval
keepAliveInterval = time.Duration(cfg.PollNet.KeepAliveInterval)
magicDNSSuffix = cfg.DNS.MagicDNSSuffix
if cfg.DNS.Provider.Zone != "" {
@@ -117,7 +117,7 @@ func defaultConfig() *Config {
AcmeCA: certmagic.LetsEncryptProductionCA,
},
PollNet: PollNet{
KeepAliveInterval: defaultKeepAliveInterval,
KeepAliveInterval: Duration(defaultKeepAliveInterval),
},
DNS: DNS{
MagicDNSSuffix: defaultMagicDNSSuffix,
@@ -143,21 +143,21 @@ type ServerKeys struct {
}
type Config struct {
ListenAddr string `yaml:"listen_addr,omitempty" env:"LISTEN_ADDR"`
StunListenAddr string `yaml:"stun_listen_addr,omitempty" env:"STUN_LISTEN_ADDR"`
MetricsListenAddr string `yaml:"metrics_listen_addr,omitempty" env:"METRICS_LISTEN_ADDR"`
PublicAddr string `yaml:"public_addr,omitempty" env:"PUBLIC_ADDR"`
StunPublicAddr string `yaml:"stun_public_addr,omitempty" env:"STUN_PUBLIC_ADDR"`
Tls Tls `yaml:"tls,omitempty" envPrefix:"TLS_"`
PollNet PollNet `yaml:"poll_net,omitempty" envPrefix:"POLL_NET_"`
Keys Keys `yaml:"keys,omitempty" envPrefix:"KEYS_"`
Database Database `yaml:"database,omitempty" envPrefix:"DB_"`
Auth Auth `yaml:"auth,omitempty" envPrefix:"AUTH_"`
DNS DNS `yaml:"dns,omitempty"`
DERP DERP `yaml:"derp,omitempty" envPrefix:"DERP_"`
Logging Logging `yaml:"logging,omitempty" envPrefix:"LOGGING_"`
ListenAddr string `json:"listen_addr,omitempty"`
StunListenAddr string `json:"stun_listen_addr,omitempty"`
MetricsListenAddr string `json:"metrics_listen_addr,omitempty"`
PublicAddr string `json:"public_addr,omitempty"`
StunPublicAddr string `json:"stun_public_addr,omitempty"`
Tls Tls `json:"tls,omitempty"`
PollNet PollNet `json:"poll_net,omitempty"`
Keys Keys `json:"keys,omitempty"`
Database Database `json:"database,omitempty"`
Auth Auth `json:"auth,omitempty"`
DNS DNS `json:"dns,omitempty"`
DERP DERP `json:"derp,omitempty"`
Logging Logging `json:"logging,omitempty"`
PublicUrl *url.URL `yaml:"-"`
PublicUrl *url.URL `json:"-"`
stunHost string
stunPort int
@@ -166,79 +166,80 @@ type Config struct {
}
type Tls struct {
Disable bool `yaml:"disable" env:"DISABLE"`
ForceHttps bool `yaml:"force_https" env:"FORCE_HTTPS"`
CertFile string `yaml:"cert_file,omitempty" env:"CERT_FILE"`
KeyFile string `yaml:"key_file,omitempty" env:"KEY_FILE"`
AcmeEnabled bool `yaml:"acme,omitempty" env:"ACME_ENABLED"`
AcmeEmail string `yaml:"acme_email,omitempty" env:"ACME_EMAIL"`
AcmeCA string `yaml:"acme_ca,omitempty" env:"ACME_CA"`
Disable bool `json:"disable"`
ForceHttps bool `json:"force_https"`
CertFile string `json:"cert_file,omitempty"`
KeyFile string `json:"key_file,omitempty"`
AcmeEnabled bool `json:"acme,omitempty"`
AcmeEmail string `json:"acme_email,omitempty"`
AcmeCA string `json:"acme_ca,omitempty"`
}
type PollNet struct {
KeepAliveInterval time.Duration `yaml:"keep_alive_interval" env:"KEEP_ALIVE_INTERVAL"`
KeepAliveInterval Duration `json:"keep_alive_interval"`
}
type Logging struct {
Level string `yaml:"level,omitempty" env:"LEVEL"`
Format string `yaml:"format,omitempty" env:"FORMAT"`
File string `yaml:"file,omitempty" env:"FILE"`
Level string `json:"level,omitempty"`
Format string `json:"format,omitempty"`
File string `json:"file,omitempty"`
}
type Database struct {
Type string `yaml:"type,omitempty" env:"TYPE"`
Url string `yaml:"url,omitempty" env:"URL"`
MaxOpenConns int `yaml:"max_open_conns,omitempty" env:"MAX_OPEN_CONNS"`
MaxIdleConns int `yaml:"max_idle_conns,omitempty" env:"MAX_IDLE_CONNS"`
ConnMaxLifetime time.Duration `yaml:"conn_max_life_time,omitempty" env:"CONN_MAX_LIFE_TIME"`
ConnMaxIdleTime time.Duration `yaml:"conn_max_idle_time,omitempty" env:"CONN_MAX_IDLE_TIME"`
Type string `json:"type,omitempty"`
Url string `json:"url,omitempty"`
MaxOpenConns int `json:"max_open_conns,omitempty"`
MaxIdleConns int `json:"max_idle_conns,omitempty"`
ConnMaxLifetime Duration `json:"conn_max_life_time,omitempty"`
ConnMaxIdleTime Duration `json:"conn_max_idle_time,omitempty"`
}
type Keys struct {
ControlKey string `yaml:"control_key,omitempty" env:"CONTROL_KEY"`
LegacyControlKey string `yaml:"legacy_control_key,omitempty" env:"LEGACY_CONTROL_KEY"`
SystemAdminKey string `yaml:"system_admin_key,omitempty" env:"SYSTEM_ADMIN_KEY"`
ControlKey string `json:"control_key,omitempty"`
LegacyControlKey string `json:"legacy_control_key,omitempty"`
SystemAdminKey string `json:"system_admin_key,omitempty"`
}
type Auth struct {
Provider AuthProvider `yaml:"provider,omitempty" envPrefix:"PROVIDER_"`
SystemAdminPolicy SystemAdminPolicy `yaml:"system_admins"`
Provider AuthProvider `json:"provider,omitempty"`
SystemAdminPolicy SystemAdminPolicy `json:"system_admins"`
}
type AuthProvider struct {
Issuer string `yaml:"issuer" env:"ISSUER"`
ClientID string `yaml:"client_id" env:"CLIENT_ID"`
ClientSecret string `yaml:"client_secret" env:"CLIENT_SECRET"`
Scopes []string `yaml:"additional_scopes" env:"SCOPES"`
Issuer string `json:"issuer"`
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
Scopes []string `json:"additional_scopes" `
}
type DNS struct {
MagicDNSSuffix string `yaml:"magic_dns_suffix"`
Provider DNSProvider `yaml:"provider,omitempty"`
MagicDNSSuffix string `json:"magic_dns_suffix"`
Provider DNSProvider `json:"provider,omitempty"`
}
type DNSProvider struct {
Name string `yaml:"name"`
Zone string `yaml:"zone"`
Configuration map[string]string `yaml:"config"`
Name string `json:"name"`
PluginPath string `json:"plugin_path"`
Zone string `json:"zone"`
Configuration json.RawMessage `json:"config"`
}
type SystemAdminPolicy struct {
Subs []string `yaml:"subs,omitempty"`
Emails []string `yaml:"emails,omitempty"`
Filters []string `yaml:"filters,omitempty"`
Subs []string `json:"subs,omitempty"`
Emails []string `json:"emails,omitempty"`
Filters []string `json:"filters,omitempty"`
}
type DERP struct {
Server DERPServer `yaml:"server,omitempty"`
Sources []string `yaml:"sources,omitempty"`
Server DERPServer `json:"server,omitempty"`
Sources []string `json:"sources,omitempty"`
}
type DERPServer struct {
Disabled bool `yaml:"disabled,omitempty"`
RegionID int `yaml:"region_id,omitempty"`
RegionCode string `yaml:"region_code,omitempty"`
RegionName string `yaml:"region_name,omitempty"`
Disabled bool `json:"disabled,omitempty"`
RegionID int `json:"region_id,omitempty"`
RegionCode string `json:"region_code,omitempty"`
RegionName string `json:"region_name,omitempty"`
}
func (c *Config) Validate() (*Config, error) {
@@ -356,3 +357,76 @@ func (c *Config) DefaultDERPMap() *tailcfg.DERPMap {
},
}
}
type Duration time.Duration
func (d Duration) Std() time.Duration {
return time.Duration(d)
}
func (d Duration) MarshalJSON() ([]byte, error) {
return json.Marshal(time.Duration(d).String())
}
func (d *Duration) UnmarshalJSON(b []byte) error {
var v interface{}
if err := json.Unmarshal(b, &v); err != nil {
return err
}
switch value := v.(type) {
case float64:
*d = Duration(value)
return nil
case string:
tmp, err := time.ParseDuration(value)
if err != nil {
return err
}
*d = Duration(tmp)
return nil
default:
return fmt.Errorf("invalid duration")
}
}
// Match ${VAR:default} syntax for variables with default values
var optionalEnvRegex = regexp.MustCompile(`\${([a-zA-Z0-9_]+):([^}]*)}`)
// Match ${VAR} syntax (without default) - these are required
var requiredEnvRegex = regexp.MustCompile(`\${([a-zA-Z0-9_]+)}`)
func expandEnvVars(config []byte) ([]byte, error) {
var result = config
var missingVars []string
result = optionalEnvRegex.ReplaceAllFunc(result, func(match []byte) []byte {
parts := optionalEnvRegex.FindSubmatch(match)
envVar := string(parts[1])
defaultValue := parts[2]
envValue := os.Getenv(envVar)
if envValue != "" {
return []byte(envValue)
}
return defaultValue
})
result = requiredEnvRegex.ReplaceAllFunc(result, func(match []byte) []byte {
parts := requiredEnvRegex.FindSubmatch(match)
envVar := string(parts[1])
envValue := os.Getenv(envVar)
if envValue == "" {
missingVars = append(missingVars, envVar)
return match
}
return []byte(envValue)
})
if len(missingVars) > 0 {
return nil, fmt.Errorf("missing required environment variables: %s", strings.Join(missingVars, ", "))
}
return result, nil
}
+130
View File
@@ -0,0 +1,130 @@
package config
import (
"bytes"
"github.com/stretchr/testify/require"
"os"
"testing"
)
func TestLoadConfig(t *testing.T) {
// Create a temporary config file
tempFile, err := os.CreateTemp("", "config-*.yaml")
if err != nil {
t.Fatalf("Failed to create temp file: %v", err)
}
defer os.Remove(tempFile.Name())
// Write test configuration
yamlContent := `
public_addr: "ionscale.localtest.me:443"
stun_public_addr: "ionscale.localtest.me:3478"
database:
type: ${DB_TYPE:sqlite}
url: ${DB_URL}
max_open_conns: ${DB_MAX_OPEN_CONNS:5}
conn_max_life_time: ${DB_CONN_MAX_LIFE_TIME:5s}
`
if _, err := tempFile.Write([]byte(yamlContent)); err != nil {
t.Fatalf("Failed to write to temp file: %v", err)
}
tempFile.Close()
t.Run("With DB_URL set", func(t *testing.T) {
require.NoError(t, os.Setenv("DB_URL", "./ionscale.db"))
config, err := LoadConfig(tempFile.Name())
require.NoError(t, err)
require.Equal(t, "sqlite", config.Database.Type)
require.Equal(t, "./ionscale.db", config.Database.Url)
require.Equal(t, 5, config.Database.MaxOpenConns)
})
t.Run("Without required DB_URL", func(t *testing.T) {
require.NoError(t, os.Unsetenv("DB_URL"))
_, err := LoadConfig(tempFile.Name())
require.Error(t, err)
})
}
func TestExpandEnvVars(t *testing.T) {
// Setup test environment variables
require.NoError(t, os.Setenv("TEST_VAR", "test_value"))
require.NoError(t, os.Setenv("PORT", "9090"))
// Ensure TEST_DEFAULT is not set
require.NoError(t, os.Unsetenv("TEST_DEFAULT"))
tests := []struct {
name string
input []byte
expected []byte
expectError bool
}{
{
name: "Braced variable",
input: []byte("Port: ${PORT}"),
expected: []byte("Port: 9090"),
expectError: false,
},
{
name: "Default value used",
input: []byte("Default: ${TEST_DEFAULT:fallback}"),
expected: []byte("Default: fallback"),
expectError: false,
},
{
name: "Default value not used when env var exists",
input: []byte("Not default: ${PORT:8080}"),
expected: []byte("Not default: 9090"),
expectError: false,
},
{
name: "Multiple replacements",
input: []byte("Config: ${TEST_VAR} ${PORT} ${TEST_DEFAULT:default}"),
expected: []byte("Config: test_value 9090 default"),
expectError: false,
},
{
name: "Missing required variable",
input: []byte("Required: ${MISSING_VAR}"),
expected: nil,
expectError: true,
},
{
name: "Mixed variables with one missing",
input: []byte("Mixed: ${TEST_VAR} ${MISSING_VAR} ${TEST_DEFAULT:default}"),
expected: nil,
expectError: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := expandEnvVars(tt.input)
// Check error expectation
if tt.expectError && err == nil {
t.Errorf("expandEnvVars() expected error but got none")
return
}
if !tt.expectError && err != nil {
t.Errorf("expandEnvVars() got unexpected error: %v", err)
return
}
// If we expected an error, don't check the result further
if tt.expectError {
return
}
// Check result
if !bytes.Equal(result, tt.expected) {
t.Errorf("expandEnvVars() got = %s, want %s", result, tt.expected)
}
})
}
}
-12
View File
@@ -25,18 +25,6 @@ func GetString(key, defaultValue string) string {
return defaultValue
}
func GetUint64(key string, defaultValue uint64) uint64 {
v := os.Getenv(key)
if v != "" {
vi, err := strconv.ParseUint(v, 10, 64)
if err != nil {
return defaultValue
}
return vi
}
return defaultValue
}
func validatePublicAddr(addr string) (*url.URL, string, int, error) {
scheme := "https"
+72 -43
View File
@@ -1,6 +1,7 @@
package core
import (
"github.com/puzpuzpuz/xsync/v3"
"slices"
"sync"
"time"
@@ -9,35 +10,81 @@ import (
type Ping struct{}
type PollMapSessionManager interface {
Register(tailnetID uint64, machineID uint64, ch chan *Ping)
Deregister(tailnetID uint64, machineID uint64)
Register(tailnetID uint64, machineID uint64, ch chan<- *Ping)
Deregister(tailnetID uint64, machineID uint64, ch chan<- *Ping)
HasSession(tailnetID uint64, machineID uint64) bool
NotifyAll(tailnetID uint64, ignoreMachineIDs ...uint64)
}
func NewPollMapSessionManager() PollMapSessionManager {
return &pollMapSessionManager{
data: map[uint64]map[uint64]chan *Ping{},
timers: map[uint64]*time.Timer{},
tailnets: xsync.NewMapOf[uint64, *tailnetSessionManager](),
}
}
type pollMapSessionManager struct {
sync.RWMutex
data map[uint64]map[uint64]chan *Ping
timers map[uint64]*time.Timer
tailnets *xsync.MapOf[uint64, *tailnetSessionManager]
}
func (n *pollMapSessionManager) Register(tailnetID uint64, machineID uint64, ch chan *Ping) {
func (n *pollMapSessionManager) load(tailnetID uint64) *tailnetSessionManager {
m, _ := n.tailnets.LoadOrCompute(tailnetID, func() *tailnetSessionManager {
return &tailnetSessionManager{
targets: make(map[uint64]chan<- *Ping),
timers: make(map[uint64]*time.Timer),
sessions: xsync.NewMapOf[uint64, bool](),
}
})
return m
}
func (n *pollMapSessionManager) Register(tailnetID uint64, machineID uint64, ch chan<- *Ping) {
n.load(tailnetID).Register(machineID, ch)
}
func (n *pollMapSessionManager) Deregister(tailnetID uint64, machineID uint64, ch chan<- *Ping) {
n.load(tailnetID).Deregister(machineID, ch)
}
func (n *pollMapSessionManager) HasSession(tailnetID uint64, machineID uint64) bool {
return n.load(tailnetID).HasSession(machineID)
}
func (n *pollMapSessionManager) NotifyAll(tailnetID uint64, ignoreMachineIDs ...uint64) {
n.load(tailnetID).NotifyAll(ignoreMachineIDs...)
}
type tailnetSessionManager struct {
sync.RWMutex
targets map[uint64]chan<- *Ping
timers map[uint64]*time.Timer
sessions *xsync.MapOf[uint64, bool]
}
func (n *tailnetSessionManager) NotifyAll(ignoreMachineIDs ...uint64) {
n.RLock()
defer n.RUnlock()
for i, p := range n.targets {
if !slices.Contains(ignoreMachineIDs, i) {
select {
case p <- &Ping{}:
default: // ignore, channel has a small buffer, failing to insert means there is already a ping pending
}
}
}
}
func (n *tailnetSessionManager) Register(machineID uint64, ch chan<- *Ping) {
n.Lock()
defer n.Unlock()
if ss := n.data[tailnetID]; ss == nil {
n.data[tailnetID] = map[uint64]chan *Ping{machineID: ch}
} else {
ss[machineID] = ch
if curr, ok := n.targets[machineID]; ok {
close(curr)
}
n.targets[machineID] = ch
n.sessions.Store(machineID, true)
t, ok := n.timers[machineID]
if ok {
t.Stop()
@@ -47,22 +94,25 @@ func (n *pollMapSessionManager) Register(tailnetID uint64, machineID uint64, ch
timer := time.NewTimer(5 * time.Second)
go func() {
<-timer.C
if n.HasSession(tailnetID, machineID) {
n.NotifyAll(tailnetID, machineID)
if n.HasSession(machineID) {
n.NotifyAll(machineID)
}
}()
n.timers[machineID] = timer
}
func (n *pollMapSessionManager) Deregister(tailnetID uint64, machineID uint64) {
func (n *tailnetSessionManager) Deregister(machineID uint64, ch chan<- *Ping) {
n.Lock()
defer n.Unlock()
if ss := n.data[tailnetID]; ss != nil {
delete(ss, machineID)
if curr, ok := n.targets[machineID]; ok && curr != ch {
return
}
delete(n.targets, machineID)
n.sessions.Store(machineID, false)
t, ok := n.timers[machineID]
if ok {
t.Stop()
@@ -72,36 +122,15 @@ func (n *pollMapSessionManager) Deregister(tailnetID uint64, machineID uint64) {
timer := time.NewTimer(10 * time.Second)
go func() {
<-timer.C
if !n.HasSession(tailnetID, machineID) {
n.NotifyAll(tailnetID)
if !n.HasSession(machineID) {
n.NotifyAll()
}
}()
n.timers[machineID] = timer
}
func (n *pollMapSessionManager) HasSession(tailnetID uint64, machineID uint64) bool {
n.RLock()
defer n.RUnlock()
if ss := n.data[tailnetID]; ss != nil {
if _, ok := ss[machineID]; ok {
return true
}
}
return false
}
func (n *pollMapSessionManager) NotifyAll(tailnetID uint64, ignoreMachineIDs ...uint64) {
n.RLock()
defer n.RUnlock()
if ss := n.data[tailnetID]; ss != nil {
for i, p := range ss {
if !slices.Contains(ignoreMachineIDs, i) {
p <- &Ping{}
}
}
}
func (n *tailnetSessionManager) HasSession(machineID uint64) bool {
v, ok := n.sessions.Load(machineID)
return ok && v
}
+2 -2
View File
@@ -39,8 +39,8 @@ func OpenDB(config *config.Database, logger *zap.Logger) (*sql.DB, domain.Reposi
sqlDB.SetMaxOpenConns(config.MaxOpenConns)
sqlDB.SetMaxIdleConns(config.MaxIdleConns)
sqlDB.SetConnMaxLifetime(config.ConnMaxLifetime)
sqlDB.SetConnMaxIdleTime(config.ConnMaxIdleTime)
sqlDB.SetConnMaxLifetime(config.ConnMaxLifetime.Std())
sqlDB.SetConnMaxIdleTime(config.ConnMaxIdleTime.Std())
repository := domain.NewRepository(db)
@@ -0,0 +1,24 @@
package migration
import (
"github.com/go-gormigrate/gormigrate/v2"
"gorm.io/gorm"
)
func m202502150830_use_hostname() *gormigrate.Migration {
return &gormigrate.Migration{
ID: "202502150830",
Migrate: func(db *gorm.DB) error {
type Machine struct {
UseOSHostname bool `gorm:"default:true"`
}
if err := db.Migrator().AddColumn(&Machine{}, "UseOSHostname"); err != nil {
return err
}
return nil
},
Rollback: nil,
}
}
@@ -21,6 +21,7 @@ func Migrations() []*gormigrate.Migration {
m202401061400_machine_indeces(),
m202402120800_user_last_authenticated(),
m202403130830_json_to_text(),
m202502150830_use_hostname(),
}
return migrations
}
+124
View File
@@ -0,0 +1,124 @@
package dns
import (
"context"
"encoding/json"
"fmt"
"github.com/hashicorp/go-plugin"
"github.com/jsiebens/ionscale/internal/util"
dnsplugin "github.com/jsiebens/libdns-plugin"
"github.com/libdns/libdns"
"go.uber.org/zap"
"os/exec"
"sync"
"time"
)
// pluginManager handles plugin lifecycle and resilience
type pluginManager struct {
pluginPath string
client *plugin.Client
instance dnsplugin.Provider
lock sync.RWMutex
logger *zap.Logger
zone string
config json.RawMessage
}
// NewPluginManager creates a new plugin manager
func newPluginManager(pluginPath string, zone string, config json.RawMessage) (*pluginManager, error) {
logger := zap.L().Named("dns").With(zap.String("plugin_path", pluginPath))
p := &pluginManager{
pluginPath: pluginPath,
logger: logger,
zone: zone,
config: config,
}
if err := p.ensureRunning(true); err != nil {
return nil, err
}
return p, nil
}
// ensureRunning makes sure the plugin is running
func (pm *pluginManager) ensureRunning(start bool) error {
pm.lock.RLock()
running := pm.client != nil && !pm.client.Exited()
instance := pm.instance
pm.lock.RUnlock()
if running && instance != nil {
return nil
}
// Need to restart
pm.lock.Lock()
defer pm.lock.Unlock()
if !start {
pm.logger.Info("Restarting DNS plugin")
}
if pm.client != nil {
pm.client.Kill()
}
// Create a new client
cmd := exec.Command(pm.pluginPath)
pm.client = plugin.NewClient(&plugin.ClientConfig{
HandshakeConfig: dnsplugin.Handshake,
Plugins: dnsplugin.PluginMap,
Cmd: cmd,
AllowedProtocols: []plugin.Protocol{
plugin.ProtocolNetRPC,
plugin.ProtocolGRPC,
},
Managed: true,
Logger: util.NewZapAdapter(pm.logger, "dns"),
})
// Connect via RPC
rpcClient, err := pm.client.Client()
if err != nil {
return fmt.Errorf("error creating plugin client: %w", err)
}
// Request the plugin
raw, err := rpcClient.Dispense(dnsplugin.ProviderPluginName)
if err != nil {
return fmt.Errorf("error dispensing plugin: %w", err)
}
// Convert to the interface
pm.instance = raw.(dnsplugin.Provider)
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
if err := pm.instance.Configure(ctx, pm.config); err != nil {
return fmt.Errorf("error configuring plugin: %w", err)
}
pm.logger.Info("DNS plugin started")
return nil
}
func (pm *pluginManager) SetRecord(ctx context.Context, recordType, recordName, value string) error {
if err := pm.ensureRunning(false); err != nil {
return err
}
_, err := pm.instance.SetRecords(ctx, pm.zone, []libdns.Record{{
Type: recordType,
Name: libdns.RelativeName(recordName, pm.zone),
Value: value,
TTL: 1 * time.Minute,
}})
return err
}
+42 -103
View File
@@ -2,20 +2,28 @@ package dns
import (
"context"
"encoding/json"
"fmt"
"github.com/imdario/mergo"
"github.com/jsiebens/ionscale/internal/config"
"github.com/jsiebens/ionscale/internal/mapping"
"github.com/libdns/azure"
"github.com/libdns/cloudflare"
"github.com/libdns/digitalocean"
"github.com/libdns/googleclouddns"
"github.com/libdns/libdns"
"github.com/libdns/route53"
"go.uber.org/zap"
"strings"
"time"
)
var factories = map[string]func() libdns.RecordSetter{
"azure": azureProvider,
"cloudflare": cloudflareProvider,
"digitalocean": digitalOceanProvider,
"googleclouddns": googleCloudDNSProvider,
"route53": route53Provider,
}
type Provider interface {
SetRecord(ctx context.Context, recordType, recordName, value string) error
}
@@ -26,126 +34,57 @@ func NewProvider(config config.DNS) (Provider, error) {
return nil, nil
}
if p.Name == "" && p.PluginPath == "" {
return nil, fmt.Errorf("invalid dns provider configuration, either name or plugin_path should be set")
}
if p.Name != "" && p.PluginPath != "" {
return nil, fmt.Errorf("invalid dns provider configuration, only one of name or plugin_path should be set")
}
if !strings.HasSuffix(config.MagicDNSSuffix, p.Zone) {
return nil, fmt.Errorf("invalid MagicDNS suffix [%s], not part of zone [%s]", config.MagicDNSSuffix, p.Zone)
}
switch p.Name {
case "azure":
return configureAzureProvider(p.Zone, p.Configuration)
case "cloudflare":
return configureCloudflareProvider(p.Zone, p.Configuration)
case "digitalocean":
return configureDigitalOceanProvider(p.Zone, p.Configuration)
case "googleclouddns":
return configureGoogleCloudDNSProvider(p.Zone, p.Configuration)
case "route53":
return configureRoute53Provider(p.Zone, p.Configuration)
default:
return nil, fmt.Errorf("unknown dns provider: %s", p.Name)
}
factory, ok := factories[p.Name]
if ok {
return newProvider(p.Zone, p.Configuration, factory)
}
func configureAzureProvider(zone string, values map[string]string) (Provider, error) {
p := &azure.Provider{}
if err := mapping.CopyViaJson(values, p); err != nil {
return newPluginManager(p.PluginPath, fqdn(p.Zone), p.Configuration)
}
func newProvider(zone string, values json.RawMessage, factory func() libdns.RecordSetter) (Provider, error) {
p := factory()
if err := json.Unmarshal(values, p); err != nil {
return nil, err
}
e := &azure.Provider{
TenantId: config.GetString("IONSCALE_DNS_AZURE_TENANT_ID", ""),
ClientId: config.GetString("IONSCALE_DNS_AZURE_CLIENT_ID", ""),
ClientSecret: config.GetString("IONSCALE_DNS_AZURE_CLIENT_SECRET", ""),
SubscriptionId: config.GetString("IONSCALE_DNS_AZURE_SUBSCRIPTION_ID", ""),
ResourceGroupName: config.GetString("IONSCALE_DNS_AZURE_RESOURCE_GROUP_NAME", ""),
}
// merge env configuration on top of the default/file configuration
if err := mergo.Merge(p, e, mergo.WithOverride); err != nil {
return nil, err
}
return &externalProvider{zone: fqdn(zone), setter: p}, nil
}
func configureCloudflareProvider(zone string, values map[string]string) (Provider, error) {
p := &cloudflare.Provider{}
if err := mapping.CopyViaJson(values, p); err != nil {
return nil, err
func azureProvider() libdns.RecordSetter {
zap.L().Warn("Builtin azure DNS plugin is deprecated and will be removed in a future release.")
return &azure.Provider{}
}
e := &cloudflare.Provider{
APIToken: config.GetString("IONSCALE_DNS_CLOUDFLARE_API_TOKEN", ""),
func cloudflareProvider() libdns.RecordSetter {
zap.L().Warn("Builtin cloudflare DNS plugin is deprecated and will be removed in a future release.")
return &cloudflare.Provider{}
}
// merge env configuration on top of the default/file configuration
if err := mergo.Merge(p, e, mergo.WithOverride); err != nil {
return nil, err
func digitalOceanProvider() libdns.RecordSetter {
zap.L().Warn("Builtin digitalocean DNS plugin is deprecated and will be removed in a future release.")
return &digitalocean.Provider{}
}
return &externalProvider{zone: fqdn(zone), setter: p}, nil
func googleCloudDNSProvider() libdns.RecordSetter {
zap.L().Warn("Builtin googleclouddns DNS plugin is deprecated and will be removed in a future release.")
return &googleclouddns.Provider{}
}
func configureDigitalOceanProvider(zone string, values map[string]string) (Provider, error) {
p := &digitalocean.Provider{}
if err := mapping.CopyViaJson(values, p); err != nil {
return nil, err
}
e := &digitalocean.Provider{
APIToken: config.GetString("IONSCALE_DNS_DIGITALOCEAN_API_TOKEN", ""),
}
// merge env configuration on top of the default/file configuration
if err := mergo.Merge(p, e, mergo.WithOverride); err != nil {
return nil, err
}
return &externalProvider{zone: fqdn(zone), setter: p}, nil
}
func configureGoogleCloudDNSProvider(zone string, values map[string]string) (Provider, error) {
p := &googleclouddns.Provider{}
if err := mapping.CopyViaJson(values, p); err != nil {
return nil, err
}
e := &googleclouddns.Provider{
Project: config.GetString("IONSCALE_DNS_GOOGLECLOUDDNS_PROJECT", ""),
ServiceAccountJSON: config.GetString("IONSCALE_DNS_GOOGLECLOUDDNS_SERVICE_ACCOUNT_JSON", ""),
}
// merge env configuration on top of the default/file configuration
if err := mergo.Merge(p, e, mergo.WithOverride); err != nil {
return nil, err
}
return &externalProvider{zone: fqdn(zone), setter: p}, nil
}
func configureRoute53Provider(zone string, values map[string]string) (Provider, error) {
p := &route53.Provider{}
if err := mapping.CopyViaJson(values, p); err != nil {
return nil, err
}
e := &route53.Provider{
MaxRetries: 0,
MaxWaitDur: 0,
WaitForPropagation: false,
Region: config.GetString("IONSCALE_DNS_ROUTE53_REGION", ""),
AWSProfile: config.GetString("IONSCALE_DNS_ROUTE53_AWS_PROFILE", ""),
AccessKeyId: config.GetString("IONSCALE_DNS_ROUTE53_ACCESS_KEY_ID", ""),
SecretAccessKey: config.GetString("IONSCALE_DNS_ROUTE53_SECRET_ACCESS_KEY", ""),
Token: config.GetString("IONSCALE_DNS_ROUTE53_TOKEN", ""),
}
// merge env configuration on top of the default/file configuration
if err := mergo.Merge(p, e, mergo.WithOverride); err != nil {
return nil, err
}
return &externalProvider{zone: fqdn(zone), setter: p}, nil
func route53Provider() libdns.RecordSetter {
zap.L().Warn("Builtin route53 DNS plugin is deprecated and will be removed in a future release.")
return &route53.Provider{}
}
type externalProvider struct {
+4
View File
@@ -164,6 +164,10 @@ func (a ACLPolicy) NodeCapabilities(m *Machine) []tailcfg.NodeCapability {
}
}
}
if (alias == AutoGroupMember || alias == AutoGroupMembers) && !m.HasTags() {
return true
}
}
return false
+32
View File
@@ -113,6 +113,38 @@ func TestACLPolicy_NodeAttributesWithUserAndTags(t *testing.T) {
assert.Equal(t, expectedAttrs, actualAttrs)
}
func TestACLPolicy_NodeAttributesWithAutoGroupMember(t *testing.T) {
p1 := createMachine("john@example.com")
policy := ACLPolicy{
ionscale.ACLPolicy{
NodeAttrs: []ionscale.ACLNodeAttrGrant{
{
Target: []string{"autogroup:member"},
Attr: []string{
"attr1",
"attr2",
},
},
{
Target: []string{"tag:web"},
Attr: []string{
"attr3",
},
},
},
},
}
actualAttrs := policy.NodeCapabilities(p1)
expectedAttrs := []tailcfg.NodeCapability{
tailcfg.NodeCapability("attr1"),
tailcfg.NodeCapability("attr2"),
}
assert.Equal(t, expectedAttrs, actualAttrs)
}
func TestACLPolicy_BuildFilterRulesEmptyACL(t *testing.T) {
p1 := createMachine("john@example.com")
p2 := createMachine("jane@example.com")
+2 -1
View File
@@ -42,6 +42,7 @@ type Machine struct {
Tags Tags
KeyExpiryDisabled bool
Authorized bool
UseOSHostname bool `gorm:"default:true"`
HostInfo HostInfo
Endpoints Endpoints
@@ -124,7 +125,7 @@ func (m *Machine) IsAllowedExitNode() bool {
}
func (m *Machine) AdvertisedPrefixes() []string {
result := []string{}
var result []string
for _, r := range m.HostInfo.RoutableIPs {
if r.Bits() != 0 {
result = append(result, r.String())
+2 -2
View File
@@ -30,9 +30,9 @@ type TailnetRepository interface {
DeleteTailnet(ctx context.Context, id uint64) error
}
func (t Tailnet) GetDERPMap(ctx context.Context, fallack DefaultDERPMap) (*DERPMap, error) {
func (t Tailnet) GetDERPMap(ctx context.Context, fallback DefaultDERPMap) (*DERPMap, error) {
if t.DERPMap.Checksum == "" {
return fallack.GetDERPMap(ctx)
return fallback.GetDERPMap(ctx)
} else {
return &t.DERPMap, nil
}
+2 -1
View File
@@ -482,6 +482,7 @@ func (h *AuthenticationHandlers) endMachineRegistrationFlow(c echo.Context, form
ID: util.NextID(),
Name: sanitizeHostname,
NameIdx: nameIdx,
UseOSHostname: true,
MachineKey: machineKey,
NodeKey: nodeKey,
Ephemeral: ephemeral || req.Ephemeral,
@@ -511,7 +512,7 @@ func (h *AuthenticationHandlers) endMachineRegistrationFlow(c echo.Context, form
tags := append(registeredTags, advertisedTags...)
sanitizeHostname := dnsname.SanitizeHostname(req.Hostinfo.Hostname)
if m.Name != sanitizeHostname {
if m.UseOSHostname && m.Name != sanitizeHostname {
nameIdx, err := h.repository.GetNextMachineNameIndex(ctx, tailnet.ID, sanitizeHostname)
if err != nil {
return logError(err)
+2 -2
View File
@@ -7,7 +7,7 @@ import (
"golang.org/x/net/http2/h2c"
"io"
"net/http"
"tailscale.com/control/controlhttp"
"tailscale.com/control/controlhttp/controlhttpserver"
"tailscale.com/net/netutil"
"tailscale.com/types/key"
)
@@ -27,7 +27,7 @@ func NewNoiseHandlers(controlKey key.MachinePrivate, createPeerHandler CreatePee
}
func (h *NoiseHandlers) Upgrade(c echo.Context) error {
conn, err := controlhttp.AcceptHTTP(c.Request().Context(), c.Response(), c.Request(), h.controlKey, nil)
conn, err := controlhttpserver.AcceptHTTP(c.Request().Context(), c.Response(), c.Request(), h.controlKey, nil)
if err != nil {
return logError(err)
}
+25 -7
View File
@@ -11,10 +11,12 @@ import (
"github.com/klauspost/compress/zstd"
"github.com/labstack/echo/v4"
"net/http"
"slices"
"sync"
"tailscale.com/smallzstd"
"tailscale.com/tailcfg"
"tailscale.com/types/key"
"tailscale.com/util/dnsname"
"time"
)
@@ -81,11 +83,25 @@ func (h *PollNetMapHandler) handlePollNetMap(c echo.Context, m *domain.Machine,
}
if !mapRequest.Stream {
if !slices.Equal(m.HostInfo.RoutableIPs, mapRequest.Hostinfo.RoutableIPs) {
m.AutoAllowIPs = m.Tailnet.ACLPolicy.Get().FindAutoApprovedIPs(mapRequest.Hostinfo.RoutableIPs, m.Tags, &m.User)
}
m.HostInfo = domain.HostInfo(*mapRequest.Hostinfo)
m.DiscoKey = mapRequest.DiscoKey.String()
m.Endpoints = mapRequest.Endpoints
m.LastSeen = &now
sanitizeHostname := dnsname.SanitizeHostname(m.HostInfo.Hostname)
if m.UseOSHostname && m.Name != sanitizeHostname {
nameIdx, err := h.repository.GetNextMachineNameIndex(ctx, m.TailnetID, sanitizeHostname)
if err != nil {
return logError(err)
}
m.Name = sanitizeHostname
m.NameIdx = nameIdx
}
if err := h.repository.SaveMachine(ctx, m); err != nil {
return logError(err)
}
@@ -120,19 +136,21 @@ func (h *PollNetMapHandler) handlePollNetMap(c echo.Context, m *domain.Machine,
defer func() {
connectedDevices.WithLabelValues(m.Tailnet.Name).Dec()
h.sessionManager.Deregister(m.TailnetID, m.ID)
h.sessionManager.Deregister(m.TailnetID, m.ID, updateChan)
keepAliveTicker.Stop()
syncTicker.Stop()
_ = h.repository.SetMachineLastSeen(ctx, machineID)
}()
var latestSync = time.Now()
var latestUpdate = latestSync
var shouldUpdate bool = false
for {
select {
case <-updateChan:
latestUpdate = time.Now()
case _, ok := <-updateChan:
if !ok {
return nil
}
shouldUpdate = true
case <-keepAliveTicker.C:
if mapRequest.KeepAlive {
if _, err := c.Response().Write(keepAliveResponse); err != nil {
@@ -142,7 +160,7 @@ func (h *PollNetMapHandler) handlePollNetMap(c echo.Context, m *domain.Machine,
c.Response().Flush()
}
case <-syncTicker.C:
if latestSync.Before(latestUpdate) {
if shouldUpdate {
machine, err := h.repository.GetMachine(ctx, machineID)
if err != nil {
return logError(err)
@@ -165,7 +183,7 @@ func (h *PollNetMapHandler) handlePollNetMap(c echo.Context, m *domain.Machine,
}
c.Response().Flush()
latestSync = latestUpdate
shouldUpdate = false
}
case <-notify:
return nil
+4 -4
View File
@@ -86,14 +86,13 @@ func (h *RegistrationHandlers) Register(c echo.Context) error {
}
sanitizeHostname := dnsname.SanitizeHostname(req.Hostinfo.Hostname)
if m.Name != sanitizeHostname {
if m.UseOSHostname && m.Name != sanitizeHostname {
nameIdx, err := h.repository.GetNextMachineNameIndex(ctx, m.TailnetID, sanitizeHostname)
if err != nil {
return logError(err)
}
m.Name = sanitizeHostname
m.NameIdx = nameIdx
}
advertisedTags := domain.SanitizeTags(req.Hostinfo.RequestTags)
@@ -124,7 +123,7 @@ func (h *RegistrationHandlers) authenticateMachine(c echo.Context, machineKey st
return h.followup(c, req)
}
if req.Auth.AuthKey == "" {
if req.Auth == nil || req.Auth.AuthKey == "" {
key := util.RandStringBytes(8)
authUrl := h.config.CreateUrl("/a/r/%s", key)
@@ -196,6 +195,7 @@ func (h *RegistrationHandlers) authenticateMachineWithAuthKey(c echo.Context, ma
ID: util.NextID(),
Name: sanitizeHostname,
NameIdx: nameIdx,
UseOSHostname: true,
MachineKey: machineKey,
NodeKey: nodeKey,
Ephemeral: authKey.Ephemeral || req.Ephemeral,
@@ -225,7 +225,7 @@ func (h *RegistrationHandlers) authenticateMachineWithAuthKey(c echo.Context, ma
m.IPv6 = domain.IP{Addr: ipv6}
} else {
sanitizeHostname := dnsname.SanitizeHostname(req.Hostinfo.Hostname)
if m.Name != sanitizeHostname {
if m.UseOSHostname && m.Name != sanitizeHostname {
nameIdx, err := h.repository.GetNextMachineNameIndex(ctx, tailnet.ID, sanitizeHostname)
if err != nil {
return logError(err)
+49
View File
@@ -0,0 +1,49 @@
package handlers
import (
"github.com/jsiebens/ionscale/internal/domain"
"github.com/labstack/echo/v4"
"go.uber.org/zap"
"net/http"
"tailscale.com/tailcfg"
"tailscale.com/types/key"
)
func NewUpdateHealthHandlers(machineKey key.MachinePublic, repository domain.Repository) *UpdateFeatureHandlers {
return &UpdateFeatureHandlers{machineKey: machineKey, repository: repository}
}
type UpdateFeatureHandlers struct {
machineKey key.MachinePublic
repository domain.Repository
}
func (h *UpdateFeatureHandlers) UpdateHealth(c echo.Context) error {
ctx := c.Request().Context()
req := new(tailcfg.HealthChangeRequest)
if err := c.Bind(req); err != nil {
return logError(err)
}
machineKey := h.machineKey.String()
nodeKey := req.NodeKey.String()
machine, err := h.repository.GetMachineByKeys(ctx, machineKey, nodeKey)
if err != nil {
return err
}
if machine == nil {
return echo.NewHTTPError(http.StatusBadRequest)
}
zap.L().Debug("Health checks updated",
zap.Uint64("tailnet", machine.TailnetID),
zap.Uint64("machine", machine.ID),
zap.String("subsystem", req.Subsys),
zap.String("err", req.Error),
)
return c.String(http.StatusOK, "OK")
}
+9 -20
View File
@@ -1,7 +1,6 @@
package mapping
import (
"encoding/json"
"fmt"
"github.com/jsiebens/ionscale/internal/config"
"github.com/jsiebens/ionscale/internal/domain"
@@ -15,19 +14,6 @@ import (
"time"
)
func CopyViaJson[F any, T any](f F, t T) error {
raw, err := json.Marshal(f)
if err != nil {
return err
}
if err := json.Unmarshal(raw, t); err != nil {
return err
}
return nil
}
func ToDNSConfig(m *domain.Machine, tailnet *domain.Tailnet, c *domain.DNSConfig) *tailcfg.DNSConfig {
certsEnabled := c.HttpsCertsEnabled && config.DNSProviderConfigured()
@@ -138,11 +124,14 @@ func ToNode(capVer tailcfg.CapabilityVersion, m *domain.Machine, tailnet *domain
allowedIPs = append(allowedIPs, netip.MustParsePrefix("0.0.0.0/0"), netip.MustParsePrefix("::/0"))
}
var derp string
var derp int
var legacyDerp string
if hostinfo.NetInfo != nil {
derp = fmt.Sprintf("127.3.3.40:%d", hostinfo.NetInfo.PreferredDERP)
derp = hostinfo.NetInfo.PreferredDERP
legacyDerp = fmt.Sprintf("127.3.3.40:%d", hostinfo.NetInfo.PreferredDERP)
} else {
derp = "127.3.3.40:0"
derp = 0
legacyDerp = "127.3.3.40:0"
}
var name = m.CompleteName()
@@ -166,7 +155,8 @@ func ToNode(capVer tailcfg.CapabilityVersion, m *domain.Machine, tailnet *domain
Addresses: addrs,
AllowedIPs: allowedIPs,
Endpoints: endpoints,
DERP: derp,
HomeDERP: derp,
LegacyDERPString: legacyDerp,
Hostinfo: hostInfo.View(),
Created: m.CreatedAt.UTC(),
@@ -235,6 +225,7 @@ func ToNode(capVer tailcfg.CapabilityVersion, m *domain.Machine, tailnet *domain
if m.HasTags() {
n.User = tailcfg.UserID(taggedDevicesUser.ID)
n.Tags = m.Tags
user = tailcfg.UserProfile{
ID: tailcfg.UserID(taggedDevicesUser.ID),
LoginName: "tagged-devices",
@@ -257,9 +248,7 @@ func ToUserProfile(u domain.User) tailcfg.UserProfile {
func ToUser(u domain.User) (tailcfg.User, tailcfg.Login) {
user := tailcfg.User{
ID: tailcfg.UserID(u.ID),
LoginName: u.Name,
DisplayName: u.Name,
Logins: []tailcfg.LoginID{tailcfg.LoginID(u.ID)},
}
login := tailcfg.Login{
ID: tailcfg.LoginID(u.ID),
+7
View File
@@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"github.com/caddyserver/certmagic"
"github.com/hashicorp/go-plugin"
"github.com/jsiebens/ionscale/internal/auth"
"github.com/jsiebens/ionscale/internal/config"
"github.com/jsiebens/ionscale/internal/core"
@@ -17,6 +18,7 @@ import (
"github.com/jsiebens/ionscale/internal/service"
"github.com/jsiebens/ionscale/internal/stunserver"
"github.com/jsiebens/ionscale/internal/templates"
"github.com/jsiebens/ionscale/internal/util"
"github.com/labstack/echo-contrib/echoprometheus"
"github.com/labstack/echo-contrib/pprof"
"github.com/labstack/echo/v4"
@@ -53,6 +55,8 @@ func Start(ctx context.Context, c *config.Config) error {
return err
}
util.EnsureIDProvider()
derpMap, err := derp.LoadDERPSources(c)
if err != nil {
logger.Warn("not all derp sources are read successfully", zap.Error(err))
@@ -122,6 +126,7 @@ func Start(ctx context.Context, c *config.Config) error {
idTokenHandlers := handlers.NewIDTokenHandlers(machinePublicKey, c, repository)
sshActionHandlers := handlers.NewSSHActionHandlers(machinePublicKey, c, repository)
queryFeatureHandlers := handlers.NewQueryFeatureHandlers(machinePublicKey, dnsProvider, repository)
updateHealthHandlers := handlers.NewUpdateHealthHandlers(machinePublicKey, repository)
e := echo.New()
e.Binder = handlers.JsonBinder{}
@@ -134,6 +139,7 @@ func Start(ctx context.Context, c *config.Config) error {
e.GET("/machine/ssh/action/:src_machine_id/to/:dst_machine_id/:check_period", sshActionHandlers.StartAuth)
e.GET("/machine/ssh/action/check/:key", sshActionHandlers.CheckAuth)
e.POST("/machine/feature/query", queryFeatureHandlers.QueryFeature)
e.POST("/machine/update-health", updateHealthHandlers.UpdateHealth)
return e
}
@@ -216,6 +222,7 @@ func Start(ctx context.Context, c *config.Config) error {
go func() {
<-gCtx.Done()
logger.Sugar().Infow("Shutting down ionscale server")
plugin.CleanupClients()
shutdownHttpServer(metricsServer)
shutdownHttpServer(webServer)
_ = stunServer.Shutdown()
+2 -1
View File
@@ -2,6 +2,7 @@ package service
import (
"context"
"errors"
"fmt"
"github.com/bufbuild/connect-go"
"github.com/jsiebens/ionscale/internal/domain"
@@ -59,7 +60,7 @@ func (s *Service) Authenticate(ctx context.Context, req *connect.Request[api.Aut
}
if len(m.Error) != 0 {
return connect.NewError(connect.CodePermissionDenied, fmt.Errorf(m.Error))
return connect.NewError(connect.CodePermissionDenied, errors.New(m.Error))
}
if err := stream.Send(&api.AuthenticateResponse{AuthUrl: authUrl}); err != nil {
+68
View File
@@ -8,6 +8,8 @@ import (
api "github.com/jsiebens/ionscale/pkg/gen/ionscale/v1"
"google.golang.org/protobuf/types/known/timestamppb"
"net/netip"
"strings"
"tailscale.com/util/dnsname"
"time"
)
@@ -162,6 +164,72 @@ func (s *Service) ExpireMachine(ctx context.Context, req *connect.Request[api.Ex
return connect.NewResponse(&api.ExpireMachineResponse{}), nil
}
func (s *Service) SetMachineName(ctx context.Context, req *connect.Request[api.SetMachineNameRequest]) (*connect.Response[api.SetMachineNameResponse], error) {
principal := CurrentPrincipal(ctx)
m, err := s.repository.GetMachine(ctx, req.Msg.MachineId)
if err != nil {
return nil, logError(err)
}
if m == nil {
return nil, connect.NewError(connect.CodeNotFound, fmt.Errorf("machine not found"))
}
if !principal.IsSystemAdmin() && !principal.IsTailnetAdmin(m.TailnetID) {
return nil, connect.NewError(connect.CodePermissionDenied, fmt.Errorf("permission denied"))
}
if req.Msg.UseOsHostname {
sanitizeHostname := dnsname.SanitizeHostname(m.HostInfo.Hostname)
nameIdx, err := s.repository.GetNextMachineNameIndex(ctx, m.TailnetID, sanitizeHostname)
if err != nil {
return nil, logError(err)
}
m.Name = sanitizeHostname
m.NameIdx = nameIdx
m.UseOSHostname = true
if err := s.repository.SaveMachine(ctx, m); err != nil {
return nil, logError(err)
}
s.sessionManager.NotifyAll(m.TailnetID)
return connect.NewResponse(&api.SetMachineNameResponse{}), nil
}
if strings.TrimSpace(req.Msg.Name) == "" {
return nil, connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("machine name is required when not using os hostname"))
}
sanitizeHostname := dnsname.SanitizeHostname(req.Msg.Name)
if sanitizeHostname == m.Name {
return connect.NewResponse(&api.SetMachineNameResponse{}), nil
}
nameIdx, err := s.repository.GetNextMachineNameIndex(ctx, m.TailnetID, sanitizeHostname)
if err != nil {
return nil, logError(err)
}
if nameIdx > 0 {
return nil, connect.NewError(connect.CodeAlreadyExists, fmt.Errorf("machine name already in use"))
}
m.Name = sanitizeHostname
m.NameIdx = 0
m.UseOSHostname = false
if err := s.repository.SaveMachine(ctx, m); err != nil {
return nil, logError(err)
}
s.sessionManager.NotifyAll(m.TailnetID)
return connect.NewResponse(&api.SetMachineNameResponse{}), nil
}
func (s *Service) AuthorizeMachine(ctx context.Context, req *connect.Request[api.AuthorizeMachineRequest]) (*connect.Response[api.AuthorizeMachineResponse], error) {
principal := CurrentPrincipal(ctx)
+50 -12
View File
@@ -1,8 +1,10 @@
package util
import (
"errors"
"fmt"
"github.com/sony/sonyflake"
"go.uber.org/zap"
"net"
"os"
"strconv"
@@ -11,30 +13,66 @@ import (
)
var (
sf *sonyflake.Sonyflake
sf provider
sfOnce sync.Once
)
func NextID() uint64 {
ensureProvider()
id, _ := sf.NextID()
EnsureIDProvider()
id, err := sf.NextID()
if err != nil {
panic(err)
}
return id
}
func ensureProvider() {
sfOnce.Do(func() {
sfInstance, err := sonyflake.New(sonyflake.Settings{
MachineID: machineID(),
StartTime: time.Date(2022, 05, 01, 00, 0, 0, 0, time.UTC),
})
if err != nil {
panic("unable to initialize sonyflake: " + err.Error())
type provider interface {
NextID() (uint64, error)
}
sf = sfInstance
type errorProvider struct {
err error
}
func (e errorProvider) NextID() (uint64, error) {
return 0, fmt.Errorf("unable to generate ID, sonyflake not configured properly: %w", e.err)
}
func EnsureIDProvider() {
sfOnce.Do(func() {
sf = createIDProvider()
})
}
func createIDProvider() provider {
startTime := time.Date(2022, 05, 01, 00, 0, 0, 0, time.UTC)
sfInstance, err := sonyflake.New(sonyflake.Settings{
MachineID: machineID(),
StartTime: startTime,
})
if err != nil && errors.Is(err, sonyflake.ErrNoPrivateAddress) {
id := RandUint16()
zap.L().Warn("failed to generate sonyflake machine id from private ip address, using a random machine id", zap.Uint16("id", id))
sfInstance, err = sonyflake.New(sonyflake.Settings{
MachineID: func() (uint16, error) { return id, nil },
StartTime: startTime,
})
if err != nil {
return errorProvider{err}
}
}
if err != nil {
return errorProvider{err}
}
return sfInstance
}
func machineID() func() (uint16, error) {
envMachineID := os.Getenv("IONSCALE_MACHINE_ID")
if len(envMachineID) != 0 {
+10
View File
@@ -4,6 +4,7 @@ import (
"crypto/md5"
"crypto/rand"
"crypto/rsa"
"encoding/binary"
"encoding/hex"
"encoding/json"
"math/big"
@@ -31,6 +32,15 @@ func RandUint64(n uint64) uint64 {
return val.Uint64()
}
func RandUint16() uint16 {
var randomBytes [2]byte
_, err := rand.Read(randomBytes[:])
if err != nil {
panic(err)
}
return binary.BigEndian.Uint16(randomBytes[:])
}
func RandomBytes(size int) ([]byte, error) {
buf := make([]byte, size)
if _, err := rand.Read(buf); err != nil {
+152
View File
@@ -0,0 +1,152 @@
package util
import (
"fmt"
"io"
"log"
"strings"
"github.com/hashicorp/go-hclog"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
type ZapHCLogAdapter struct {
zapLogger *zap.Logger
name string
}
func NewZapAdapter(zapLogger *zap.Logger, name string) *ZapHCLogAdapter {
return &ZapHCLogAdapter{
zapLogger: zapLogger.WithOptions(zap.AddCallerSkip(2)),
name: name,
}
}
func (z *ZapHCLogAdapter) Log(level hclog.Level, msg string, args ...interface{}) {
fields := make([]zap.Field, 0, len(args)/2)
for i := 0; i < len(args); i += 2 {
if i+1 < len(args) {
key, ok := args[i].(string)
if !ok {
key = fmt.Sprintf("%v", args[i])
}
fields = append(fields, zap.Any(key, args[i+1]))
}
}
switch level {
case hclog.Trace:
z.zapLogger.Debug(msg, fields...)
case hclog.Debug:
z.zapLogger.Debug(msg, fields...)
case hclog.Info:
z.zapLogger.Info(msg, fields...)
case hclog.Warn:
z.zapLogger.Warn(msg, fields...)
case hclog.Error:
z.zapLogger.Error(msg, fields...)
}
}
func (z *ZapHCLogAdapter) Trace(msg string, args ...interface{}) {
z.Log(hclog.Trace, msg, args...)
}
func (z *ZapHCLogAdapter) Debug(msg string, args ...interface{}) {
z.Log(hclog.Debug, msg, args...)
}
func (z *ZapHCLogAdapter) Info(msg string, args ...interface{}) {
z.Log(hclog.Info, msg, args...)
}
func (z *ZapHCLogAdapter) Warn(msg string, args ...interface{}) {
z.Log(hclog.Warn, msg, args...)
}
func (z *ZapHCLogAdapter) Error(msg string, args ...interface{}) {
z.Log(hclog.Error, msg, args...)
}
func (z *ZapHCLogAdapter) IsTrace() bool {
return z.zapLogger.Core().Enabled(zapcore.DebugLevel)
}
func (z *ZapHCLogAdapter) IsDebug() bool {
return z.zapLogger.Core().Enabled(zapcore.DebugLevel)
}
func (z *ZapHCLogAdapter) IsInfo() bool {
return z.zapLogger.Core().Enabled(zapcore.InfoLevel)
}
func (z *ZapHCLogAdapter) IsWarn() bool {
return z.zapLogger.Core().Enabled(zapcore.WarnLevel)
}
func (z *ZapHCLogAdapter) IsError() bool {
return z.zapLogger.Core().Enabled(zapcore.ErrorLevel)
}
func (z *ZapHCLogAdapter) ImpliedArgs() []interface{} {
return nil
}
func (z *ZapHCLogAdapter) With(args ...interface{}) hclog.Logger {
if len(args) == 0 {
return z
}
fields := make([]zap.Field, 0, len(args)/2)
for i := 0; i < len(args); i += 2 {
if i+1 < len(args) {
key, ok := args[i].(string)
if !ok {
key = fmt.Sprintf("%v", args[i])
}
fields = append(fields, zap.Any(key, args[i+1]))
}
}
newLogger := z.zapLogger.With(fields...)
return &ZapHCLogAdapter{
zapLogger: newLogger,
}
}
func (z *ZapHCLogAdapter) Name() string {
return z.name
}
func (z *ZapHCLogAdapter) Named(name string) hclog.Logger {
return &ZapHCLogAdapter{zapLogger: z.zapLogger.Named(name), name: name}
}
func (z *ZapHCLogAdapter) ResetNamed(name string) hclog.Logger {
return &ZapHCLogAdapter{
zapLogger: z.zapLogger,
name: name,
}
}
func (z *ZapHCLogAdapter) SetLevel(level hclog.Level) {
}
func (z *ZapHCLogAdapter) GetLevel() hclog.Level {
return hclog.LevelFromString(z.zapLogger.Level().String())
}
func (z *ZapHCLogAdapter) StandardLogger(opts *hclog.StandardLoggerOptions) *log.Logger {
return log.New(z, "", log.LstdFlags)
}
func (z *ZapHCLogAdapter) StandardWriter(opts *hclog.StandardLoggerOptions) io.Writer {
return z
}
func (z *ZapHCLogAdapter) Write(p []byte) (n int, err error) {
s := strings.TrimSpace(string(p))
z.Info(s)
return len(p), nil
}
+191
View File
@@ -0,0 +1,191 @@
# Configuring authentication with OIDC
While ionscale can operate without an OIDC (OpenID Connect) provider using only static keys, configuring an OIDC provider is highly recommended for enhanced security, user management, and a smoother administrative experience.
## Why configure an OIDC provider?
Without an OIDC provider, ionscale operates in a key-only mode:
- System administrators can only use the system admin key for administrative tasks
- Tailscale devices can only connect using [tags](https://tailscale.com/kb/1068/tags) and [pre-authentication keys](https://tailscale.com/kb/1085/auth-keys)
- No user accounts or user-specific permissions are available
With an OIDC provider configured:
- Users can authenticate using their existing identity provider credentials
- Administrators can assign specific permissions to users
- System administration can be delegated to specific users
- Fine-grained access control based on user identity becomes possible
- More seamless user experience with browser-based authentication
## Supported OIDC providers
ionscale supports any standard OIDC provider, including:
- Google Workspace
- Auth0
- Okta
- Azure AD / Microsoft Entra ID
- Keycloak
- GitLab
- GitHub (OAuth 2.0 with OIDC extensions)
- And many others
## Basic OIDC configuration
To configure an OIDC provider, update your ionscale configuration file (`config.yaml`) with the following settings:
```yaml
auth:
provider:
# OIDC issuer URL where ionscale can find the OpenID Provider Configuration Document
issuer: "https://your-oidc-provider.com"
# OIDC client ID and secret
client_id: "your-client-id"
client_secret: "your-client-secret"
# Optional: additional OIDC scopes used in the OIDC flow
additional_scopes: "groups"
```
### Required configuration fields
- `issuer`: The URL to your OIDC provider's issuer. This URL is used to discover your provider's endpoints.
- `client_id`: The client ID from your OIDC provider application registration.
- `client_secret`: The client secret from your OIDC provider application registration.
### Optional configuration
- `additional_scopes`: A space-separated list of additional OAuth scopes to request during authentication.
By default, ionscale requests the `openid`, `email`, and `profile` scopes.
## Configuring your OIDC provider
When registering ionscale with your OIDC provider, you'll need to configure the following:
**Redirect URI**: Set to `https://your-ionscale-domain.com/auth/callback`
## System administrator access
With OIDC configured, you'll want to specify which users have system administrator privileges.
This is done in the `auth.system_admins` section of your configuration:
```yaml
auth:
# Configuration from previous section...
system_admins:
# By email address
emails:
- "admin@example.com"
- "secadmin@example.com"
# By subject identifier (sub claim from OIDC)
subs:
- "user|123456"
# By attribute expression (using BEXPR syntax)
filters:
- "token.groups contains \"admin\""
- "domain == \"admin.example.com\""
```
You can use one or more of these methods to designate system administrators:
1. **By Email**: List specific email addresses that should have admin privileges.
2. **By Subject ID**: List specific user IDs (the `sub` claim from your OIDC provider).
3. **By Expression**: Use BEXPR filters to determine admin status based on token claims.
## OIDC authentication flow
When a user attempts to authenticate with ionscale:
1. The user is redirected to the OIDC provider's login page.
2. After successful authentication, the user is redirected back to ionscale.
3. ionscale verifies the authentication and checks if:
- The user is a system administrator (based on the `system_admins` configuration).
- The user has access to any tailnets (based on IAM policies configured for individual tailnets).
## Provider-specific setup instructions
### Google
1. Go to the [Google Cloud Console](https://console.cloud.google.com/).
2. Create a new project or select an existing one.
3. Navigate to "APIs & Services" > "Credentials".
4. Click "Create Credentials" > "OAuth client ID".
5. Select "Web application" as the application type.
6. Add `https://your-ionscale-domain.com/auth/callback` as an authorized redirect URI.
7. Copy the client ID and client secret.
Configure ionscale:
```yaml
auth:
provider:
issuer: "https://accounts.google.com"
client_id: "your-client-id.apps.googleusercontent.com"
client_secret: "your-client-secret"
```
### Auth0
1. Go to the [Auth0 Dashboard](https://manage.auth0.com/).
2. Create a new application or select an existing one of type "Regular Web Application".
3. Under "Settings", configure:
- Allowed Callback URLs: `https://your-ionscale-domain.com/auth/callback`
4. Copy the Domain, Client ID, and Client Secret.
Configure ionscale:
```yaml
auth:
provider:
issuer: "https://your-tenant.auth0.com/"
client_id: "your-client-id"
client_secret: "your-client-secret"
```
### Microsoft Azure AD / Entra ID
1. Go to the [Azure Portal](https://portal.azure.com/).
2. Navigate to "Azure Active Directory" > "App registrations".
3. Create a new registration.
4. Add `https://your-ionscale-domain.com/auth/callback` as a redirect URI of type "Web".
5. Under "Certificates & secrets", create a new client secret.
6. Copy the Application (client) ID and the new secret.
Configure ionscale:
```yaml
auth:
provider:
issuer: "https://login.microsoftonline.com/your-tenant-id/v2.0"
client_id: "your-client-id"
client_secret: "your-client-secret"
additional_scopes: "offline_access"
```
## Complete configuration example
```yaml
auth:
provider:
issuer: "https://accounts.google.com"
client_id: "your-client-id.apps.googleusercontent.com"
client_secret: "your-client-secret"
additional_scopes: "groups"
system_admins:
emails:
- "admin@example.com"
filters:
- "domain == \"example.com\" && token.groups contains \"admin\""
```
## OIDC without system admin
If you've configured OIDC but no system administrators, you can still use the system admin key from your initial setup for administrative tasks:
```bash
export IONSCALE_ADDR="https://your-ionscale-domain.com"
export IONSCALE_SYSTEM_ADMIN_KEY="your-system-admin-key"
ionscale tailnet list
```
+199
View File
@@ -0,0 +1,199 @@
# DERP Configuration
DERP (Designated Encrypted Relay for Packets) servers are relay servers that help Tailscale clients establish connections when direct connections aren't possible due to NAT, firewalls, or other network impediments. ionscale provides flexible DERP configuration options to support various deployment scenarios.
## Embedded DERP Server
ionscale includes a built-in DERP server that is enabled by default. This provides an out-of-the-box relay solution without requiring additional infrastructure.
### Configuration
The embedded DERP server can be configured in your ionscale configuration file:
```yaml
derp:
server:
disabled: false # Set to true to disable the embedded DERP server
region_id: 1000 # The region ID for the embedded DERP server
region_code: "ionscale" # The region code (short name)
region_name: "ionscale Embedded DERP" # Human-readable region name
```
Additional networking parameters that affect the DERP server:
```yaml
# The HTTP(S) listen address for the control plane (also used for DERP)
listen_addr: ":8080"
# The STUN listen address when using the embedded DERP
stun_listen_addr: ":3478"
# The DNS name of the server HTTP(S) endpoint as accessible by clients
public_addr: "ionscale.example.com:443"
# The DNS name of the STUN endpoint as accessible by clients
stun_public_addr: "ionscale.example.com:3478"
```
!!! important
For the embedded DERP server to function properly, clients must be able to reach your ionscale server at the configured `public_addr` and `stun_public_addr`. Ensure these addresses are publicly accessible and have the appropriate ports open in your firewall.
## External DERP Sources
In addition to or instead of the embedded DERP server, ionscale can use external DERP servers. This is useful for:
- Using Tailscale's global DERP infrastructure
- Setting up your own geographically distributed DERP servers
- Optimizing connection paths for globally distributed teams
To configure external DERP sources:
```yaml
derp:
sources:
- https://controlplane.tailscale.com/derpmap/default # Tailscale's default DERP map
- https://example.com/my-custom-derpmap.json # Custom DERP map
- git::https://github.com/example/derpmap//config.json # From a git repository
- file:///etc/ionscale/derpmaps/custom.json # From a local file
```
The `derp.sources` field accepts a list of URLs that point to JSON files containing DERP map configurations. These sources are loaded at server startup and merged with the embedded DERP configuration (if enabled).
!!! info "Source locations"
ionscale uses HashiCorp's [go-getter](https://github.com/hashicorp/go-getter) library to fetch external sources, which supports multiple protocols and source types:
- **HTTP/HTTPS**: `https://example.com/derpmap.json`
- **Local files**: `file:///path/to/derpmap.json`
- **Git repositories**: `git::https://github.com/user/repo//path/to/file.json`
- **S3 buckets**: `s3::https://s3.amazonaws.com/bucket/derpmap.json`
- **GCS buckets**: `gcs::https://www.googleapis.com/storage/v1/bucket/derpmap.json`
This flexibility allows you to store and manage your DERP maps in various locations based on your organization's needs.
!!! note
At the time of writing, ionscale only loads external DERP sources at startup and does not automatically poll them for changes. To apply changes to external DERP sources, you will need to restart the ionscale server.
## Instance and Tailnet DERP Configuration
ionscale provides a flexible DERP configuration model:
### Default Instance Configuration
By default, all tailnets use the DERP map defined at the instance level, which includes:
- The embedded DERP server (if enabled)
- Any external DERP sources configured in your ionscale configuration file
You can view the instance-level DERP map with:
```bash
ionscale system get-derp-map [--json]
```
### Tailnet-Specific Configuration
Each tailnet can be configured with its own custom DERP map. This gives you the flexibility to:
- Provide optimized DERP configurations for teams in different regions
- Test new DERP setups on specific tailnets before broader deployment
- Create specialized network paths for particular use cases
When a tailnet doesn't have a custom DERP map configured, it automatically uses the instance's default DERP map.
Managing tailnet-specific DERP maps:
```bash
# View a tailnet's current DERP map
ionscale tailnets get-derp-map --tailnet <tailnet-id> [--json]
# Set a custom DERP map for a specific tailnet
ionscale tailnets set-derp-map --tailnet <tailnet-id> --file <derpmap.json>
# Remove the custom configuration and revert to the instance default
ionscale tailnets reset-derp-map --tailnet <tailnet-id>
```
## Creating Custom DERP Maps
A DERP map is a JSON structure containing regions and nodes. Here's an example:
```json
{
"Regions": {
"1": {
"RegionID": 1,
"RegionCode": "nyc",
"RegionName": "New York City",
"Nodes": [
{
"Name": "1a",
"RegionID": 1,
"HostName": "derp1.example.com",
"DERPPort": 443,
"STUNPort": 3478
}
]
},
"2": {
"RegionID": 2,
"RegionCode": "sfo",
"RegionName": "San Francisco",
"Nodes": [
{
"Name": "2a",
"RegionID": 2,
"HostName": "derp2.example.com",
"DERPPort": 443,
"STUNPort": 3478
}
]
}
}
}
```
Important fields:
- `RegionID`: A unique identifier for the region (1-999 for custom regions, 1000+ reserved for ionscale)
- `RegionCode`: A short code for the region (e.g., "nyc", "sfo")
- `RegionName`: A human-readable name for the region
- `Nodes`: A list of DERP servers in the region
- `Name`: A unique name for the node within the region
- `HostName`: The DNS name of the DERP server
- `DERPPort`: The port for DERP traffic (typically 443)
- `STUNPort`: The port for STUN traffic (typically 3478)
To apply a custom DERP map to a tailnet:
```bash
# Create the DERP map file
cat > my-derpmap.json <<EOF
{
"Regions": {
"1": {
"RegionID": 1,
"RegionCode": "custom",
"RegionName": "My Custom DERP",
"Nodes": [
{
"Name": "derp1",
"RegionID": 1,
"HostName": "derp.example.com",
"DERPPort": 443,
"STUNPort": 3478
}
]
}
}
}
EOF
# Apply it to a tailnet
ionscale tailnets set-derp-map --tailnet <tailnet-id> --file my-derpmap.json
```
!!! tip
DERP servers primarily help with establishing connections when direct peer-to-peer connections aren't possible. Having DERP servers geographically close to your users can improve connection establishment times and provide better fallback performance.
!!! note
Changes to DERP maps are automatically distributed to clients during their regular polling. There's no need to manually update clients when changing DERP configurations.
+244
View File
@@ -0,0 +1,244 @@
# Configuring DNS providers
ionscale supports integration with various DNS providers to enable Tailscale's HTTPS certificate functionality. When a DNS provider is properly configured, ionscale can automatically manage TXT records required for the DNS-01 challenge when requesting certificates.
## Why configure a DNS provider
While not strictly required for basic ionscale operation, configuring a DNS provider enables important Tailscale features:
1. **Tailscale HTTPS Certificates**: Allows nodes to receive valid HTTPS certificates for their Tailscale hostnames, enabling secure web services within your tailnet.
2. **Tailscale Serve**: Supports the `tailscale serve` feature, which allows users to easily share web services with proper HTTPS.
Without a configured DNS provider, these features will not be available to your users.
## Supported DNS providers
ionscale supports DNS providers through two methods:
### Built-in providers (deprecated)
ionscale includes built-in support for the following DNS providers using [libdns](https://github.com/libdns) libraries:
- [Azure DNS](https://github.com/libdns/azure)
- [Cloudflare](https://github.com/libdns/cloudflare)
- [DigitalOcean](https://github.com/libdns/digitalocean)
- [Google Cloud DNS](https://github.com/libdns/googleclouddns)
- [Amazon Route 53](https://github.com/libdns/route53)
!!! warning "Built-in providers are deprecated"
The built-in DNS providers are deprecated and will be removed in a future release. Please migrate to external DNS plugins for continued support.
### External DNS plugins (recommended)
ionscale now supports external DNS plugins through a plugin system. This allows for:
- **Extensibility**: Add support for any DNS provider without modifying ionscale
- **Maintainability**: Plugins are maintained independently
- **Flexibility**: Plugin configuration specific to each provider's needs
!!! info "Plugin availability"
External DNS plugins implement the [libdns-plugin](https://github.com/libdns/libdns-plugin) interface. Official plugin implementations can be found in the [ionscale GitHub organization](https://github.com/ionscale) with repositories named `ionscale-<provider>-dns`. You can also create your own following the plugin specification.
## DNS provider configuration
To configure a DNS provider, add the appropriate settings to your ionscale configuration file (`config.yaml`):
### Built-in provider configuration
```yaml
dns:
# The base domain for MagicDNS FQDN hostnames
magic_dns_suffix: "ionscale.net"
# DNS provider configuration for HTTPS certificates
provider:
# Name of your DNS provider
name: "cloudflare"
# The DNS zone to use (typically your domain name)
zone: "example.com"
# Provider-specific configuration (varies by provider)
config:
# Provider-specific credentials and settings go here
# See provider-specific examples below
```
### External plugin configuration
```yaml
dns:
# The base domain for MagicDNS FQDN hostnames
magic_dns_suffix: "ionscale.net"
# DNS provider configuration for HTTPS certificates
provider:
# Path to your DNS plugin executable
plugin_path: "/path/to/your/dns-plugin"
# The DNS zone to use (typically your domain name)
zone: "example.com"
# Plugin-specific configuration (varies by plugin)
config:
# Plugin-specific credentials and settings go here
# See plugin documentation for configuration options
```
### Important requirements
1. The `magic_dns_suffix` must be a subdomain of the provider's zone (or the zone itself).
2. MagicDNS must be enabled for the tailnet to use HTTPS certificates.
3. You must have administrative access to the DNS zone to configure the provider.
4. For external plugins, the plugin executable must be accessible and executable by the ionscale process.
## Provider-specific examples
### Cloudflare
```yaml
dns:
magic_dns_suffix: "ts.example.com"
provider:
name: "cloudflare"
zone: "example.com"
config:
api_token: "your-cloudflare-api-token"
```
For Cloudflare, create an API token with the "Edit" permission for "Zone:DNS".
### Azure DNS
```yaml
dns:
magic_dns_suffix: "ts.example.com"
provider:
name: "azure"
zone: "example.com"
config:
tenant_id: "your-tenant-id"
client_id: "your-client-id"
client_secret: "your-client-secret"
subscription_id: "your-subscription-id"
resource_group_name: "your-resource-group"
```
For Azure, create a service principal with "DNS Zone Contributor" role for your DNS zone's resource group.
### Amazon Route 53
```yaml
dns:
magic_dns_suffix: "ts.example.com"
provider:
name: "route53"
zone: "example.com"
config:
access_key_id: "your-access-key-id"
secret_access_key: "your-secret-access-key"
# Optional region, defaults to us-east-1
region: "us-east-1"
...
```
For AWS Route 53, create an IAM user with permissions to modify records in your hosted zone.
### Google Cloud DNS
```yaml
dns:
magic_dns_suffix: "ts.example.com"
provider:
name: "googleclouddns"
zone: "example-com" # Note: GCP uses zone names without dots
config:
gcp_project: "your-project-id"
# Optional path to a service account key file
# gcp_application_default: "/path/to/service-account-key.json"
```
For Google Cloud DNS, create a service account with the "DNS Administrator" role.
### DigitalOcean
```yaml
dns:
magic_dns_suffix: "ts.example.com"
provider:
name: "digitalocean"
zone: "example.com"
config:
auth_token: "your-digitalocean-api-token"
```
For DigitalOcean, create an API token with read and write access.
## External DNS plugin examples
### Using a hypothetical Cloudflare plugin
```yaml
dns:
magic_dns_suffix: "ts.example.com"
provider:
plugin_path: "/usr/local/bin/libdns-cloudflare-plugin"
zone: "example.com"
config:
api_token: "your-cloudflare-api-token"
```
### Using a custom DNS plugin
```yaml
dns:
magic_dns_suffix: "ts.example.com"
provider:
plugin_path: "/opt/dns-plugins/my-custom-provider"
zone: "example.com"
config:
# Configuration specific to your custom plugin
endpoint: "https://api.mydnsprovider.com"
api_key: "your-api-key"
custom_setting: "value"
```
!!! tip "Plugin development"
To create your own DNS plugin, implement the [libdns-plugin](https://github.com/libdns/libdns-plugin) interface. The plugin system uses HashiCorp's go-plugin framework for communication between ionscale and your plugin.
## Enabling HTTPS certificates for a tailnet
After configuring a DNS provider in your ionscale server, you can enable HTTPS certificates for a tailnet:
```bash
# Enable MagicDNS and HTTPS certificates for a tailnet
ionscale dns update --tailnet "my-tailnet" --magic-dns --https-certs
```
## Verifying DNS provider configuration
To verify that your DNS provider is correctly configured:
1. Configure a tailnet with MagicDNS and HTTPS certificates enabled.
2. Connect a device to the tailnet.
3. On the device, run:
```bash
tailscale cert <hostname>
```
4. If successful, the command will obtain a certificate for the hostname.
5. You should see TXT records created in your DNS zone for the ACME challenge.
## Troubleshooting
If you encounter issues with DNS provider integration:
### General troubleshooting
1. **Check DNS Provider Credentials**: Ensure the credentials in your configuration have sufficient permissions.
2. **Verify Zone Configuration**: Make sure the zone in your configuration matches your actual DNS zone.
3. **Check MagicDNS Settings**: Confirm that `magic_dns_suffix` is properly configured as a subdomain of your zone.
4. **Review Server Logs**: The ionscale server logs may contain error messages related to DNS provider integration.
5. **Test DNS Record Creation**: Some providers offer tools to test API access for creating and updating DNS records.
### External plugin troubleshooting
1. **Plugin Executable**: Ensure the plugin path is correct and the executable has proper permissions.
2. **Plugin Logs**: Check both ionscale logs and any plugin-specific logs for error messages.
3. **Plugin Health**: ionscale automatically restarts failed plugins, but persistent failures may indicate configuration issues.
+393
View File
@@ -0,0 +1,393 @@
# Configuration Guide
ionscale uses a flexible YAML-based configuration system that supports environment variable substitution and sensible defaults. This guide explains how to configure your ionscale instance.
## Configuration File Format
ionscale uses YAML for its configuration files. Here's a basic example:
```yaml
# Server network configuration
listen_addr: ":8080"
public_addr: "ionscale.example.com:443"
stun_listen_addr: ":3478"
stun_public_addr: "ionscale.example.com:3478"
# TLS configuration
tls:
disable: false
force_https: true
cert_file: /etc/ionscale/cert.pem
key_file: /etc/ionscale/key.pem
# Database configuration
database:
type: postgres
url: postgres://user:password@localhost:5432/ionscale
```
## Loading Configuration
When starting ionscale, you can specify a configuration file using the `--config` or `-c` flag:
```bash
ionscale server --config /etc/ionscale/config.yaml
```
If no configuration file is provided, ionscale will use its default values.
## Environment Variable Support
ionscale supports two ways to use environment variables in configuration:
### 1. Direct Configuration via Environment Variables
You can provide the entire configuration as a base64-encoded string using the `IONSCALE_CONFIG_BASE64` environment variable. This is useful for containerized deployments where you want to inject configuration without mounting files.
```bash
# Create base64-encoded config
CONFIG_B64=$(cat config.yaml | base64 -w0)
# Run ionscale with environment config
IONSCALE_CONFIG_BASE64=$CONFIG_B64 ionscale server
```
### 2. Variable Substitution in YAML Files
You can reference environment variables directly in your YAML configuration files using:
- `${VAR}` syntax for required variables
- `${VAR:default}` syntax for variables with default values
For example:
```yaml
database:
type: ${DB_TYPE:sqlite}
url: ${DB_URL}
max_open_conns: ${DB_MAX_OPEN_CONNS:10}
```
In this example:
- `DB_TYPE` has a default value of "sqlite" if the environment variable is not set
- `DB_URL` is required and must be set in the environment
- `DB_MAX_OPEN_CONNS` defaults to 10 if not set
If a required variable is missing, the configuration loading will fail with an error.
## Default Configuration
If no configuration file is provided, ionscale uses these default values:
```yaml
listen_addr: ":8080"
metrics_listen_addr: ":9091"
stun_listen_addr: ":3478"
database:
type: sqlite
url: ./ionscale.db?_pragma=busy_timeout(5000)&_pragma=journal_mode(WAL)&_pragma=foreign_keys(ON)
max_idle_conns: 2
poll_net:
keep_alive_interval: 1m
dns:
magic_dns_suffix: ionscale.net
derp:
server:
disabled: false
region_id: 1000
region_code: ionscale
region_name: ionscale Embedded DERP
logging:
level: info
```
## Configuration Sections
### Server Network Configuration
Controls the network interfaces and addresses:
```yaml
# The HTTP(S) listen address for the control plane
listen_addr: ":8080"
# The metrics listen address (for Prometheus)
metrics_listen_addr: ":9091"
# The STUN listen address when using the embedded DERP
stun_listen_addr: ":3478"
# The DNS name of the server HTTP(S) endpoint as accessible by clients
public_addr: "ionscale.example.com:443"
# The DNS name of the STUN endpoint as accessible by clients
stun_public_addr: "ionscale.example.com:3478"
```
### TLS Configuration
Controls HTTPS and certificate usage:
```yaml
tls:
# Disable TLS (not recommended for production)
disable: false
# Force HTTPS redirect
force_https: true
# Path to certificate files (when not using ACME)
cert_file: /etc/ionscale/cert.pem
key_file: /etc/ionscale/key.pem
# Let's Encrypt ACME configuration
acme: true
acme_email: admin@example.com
acme_ca: https://acme-v02.api.letsencrypt.org/directory
```
### Database Configuration
Controls the database storage:
```yaml
database:
# Database type: sqlite or postgres
type: postgres
# Database connection URL
url: postgres://user:password@localhost:5432/ionscale
# Connection pool settings
max_open_conns: 10
max_idle_conns: 5
conn_max_life_time: 5m
conn_max_idle_time: 5m
```
### OIDC Configuration
Controls OpenID Connect authentication providers and admin access:
```yaml
auth:
# OIDC provider configuration
provider:
issuer: https://auth.example.com
client_id: client_id
client_secret: client_secret
additional_scopes: ["profile", "email"]
# System administrators configuration
system_admins:
emails: ["admin@example.com"]
subs: ["subject123"]
filters: ["domain == example.com"]
```
For more details about configuring OIDC authentication, see [OIDC Configuration](./auth-oidc.md).
### DNS Configuration
Controls DNS settings:
```yaml
dns:
# Suffix for MagicDNS
magic_dns_suffix: ionscale.net
# DNS provider for dynamic updates
provider:
name: cloudflare
zone: example.com
config:
auth_token: ${CLOUDFLARE_TOKEN}
```
For more details about configuring DNS providers, see [DNS Providers](./dns-providers.md).
### DERP Configuration
Controls relay server configuration:
```yaml
derp:
# Embedded DERP server configuration
server:
disabled: false
region_id: 1000
region_code: ionscale
region_name: ionscale Embedded DERP
# External DERP maps to load
sources:
- https://controlplane.tailscale.com/derpmap/default
- file:///etc/ionscale/custom-derp.json
```
For more details about configuring DERP servers, see [DERP Configuration](./derp.md).
### Logging Configuration
Controls log output:
```yaml
logging:
# Log level: debug, info, warn, error
level: info
# Log format: text, json
format: text
# Optional file output (in addition to stdout)
file: /var/log/ionscale.log
```
### Keys and Security
You can configure private keys for the system:
```yaml
keys:
# System administrator key for CLI authentication
system_admin_key: your-private-key
# Control plane keys (optional, auto-generated when not provided)
control_key: your-control-key
legacy_control_key: your-legacy-control-key
```
The `control_key` and `legacy_control_key` are optional and will be automatically generated if not provided. Once generated, they are stored in the database and reused across restarts.
!!! warning
Never commit sensitive keys in your configuration files to version control. Use environment variables for sensitive values.
## Configuration File Locations
Common locations for ionscale configuration files:
- `/etc/ionscale/config.yaml` - System-wide configuration
- `$HOME/.config/ionscale/config.yaml` - User-specific configuration
- `./config.yaml` - Local directory configuration
## Complete Configuration Example
Below is a complete configuration file example with comments:
```yaml
# Network configuration
listen_addr: ":8080" # HTTP/HTTPS control plane address
stun_listen_addr: ":3478" # STUN server listen address
metrics_listen_addr: ":9091" # Prometheus metrics address
public_addr: "ionscale.example.com:443" # Public HTTPS endpoint for clients
stun_public_addr: "ionscale.example.com:3478" # Public STUN endpoint for clients
# TLS configuration
tls:
disable: false # Set to true if behind a TLS-terminating proxy
force_https: true # Redirect HTTP to HTTPS
# Provide your own certificates
cert_file: "/etc/ionscale/cert.pem"
key_file: "/etc/ionscale/key.pem"
# Or use Let's Encrypt
acme: false # Enable ACME/Let's Encrypt
acme_email: "admin@example.com" # Contact email for Let's Encrypt
acme_ca: "https://acme-v02.api.letsencrypt.org/directory"
acme_path: "./data" # Storage path for ACME certificates
# Database configuration
database:
# SQLite configuration
type: "sqlite"
url: "/var/lib/ionscale/ionscale.db?_pragma=busy_timeout(5000)&_pragma=journal_mode(WAL)&_pragma=foreign_keys(ON)"
# Or PostgreSQL configuration
# type: "postgres"
# url: "postgres://user:password@localhost:5432/ionscale?sslmode=disable"
# Connection pool settings
max_open_conns: 10
max_idle_conns: 5
conn_max_life_time: "5m"
conn_max_idle_time: "5m"
# DERP (relay) configuration
derp:
# Embedded DERP server
server:
disabled: false # Set to true to disable embedded DERP
region_id: 1000 # Region ID (1000+ reserved for ionscale)
region_code: "ionscale" # Short code for the region
region_name: "ionscale Embedded DERP" # Human-readable name
# External DERP sources (optional)
sources:
- https://controlplane.tailscale.com/derpmap/default # Tailscale's DERP map
# - file:///etc/ionscale/custom-derp.json # Custom DERP map
# - git::https://github.com/example/derp//map.json # DERP map from git
# Security keys
keys:
# System admin key for CLI authentication (required for admin CLI usage)
system_admin_key: "${IONSCALE_SYSTEM_ADMIN_KEY}" # Use environment variable
# Control keys (optional, auto-generated if not provided)
# control_key: "privkey:xxxxxx"
# legacy_control_key: "privkey:xxxxxx"
# Network polling configuration
poll_net:
# How often to send keep-alive messages
keep_alive_interval: "60s"
# OIDC authentication configuration
auth:
# OIDC provider settings
provider:
issuer: "https://auth.example.com" # OIDC issuer URL
client_id: "your-client-id" # OAuth client ID
client_secret: "${OIDC_CLIENT_SECRET}" # OAuth client secret from env var
additional_scopes: ["profile", "email"] # Extra scopes to request
# System administrator policy
system_admins:
# Users identified by email
emails: ["admin@example.com"]
# Users identified by subject ID
subs: ["subject-id-12345"]
# Users matching expression filters
filters: ["domain == example.com"]
# DNS configuration
dns:
# Suffix for MagicDNS hostnames
magic_dns_suffix: "ionscale.net"
# DNS provider for automatic DNS management (optional)
provider:
name: "cloudflare" # Provider name (cloudflare, route53, etc.)
zone: "example.com" # DNS zone to manage
config: # Provider-specific configuration
auth_token: "${DNS_API_TOKEN}"
# Logging configuration
logging:
level: "info" # debug, info, warn, error
format: "text" # text or json
file: "/var/log/ionscale.log" # Optional log file path
```
!!! note "Environment variables"
In this example, we use environment variables for sensitive values:
```
${IONSCALE_SYSTEM_ADMIN_KEY} - System admin key for CLI authentication
${OIDC_CLIENT_SECRET} - OIDC client secret
${DNS_API_TOKEN} - DNS provider API token
```
These must be set in your environment before starting ionscale.
-117
View File
@@ -1,117 +0,0 @@
# Configuration Reference
__ionscale__ uses the YAML file format for configuration.
A full configuration reference file is shown below, this provides comments and all available options.
```yaml
# The HTTP(S) listen address to serve the control plane.
listen_addr: ":8080"
# The STUN listen address when using the embedded DERP.
stun_listen_addr: ":3478"
# The address to bind to for the metrics.
metrics_listen_addr: ":9091"
# The DNS name of the server HTTP(S) endpoint as accessible by clients and the CLI.
public_addr: "ionscale.example.com:443"
# The DNS name of the STUN endpoint as accessible by clients.
stun_public_addr: "ionscale.example.com:3478"
tls:
# Disable TLS (not recommended)
# Use this flag to disable TLS e.g. when running behind a reverse proxy
disable: false
# Redirect HTTP requests to HTTPS requests
force_https: true
# The path to the certificate for TLS.
# Required when TLS is enabled and ACME disabled
cert_file: ""
# The path to the private key for the certificate.
# Required when TLS is enabled and ACME disabled
key_file: ""
# Enable automatic TLS certificates provisioning with Let's Encrypt
acme: false
# An email address, used when creating an ACME account and keeping you up-to-date regarding your certificates
acme_email: ""
# The URL to the ACME CA's directory.
acme_ca: "https://acme-v02.api.letsencrypt.org/directory"
# Path to store certificates and metadata needed by ACME
acme_path: "./data"
database:
# Type of databas to use, supported values are sqlite or postgres
type: "sqlite"
# The URL for connecting to the database
# e.g
# url: "/data/ionscale.db?_pragma=busy_timeout(5000)&_pragma=journal_mode(WAL)"
# url: "postgres://ionscale:ionscale@localhost/ionscale?sslmode=disable"
url: "./ionscale.db"
derp:
server:
disabled: false
region_id: 1000
region_code: "ionscale"
region_name: "ionscale Embedded DERP"
sources:
- https://controlplane.tailscale.com/derpmap/default
keys:
# A private, 32 bytes in hex, system admin key
# Use this key with the CLI when configuring system-wide resources like tailnets
# A key can be generated by:
# - ionscale genkey
# - openssl rand -hex 32
system_admin_key: ""
poll_net:
# Period to send keep alive messages to the connected devices
keep_alive_interval: "60s"
# Optional authentication configuration
auth:
# OIDC provider configuration
provider:
# OIDC issuer URL where ionscale can find the OpenID Provider Configuration Document
issuer: ""
# OIDC client id and secrets
client_id: ""
client_secret: ""
# additional OIDC scopes used in the OIDC flow
additional_scopes: ""
# IAM policy to mark some authenticated users as System Admin
system_admins:
# A list of emails of users that are System Admin
emails: []
# A list of ID (sub OIDC claim) of users that are System Admin
subs: []
# A list of BEXPR filters to mark authenticated users as System Admin
filters: []
dns:
# The base domain of the MagicDNS FQDN hostnames
magic_dns_suffix: "ionscale.net"
# A DNS provider for setting public TXT records
# This is a requirement to enable Tailscale HTTPS certs.
provider:
# name of your provider, currently supported implementations:
# - azure (https://github.com/libdns/azure)
# - cloudflare (https://github.com/libdns/cloudflare)
# - digitialocean (https://github.com/libdns/digitalocean)
# - googleclouddns (https://github.com/libdns/googleclouddns)
# - route53 (https://github.com/libdns/route53)
name: ""
# DNS zone
zone: ""
# Provider specific configuration
config: {}
logging:
# Output formatting for logs: text or json
format: "text"
level: "info"
# Path of a target log file, if omitted logs are written to stdout
file: ""
```
+123
View File
@@ -0,0 +1,123 @@
# ACL Policies
Access Control Lists (ACLs) define what network access is allowed within a tailnet. By default, tailnets are created with an open policy that allows all connections between devices.
## Understanding ACL policies
ACL policies in ionscale follow the same format and rules as Tailscale's ACL system. They allow you to control:
- Which devices can communicate with each other
- What ports and protocols are allowed
- Who can use exit nodes and other special features
- SSH access between machines
- Tag ownership and management
## Basic ACL structure
A basic ACL policy contains rules that specify which sources can access which destinations:
```json
{
"acls": [
{"action": "accept", "src": ["tag:web"], "dst": ["tag:db:5432"]},
{"action": "accept", "src": ["group:admins"], "dst": ["*:*"]}
],
"groups": {
"admins": ["admin@example.com"]
},
"tagOwners": {
"tag:web": ["admin@example.com"],
"tag:db": ["admin@example.com"]
}
}
```
In this example:
- Web servers (tagged `tag:web`) can only access database servers on port 5432
- Admins have full access to all resources
- Only admin@example.com can assign the web and database tags to machines
## Managing ACL policies
You can view and update the ACL policy for a tailnet using the ionscale CLI:
```bash
# View current ACL policy
ionscale acl get --tailnet "my-tailnet"
# Update ACL policy from a file
ionscale acl update --tailnet "my-tailnet" --file acl.json
```
!!! tip
ACL changes take effect immediately for all devices in the tailnet.
## Common ACL patterns
### Allow specific tags to communicate
```json
{
"acls": [
{"action": "accept", "src": ["tag:web"], "dst": ["tag:api:8080"]},
{"action": "accept", "src": ["tag:api"], "dst": ["tag:db:5432"]}
]
}
```
### Group-based access
```json
{
"acls": [
{"action": "accept", "src": ["group:developers"], "dst": ["tag:dev-env:*"]},
{"action": "accept", "src": ["group:ops"], "dst": ["*:*"]}
],
"groups": {
"developers": ["alice@example.com", "bob@example.com"],
"ops": ["charlie@example.com", "diana@example.com"]
}
}
```
### SSH access control
```json
{
"ssh": [
{
"action": "accept",
"src": ["group:admins"],
"dst": ["tag:server"],
"users": ["root"]
},
{
"action": "accept",
"src": ["group:developers"],
"dst": ["tag:dev"],
"users": ["autogroup:nonroot"]
}
]
}
```
### Auto-approving advertised routes
```json
{
"autoApprovers": {
"routes": {
"10.0.0.0/24": ["group:network-admins"],
"192.168.1.0/24": ["user@example.com"]
},
"exitNode": ["group:network-admins"]
}
}
```
## Additional resources
For more detailed information on ACL syntax and capabilities, see the [Tailscale ACL documentation](https://tailscale.com/kb/1018/acls/).
!!! note "Feature support"
Not all ACL features from the official Tailscale control plane are supported in ionscale. Some advanced features or newer functionality may not be available.
-72
View File
@@ -1,72 +0,0 @@
# Getting started with Docker
You can install and run __ionscale__ using the Docker images published on [GitHub Container Registry](https://github.com/jsiebens/ionscale/pkgs/container/ionscale).
## Requirements
- A Linux machine with port 443 and 3478 open to ingress traffic.
- Docker installed. See the [official installation documentation](https://docs.docker.com/install/)
- A registered domain name.
## Step 1. Configure DNS
Set up a `A` DNS records: `ionscale.example.com` (We are assuming that your domain name is example.com.)
!!! tip
You can use `dig` to make sure that DNS records are propagated:
``` bash
$ dig ionscale.example.com
```
## Step 2. Run ionscale with Docker
### Configure ionscale
``` bash
mkdir -p ionscale/data
cd ./ionscale
```
Generate a configuration file for __ionscale__ with the following commands:
``` bash
export IONSCALE_ACME_EMAIL=<your email>
export IONSCALE_DOMAIN=ionscale.example.com
export IONSCALE_SYSTEM_ADMIN_KEY=$(docker run ghcr.io/jsiebens/ionscale:0.15.0 genkey -n)
```
``` bash
tee ./config.yaml >/dev/null <<EOF
listen_addr: ":443"
public_addr: "${IONSCALE_DOMAIN}:443"
stun_public_addr: "${IONSCALE_DOMAIN}:3478"
tls:
acme: true
acme_email: "${IONSCALE_ACME_EMAIL}"
keys:
system_admin_key: "${IONSCALE_SYSTEM_ADMIN_KEY}"
database:
url: "/data/ionscale.db?_pragma=busy_timeout(5000)&_pragma=journal_mode(WAL)"
logging:
level: info
EOF
```
### Start ionscale
Run an __ionscale__ instance with the following command:
``` bash
docker run \
-v $(pwd)/config.yaml:/etc/ionscale/config.yaml \
-v $(pwd)/data:/data \
-p 443:443 \
-p 3478:3478/udp \
ghcr.io/jsiebens/ionscale:0.15.0 server --config /etc/ionscale/config.yaml
```
+160
View File
@@ -0,0 +1,160 @@
# IAM Policies
Identity and Access Management (IAM) policies in ionscale control who can access a tailnet and what administrative permissions they have.
!!! important "OIDC required"
IAM policies are only relevant when an OIDC provider is configured. If your ionscale instance isn't using OIDC, access to tailnets is managed solely through auth keys.
## Understanding IAM policies
IAM policies determine:
- Which users can join a tailnet
- What roles and permissions users have within the tailnet
- How access decisions are made based on user attributes
An IAM policy consists of:
```json
{
"subs": ["auth0|123456789"],
"filters": ["domain == example.com"],
"emails": ["specific-user@otherdomain.com"],
"roles": {
"admin@example.com": "admin"
}
}
```
## IAM policy components
### Subs
The `subs` list provides direct access based on user IDs (subjects):
```json
"subs": ["auth0|123456789", "google-oauth2|12345"]
```
Any user whose ID matches an entry in this list will be granted access to the tailnet. User IDs are typically provided by the OIDC provider and are unique identifiers for each user.
### Emails
The `emails` list provides direct access to specific email addresses:
```json
"emails": ["alice@example.com", "bob@otherdomain.com"]
```
Any user with an email in this list will be granted access to the tailnet, regardless of filters.
### Filters
Filters are expressions that evaluate user attributes:
```json
"filters": ["domain == example.com", "email.endsWith('@engineering.example.com')"]
```
These expressions determine if a user can access the tailnet based on their identity attributes. Users matching any filter expression will be granted access.
### Roles
The `roles` map assigns specific roles to users:
```json
"roles": {
"admin@example.com": "admin",
"devops@example.com": "admin",
"developer@example.com": "member"
}
```
Available roles:
- `admin`: Can manage tailnet settings, ACLs, and auth keys
- `member`: Standard access to use the tailnet (default)
## Managing IAM policies
View and update IAM policies using the ionscale CLI:
```bash
# View current IAM policy
ionscale iam get-policy --tailnet "my-tailnet"
# Update IAM policy using a JSON file
ionscale iam update-policy --tailnet "my-tailnet" --file policy.json
```
## Common IAM patterns
### Domain-based tailnet
Grant access to everyone with the same email domain:
```json
{
"filters": ["domain == example.com"],
"roles": {
"admin1@example.com": "admin",
"admin2@example.com": "admin"
}
}
```
### Personal tailnet
Create a tailnet for individual use:
```json
{
"emails": ["personal@example.com"],
"roles": {
"personal@example.com": "admin"
}
}
```
## Setting IAM during tailnet creation
You can set basic IAM policies during tailnet creation with CLI flags:
```bash
# Allow all users with an @example.com email address
ionscale tailnet create --name "shared-tailnet" --domain "example.com"
# Allow only a specific user
ionscale tailnet create --name "personal-tailnet" --email "user@example.com"
```
These shortcuts create appropriate filter rules or email entries in the IAM policy.
## IAM policy evaluation
When a user attempts to access a tailnet, the following checks occur:
1. Is the user's ID in the `subs` list? If yes, grant access.
2. Is the user's email in the `emails` list? If yes, grant access.
3. Does the user match any expression in the `filters` list? If yes, grant access.
4. If none of these conditions are met, access is denied.
For role determination:
1. Check if the user has an entry in the `roles` map
2. If yes, assign that role
3. If no, assign the default `member` role
## Security considerations
- **Principle of least privilege**: Start with minimal access and add users or filters as needed
- **Regular audits**: Periodically review IAM policies to ensure only appropriate users have access
- **Admin roles**: Limit admin roles to trusted users who need to manage tailnet settings
## Troubleshooting access issues
If a user is having trouble accessing a tailnet:
1. Verify the user's email is correct and matches their OIDC identity
2. Check filter expressions to ensure they match the user's attributes
3. Verify the user is authenticating against the correct ionscale instance
4. Check OIDC provider configuration and token issuance
+78
View File
@@ -0,0 +1,78 @@
# Getting started with ionscale
After installing ionscale, you'll need to configure the CLI to interact with your server. This guide will walk you through the initial setup and explain the authentication options available.
## Installing the ionscale CLI
The ionscale CLI is the primary tool for managing your ionscale instance. It allows you to create and manage tailnets, users, and access controls.
```bash
# Download the CLI (adjust the URL for your system architecture)
curl -L -o ionscale https://github.com/jsiebens/ionscale/releases/download/v0.17.0/ionscale_linux_amd64
# Make it executable
chmod +x ionscale
# Move to system path
sudo mv ionscale /usr/local/bin/
```
## Authentication requirements
To use the ionscale CLI, you must authenticate with the server using one of two methods:
!!! important "Administrator access required"
All management operations require either:
1. **System admin key** authentication, or
2. **OIDC user** authentication with system administrator privileges
### Option 1: Using the system admin key
If you configured ionscale with a system admin key during installation, you can authenticate using that key:
```bash
# Configure environment variables
export IONSCALE_ADDR="https://ionscale.example.com"
export IONSCALE_SYSTEM_ADMIN_KEY="your-system-admin-key"
# Verify connection
ionscale version
```
The system admin key provides full administrative access to your ionscale instance. This is the default authentication method when OIDC is not configured.
### Option 2: Using OIDC authentication
If you configured ionscale with an OIDC provider, users designated as system administrators in the OIDC configuration can authenticate:
```bash
# Configure URL only
export IONSCALE_ADDR="https://ionscale.example.com"
# Authenticate through OIDC
ionscale auth login
```
This will open a browser window where you can authenticate with your OIDC provider. After successful authentication, if your account has system administrator privileges, you'll be able to use the CLI.
!!! tip "OIDC system administrators"
System administrators are defined in the ionscale configuration under the `auth.system_admins` section. See the [Authentication with OIDC](../configuration/auth-oidc.md) documentation for details.
## Basic CLI commands
Once authenticated, you can use the ionscale CLI to manage your instance:
```bash
# View general information
ionscale version # Show version information
ionscale help # Display help information
# Tailnet management
ionscale tailnet list # List all tailnets
ionscale tailnet create -n NAME # Create a new tailnet
# Auth key management
ionscale auth-key list --tailnet NAME # List auth keys for a tailnet
ionscale auth-key create --tailnet NAME # Create a new auth key
```
-115
View File
@@ -1,115 +0,0 @@
# Getting started on a Linux Server
This tutorial will guide you through the steps needed to install and run __ionscale__ on a Linux machine.
## Prerequisites
- A Linux machine with port 443 and 3478 open to ingress traffic.
- A registered domain name.
## Step 1. Configure DNS
Set up a `A` DNS records: `ionscale.example.com` (We are assuming that your domain name is example.com.)
!!! tip
You can use `dig` to make sure that DNS records are propagated:
``` bash
$ dig ionscale.example.com
```
## Step 2. Set up ionscale on your Linux host
### Prepare installation
Run the following commands to prepare the installation:
``` bash
sudo mkdir -p /etc/ionscale
sudo mkdir -p /var/lib/ionscale
sudo useradd --system --no-create-home --shell /bin/false ionscale
sudo chown ionscale:ionscale /etc/ionscale
sudo chown ionscale:ionscale /var/lib/ionscale
```
### Install ionscale
Run the following commands to install the __ionscale__ binary on your Linux host:
``` bash
sudo curl \
-o "/usr/local/bin/ionscale" \
-sfL "https://github.com/jsiebens/ionscale/releases/download/v0.15.0/ionscale_linux_amd64"
sudo chmod +x "/usr/local/bin/ionscale"
```
### Configure ionscale
Generate a system admin key for __ionscale__ using the `ionscale genkey` command and write it the an environment file:
``` bash
sudo tee /etc/default/ionscale >/dev/null <<EOF
IONSCALE_KEYS_SYSTEM_ADMIN_KEY=$(ionscale genkey -n)
EOF
```
Generate a configuration file for __ionscale__ with the following commands:
``` bash
export IONSCALE_ACME_EMAIL=<your email>
export IONSCALE_DOMAIN=ionscale.example.com
```
``` bash
sudo tee /etc/ionscale/config.yaml >/dev/null <<EOF
listen_addr: ":443"
public_addr: "${IONSCALE_DOMAIN}:443"
stun_public_addr: "${IONSCALE_DOMAIN}:3478"
tls:
acme: true
acme_email: "${IONSCALE_ACME_EMAIL}"
database:
url: "/var/lib/ionscale/ionscale.db?_pragma=busy_timeout(5000)&_pragma=journal_mode(WAL)"
logging:
level: info
EOF
```
Create a systemd service file for __ionscale__ with the following commands:
``` bash
sudo tee /etc/systemd/system/ionscale.service >/dev/null <<EOF
[Unit]
Description=ionscale - a Tailscale Controller server
Requires=network-online.target
After=network.target
[Service]
EnvironmentFile=/etc/default/ionscale
User=ionscale
Group=ionscale
ExecStart=/usr/local/bin/ionscale server --config /etc/ionscale/config.yaml
Restart=on-failure
RestartSec=10s
AmbientCapabilities=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target
EOF
```
### Start ionscale
On your Linux machine, run the following commands to enable and start the __ionscale__ daemon:
``` bash
sudo systemctl daemon-reload
sudo systemctl enable ionscale
sudo systemctl start ionscale
```
+154
View File
@@ -0,0 +1,154 @@
# Creating your first tailnet
A tailnet is a private network that connects your devices securely using Tailscale. This guide will walk you through creating your first tailnet with ionscale.
## Prerequisites
Before creating a tailnet, make sure you have:
- ionscale server installed and running
- The ionscale CLI installed and configured
- Authentication with system administrator privileges
## Creating a tailnet
The simplest way to create a tailnet is with the `tailnet create` command:
```bash
ionscale tailnet create --name "my-first-tailnet"
```
This creates a basic tailnet named "my-first-tailnet" with:
- A default ACL policy that allows all connections
```
{"acls": [{"action": "accept", "src": ["*"], "dst": ["*:*"]}]}
```
- A default IAM policy that determines who can access the tailnet
!!! note
The tailnet name must be unique within your ionscale instance and should only contain alphanumeric characters, hyphens, and underscores.
## Setting IAM policies for access control
!!! important "OIDC required"
IAM policies are only relevant when an OIDC provider is configured. If your ionscale instance isn't using OIDC, access to tailnets is managed solely through auth keys, and the configuration in this section won't apply.
When using OIDC authentication, you'll need to configure who can access your tailnet through IAM policies.
### Configuring IAM during tailnet creation
You can set a basic IAM policy when creating a tailnet using flags:
```bash
# Allow all users with an @example.com email address
ionscale tailnet create --name "company-tailnet" --domain "example.com"
# Allow only a specific user
ionscale tailnet create --name "personal-tailnet" --email "user@example.com"
```
These flags provide quick ways to set up common IAM policies:
- `--domain example.com`: Creates a **shared tailnet** that allows all users with an email address from the specified domain. This is ideal for company or team networks where multiple users need access. The IAM policy will contain a filter rule like `domain == "example.com"`.
- `--email user@example.com`: Creates a **personal tailnet** that grants access only to the specific email address. This is suitable for individual use or when you want to tightly control access to a specific user. The IAM policy will contain an entry for the specified email.
!!! note
You can't use both flags together. Choose either domain-based access for a shared network or email-based access for a personal network.
### Configuring IAM after tailnet creation
You can view and update the IAM policy for an existing tailnet:
```bash
# View current IAM policy
ionscale iam get-policy --tailnet "my-first-tailnet"
# Update IAM policy using a JSON file
ionscale iam update-policy --tailnet "my-first-tailnet" --file policy.json
```
Example policy.json file:
```json
{
"filters": ["domain == example.com"],
"emails": ["specific-user@otherdomain.com"],
"roles": {
"admin@example.com": "admin"
}
}
```
## Connecting devices to your tailnet
There are two main methods to connect devices to your tailnet:
!!! tip
For detailed instructions on configuring various Tailscale clients to use ionscale as a control server, refer to the [Tailscale Knowledge Base](https://tailscale.com/kb/1507/custom-control-server).
### Interactive login
When you have an OIDC provider configured, users can connect to their tailnet through an interactive web authentication flow:
```bash
tailscale up --login-server=https://ionscale.example.com
```
This opens a browser window where the user authenticates with the OIDC provider. After successful authentication, if the user has access based on the tailnet's IAM policy, the device will be connected to the tailnet.
!!! note
Interactive login requires an OIDC provider to be configured on your ionscale instance.
### Using pre-authentication keys
Pre-authentication keys (auth keys) allow devices to join a tailnet without interactive authentication. This is useful for automated deployments, servers, or environments where browser-based authentication isn't practical.
To create an auth key:
```bash
# Create an auth key
ionscale auth-key create --tailnet "my-first-tailnet"
# Create an auth key with specific tags
ionscale auth-key create --tailnet "my-first-tailnet" --tags "tag:server"
```
The tags assigned to the key will determine what network access the device has once connected, based on your ACL rules.
!!! note
In environments with OIDC, users with access to a tailnet can create auth keys for that tailnet. Without OIDC, only system administrators can create keys.
To connect a device using an auth key:
```bash
# Connect using the auth key
tailscale up --login-server=https://ionscale.example.com --auth-key=...
```
## Network access and security policies
By default, tailnets are created with an open policy that allows all connections between devices. For production environments, you'll want to configure:
- **[IAM Policies](iam-policies.md)**: Manage who can access your tailnet
- **[ACL Policies](acl-policies.md)**: Control which devices can communicate within your tailnet
!!! tip
For detailed information on configuring security policies, see the dedicated documentation sections on [IAM Policies](iam-policies.md) and [ACL Policies](acl-policies.md).
## Managing multiple tailnets
You can create multiple tailnets to separate different network environments:
```bash
# List all tailnets
ionscale tailnet list
# Create tailnets for different teams or businesses
ionscale tailnet create --name "tailnet-a"
ionscale tailnet create --name "tailnet-b"
ionscale tailnet create --name "tailnet-c"
```
!!! note
Each tailnet is a separate network with its own devices, ACLs, and IAM policies. Devices in different tailnets cannot communicate with each other by default.
+23 -25
View File
@@ -1,35 +1,33 @@
# ionscale
# Welcome to ionscale
> **Note**:
> ionscale is currently beta quality, actively being developed and so subject to changes
ionscale is an open-source alternative to Tailscale's control server, designed to provide a self-hosted coordination service for your Tailscale networks.
**What is Tailscale?**
!!! info "Beta status"
ionscale is currently in beta. While it's stable for production use for small tailnets, we're actively developing new features and improvements.
[Tailscale](https://tailscale.com) is a VPN service that makes the devices and applications you own accessible anywhere in the world, securely and effortlessly.
It enables encrypted point-to-point connections using the open source [WireGuard](https://www.wireguard.com/) protocol, which means only devices on your private network can communicate with each other.
!!! warning "Documentation status"
This documentation is a work in progress. Some sections may be incomplete or missing. We're continuously improving the documentation to provide comprehensive coverage of all features.
**What is ionscale?**
## What is ionscale?
While the Tailscale software running on each node is open source, their centralized "coordination server" which act as a shared drop box for public keys is not.
Tailscale allows your devices to communicate securely across networks using WireGuard®. While Tailscale's client software is open source, their centralized coordination server (which manages public keys and network configurations) is proprietary.
_ionscale_ aims to implement such lightweight, open source alternative Tailscale control server.
**ionscale aims to implement a lightweight, open-source control server that:**
## Features
- Acts as a drop-in replacement for Tailscale's coordination server
- Can be self-hosted on your infrastructure
- Gives you full control over your network configuration
- Works with the standard Tailscale clients
- Supports a [wide range of Tailscale features](./overview/features.md)
- multi [tailnet](https://tailscale.com/kb/1136/tailnet/) support
- multi user support
- OIDC integration (not required, although recommended)
- [Auth keys](https://tailscale.com/kb/1085/auth-keys/)
- [Access control list](https://tailscale.com/kb/1018/acls/)
- [DNS](https://tailscale.com/kb/1054/dns/)
- nameservers
- Split DNS
- MagicDNS
- [HTTPS Certs](https://tailscale.com/kb/1153/enabling-https/)
- [Tailscale SSH](https://tailscale.com/kb/1193/tailscale-ssh/)
- [Service collection](https://tailscale.com/kb/1100/services/)
- [Taildrop](https://tailscale.com/kb/1106/taildrop/)
## Getting started
## Disclaimer
- [**Installation guide**](./installation/index.md) - Install ionscale using Docker or directly on Linux
- [**CLI configuration**](./getting-started/index.md) - Set up the ionscale CLI and authenticate
- [**Creating a tailnet**](./getting-started/tailnet.md) - Create and manage your first tailnet
- [**OIDC authentication**](./configuration/auth-oidc.md) - Configure user authentication via OIDC
- [**DNS providers**](./configuration/dns-providers.md) - Set up DNS integration for HTTPS certificates
This is not an official Tailscale or Tailscale Inc. project.
<small>
Disclaimer: This is not an official Tailscale or Tailscale Inc. project. Tailscale and WireGuard are trademarks of their respective owners.
</small>
+101
View File
@@ -0,0 +1,101 @@
# Installing ionscale with Docker
This guide will walk you through installing and configuring ionscale using Docker containers. Docker provides a simple and consistent way to deploy ionscale across different environments.
## Prerequisites
Before you begin, make sure you have:
- A Linux server (virtual or physical)
- Docker installed ([official Docker installation guide](https://docs.docker.com/engine/install/))
- Root or sudo access
- A registered domain name pointing to your server
- Ports 443 (HTTPS) and 3478/UDP (STUN) open in your firewall
- Basic familiarity with the Linux command line
### Domain and DNS configuration
ionscale requires a domain name to function properly. This enables secure HTTPS connections and proper Tailscale device discovery.
1. Configure an A record in your domain's DNS settings:
```
ionscale.example.com → YOUR_SERVER_IP
```
(Replace "example.com" with your actual domain and "YOUR_SERVER_IP" with your server's public IP address)
2. Verify the DNS record has propagated:
```bash
dig ionscale.example.com
```
The command should return your server's public IP address.
## Container setup
### Creating a directory structure
Create a dedicated directory for ionscale files:
```bash
mkdir -p ionscale/data
cd ./ionscale
```
### Generating a configuration file
First, set up environment variables for the configuration:
```bash
export IONSCALE_ACME_EMAIL="your-email@example.com" # Used for Let's Encrypt notifications
export IONSCALE_DOMAIN="ionscale.example.com" # Your ionscale domain
export IONSCALE_SYSTEM_ADMIN_KEY=$(docker run --rm ghcr.io/jsiebens/ionscale:0.17.0 genkey -n)
```
!!! important "System admin key"
The system admin key is a critical security component that provides full administrative access to your ionscale instance. Make sure to save this key securely.
Alternatively, you can configure ionscale without a system admin key by using an OIDC provider and setting up system admin accounts through the OIDC configuration. See the [Authentication with OIDC](../configuration/auth-oidc.md) documentation for details.
Now create the configuration file:
```bash
cat > ./config.yaml <<EOF
listen_addr: ":443"
public_addr: "${IONSCALE_DOMAIN}:443"
stun_public_addr: "${IONSCALE_DOMAIN}:3478"
tls:
acme: true
acme_email: "${IONSCALE_ACME_EMAIL}"
keys:
system_admin_key: "${IONSCALE_SYSTEM_ADMIN_KEY}"
database:
url: "/data/ionscale.db?_pragma=busy_timeout(5000)&_pragma=journal_mode(WAL)"
logging:
level: info
EOF
```
### Running the container
Start the ionscale container with the following command:
```bash
docker run -d \
--name ionscale \
--restart unless-stopped \
-v $(pwd)/config.yaml:/etc/ionscale/config.yaml \
-v $(pwd)/data:/data \
-p 443:443 \
-p 3478:3478/udp \
ghcr.io/jsiebens/ionscale:0.17.0 server --config /etc/ionscale/config.yaml
```
This command:
- Creates a persistent container named "ionscale"
- Mounts your configuration file and data directory
- Maps the required ports to the host
- Automatically restarts the container if it stops unexpectedly
+38
View File
@@ -0,0 +1,38 @@
# Installation guide
ionscale can be installed in several ways, depending on your preferences and requirements. This section covers the different installation methods available.
## Choose your installation method
ionscale offers two primary installation methods:
### Docker installation
The [Docker installation](docker.md) method is recommended for:
- Quick deployments
- Testing and evaluation
- Users familiar with container environments
- Simplified upgrades and maintenance
Docker provides an isolated environment with all dependencies included, making it the easiest way to get started with ionscale.
### Linux installation
The [Linux installation](linux.md) method is suitable for:
- Production environments
- Integration with existing infrastructure
- More control over the installation
- Systems without Docker
This approach installs ionscale directly on your Linux server and configures it as a system service.
## Post-installation steps
After completing the installation, consider these next steps:
1. Configure an [OIDC provider](../configuration/auth-oidc.md) for user authentication
2. Set up a [DNS provider](../configuration/dns-providers.md) to enable HTTPS certificates for Tailscale nodes
3. Create and configure tailnets
4. Set up access controls and permissions
+194
View File
@@ -0,0 +1,194 @@
# Linux installation
This guide walks you through installing ionscale directly on a Linux server. This approach gives you more control over the installation and is suitable for production environments.
## Prerequisites
Before you begin, make sure you have:
- A Linux server (virtual or physical)
- Root or sudo access
- A registered domain name pointing to your server
- Ports 443 (HTTPS) and 3478/UDP (STUN) open in your firewall
- Basic familiarity with the Linux command line
### Domain and DNS configuration
ionscale requires a domain name to function properly. This enables secure HTTPS connections and proper Tailscale device discovery.
1. Configure an A record in your domain's DNS settings:
```
ionscale.example.com → YOUR_SERVER_IP
```
(Replace "example.com" with your actual domain and "YOUR_SERVER_IP" with your server's public IP address)
2. Verify the DNS record has propagated:
```bash
dig ionscale.example.com
```
The command should return your server's public IP address.
## Quick deployment
If you prefer an automated deployment, you can use our installation script:
```bash
# Download the script
curl -fsSL https://raw.githubusercontent.com/jsiebens/ionscale/main/scripts/install.sh -o install.sh
chmod +x install.sh
# Run the script (interactive mode)
./install.sh
```
The script will prompt you for:
1. Your domain name for ionscale
2. Your email address (for Let's Encrypt notifications)
For non-interactive installation, set the required environment variables:
```bash
export IONSCALE_DOMAIN="ionscale.example.com"
export IONSCALE_ACME_EMAIL="your-email@example.com"
./install.sh
```
The script automatically:
1. Determines your system architecture
2. Creates a dedicated service user
3. Downloads and installs the latest ionscale binary
4. Generates a secure system admin key
5. Creates necessary configuration files
6. Sets up and starts the systemd service
For a detailed explanation of each step, continue reading the manual installation instructions below.
## System preparation
### Create a dedicated service user
For security reasons, ionscale should run under a dedicated, unprivileged system user:
```bash
# Create service user
sudo useradd --system --no-create-home --shell /bin/false ionscale
# Create directories
sudo mkdir -p /etc/ionscale
sudo mkdir -p /var/lib/ionscale
# Set appropriate permissions
sudo chown ionscale:ionscale /etc/ionscale
sudo chown ionscale:ionscale /var/lib/ionscale
```
## Installation
### Download and install the binary
Install the ionscale binary on your system:
```bash
# Download the latest version (adjust for your CPU architecture)
sudo curl -o "/usr/local/bin/ionscale" \
-sfL "https://github.com/jsiebens/ionscale/releases/download/v0.17.0/ionscale_linux_amd64"
# Make it executable
sudo chmod +x "/usr/local/bin/ionscale"
# Verify installation
ionscale version
```
### Configuration
1. Generate a system admin key and store it in an environment file:
```bash
sudo tee /etc/default/ionscale >/dev/null <<EOF
IONSCALE_KEYS_SYSTEM_ADMIN_KEY=$(ionscale genkey -n)
EOF
```
!!! important "System admin key"
The system admin key is a critical security component that provides full administrative access to your ionscale instance. Make sure to save this key securely.
Alternatively, you can configure ionscale without a system admin key by using an OIDC provider and setting up system admin accounts through the OIDC configuration. See the [Authentication with OIDC](../configuration/auth-oidc.md) documentation for details.
2. Set up environment variables for the configuration:
```bash
export IONSCALE_ACME_EMAIL="your-email@example.com" # For Let's Encrypt notifications
export IONSCALE_DOMAIN="ionscale.example.com" # Your ionscale domain
```
3. Create the configuration file:
```bash
sudo tee /etc/ionscale/config.yaml >/dev/null <<EOF
listen_addr: ":443"
public_addr: "${IONSCALE_DOMAIN}:443"
stun_public_addr: "${IONSCALE_DOMAIN}:3478"
tls:
acme: true
acme_email: "${IONSCALE_ACME_EMAIL}"
database:
url: "/var/lib/ionscale/ionscale.db?_pragma=busy_timeout(5000)&_pragma=journal_mode(WAL)"
keys:
system_admin_key: "\${IONSCALE_KEYS_SYSTEM_ADMIN_KEY}"
logging:
level: info
EOF
```
## Setting up systemd service
Create a systemd service file to manage the ionscale process:
```bash
sudo tee /etc/systemd/system/ionscale.service >/dev/null <<EOF
[Unit]
Description=ionscale - a Tailscale control server
Requires=network-online.target
After=network.target
[Service]
EnvironmentFile=/etc/default/ionscale
User=ionscale
Group=ionscale
ExecStart=/usr/local/bin/ionscale server --config /etc/ionscale/config.yaml
Restart=on-failure
RestartSec=10s
AmbientCapabilities=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target
EOF
```
The `AmbientCapabilities=CAP_NET_BIND_SERVICE` line allows ionscale to bind to privileged ports (443) without running as root.
## Starting ionscale
Enable and start the ionscale service:
```bash
# Reload systemd to recognize the new service
sudo systemctl daemon-reload
# Enable service to start on boot
sudo systemctl enable ionscale
# Start the service
sudo systemctl start ionscale
# Check status
sudo systemctl status ionscale
```
If everything started successfully, you should see an "active (running)" status.
+59
View File
@@ -0,0 +1,59 @@
# Supported features
ionscale implements key Tailscale features to provide a complete control server experience. This page outlines the major features that ionscale supports.
## Multi-tailnet support
ionscale allows you to create and manage multiple tailnets (Tailscale private networks) from a single server:
- Create isolated networks for different teams or environments
- Manage separate tailnets for personal and organizational use
- Configure each tailnet with its own ACLs and settings
## User management
- **Multi-user support**: Multiple users can access and use the same tailnet based on permissions
- **OIDC integration**: Optional but recommended for user authentication and management
## Authentication
- **[Auth keys](https://tailscale.com/kb/1085/auth-keys/)**: Generate and manage pre-authentication keys for devices
- **[Device tagging](https://tailscale.com/kb/1068/tags/)**: Apply tags to devices for better management and ACL control
## Network control
- **[Access control lists (ACLs)](https://tailscale.com/kb/1018/acls/)**: Define fine-grained rules for who can access what
- **[Subnet routers](https://tailscale.com/kb/1019/subnets/)**: Connect existing networks to your tailnet
- **[Exit nodes](https://tailscale.com/kb/1103/exit-nodes/)**: Configure nodes to act as VPN exit points
## DNS management
- **[MagicDNS](https://tailscale.com/kb/1081/magicdns/)**: Automatic DNS for tailnet devices
- **[Split DNS](https://tailscale.com/kb/1054/dns/)**: Route specific DNS queries to specific resolvers
- **Custom nameservers**: Configure any DNS servers for your tailnet
## HTTPS and certificates
- **[HTTPS certificates](https://tailscale.com/kb/1153/enabling-https/)**: Automatic SSL/TLS certificates for devices
- **DNS provider integration**: Support for various DNS providers to facilitate ACME challenges
- **[Tailscale Serve](https://tailscale.com/kb/1242/tailscale-serve/)**: Share web services easily with HTTPS
## SSH
- **[Tailscale SSH](https://tailscale.com/kb/1193/tailscale-ssh/)**: Built-in SSH server support
- **SSH policy management**: Control who can SSH into which devices
## DERP
- **Embedded DERP server**
- **Custom DERP maps**: Configure your own DERP servers
## File sharing
- **[Taildrop](https://tailscale.com/kb/1106/taildrop/)**: Send files directly between tailnet devices
## Feature status
Most features are fully implemented and compatible with the official Tailscale clients. As ionscale is continuously developed, new features from Tailscale are regularly added.
If you find any issues with specific features or have requests for additional functionality, please check the [project repository](https://github.com/jsiebens/ionscale) for the latest updates or to submit feedback.
+126
View File
@@ -0,0 +1,126 @@
/* Custom CSS for ionscale documentation */
/* Enhance code blocks */
.md-typeset pre {
border-radius: 6px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
}
/* Enhance code block headers */
.md-typeset code {
border-radius: 3px;
font-size: 0.9em;
padding: 0.2em 0.4em;
}
/* Make admonitions stand out more */
.md-typeset .admonition {
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
margin: 1.5em 0;
}
.md-typeset .admonition-title {
padding-left: 2.5rem;
}
/* Make tables more professional */
.md-typeset table:not([class]) {
border-radius: 6px;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
overflow: hidden;
}
.md-typeset table:not([class]) th {
background-color: rgba(63, 81, 181, 0.08);
font-weight: 600;
}
/* Enhance UI element spacing */
.md-typeset ul li,
.md-typeset ol li {
margin-bottom: 0.35em;
}
.md-typeset h1,
.md-typeset h2,
.md-typeset h3,
.md-typeset h4 {
font-weight: 500;
margin-top: 1.5em;
}
.md-typeset h2 {
border-bottom: 1px solid rgba(63, 81, 181, 0.1);
padding-bottom: 0.3em;
}
/* Subtle border on the right for table of contents */
.md-sidebar--secondary {
border-left: 1px solid rgba(0, 0, 0, 0.07);
background-color: rgba(0, 0, 0, 0.01);
}
/* Navigation improvements */
.md-nav__item .md-nav__link--active {
font-weight: 600;
}
/* Responsive improvements */
@media screen and (min-width: 76.25em) {
.md-sidebar--primary {
border-right: 1px solid rgba(0, 0, 0, 0.07);
background-color: rgba(0, 0, 0, 0.01);
}
}
/* Better footer */
.md-footer-meta {
background-color: rgba(0, 0, 0, 0.87);
}
/* Remove the logo and style site name */
.md-header__button.md-logo {
display: none;
}
/* Move the site name to the left */
.md-header__title {
margin-left: 0;
font-weight: 500;
letter-spacing: 0.02em;
font-family: Lato, sans-serif;
}
.md-header__topic {
color: white;
font-size: 1.2rem;
line-height: 2.4rem;
margin-left: 0.6rem;
}
/* Badge styles for version/status indicators */
.md-typeset .md-badge {
border-radius: 4px;
display: inline-block;
font-size: 0.75em;
font-weight: 700;
padding: 4px 6px;
margin: 0 0.5em;
vertical-align: middle;
}
.md-typeset .md-badge--new {
background-color: #28a745;
color: white;
}
.md-typeset .md-badge--beta {
background-color: #f0ad4e;
color: white;
}
.md-typeset .md-badge--deprecated {
background-color: #dc3545;
color: white;
}
+107 -11
View File
@@ -1,28 +1,54 @@
site_name: ionscale
repo_name: jsiebens/ionscale
repo_url: https://github.com/jsiebens/ionscale
edit_uri: ""
# Remove the GitHub repository link from the top-right corner
# repo_name: jsiebens/ionscale
# repo_url: https://github.com/jsiebens/ionscale
# edit_uri: ""
nav:
- Overview:
- Introduction: index.md
- Supported Features: overview/features.md
- Installation:
- Manual: ./getting-started/manual.md
- Docker: ./getting-started/docker.md
- Installation: ./installation/index.md
- Linux installation: ./installation/linux.md
- Docker installation: ./installation/docker.md
- Configuration:
- Reference: ./configuration/reference.md
- Configuration: ./configuration/index.md
- DERP: ./configuration/derp.md
- OIDC: ./configuration/auth-oidc.md
- DNS providers: ./configuration/dns-providers.md
- Getting started:
- Getting started: ./getting-started/index.md
- Creating a tailnet: ./getting-started/tailnet.md
- IAM Policies: ./getting-started/iam-policies.md
- ACL Policies: ./getting-started/acl-policies.md
theme:
name: material
custom_dir: overrides
# Custom stylesheets
extra_css:
- stylesheets/extra.css
# Explicitly disable the logo to show only the site name
#logo: ""
favicon: assets/favicon.png
# Enhanced color scheme
palette:
- scheme: default
- media: "(prefers-color-scheme: light)"
scheme: default
primary: indigo
accent: indigo
toggle:
icon: material/toggle-switch-off-outline
name: Switch to dark mode
- scheme: slate
- media: "(prefers-color-scheme: dark)"
scheme: slate
primary: indigo
accent: indigo
toggle:
icon: material/toggle-switch
name: Switch to light mode
@@ -32,9 +58,28 @@ theme:
code: Roboto Mono
features:
# Navigation
- navigation.tracking
- navigation.sections
- toc.integrate
- navigation.indexes
- navigation.top # Back-to-top button
- navigation.footer # Footer with previous/next links
# Content
- content.code.copy # Add copy button to code blocks
- content.code.annotate # Allow code annotations
- content.tabs.link # Sync all tabs with the same label
# Search
- search.highlight
- search.share
- search.suggest
# Table of contents
- toc.follow
# Hide the table of contents on the navigation
toc_depth: 0
include_search_page: false
search_index_only: true
@@ -42,15 +87,66 @@ theme:
language: en
markdown_extensions:
# Admonitions and callouts
- admonition
- pymdownx.details
- pymdownx.superfences
# Code blocks with syntax highlighting
- pymdownx.highlight:
anchor_linenums: true
line_spans: __span
pygments_lang_class: true
- pymdownx.inlinehilite
# Code annotations
- pymdownx.snippets
- pymdownx.superfences
# Tabbed content
- pymdownx.tabbed:
alternate_style: true
# Content tabs
- pymdownx.superfences:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:pymdownx.superfences.fence_code_format
# Better formatting options
- attr_list # Add HTML attributes and CSS classes
- def_list # Definition lists
- md_in_html # Markdown within HTML
- tables # Tables
- footnotes # Footnotes
# Typography improvements
- pymdownx.critic # Track changes
- pymdownx.caret # Superscript/subscript
- pymdownx.mark # Highlighting
- pymdownx.tilde # Strikethrough
- pymdownx.smartsymbols # Smart symbols (arrows, fractions)
extra:
# Page status annotations
status:
new: Recently added
deprecated: No longer supported
beta: Currently in beta
# Enhanced social cards
social:
- icon: fontawesome/brands/github
link: https://github.com/jsiebens/ionscale
- icon: fontawesome/brands/docker
link: https://github.com/jsiebens/ionscale/pkgs/container/ionscale
# Page customization
# version:
# provider: mike
# Footer customization
generator: false # Hide "Made with Material for MkDocs"
# Analytics (existing)
analytics:
provider: custom
+23 -84
View File
@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.32.0
// protoc-gen-go v1.36.5
// protoc (unknown)
// source: ionscale/v1/acl.proto
@@ -11,6 +11,7 @@ import (
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
@@ -21,21 +22,18 @@ const (
)
type GetACLPolicyRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
TailnetId uint64 `protobuf:"varint,1,opt,name=tailnet_id,json=tailnetId,proto3" json:"tailnet_id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetACLPolicyRequest) Reset() {
*x = GetACLPolicyRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_acl_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetACLPolicyRequest) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -45,7 +43,7 @@ func (*GetACLPolicyRequest) ProtoMessage() {}
func (x *GetACLPolicyRequest) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_acl_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -68,21 +66,18 @@ func (x *GetACLPolicyRequest) GetTailnetId() uint64 {
}
type GetACLPolicyResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
Policy string `protobuf:"bytes,1,opt,name=policy,proto3" json:"policy,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetACLPolicyResponse) Reset() {
*x = GetACLPolicyResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_acl_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetACLPolicyResponse) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -92,7 +87,7 @@ func (*GetACLPolicyResponse) ProtoMessage() {}
func (x *GetACLPolicyResponse) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_acl_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -115,22 +110,19 @@ func (x *GetACLPolicyResponse) GetPolicy() string {
}
type SetACLPolicyRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
TailnetId uint64 `protobuf:"varint,1,opt,name=tailnet_id,json=tailnetId,proto3" json:"tailnet_id,omitempty"`
Policy string `protobuf:"bytes,2,opt,name=policy,proto3" json:"policy,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SetACLPolicyRequest) Reset() {
*x = SetACLPolicyRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_acl_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *SetACLPolicyRequest) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -140,7 +132,7 @@ func (*SetACLPolicyRequest) ProtoMessage() {}
func (x *SetACLPolicyRequest) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_acl_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -170,19 +162,17 @@ func (x *SetACLPolicyRequest) GetPolicy() string {
}
type SetACLPolicyResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SetACLPolicyResponse) Reset() {
*x = SetACLPolicyResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_acl_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *SetACLPolicyResponse) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -192,7 +182,7 @@ func (*SetACLPolicyResponse) ProtoMessage() {}
func (x *SetACLPolicyResponse) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_acl_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -209,7 +199,7 @@ func (*SetACLPolicyResponse) Descriptor() ([]byte, []int) {
var File_ionscale_v1_acl_proto protoreflect.FileDescriptor
var file_ionscale_v1_acl_proto_rawDesc = []byte{
var file_ionscale_v1_acl_proto_rawDesc = string([]byte{
0x0a, 0x15, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x63,
0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c,
0x65, 0x2e, 0x76, 0x31, 0x22, 0x34, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x41, 0x43, 0x4c, 0x50, 0x6f,
@@ -230,22 +220,22 @@ var file_ionscale_v1_acl_proto_rawDesc = []byte{
0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c,
0x65, 0x2f, 0x76, 0x31, 0x3b, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x76, 0x31, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
})
var (
file_ionscale_v1_acl_proto_rawDescOnce sync.Once
file_ionscale_v1_acl_proto_rawDescData = file_ionscale_v1_acl_proto_rawDesc
file_ionscale_v1_acl_proto_rawDescData []byte
)
func file_ionscale_v1_acl_proto_rawDescGZIP() []byte {
file_ionscale_v1_acl_proto_rawDescOnce.Do(func() {
file_ionscale_v1_acl_proto_rawDescData = protoimpl.X.CompressGZIP(file_ionscale_v1_acl_proto_rawDescData)
file_ionscale_v1_acl_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_ionscale_v1_acl_proto_rawDesc), len(file_ionscale_v1_acl_proto_rawDesc)))
})
return file_ionscale_v1_acl_proto_rawDescData
}
var file_ionscale_v1_acl_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_ionscale_v1_acl_proto_goTypes = []interface{}{
var file_ionscale_v1_acl_proto_goTypes = []any{
(*GetACLPolicyRequest)(nil), // 0: ionscale.v1.GetACLPolicyRequest
(*GetACLPolicyResponse)(nil), // 1: ionscale.v1.GetACLPolicyResponse
(*SetACLPolicyRequest)(nil), // 2: ionscale.v1.SetACLPolicyRequest
@@ -264,61 +254,11 @@ func file_ionscale_v1_acl_proto_init() {
if File_ionscale_v1_acl_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_ionscale_v1_acl_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetACLPolicyRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_acl_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetACLPolicyResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_acl_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SetACLPolicyRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_acl_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SetACLPolicyResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_ionscale_v1_acl_proto_rawDesc,
RawDescriptor: unsafe.Slice(unsafe.StringData(file_ionscale_v1_acl_proto_rawDesc), len(file_ionscale_v1_acl_proto_rawDesc)),
NumEnums: 0,
NumMessages: 4,
NumExtensions: 0,
@@ -329,7 +269,6 @@ func file_ionscale_v1_acl_proto_init() {
MessageInfos: file_ionscale_v1_acl_proto_msgTypes,
}.Build()
File_ionscale_v1_acl_proto = out.File
file_ionscale_v1_acl_proto_rawDesc = nil
file_ionscale_v1_acl_proto_goTypes = nil
file_ionscale_v1_acl_proto_depIdxs = nil
}
+16 -47
View File
@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.32.0
// protoc-gen-go v1.36.5
// protoc (unknown)
// source: ionscale/v1/auth.proto
@@ -11,6 +11,7 @@ import (
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
@@ -21,19 +22,17 @@ const (
)
type AuthenticateRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *AuthenticateRequest) Reset() {
*x = AuthenticateRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_auth_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *AuthenticateRequest) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -43,7 +42,7 @@ func (*AuthenticateRequest) ProtoMessage() {}
func (x *AuthenticateRequest) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_auth_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -59,23 +58,20 @@ func (*AuthenticateRequest) Descriptor() ([]byte, []int) {
}
type AuthenticateResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
AuthUrl string `protobuf:"bytes,1,opt,name=auth_url,json=authUrl,proto3" json:"auth_url,omitempty"`
Token string `protobuf:"bytes,2,opt,name=token,proto3" json:"token,omitempty"`
TailnetId *uint64 `protobuf:"varint,3,opt,name=tailnet_id,json=tailnetId,proto3,oneof" json:"tailnet_id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *AuthenticateResponse) Reset() {
*x = AuthenticateResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_auth_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *AuthenticateResponse) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -85,7 +81,7 @@ func (*AuthenticateResponse) ProtoMessage() {}
func (x *AuthenticateResponse) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_auth_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -123,7 +119,7 @@ func (x *AuthenticateResponse) GetTailnetId() uint64 {
var File_ionscale_v1_auth_proto protoreflect.FileDescriptor
var file_ionscale_v1_auth_proto_rawDesc = []byte{
var file_ionscale_v1_auth_proto_rawDesc = string([]byte{
0x0a, 0x16, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x75,
0x74, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61,
0x6c, 0x65, 0x2e, 0x76, 0x31, 0x22, 0x15, 0x0a, 0x13, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74,
@@ -140,22 +136,22 @@ var file_ionscale_v1_auth_proto_rawDesc = []byte{
0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x65, 0x6e,
0x2f, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x69, 0x6f, 0x6e,
0x73, 0x63, 0x61, 0x6c, 0x65, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
})
var (
file_ionscale_v1_auth_proto_rawDescOnce sync.Once
file_ionscale_v1_auth_proto_rawDescData = file_ionscale_v1_auth_proto_rawDesc
file_ionscale_v1_auth_proto_rawDescData []byte
)
func file_ionscale_v1_auth_proto_rawDescGZIP() []byte {
file_ionscale_v1_auth_proto_rawDescOnce.Do(func() {
file_ionscale_v1_auth_proto_rawDescData = protoimpl.X.CompressGZIP(file_ionscale_v1_auth_proto_rawDescData)
file_ionscale_v1_auth_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_ionscale_v1_auth_proto_rawDesc), len(file_ionscale_v1_auth_proto_rawDesc)))
})
return file_ionscale_v1_auth_proto_rawDescData
}
var file_ionscale_v1_auth_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_ionscale_v1_auth_proto_goTypes = []interface{}{
var file_ionscale_v1_auth_proto_goTypes = []any{
(*AuthenticateRequest)(nil), // 0: ionscale.v1.AuthenticateRequest
(*AuthenticateResponse)(nil), // 1: ionscale.v1.AuthenticateResponse
}
@@ -172,38 +168,12 @@ func file_ionscale_v1_auth_proto_init() {
if File_ionscale_v1_auth_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_ionscale_v1_auth_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*AuthenticateRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_auth_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*AuthenticateResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
file_ionscale_v1_auth_proto_msgTypes[1].OneofWrappers = []interface{}{}
file_ionscale_v1_auth_proto_msgTypes[1].OneofWrappers = []any{}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_ionscale_v1_auth_proto_rawDesc,
RawDescriptor: unsafe.Slice(unsafe.StringData(file_ionscale_v1_auth_proto_rawDesc), len(file_ionscale_v1_auth_proto_rawDesc)),
NumEnums: 0,
NumMessages: 2,
NumExtensions: 0,
@@ -214,7 +184,6 @@ func file_ionscale_v1_auth_proto_init() {
MessageInfos: file_ionscale_v1_auth_proto_msgTypes,
}.Build()
File_ionscale_v1_auth_proto = out.File
file_ionscale_v1_auth_proto_rawDesc = nil
file_ionscale_v1_auth_proto_goTypes = nil
file_ionscale_v1_auth_proto_depIdxs = nil
}
+45 -181
View File
@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.32.0
// protoc-gen-go v1.36.5
// protoc (unknown)
// source: ionscale/v1/auth_keys.proto
@@ -13,6 +13,7 @@ import (
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
@@ -23,21 +24,18 @@ const (
)
type GetAuthKeyRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
AuthKeyId uint64 `protobuf:"varint,1,opt,name=auth_key_id,json=authKeyId,proto3" json:"auth_key_id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetAuthKeyRequest) Reset() {
*x = GetAuthKeyRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_auth_keys_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetAuthKeyRequest) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -47,7 +45,7 @@ func (*GetAuthKeyRequest) ProtoMessage() {}
func (x *GetAuthKeyRequest) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_auth_keys_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -70,21 +68,18 @@ func (x *GetAuthKeyRequest) GetAuthKeyId() uint64 {
}
type GetAuthKeyResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
AuthKey *AuthKey `protobuf:"bytes,1,opt,name=auth_key,json=authKey,proto3" json:"auth_key,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetAuthKeyResponse) Reset() {
*x = GetAuthKeyResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_auth_keys_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetAuthKeyResponse) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -94,7 +89,7 @@ func (*GetAuthKeyResponse) ProtoMessage() {}
func (x *GetAuthKeyResponse) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_auth_keys_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -117,25 +112,22 @@ func (x *GetAuthKeyResponse) GetAuthKey() *AuthKey {
}
type CreateAuthKeyRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
TailnetId uint64 `protobuf:"varint,1,opt,name=tailnet_id,json=tailnetId,proto3" json:"tailnet_id,omitempty"`
Ephemeral bool `protobuf:"varint,2,opt,name=ephemeral,proto3" json:"ephemeral,omitempty"`
Expiry *durationpb.Duration `protobuf:"bytes,3,opt,name=expiry,proto3,oneof" json:"expiry,omitempty"`
Tags []string `protobuf:"bytes,4,rep,name=tags,proto3" json:"tags,omitempty"`
PreAuthorized bool `protobuf:"varint,5,opt,name=pre_authorized,json=preAuthorized,proto3" json:"pre_authorized,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *CreateAuthKeyRequest) Reset() {
*x = CreateAuthKeyRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_auth_keys_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CreateAuthKeyRequest) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -145,7 +137,7 @@ func (*CreateAuthKeyRequest) ProtoMessage() {}
func (x *CreateAuthKeyRequest) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_auth_keys_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -196,22 +188,19 @@ func (x *CreateAuthKeyRequest) GetPreAuthorized() bool {
}
type CreateAuthKeyResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
AuthKey *AuthKey `protobuf:"bytes,1,opt,name=auth_key,json=authKey,proto3" json:"auth_key,omitempty"`
Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *CreateAuthKeyResponse) Reset() {
*x = CreateAuthKeyResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_auth_keys_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CreateAuthKeyResponse) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -221,7 +210,7 @@ func (*CreateAuthKeyResponse) ProtoMessage() {}
func (x *CreateAuthKeyResponse) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_auth_keys_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -251,21 +240,18 @@ func (x *CreateAuthKeyResponse) GetValue() string {
}
type DeleteAuthKeyRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
AuthKeyId uint64 `protobuf:"varint,1,opt,name=auth_key_id,json=authKeyId,proto3" json:"auth_key_id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *DeleteAuthKeyRequest) Reset() {
*x = DeleteAuthKeyRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_auth_keys_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DeleteAuthKeyRequest) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -275,7 +261,7 @@ func (*DeleteAuthKeyRequest) ProtoMessage() {}
func (x *DeleteAuthKeyRequest) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_auth_keys_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -298,19 +284,17 @@ func (x *DeleteAuthKeyRequest) GetAuthKeyId() uint64 {
}
type DeleteAuthKeyResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *DeleteAuthKeyResponse) Reset() {
*x = DeleteAuthKeyResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_auth_keys_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DeleteAuthKeyResponse) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -320,7 +304,7 @@ func (*DeleteAuthKeyResponse) ProtoMessage() {}
func (x *DeleteAuthKeyResponse) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_auth_keys_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -336,21 +320,18 @@ func (*DeleteAuthKeyResponse) Descriptor() ([]byte, []int) {
}
type ListAuthKeysRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
TailnetId uint64 `protobuf:"varint,1,opt,name=tailnet_id,json=tailnetId,proto3" json:"tailnet_id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListAuthKeysRequest) Reset() {
*x = ListAuthKeysRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_auth_keys_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ListAuthKeysRequest) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -360,7 +341,7 @@ func (*ListAuthKeysRequest) ProtoMessage() {}
func (x *ListAuthKeysRequest) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_auth_keys_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -383,21 +364,18 @@ func (x *ListAuthKeysRequest) GetTailnetId() uint64 {
}
type ListAuthKeysResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
AuthKeys []*AuthKey `protobuf:"bytes,1,rep,name=auth_keys,json=authKeys,proto3" json:"auth_keys,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListAuthKeysResponse) Reset() {
*x = ListAuthKeysResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_auth_keys_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ListAuthKeysResponse) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -407,7 +385,7 @@ func (*ListAuthKeysResponse) ProtoMessage() {}
func (x *ListAuthKeysResponse) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_auth_keys_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -430,10 +408,7 @@ func (x *ListAuthKeysResponse) GetAuthKeys() []*AuthKey {
}
type AuthKey struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
Id uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
Ephemeral bool `protobuf:"varint,3,opt,name=ephemeral,proto3" json:"ephemeral,omitempty"`
@@ -441,16 +416,16 @@ type AuthKey struct {
CreatedAt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
ExpiresAt *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=expires_at,json=expiresAt,proto3,oneof" json:"expires_at,omitempty"`
Tailnet *Ref `protobuf:"bytes,7,opt,name=tailnet,proto3" json:"tailnet,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *AuthKey) Reset() {
*x = AuthKey{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_auth_keys_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *AuthKey) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -460,7 +435,7 @@ func (*AuthKey) ProtoMessage() {}
func (x *AuthKey) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_auth_keys_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -526,7 +501,7 @@ func (x *AuthKey) GetTailnet() *Ref {
var File_ionscale_v1_auth_keys_proto protoreflect.FileDescriptor
var file_ionscale_v1_auth_keys_proto_rawDesc = []byte{
var file_ionscale_v1_auth_keys_proto_rawDesc = string([]byte{
0x0a, 0x1b, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x75,
0x74, 0x68, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x69,
0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67,
@@ -598,22 +573,22 @@ var file_ionscale_v1_auth_keys_proto_rawDesc = []byte{
0x65, 0x6e, 0x2f, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x69,
0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x33,
}
})
var (
file_ionscale_v1_auth_keys_proto_rawDescOnce sync.Once
file_ionscale_v1_auth_keys_proto_rawDescData = file_ionscale_v1_auth_keys_proto_rawDesc
file_ionscale_v1_auth_keys_proto_rawDescData []byte
)
func file_ionscale_v1_auth_keys_proto_rawDescGZIP() []byte {
file_ionscale_v1_auth_keys_proto_rawDescOnce.Do(func() {
file_ionscale_v1_auth_keys_proto_rawDescData = protoimpl.X.CompressGZIP(file_ionscale_v1_auth_keys_proto_rawDescData)
file_ionscale_v1_auth_keys_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_ionscale_v1_auth_keys_proto_rawDesc), len(file_ionscale_v1_auth_keys_proto_rawDesc)))
})
return file_ionscale_v1_auth_keys_proto_rawDescData
}
var file_ionscale_v1_auth_keys_proto_msgTypes = make([]protoimpl.MessageInfo, 9)
var file_ionscale_v1_auth_keys_proto_goTypes = []interface{}{
var file_ionscale_v1_auth_keys_proto_goTypes = []any{
(*GetAuthKeyRequest)(nil), // 0: ionscale.v1.GetAuthKeyRequest
(*GetAuthKeyResponse)(nil), // 1: ionscale.v1.GetAuthKeyResponse
(*CreateAuthKeyRequest)(nil), // 2: ionscale.v1.CreateAuthKeyRequest
@@ -648,123 +623,13 @@ func file_ionscale_v1_auth_keys_proto_init() {
return
}
file_ionscale_v1_ref_proto_init()
if !protoimpl.UnsafeEnabled {
file_ionscale_v1_auth_keys_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetAuthKeyRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_auth_keys_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetAuthKeyResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_auth_keys_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CreateAuthKeyRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_auth_keys_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CreateAuthKeyResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_auth_keys_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeleteAuthKeyRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_auth_keys_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeleteAuthKeyResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_auth_keys_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListAuthKeysRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_auth_keys_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListAuthKeysResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_auth_keys_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*AuthKey); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
file_ionscale_v1_auth_keys_proto_msgTypes[2].OneofWrappers = []interface{}{}
file_ionscale_v1_auth_keys_proto_msgTypes[8].OneofWrappers = []interface{}{}
file_ionscale_v1_auth_keys_proto_msgTypes[2].OneofWrappers = []any{}
file_ionscale_v1_auth_keys_proto_msgTypes[8].OneofWrappers = []any{}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_ionscale_v1_auth_keys_proto_rawDesc,
RawDescriptor: unsafe.Slice(unsafe.StringData(file_ionscale_v1_auth_keys_proto_rawDesc), len(file_ionscale_v1_auth_keys_proto_rawDesc)),
NumEnums: 0,
NumMessages: 9,
NumExtensions: 0,
@@ -775,7 +640,6 @@ func file_ionscale_v1_auth_keys_proto_init() {
MessageInfos: file_ionscale_v1_auth_keys_proto_msgTypes,
}.Build()
File_ionscale_v1_auth_keys_proto = out.File
file_ionscale_v1_auth_keys_proto_rawDesc = nil
file_ionscale_v1_auth_keys_proto_goTypes = nil
file_ionscale_v1_auth_keys_proto_depIdxs = nil
}
+15 -46
View File
@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.32.0
// protoc-gen-go v1.36.5
// protoc (unknown)
// source: ionscale/v1/derp.proto
@@ -11,6 +11,7 @@ import (
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
@@ -21,19 +22,17 @@ const (
)
type GetDefaultDERPMapRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetDefaultDERPMapRequest) Reset() {
*x = GetDefaultDERPMapRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_derp_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetDefaultDERPMapRequest) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -43,7 +42,7 @@ func (*GetDefaultDERPMapRequest) ProtoMessage() {}
func (x *GetDefaultDERPMapRequest) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_derp_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -59,21 +58,18 @@ func (*GetDefaultDERPMapRequest) Descriptor() ([]byte, []int) {
}
type GetDefaultDERPMapResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
Value []byte `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetDefaultDERPMapResponse) Reset() {
*x = GetDefaultDERPMapResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_derp_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetDefaultDERPMapResponse) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -83,7 +79,7 @@ func (*GetDefaultDERPMapResponse) ProtoMessage() {}
func (x *GetDefaultDERPMapResponse) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_derp_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -107,7 +103,7 @@ func (x *GetDefaultDERPMapResponse) GetValue() []byte {
var File_ionscale_v1_derp_proto protoreflect.FileDescriptor
var file_ionscale_v1_derp_proto_rawDesc = []byte{
var file_ionscale_v1_derp_proto_rawDesc = string([]byte{
0x0a, 0x16, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x65,
0x72, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61,
0x6c, 0x65, 0x2e, 0x76, 0x31, 0x22, 0x1a, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x44, 0x65, 0x66, 0x61,
@@ -120,22 +116,22 @@ var file_ionscale_v1_derp_proto_rawDesc = []byte{
0x63, 0x61, 0x6c, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x69, 0x6f, 0x6e,
0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c,
0x65, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
})
var (
file_ionscale_v1_derp_proto_rawDescOnce sync.Once
file_ionscale_v1_derp_proto_rawDescData = file_ionscale_v1_derp_proto_rawDesc
file_ionscale_v1_derp_proto_rawDescData []byte
)
func file_ionscale_v1_derp_proto_rawDescGZIP() []byte {
file_ionscale_v1_derp_proto_rawDescOnce.Do(func() {
file_ionscale_v1_derp_proto_rawDescData = protoimpl.X.CompressGZIP(file_ionscale_v1_derp_proto_rawDescData)
file_ionscale_v1_derp_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_ionscale_v1_derp_proto_rawDesc), len(file_ionscale_v1_derp_proto_rawDesc)))
})
return file_ionscale_v1_derp_proto_rawDescData
}
var file_ionscale_v1_derp_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_ionscale_v1_derp_proto_goTypes = []interface{}{
var file_ionscale_v1_derp_proto_goTypes = []any{
(*GetDefaultDERPMapRequest)(nil), // 0: ionscale.v1.GetDefaultDERPMapRequest
(*GetDefaultDERPMapResponse)(nil), // 1: ionscale.v1.GetDefaultDERPMapResponse
}
@@ -152,37 +148,11 @@ func file_ionscale_v1_derp_proto_init() {
if File_ionscale_v1_derp_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_ionscale_v1_derp_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetDefaultDERPMapRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_derp_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetDefaultDERPMapResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_ionscale_v1_derp_proto_rawDesc,
RawDescriptor: unsafe.Slice(unsafe.StringData(file_ionscale_v1_derp_proto_rawDesc), len(file_ionscale_v1_derp_proto_rawDesc)),
NumEnums: 0,
NumMessages: 2,
NumExtensions: 0,
@@ -193,7 +163,6 @@ func file_ionscale_v1_derp_proto_init() {
MessageInfos: file_ionscale_v1_derp_proto_msgTypes,
}.Build()
File_ionscale_v1_derp_proto = out.File
file_ionscale_v1_derp_proto_rawDesc = nil
file_ionscale_v1_derp_proto_goTypes = nil
file_ionscale_v1_derp_proto_depIdxs = nil
}
+33 -125
View File
@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.32.0
// protoc-gen-go v1.36.5
// protoc (unknown)
// source: ionscale/v1/dns.proto
@@ -11,6 +11,7 @@ import (
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
@@ -21,21 +22,18 @@ const (
)
type GetDNSConfigRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
TailnetId uint64 `protobuf:"varint,1,opt,name=tailnet_id,json=tailnetId,proto3" json:"tailnet_id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetDNSConfigRequest) Reset() {
*x = GetDNSConfigRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_dns_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetDNSConfigRequest) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -45,7 +43,7 @@ func (*GetDNSConfigRequest) ProtoMessage() {}
func (x *GetDNSConfigRequest) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_dns_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -68,21 +66,18 @@ func (x *GetDNSConfigRequest) GetTailnetId() uint64 {
}
type GetDNSConfigResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
Config *DNSConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetDNSConfigResponse) Reset() {
*x = GetDNSConfigResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_dns_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetDNSConfigResponse) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -92,7 +87,7 @@ func (*GetDNSConfigResponse) ProtoMessage() {}
func (x *GetDNSConfigResponse) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_dns_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -115,22 +110,19 @@ func (x *GetDNSConfigResponse) GetConfig() *DNSConfig {
}
type SetDNSConfigRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
TailnetId uint64 `protobuf:"varint,1,opt,name=tailnet_id,json=tailnetId,proto3" json:"tailnet_id,omitempty"`
Config *DNSConfig `protobuf:"bytes,2,opt,name=config,proto3" json:"config,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SetDNSConfigRequest) Reset() {
*x = SetDNSConfigRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_dns_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *SetDNSConfigRequest) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -140,7 +132,7 @@ func (*SetDNSConfigRequest) ProtoMessage() {}
func (x *SetDNSConfigRequest) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_dns_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -170,22 +162,19 @@ func (x *SetDNSConfigRequest) GetConfig() *DNSConfig {
}
type SetDNSConfigResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
Config *DNSConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"`
Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SetDNSConfigResponse) Reset() {
*x = SetDNSConfigResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_dns_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *SetDNSConfigResponse) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -195,7 +184,7 @@ func (*SetDNSConfigResponse) ProtoMessage() {}
func (x *SetDNSConfigResponse) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_dns_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -225,27 +214,24 @@ func (x *SetDNSConfigResponse) GetMessage() string {
}
type DNSConfig struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
MagicDns bool `protobuf:"varint,1,opt,name=magic_dns,json=magicDns,proto3" json:"magic_dns,omitempty"`
OverrideLocalDns bool `protobuf:"varint,2,opt,name=override_local_dns,json=overrideLocalDns,proto3" json:"override_local_dns,omitempty"`
Nameservers []string `protobuf:"bytes,3,rep,name=nameservers,proto3" json:"nameservers,omitempty"`
Routes map[string]*Routes `protobuf:"bytes,4,rep,name=routes,proto3" json:"routes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
Routes map[string]*Routes `protobuf:"bytes,4,rep,name=routes,proto3" json:"routes,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
MagicDnsSuffix string `protobuf:"bytes,5,opt,name=magic_dns_suffix,json=magicDnsSuffix,proto3" json:"magic_dns_suffix,omitempty"`
HttpsCerts bool `protobuf:"varint,6,opt,name=https_certs,json=httpsCerts,proto3" json:"https_certs,omitempty"`
SearchDomains []string `protobuf:"bytes,7,rep,name=search_domains,json=searchDomains,proto3" json:"search_domains,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *DNSConfig) Reset() {
*x = DNSConfig{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_dns_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DNSConfig) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -255,7 +241,7 @@ func (*DNSConfig) ProtoMessage() {}
func (x *DNSConfig) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_dns_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -320,21 +306,18 @@ func (x *DNSConfig) GetSearchDomains() []string {
}
type Routes struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
Routes []string `protobuf:"bytes,1,rep,name=routes,proto3" json:"routes,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *Routes) Reset() {
*x = Routes{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_dns_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Routes) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -344,7 +327,7 @@ func (*Routes) ProtoMessage() {}
func (x *Routes) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_dns_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -368,7 +351,7 @@ func (x *Routes) GetRoutes() []string {
var File_ionscale_v1_dns_proto protoreflect.FileDescriptor
var file_ionscale_v1_dns_proto_rawDesc = []byte{
var file_ionscale_v1_dns_proto_rawDesc = string([]byte{
0x0a, 0x15, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x6e,
0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c,
0x65, 0x2e, 0x76, 0x31, 0x22, 0x34, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x44, 0x4e, 0x53, 0x43, 0x6f,
@@ -422,22 +405,22 @@ var file_ionscale_v1_dns_proto_rawDesc = []byte{
0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x69, 0x6f,
0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61,
0x6c, 0x65, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
})
var (
file_ionscale_v1_dns_proto_rawDescOnce sync.Once
file_ionscale_v1_dns_proto_rawDescData = file_ionscale_v1_dns_proto_rawDesc
file_ionscale_v1_dns_proto_rawDescData []byte
)
func file_ionscale_v1_dns_proto_rawDescGZIP() []byte {
file_ionscale_v1_dns_proto_rawDescOnce.Do(func() {
file_ionscale_v1_dns_proto_rawDescData = protoimpl.X.CompressGZIP(file_ionscale_v1_dns_proto_rawDescData)
file_ionscale_v1_dns_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_ionscale_v1_dns_proto_rawDesc), len(file_ionscale_v1_dns_proto_rawDesc)))
})
return file_ionscale_v1_dns_proto_rawDescData
}
var file_ionscale_v1_dns_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
var file_ionscale_v1_dns_proto_goTypes = []interface{}{
var file_ionscale_v1_dns_proto_goTypes = []any{
(*GetDNSConfigRequest)(nil), // 0: ionscale.v1.GetDNSConfigRequest
(*GetDNSConfigResponse)(nil), // 1: ionscale.v1.GetDNSConfigResponse
(*SetDNSConfigRequest)(nil), // 2: ionscale.v1.SetDNSConfigRequest
@@ -464,85 +447,11 @@ func file_ionscale_v1_dns_proto_init() {
if File_ionscale_v1_dns_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_ionscale_v1_dns_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetDNSConfigRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_dns_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetDNSConfigResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_dns_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SetDNSConfigRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_dns_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SetDNSConfigResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_dns_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DNSConfig); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_dns_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Routes); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_ionscale_v1_dns_proto_rawDesc,
RawDescriptor: unsafe.Slice(unsafe.StringData(file_ionscale_v1_dns_proto_rawDesc), len(file_ionscale_v1_dns_proto_rawDesc)),
NumEnums: 0,
NumMessages: 7,
NumExtensions: 0,
@@ -553,7 +462,6 @@ func file_ionscale_v1_dns_proto_init() {
MessageInfos: file_ionscale_v1_dns_proto_msgTypes,
}.Build()
File_ionscale_v1_dns_proto = out.File
file_ionscale_v1_dns_proto_rawDesc = nil
file_ionscale_v1_dns_proto_goTypes = nil
file_ionscale_v1_dns_proto_depIdxs = nil
}
+23 -84
View File
@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.32.0
// protoc-gen-go v1.36.5
// protoc (unknown)
// source: ionscale/v1/iam.proto
@@ -11,6 +11,7 @@ import (
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
@@ -21,21 +22,18 @@ const (
)
type GetIAMPolicyRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
TailnetId uint64 `protobuf:"varint,1,opt,name=tailnet_id,json=tailnetId,proto3" json:"tailnet_id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetIAMPolicyRequest) Reset() {
*x = GetIAMPolicyRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_iam_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetIAMPolicyRequest) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -45,7 +43,7 @@ func (*GetIAMPolicyRequest) ProtoMessage() {}
func (x *GetIAMPolicyRequest) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_iam_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -68,21 +66,18 @@ func (x *GetIAMPolicyRequest) GetTailnetId() uint64 {
}
type GetIAMPolicyResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
Policy string `protobuf:"bytes,1,opt,name=policy,proto3" json:"policy,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetIAMPolicyResponse) Reset() {
*x = GetIAMPolicyResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_iam_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetIAMPolicyResponse) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -92,7 +87,7 @@ func (*GetIAMPolicyResponse) ProtoMessage() {}
func (x *GetIAMPolicyResponse) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_iam_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -115,22 +110,19 @@ func (x *GetIAMPolicyResponse) GetPolicy() string {
}
type SetIAMPolicyRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
TailnetId uint64 `protobuf:"varint,1,opt,name=tailnet_id,json=tailnetId,proto3" json:"tailnet_id,omitempty"`
Policy string `protobuf:"bytes,2,opt,name=policy,proto3" json:"policy,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SetIAMPolicyRequest) Reset() {
*x = SetIAMPolicyRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_iam_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *SetIAMPolicyRequest) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -140,7 +132,7 @@ func (*SetIAMPolicyRequest) ProtoMessage() {}
func (x *SetIAMPolicyRequest) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_iam_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -170,19 +162,17 @@ func (x *SetIAMPolicyRequest) GetPolicy() string {
}
type SetIAMPolicyResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SetIAMPolicyResponse) Reset() {
*x = SetIAMPolicyResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_iam_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *SetIAMPolicyResponse) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -192,7 +182,7 @@ func (*SetIAMPolicyResponse) ProtoMessage() {}
func (x *SetIAMPolicyResponse) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_iam_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -209,7 +199,7 @@ func (*SetIAMPolicyResponse) Descriptor() ([]byte, []int) {
var File_ionscale_v1_iam_proto protoreflect.FileDescriptor
var file_ionscale_v1_iam_proto_rawDesc = []byte{
var file_ionscale_v1_iam_proto_rawDesc = string([]byte{
0x0a, 0x15, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x61,
0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c,
0x65, 0x2e, 0x76, 0x31, 0x22, 0x34, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x49, 0x41, 0x4d, 0x50, 0x6f,
@@ -230,22 +220,22 @@ var file_ionscale_v1_iam_proto_rawDesc = []byte{
0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c,
0x65, 0x2f, 0x76, 0x31, 0x3b, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x76, 0x31, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
})
var (
file_ionscale_v1_iam_proto_rawDescOnce sync.Once
file_ionscale_v1_iam_proto_rawDescData = file_ionscale_v1_iam_proto_rawDesc
file_ionscale_v1_iam_proto_rawDescData []byte
)
func file_ionscale_v1_iam_proto_rawDescGZIP() []byte {
file_ionscale_v1_iam_proto_rawDescOnce.Do(func() {
file_ionscale_v1_iam_proto_rawDescData = protoimpl.X.CompressGZIP(file_ionscale_v1_iam_proto_rawDescData)
file_ionscale_v1_iam_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_ionscale_v1_iam_proto_rawDesc), len(file_ionscale_v1_iam_proto_rawDesc)))
})
return file_ionscale_v1_iam_proto_rawDescData
}
var file_ionscale_v1_iam_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_ionscale_v1_iam_proto_goTypes = []interface{}{
var file_ionscale_v1_iam_proto_goTypes = []any{
(*GetIAMPolicyRequest)(nil), // 0: ionscale.v1.GetIAMPolicyRequest
(*GetIAMPolicyResponse)(nil), // 1: ionscale.v1.GetIAMPolicyResponse
(*SetIAMPolicyRequest)(nil), // 2: ionscale.v1.SetIAMPolicyRequest
@@ -264,61 +254,11 @@ func file_ionscale_v1_iam_proto_init() {
if File_ionscale_v1_iam_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_ionscale_v1_iam_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetIAMPolicyRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_iam_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetIAMPolicyResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_iam_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SetIAMPolicyRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_iam_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SetIAMPolicyResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_ionscale_v1_iam_proto_rawDesc,
RawDescriptor: unsafe.Slice(unsafe.StringData(file_ionscale_v1_iam_proto_rawDesc), len(file_ionscale_v1_iam_proto_rawDesc)),
NumEnums: 0,
NumMessages: 4,
NumExtensions: 0,
@@ -329,7 +269,6 @@ func file_ionscale_v1_iam_proto_init() {
MessageInfos: file_ionscale_v1_iam_proto_msgTypes,
}.Build()
File_ionscale_v1_iam_proto = out.File
file_ionscale_v1_iam_proto_rawDesc = nil
file_ionscale_v1_iam_proto_goTypes = nil
file_ionscale_v1_iam_proto_depIdxs = nil
}
+179 -169
View File
@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.32.0
// protoc-gen-go v1.36.5
// protoc (unknown)
// source: ionscale/v1/ionscale.proto
@@ -10,6 +10,7 @@ import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
unsafe "unsafe"
)
const (
@@ -21,7 +22,7 @@ const (
var File_ionscale_v1_ionscale_proto protoreflect.FileDescriptor
var file_ionscale_v1_ionscale_proto_rawDesc = []byte{
var file_ionscale_v1_ionscale_proto_rawDesc = string([]byte{
0x0a, 0x1a, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6f,
0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x69, 0x6f,
0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x1a, 0x15, 0x69, 0x6f, 0x6e, 0x73, 0x63,
@@ -42,7 +43,7 @@ var file_ionscale_v1_ionscale_proto_rawDesc = []byte{
0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x73,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65,
0x2f, 0x76, 0x31, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x32, 0xe2, 0x1e, 0x0a, 0x0f, 0x49, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x53, 0x65,
0x6f, 0x32, 0xbf, 0x1f, 0x0a, 0x0f, 0x49, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x53, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4f, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73,
0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76,
0x31, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75,
@@ -232,70 +233,76 @@ var file_ionscale_v1_ionscale_proto_rawDesc = []byte{
0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76,
0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x61, 0x0a, 0x10, 0x41, 0x75, 0x74, 0x68,
0x6f, 0x72, 0x69, 0x7a, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x24, 0x2e, 0x69,
0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f,
0x72, 0x69, 0x7a, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x25, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31,
0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e,
0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x58, 0x0a, 0x0d, 0x45,
0x78, 0x70, 0x69, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x21, 0x2e, 0x69,
0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5b, 0x0a, 0x0e, 0x53, 0x65, 0x74, 0x4d,
0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x2e, 0x69, 0x6f, 0x6e,
0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68,
0x69, 0x6e, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23,
0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74,
0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x61, 0x0a, 0x10, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69,
0x7a, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x24, 0x2e, 0x69, 0x6f, 0x6e, 0x73,
0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a,
0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x22, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78,
0x70, 0x69, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x58, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d,
0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x21, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c,
0x25, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75,
0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x58, 0x0a, 0x0d, 0x45, 0x78, 0x70, 0x69,
0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x21, 0x2e, 0x69, 0x6f, 0x6e, 0x73,
0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x4d, 0x61,
0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x69,
0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72,
0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x22, 0x00, 0x12, 0x58, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68,
0x69, 0x6e, 0x65, 0x12, 0x21, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76,
0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c,
0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69,
0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x69, 0x6f, 0x6e, 0x73,
0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61,
0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12,
0x6a, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x4b, 0x65, 0x79,
0x45, 0x78, 0x70, 0x69, 0x72, 0x79, 0x12, 0x27, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c,
0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x4b,
0x65, 0x79, 0x45, 0x78, 0x70, 0x69, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x28, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65,
0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x4b, 0x65, 0x79, 0x45, 0x78, 0x70, 0x69, 0x72,
0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x61, 0x0a, 0x10, 0x47,
0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12,
0x24, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65,
0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65,
0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f,
0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6a,
0x0a, 0x13, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52,
0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x27, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65,
0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e,
0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28,
0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x61,
0x62, 0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6d, 0x0a, 0x14, 0x44, 0x69,
0x73, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74,
0x65, 0x73, 0x12, 0x28, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31,
0x2e, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52,
0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x69,
0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x61, 0x62,
0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5b, 0x0a, 0x0e, 0x45, 0x6e, 0x61,
0x62, 0x6c, 0x65, 0x45, 0x78, 0x69, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x22, 0x2e, 0x69, 0x6f,
0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6a, 0x0a, 0x13,
0x53, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x4b, 0x65, 0x79, 0x45, 0x78, 0x70,
0x69, 0x72, 0x79, 0x12, 0x27, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76,
0x31, 0x2e, 0x53, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x4b, 0x65, 0x79, 0x45,
0x78, 0x70, 0x69, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x69,
0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4d, 0x61,
0x63, 0x68, 0x69, 0x6e, 0x65, 0x4b, 0x65, 0x79, 0x45, 0x78, 0x70, 0x69, 0x72, 0x79, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x61, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4d,
0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x24, 0x2e, 0x69,
0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61,
0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x25, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31,
0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65,
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6a, 0x0a, 0x13, 0x45,
0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74,
0x65, 0x73, 0x12, 0x27, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31,
0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f,
0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x69, 0x6f,
0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65,
0x45, 0x78, 0x69, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x23, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e,
0x61, 0x62, 0x6c, 0x65, 0x45, 0x78, 0x69, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5e, 0x0a, 0x0f, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c,
0x65, 0x45, 0x78, 0x69, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x23, 0x2e, 0x69, 0x6f, 0x6e, 0x73,
0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x45,
0x78, 0x69, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24,
0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73,
0x61, 0x62, 0x6c, 0x65, 0x45, 0x78, 0x69, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x3d, 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6a, 0x73, 0x69, 0x65, 0x62, 0x65, 0x6e, 0x73, 0x2f, 0x69, 0x6f,
0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x69,
0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x69, 0x6f, 0x6e, 0x73, 0x63,
0x61, 0x6c, 0x65, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6d, 0x0a, 0x14, 0x44, 0x69, 0x73, 0x61, 0x62,
0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12,
0x28, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69,
0x73, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74,
0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x69, 0x6f, 0x6e, 0x73,
0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x4d,
0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5b, 0x0a, 0x0e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65,
0x45, 0x78, 0x69, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x22, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63,
0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x78, 0x69,
0x74, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x69,
0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c,
0x65, 0x45, 0x78, 0x69, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x22, 0x00, 0x12, 0x5e, 0x0a, 0x0f, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x78,
0x69, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x23, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c,
0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x78, 0x69, 0x74,
0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x69, 0x6f,
0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c,
0x65, 0x45, 0x78, 0x69, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x22, 0x00, 0x42, 0x3d, 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
0x6d, 0x2f, 0x6a, 0x73, 0x69, 0x65, 0x62, 0x65, 0x6e, 0x73, 0x2f, 0x69, 0x6f, 0x6e, 0x73, 0x63,
0x61, 0x6c, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x69, 0x6f, 0x6e, 0x73,
0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65,
0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
})
var file_ionscale_v1_ionscale_proto_goTypes = []interface{}{
var file_ionscale_v1_ionscale_proto_goTypes = []any{
(*GetVersionRequest)(nil), // 0: ionscale.v1.GetVersionRequest
(*AuthenticateRequest)(nil), // 1: ionscale.v1.AuthenticateRequest
(*GetDefaultDERPMapRequest)(nil), // 2: ionscale.v1.GetDefaultDERPMapRequest
@@ -329,57 +336,59 @@ var file_ionscale_v1_ionscale_proto_goTypes = []interface{}{
(*DeleteUserRequest)(nil), // 30: ionscale.v1.DeleteUserRequest
(*GetMachineRequest)(nil), // 31: ionscale.v1.GetMachineRequest
(*ListMachinesRequest)(nil), // 32: ionscale.v1.ListMachinesRequest
(*AuthorizeMachineRequest)(nil), // 33: ionscale.v1.AuthorizeMachineRequest
(*ExpireMachineRequest)(nil), // 34: ionscale.v1.ExpireMachineRequest
(*DeleteMachineRequest)(nil), // 35: ionscale.v1.DeleteMachineRequest
(*SetMachineKeyExpiryRequest)(nil), // 36: ionscale.v1.SetMachineKeyExpiryRequest
(*GetMachineRoutesRequest)(nil), // 37: ionscale.v1.GetMachineRoutesRequest
(*EnableMachineRoutesRequest)(nil), // 38: ionscale.v1.EnableMachineRoutesRequest
(*DisableMachineRoutesRequest)(nil), // 39: ionscale.v1.DisableMachineRoutesRequest
(*EnableExitNodeRequest)(nil), // 40: ionscale.v1.EnableExitNodeRequest
(*DisableExitNodeRequest)(nil), // 41: ionscale.v1.DisableExitNodeRequest
(*GetVersionResponse)(nil), // 42: ionscale.v1.GetVersionResponse
(*AuthenticateResponse)(nil), // 43: ionscale.v1.AuthenticateResponse
(*GetDefaultDERPMapResponse)(nil), // 44: ionscale.v1.GetDefaultDERPMapResponse
(*CreateTailnetResponse)(nil), // 45: ionscale.v1.CreateTailnetResponse
(*UpdateTailnetResponse)(nil), // 46: ionscale.v1.UpdateTailnetResponse
(*GetTailnetResponse)(nil), // 47: ionscale.v1.GetTailnetResponse
(*ListTailnetsResponse)(nil), // 48: ionscale.v1.ListTailnetsResponse
(*DeleteTailnetResponse)(nil), // 49: ionscale.v1.DeleteTailnetResponse
(*GetDERPMapResponse)(nil), // 50: ionscale.v1.GetDERPMapResponse
(*SetDERPMapResponse)(nil), // 51: ionscale.v1.SetDERPMapResponse
(*ResetDERPMapResponse)(nil), // 52: ionscale.v1.ResetDERPMapResponse
(*EnableFileSharingResponse)(nil), // 53: ionscale.v1.EnableFileSharingResponse
(*DisableFileSharingResponse)(nil), // 54: ionscale.v1.DisableFileSharingResponse
(*EnableServiceCollectionResponse)(nil), // 55: ionscale.v1.EnableServiceCollectionResponse
(*DisableServiceCollectionResponse)(nil), // 56: ionscale.v1.DisableServiceCollectionResponse
(*EnableSSHResponse)(nil), // 57: ionscale.v1.EnableSSHResponse
(*DisableSSHResponse)(nil), // 58: ionscale.v1.DisableSSHResponse
(*EnableMachineAuthorizationResponse)(nil), // 59: ionscale.v1.EnableMachineAuthorizationResponse
(*DisableMachineAuthorizationResponse)(nil), // 60: ionscale.v1.DisableMachineAuthorizationResponse
(*GetDNSConfigResponse)(nil), // 61: ionscale.v1.GetDNSConfigResponse
(*SetDNSConfigResponse)(nil), // 62: ionscale.v1.SetDNSConfigResponse
(*GetIAMPolicyResponse)(nil), // 63: ionscale.v1.GetIAMPolicyResponse
(*SetIAMPolicyResponse)(nil), // 64: ionscale.v1.SetIAMPolicyResponse
(*GetACLPolicyResponse)(nil), // 65: ionscale.v1.GetACLPolicyResponse
(*SetACLPolicyResponse)(nil), // 66: ionscale.v1.SetACLPolicyResponse
(*GetAuthKeyResponse)(nil), // 67: ionscale.v1.GetAuthKeyResponse
(*CreateAuthKeyResponse)(nil), // 68: ionscale.v1.CreateAuthKeyResponse
(*DeleteAuthKeyResponse)(nil), // 69: ionscale.v1.DeleteAuthKeyResponse
(*ListAuthKeysResponse)(nil), // 70: ionscale.v1.ListAuthKeysResponse
(*ListUsersResponse)(nil), // 71: ionscale.v1.ListUsersResponse
(*DeleteUserResponse)(nil), // 72: ionscale.v1.DeleteUserResponse
(*GetMachineResponse)(nil), // 73: ionscale.v1.GetMachineResponse
(*ListMachinesResponse)(nil), // 74: ionscale.v1.ListMachinesResponse
(*AuthorizeMachineResponse)(nil), // 75: ionscale.v1.AuthorizeMachineResponse
(*ExpireMachineResponse)(nil), // 76: ionscale.v1.ExpireMachineResponse
(*DeleteMachineResponse)(nil), // 77: ionscale.v1.DeleteMachineResponse
(*SetMachineKeyExpiryResponse)(nil), // 78: ionscale.v1.SetMachineKeyExpiryResponse
(*GetMachineRoutesResponse)(nil), // 79: ionscale.v1.GetMachineRoutesResponse
(*EnableMachineRoutesResponse)(nil), // 80: ionscale.v1.EnableMachineRoutesResponse
(*DisableMachineRoutesResponse)(nil), // 81: ionscale.v1.DisableMachineRoutesResponse
(*EnableExitNodeResponse)(nil), // 82: ionscale.v1.EnableExitNodeResponse
(*DisableExitNodeResponse)(nil), // 83: ionscale.v1.DisableExitNodeResponse
(*SetMachineNameRequest)(nil), // 33: ionscale.v1.SetMachineNameRequest
(*AuthorizeMachineRequest)(nil), // 34: ionscale.v1.AuthorizeMachineRequest
(*ExpireMachineRequest)(nil), // 35: ionscale.v1.ExpireMachineRequest
(*DeleteMachineRequest)(nil), // 36: ionscale.v1.DeleteMachineRequest
(*SetMachineKeyExpiryRequest)(nil), // 37: ionscale.v1.SetMachineKeyExpiryRequest
(*GetMachineRoutesRequest)(nil), // 38: ionscale.v1.GetMachineRoutesRequest
(*EnableMachineRoutesRequest)(nil), // 39: ionscale.v1.EnableMachineRoutesRequest
(*DisableMachineRoutesRequest)(nil), // 40: ionscale.v1.DisableMachineRoutesRequest
(*EnableExitNodeRequest)(nil), // 41: ionscale.v1.EnableExitNodeRequest
(*DisableExitNodeRequest)(nil), // 42: ionscale.v1.DisableExitNodeRequest
(*GetVersionResponse)(nil), // 43: ionscale.v1.GetVersionResponse
(*AuthenticateResponse)(nil), // 44: ionscale.v1.AuthenticateResponse
(*GetDefaultDERPMapResponse)(nil), // 45: ionscale.v1.GetDefaultDERPMapResponse
(*CreateTailnetResponse)(nil), // 46: ionscale.v1.CreateTailnetResponse
(*UpdateTailnetResponse)(nil), // 47: ionscale.v1.UpdateTailnetResponse
(*GetTailnetResponse)(nil), // 48: ionscale.v1.GetTailnetResponse
(*ListTailnetsResponse)(nil), // 49: ionscale.v1.ListTailnetsResponse
(*DeleteTailnetResponse)(nil), // 50: ionscale.v1.DeleteTailnetResponse
(*GetDERPMapResponse)(nil), // 51: ionscale.v1.GetDERPMapResponse
(*SetDERPMapResponse)(nil), // 52: ionscale.v1.SetDERPMapResponse
(*ResetDERPMapResponse)(nil), // 53: ionscale.v1.ResetDERPMapResponse
(*EnableFileSharingResponse)(nil), // 54: ionscale.v1.EnableFileSharingResponse
(*DisableFileSharingResponse)(nil), // 55: ionscale.v1.DisableFileSharingResponse
(*EnableServiceCollectionResponse)(nil), // 56: ionscale.v1.EnableServiceCollectionResponse
(*DisableServiceCollectionResponse)(nil), // 57: ionscale.v1.DisableServiceCollectionResponse
(*EnableSSHResponse)(nil), // 58: ionscale.v1.EnableSSHResponse
(*DisableSSHResponse)(nil), // 59: ionscale.v1.DisableSSHResponse
(*EnableMachineAuthorizationResponse)(nil), // 60: ionscale.v1.EnableMachineAuthorizationResponse
(*DisableMachineAuthorizationResponse)(nil), // 61: ionscale.v1.DisableMachineAuthorizationResponse
(*GetDNSConfigResponse)(nil), // 62: ionscale.v1.GetDNSConfigResponse
(*SetDNSConfigResponse)(nil), // 63: ionscale.v1.SetDNSConfigResponse
(*GetIAMPolicyResponse)(nil), // 64: ionscale.v1.GetIAMPolicyResponse
(*SetIAMPolicyResponse)(nil), // 65: ionscale.v1.SetIAMPolicyResponse
(*GetACLPolicyResponse)(nil), // 66: ionscale.v1.GetACLPolicyResponse
(*SetACLPolicyResponse)(nil), // 67: ionscale.v1.SetACLPolicyResponse
(*GetAuthKeyResponse)(nil), // 68: ionscale.v1.GetAuthKeyResponse
(*CreateAuthKeyResponse)(nil), // 69: ionscale.v1.CreateAuthKeyResponse
(*DeleteAuthKeyResponse)(nil), // 70: ionscale.v1.DeleteAuthKeyResponse
(*ListAuthKeysResponse)(nil), // 71: ionscale.v1.ListAuthKeysResponse
(*ListUsersResponse)(nil), // 72: ionscale.v1.ListUsersResponse
(*DeleteUserResponse)(nil), // 73: ionscale.v1.DeleteUserResponse
(*GetMachineResponse)(nil), // 74: ionscale.v1.GetMachineResponse
(*ListMachinesResponse)(nil), // 75: ionscale.v1.ListMachinesResponse
(*SetMachineNameResponse)(nil), // 76: ionscale.v1.SetMachineNameResponse
(*AuthorizeMachineResponse)(nil), // 77: ionscale.v1.AuthorizeMachineResponse
(*ExpireMachineResponse)(nil), // 78: ionscale.v1.ExpireMachineResponse
(*DeleteMachineResponse)(nil), // 79: ionscale.v1.DeleteMachineResponse
(*SetMachineKeyExpiryResponse)(nil), // 80: ionscale.v1.SetMachineKeyExpiryResponse
(*GetMachineRoutesResponse)(nil), // 81: ionscale.v1.GetMachineRoutesResponse
(*EnableMachineRoutesResponse)(nil), // 82: ionscale.v1.EnableMachineRoutesResponse
(*DisableMachineRoutesResponse)(nil), // 83: ionscale.v1.DisableMachineRoutesResponse
(*EnableExitNodeResponse)(nil), // 84: ionscale.v1.EnableExitNodeResponse
(*DisableExitNodeResponse)(nil), // 85: ionscale.v1.DisableExitNodeResponse
}
var file_ionscale_v1_ionscale_proto_depIdxs = []int32{
0, // 0: ionscale.v1.IonscaleService.GetVersion:input_type -> ionscale.v1.GetVersionRequest
@@ -415,59 +424,61 @@ var file_ionscale_v1_ionscale_proto_depIdxs = []int32{
30, // 30: ionscale.v1.IonscaleService.DeleteUser:input_type -> ionscale.v1.DeleteUserRequest
31, // 31: ionscale.v1.IonscaleService.GetMachine:input_type -> ionscale.v1.GetMachineRequest
32, // 32: ionscale.v1.IonscaleService.ListMachines:input_type -> ionscale.v1.ListMachinesRequest
33, // 33: ionscale.v1.IonscaleService.AuthorizeMachine:input_type -> ionscale.v1.AuthorizeMachineRequest
34, // 34: ionscale.v1.IonscaleService.ExpireMachine:input_type -> ionscale.v1.ExpireMachineRequest
35, // 35: ionscale.v1.IonscaleService.DeleteMachine:input_type -> ionscale.v1.DeleteMachineRequest
36, // 36: ionscale.v1.IonscaleService.SetMachineKeyExpiry:input_type -> ionscale.v1.SetMachineKeyExpiryRequest
37, // 37: ionscale.v1.IonscaleService.GetMachineRoutes:input_type -> ionscale.v1.GetMachineRoutesRequest
38, // 38: ionscale.v1.IonscaleService.EnableMachineRoutes:input_type -> ionscale.v1.EnableMachineRoutesRequest
39, // 39: ionscale.v1.IonscaleService.DisableMachineRoutes:input_type -> ionscale.v1.DisableMachineRoutesRequest
40, // 40: ionscale.v1.IonscaleService.EnableExitNode:input_type -> ionscale.v1.EnableExitNodeRequest
41, // 41: ionscale.v1.IonscaleService.DisableExitNode:input_type -> ionscale.v1.DisableExitNodeRequest
42, // 42: ionscale.v1.IonscaleService.GetVersion:output_type -> ionscale.v1.GetVersionResponse
43, // 43: ionscale.v1.IonscaleService.Authenticate:output_type -> ionscale.v1.AuthenticateResponse
44, // 44: ionscale.v1.IonscaleService.GetDefaultDERPMap:output_type -> ionscale.v1.GetDefaultDERPMapResponse
45, // 45: ionscale.v1.IonscaleService.CreateTailnet:output_type -> ionscale.v1.CreateTailnetResponse
46, // 46: ionscale.v1.IonscaleService.UpdateTailnet:output_type -> ionscale.v1.UpdateTailnetResponse
47, // 47: ionscale.v1.IonscaleService.GetTailnet:output_type -> ionscale.v1.GetTailnetResponse
48, // 48: ionscale.v1.IonscaleService.ListTailnets:output_type -> ionscale.v1.ListTailnetsResponse
49, // 49: ionscale.v1.IonscaleService.DeleteTailnet:output_type -> ionscale.v1.DeleteTailnetResponse
50, // 50: ionscale.v1.IonscaleService.GetDERPMap:output_type -> ionscale.v1.GetDERPMapResponse
51, // 51: ionscale.v1.IonscaleService.SetDERPMap:output_type -> ionscale.v1.SetDERPMapResponse
52, // 52: ionscale.v1.IonscaleService.ResetDERPMap:output_type -> ionscale.v1.ResetDERPMapResponse
53, // 53: ionscale.v1.IonscaleService.EnableFileSharing:output_type -> ionscale.v1.EnableFileSharingResponse
54, // 54: ionscale.v1.IonscaleService.DisableFileSharing:output_type -> ionscale.v1.DisableFileSharingResponse
55, // 55: ionscale.v1.IonscaleService.EnableServiceCollection:output_type -> ionscale.v1.EnableServiceCollectionResponse
56, // 56: ionscale.v1.IonscaleService.DisableServiceCollection:output_type -> ionscale.v1.DisableServiceCollectionResponse
57, // 57: ionscale.v1.IonscaleService.EnableSSH:output_type -> ionscale.v1.EnableSSHResponse
58, // 58: ionscale.v1.IonscaleService.DisableSSH:output_type -> ionscale.v1.DisableSSHResponse
59, // 59: ionscale.v1.IonscaleService.EnableMachineAuthorization:output_type -> ionscale.v1.EnableMachineAuthorizationResponse
60, // 60: ionscale.v1.IonscaleService.DisableMachineAuthorization:output_type -> ionscale.v1.DisableMachineAuthorizationResponse
61, // 61: ionscale.v1.IonscaleService.GetDNSConfig:output_type -> ionscale.v1.GetDNSConfigResponse
62, // 62: ionscale.v1.IonscaleService.SetDNSConfig:output_type -> ionscale.v1.SetDNSConfigResponse
63, // 63: ionscale.v1.IonscaleService.GetIAMPolicy:output_type -> ionscale.v1.GetIAMPolicyResponse
64, // 64: ionscale.v1.IonscaleService.SetIAMPolicy:output_type -> ionscale.v1.SetIAMPolicyResponse
65, // 65: ionscale.v1.IonscaleService.GetACLPolicy:output_type -> ionscale.v1.GetACLPolicyResponse
66, // 66: ionscale.v1.IonscaleService.SetACLPolicy:output_type -> ionscale.v1.SetACLPolicyResponse
67, // 67: ionscale.v1.IonscaleService.GetAuthKey:output_type -> ionscale.v1.GetAuthKeyResponse
68, // 68: ionscale.v1.IonscaleService.CreateAuthKey:output_type -> ionscale.v1.CreateAuthKeyResponse
69, // 69: ionscale.v1.IonscaleService.DeleteAuthKey:output_type -> ionscale.v1.DeleteAuthKeyResponse
70, // 70: ionscale.v1.IonscaleService.ListAuthKeys:output_type -> ionscale.v1.ListAuthKeysResponse
71, // 71: ionscale.v1.IonscaleService.ListUsers:output_type -> ionscale.v1.ListUsersResponse
72, // 72: ionscale.v1.IonscaleService.DeleteUser:output_type -> ionscale.v1.DeleteUserResponse
73, // 73: ionscale.v1.IonscaleService.GetMachine:output_type -> ionscale.v1.GetMachineResponse
74, // 74: ionscale.v1.IonscaleService.ListMachines:output_type -> ionscale.v1.ListMachinesResponse
75, // 75: ionscale.v1.IonscaleService.AuthorizeMachine:output_type -> ionscale.v1.AuthorizeMachineResponse
76, // 76: ionscale.v1.IonscaleService.ExpireMachine:output_type -> ionscale.v1.ExpireMachineResponse
77, // 77: ionscale.v1.IonscaleService.DeleteMachine:output_type -> ionscale.v1.DeleteMachineResponse
78, // 78: ionscale.v1.IonscaleService.SetMachineKeyExpiry:output_type -> ionscale.v1.SetMachineKeyExpiryResponse
79, // 79: ionscale.v1.IonscaleService.GetMachineRoutes:output_type -> ionscale.v1.GetMachineRoutesResponse
80, // 80: ionscale.v1.IonscaleService.EnableMachineRoutes:output_type -> ionscale.v1.EnableMachineRoutesResponse
81, // 81: ionscale.v1.IonscaleService.DisableMachineRoutes:output_type -> ionscale.v1.DisableMachineRoutesResponse
82, // 82: ionscale.v1.IonscaleService.EnableExitNode:output_type -> ionscale.v1.EnableExitNodeResponse
83, // 83: ionscale.v1.IonscaleService.DisableExitNode:output_type -> ionscale.v1.DisableExitNodeResponse
42, // [42:84] is the sub-list for method output_type
0, // [0:42] is the sub-list for method input_type
33, // 33: ionscale.v1.IonscaleService.SetMachineName:input_type -> ionscale.v1.SetMachineNameRequest
34, // 34: ionscale.v1.IonscaleService.AuthorizeMachine:input_type -> ionscale.v1.AuthorizeMachineRequest
35, // 35: ionscale.v1.IonscaleService.ExpireMachine:input_type -> ionscale.v1.ExpireMachineRequest
36, // 36: ionscale.v1.IonscaleService.DeleteMachine:input_type -> ionscale.v1.DeleteMachineRequest
37, // 37: ionscale.v1.IonscaleService.SetMachineKeyExpiry:input_type -> ionscale.v1.SetMachineKeyExpiryRequest
38, // 38: ionscale.v1.IonscaleService.GetMachineRoutes:input_type -> ionscale.v1.GetMachineRoutesRequest
39, // 39: ionscale.v1.IonscaleService.EnableMachineRoutes:input_type -> ionscale.v1.EnableMachineRoutesRequest
40, // 40: ionscale.v1.IonscaleService.DisableMachineRoutes:input_type -> ionscale.v1.DisableMachineRoutesRequest
41, // 41: ionscale.v1.IonscaleService.EnableExitNode:input_type -> ionscale.v1.EnableExitNodeRequest
42, // 42: ionscale.v1.IonscaleService.DisableExitNode:input_type -> ionscale.v1.DisableExitNodeRequest
43, // 43: ionscale.v1.IonscaleService.GetVersion:output_type -> ionscale.v1.GetVersionResponse
44, // 44: ionscale.v1.IonscaleService.Authenticate:output_type -> ionscale.v1.AuthenticateResponse
45, // 45: ionscale.v1.IonscaleService.GetDefaultDERPMap:output_type -> ionscale.v1.GetDefaultDERPMapResponse
46, // 46: ionscale.v1.IonscaleService.CreateTailnet:output_type -> ionscale.v1.CreateTailnetResponse
47, // 47: ionscale.v1.IonscaleService.UpdateTailnet:output_type -> ionscale.v1.UpdateTailnetResponse
48, // 48: ionscale.v1.IonscaleService.GetTailnet:output_type -> ionscale.v1.GetTailnetResponse
49, // 49: ionscale.v1.IonscaleService.ListTailnets:output_type -> ionscale.v1.ListTailnetsResponse
50, // 50: ionscale.v1.IonscaleService.DeleteTailnet:output_type -> ionscale.v1.DeleteTailnetResponse
51, // 51: ionscale.v1.IonscaleService.GetDERPMap:output_type -> ionscale.v1.GetDERPMapResponse
52, // 52: ionscale.v1.IonscaleService.SetDERPMap:output_type -> ionscale.v1.SetDERPMapResponse
53, // 53: ionscale.v1.IonscaleService.ResetDERPMap:output_type -> ionscale.v1.ResetDERPMapResponse
54, // 54: ionscale.v1.IonscaleService.EnableFileSharing:output_type -> ionscale.v1.EnableFileSharingResponse
55, // 55: ionscale.v1.IonscaleService.DisableFileSharing:output_type -> ionscale.v1.DisableFileSharingResponse
56, // 56: ionscale.v1.IonscaleService.EnableServiceCollection:output_type -> ionscale.v1.EnableServiceCollectionResponse
57, // 57: ionscale.v1.IonscaleService.DisableServiceCollection:output_type -> ionscale.v1.DisableServiceCollectionResponse
58, // 58: ionscale.v1.IonscaleService.EnableSSH:output_type -> ionscale.v1.EnableSSHResponse
59, // 59: ionscale.v1.IonscaleService.DisableSSH:output_type -> ionscale.v1.DisableSSHResponse
60, // 60: ionscale.v1.IonscaleService.EnableMachineAuthorization:output_type -> ionscale.v1.EnableMachineAuthorizationResponse
61, // 61: ionscale.v1.IonscaleService.DisableMachineAuthorization:output_type -> ionscale.v1.DisableMachineAuthorizationResponse
62, // 62: ionscale.v1.IonscaleService.GetDNSConfig:output_type -> ionscale.v1.GetDNSConfigResponse
63, // 63: ionscale.v1.IonscaleService.SetDNSConfig:output_type -> ionscale.v1.SetDNSConfigResponse
64, // 64: ionscale.v1.IonscaleService.GetIAMPolicy:output_type -> ionscale.v1.GetIAMPolicyResponse
65, // 65: ionscale.v1.IonscaleService.SetIAMPolicy:output_type -> ionscale.v1.SetIAMPolicyResponse
66, // 66: ionscale.v1.IonscaleService.GetACLPolicy:output_type -> ionscale.v1.GetACLPolicyResponse
67, // 67: ionscale.v1.IonscaleService.SetACLPolicy:output_type -> ionscale.v1.SetACLPolicyResponse
68, // 68: ionscale.v1.IonscaleService.GetAuthKey:output_type -> ionscale.v1.GetAuthKeyResponse
69, // 69: ionscale.v1.IonscaleService.CreateAuthKey:output_type -> ionscale.v1.CreateAuthKeyResponse
70, // 70: ionscale.v1.IonscaleService.DeleteAuthKey:output_type -> ionscale.v1.DeleteAuthKeyResponse
71, // 71: ionscale.v1.IonscaleService.ListAuthKeys:output_type -> ionscale.v1.ListAuthKeysResponse
72, // 72: ionscale.v1.IonscaleService.ListUsers:output_type -> ionscale.v1.ListUsersResponse
73, // 73: ionscale.v1.IonscaleService.DeleteUser:output_type -> ionscale.v1.DeleteUserResponse
74, // 74: ionscale.v1.IonscaleService.GetMachine:output_type -> ionscale.v1.GetMachineResponse
75, // 75: ionscale.v1.IonscaleService.ListMachines:output_type -> ionscale.v1.ListMachinesResponse
76, // 76: ionscale.v1.IonscaleService.SetMachineName:output_type -> ionscale.v1.SetMachineNameResponse
77, // 77: ionscale.v1.IonscaleService.AuthorizeMachine:output_type -> ionscale.v1.AuthorizeMachineResponse
78, // 78: ionscale.v1.IonscaleService.ExpireMachine:output_type -> ionscale.v1.ExpireMachineResponse
79, // 79: ionscale.v1.IonscaleService.DeleteMachine:output_type -> ionscale.v1.DeleteMachineResponse
80, // 80: ionscale.v1.IonscaleService.SetMachineKeyExpiry:output_type -> ionscale.v1.SetMachineKeyExpiryResponse
81, // 81: ionscale.v1.IonscaleService.GetMachineRoutes:output_type -> ionscale.v1.GetMachineRoutesResponse
82, // 82: ionscale.v1.IonscaleService.EnableMachineRoutes:output_type -> ionscale.v1.EnableMachineRoutesResponse
83, // 83: ionscale.v1.IonscaleService.DisableMachineRoutes:output_type -> ionscale.v1.DisableMachineRoutesResponse
84, // 84: ionscale.v1.IonscaleService.EnableExitNode:output_type -> ionscale.v1.EnableExitNodeResponse
85, // 85: ionscale.v1.IonscaleService.DisableExitNode:output_type -> ionscale.v1.DisableExitNodeResponse
43, // [43:86] is the sub-list for method output_type
0, // [0:43] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
@@ -493,7 +504,7 @@ func file_ionscale_v1_ionscale_proto_init() {
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_ionscale_v1_ionscale_proto_rawDesc,
RawDescriptor: unsafe.Slice(unsafe.StringData(file_ionscale_v1_ionscale_proto_rawDesc), len(file_ionscale_v1_ionscale_proto_rawDesc)),
NumEnums: 0,
NumMessages: 0,
NumExtensions: 0,
@@ -503,7 +514,6 @@ func file_ionscale_v1_ionscale_proto_init() {
DependencyIndexes: file_ionscale_v1_ionscale_proto_depIdxs,
}.Build()
File_ionscale_v1_ionscale_proto = out.File
file_ionscale_v1_ionscale_proto_rawDesc = nil
file_ionscale_v1_ionscale_proto_goTypes = nil
file_ionscale_v1_ionscale_proto_depIdxs = nil
}
@@ -132,6 +132,9 @@ const (
// IonscaleServiceListMachinesProcedure is the fully-qualified name of the IonscaleService's
// ListMachines RPC.
IonscaleServiceListMachinesProcedure = "/ionscale.v1.IonscaleService/ListMachines"
// IonscaleServiceSetMachineNameProcedure is the fully-qualified name of the IonscaleService's
// SetMachineName RPC.
IonscaleServiceSetMachineNameProcedure = "/ionscale.v1.IonscaleService/SetMachineName"
// IonscaleServiceAuthorizeMachineProcedure is the fully-qualified name of the IonscaleService's
// AuthorizeMachine RPC.
IonscaleServiceAuthorizeMachineProcedure = "/ionscale.v1.IonscaleService/AuthorizeMachine"
@@ -196,6 +199,7 @@ type IonscaleServiceClient interface {
DeleteUser(context.Context, *connect_go.Request[v1.DeleteUserRequest]) (*connect_go.Response[v1.DeleteUserResponse], error)
GetMachine(context.Context, *connect_go.Request[v1.GetMachineRequest]) (*connect_go.Response[v1.GetMachineResponse], error)
ListMachines(context.Context, *connect_go.Request[v1.ListMachinesRequest]) (*connect_go.Response[v1.ListMachinesResponse], error)
SetMachineName(context.Context, *connect_go.Request[v1.SetMachineNameRequest]) (*connect_go.Response[v1.SetMachineNameResponse], error)
AuthorizeMachine(context.Context, *connect_go.Request[v1.AuthorizeMachineRequest]) (*connect_go.Response[v1.AuthorizeMachineResponse], error)
ExpireMachine(context.Context, *connect_go.Request[v1.ExpireMachineRequest]) (*connect_go.Response[v1.ExpireMachineResponse], error)
DeleteMachine(context.Context, *connect_go.Request[v1.DeleteMachineRequest]) (*connect_go.Response[v1.DeleteMachineResponse], error)
@@ -382,6 +386,11 @@ func NewIonscaleServiceClient(httpClient connect_go.HTTPClient, baseURL string,
baseURL+IonscaleServiceListMachinesProcedure,
opts...,
),
setMachineName: connect_go.NewClient[v1.SetMachineNameRequest, v1.SetMachineNameResponse](
httpClient,
baseURL+IonscaleServiceSetMachineNameProcedure,
opts...,
),
authorizeMachine: connect_go.NewClient[v1.AuthorizeMachineRequest, v1.AuthorizeMachineResponse](
httpClient,
baseURL+IonscaleServiceAuthorizeMachineProcedure,
@@ -465,6 +474,7 @@ type ionscaleServiceClient struct {
deleteUser *connect_go.Client[v1.DeleteUserRequest, v1.DeleteUserResponse]
getMachine *connect_go.Client[v1.GetMachineRequest, v1.GetMachineResponse]
listMachines *connect_go.Client[v1.ListMachinesRequest, v1.ListMachinesResponse]
setMachineName *connect_go.Client[v1.SetMachineNameRequest, v1.SetMachineNameResponse]
authorizeMachine *connect_go.Client[v1.AuthorizeMachineRequest, v1.AuthorizeMachineResponse]
expireMachine *connect_go.Client[v1.ExpireMachineRequest, v1.ExpireMachineResponse]
deleteMachine *connect_go.Client[v1.DeleteMachineRequest, v1.DeleteMachineResponse]
@@ -641,6 +651,11 @@ func (c *ionscaleServiceClient) ListMachines(ctx context.Context, req *connect_g
return c.listMachines.CallUnary(ctx, req)
}
// SetMachineName calls ionscale.v1.IonscaleService.SetMachineName.
func (c *ionscaleServiceClient) SetMachineName(ctx context.Context, req *connect_go.Request[v1.SetMachineNameRequest]) (*connect_go.Response[v1.SetMachineNameResponse], error) {
return c.setMachineName.CallUnary(ctx, req)
}
// AuthorizeMachine calls ionscale.v1.IonscaleService.AuthorizeMachine.
func (c *ionscaleServiceClient) AuthorizeMachine(ctx context.Context, req *connect_go.Request[v1.AuthorizeMachineRequest]) (*connect_go.Response[v1.AuthorizeMachineResponse], error) {
return c.authorizeMachine.CallUnary(ctx, req)
@@ -721,6 +736,7 @@ type IonscaleServiceHandler interface {
DeleteUser(context.Context, *connect_go.Request[v1.DeleteUserRequest]) (*connect_go.Response[v1.DeleteUserResponse], error)
GetMachine(context.Context, *connect_go.Request[v1.GetMachineRequest]) (*connect_go.Response[v1.GetMachineResponse], error)
ListMachines(context.Context, *connect_go.Request[v1.ListMachinesRequest]) (*connect_go.Response[v1.ListMachinesResponse], error)
SetMachineName(context.Context, *connect_go.Request[v1.SetMachineNameRequest]) (*connect_go.Response[v1.SetMachineNameResponse], error)
AuthorizeMachine(context.Context, *connect_go.Request[v1.AuthorizeMachineRequest]) (*connect_go.Response[v1.AuthorizeMachineResponse], error)
ExpireMachine(context.Context, *connect_go.Request[v1.ExpireMachineRequest]) (*connect_go.Response[v1.ExpireMachineResponse], error)
DeleteMachine(context.Context, *connect_go.Request[v1.DeleteMachineRequest]) (*connect_go.Response[v1.DeleteMachineResponse], error)
@@ -903,6 +919,11 @@ func NewIonscaleServiceHandler(svc IonscaleServiceHandler, opts ...connect_go.Ha
svc.ListMachines,
opts...,
)
ionscaleServiceSetMachineNameHandler := connect_go.NewUnaryHandler(
IonscaleServiceSetMachineNameProcedure,
svc.SetMachineName,
opts...,
)
ionscaleServiceAuthorizeMachineHandler := connect_go.NewUnaryHandler(
IonscaleServiceAuthorizeMachineProcedure,
svc.AuthorizeMachine,
@@ -1016,6 +1037,8 @@ func NewIonscaleServiceHandler(svc IonscaleServiceHandler, opts ...connect_go.Ha
ionscaleServiceGetMachineHandler.ServeHTTP(w, r)
case IonscaleServiceListMachinesProcedure:
ionscaleServiceListMachinesHandler.ServeHTTP(w, r)
case IonscaleServiceSetMachineNameProcedure:
ionscaleServiceSetMachineNameHandler.ServeHTTP(w, r)
case IonscaleServiceAuthorizeMachineProcedure:
ionscaleServiceAuthorizeMachineHandler.ServeHTTP(w, r)
case IonscaleServiceExpireMachineProcedure:
@@ -1175,6 +1198,10 @@ func (UnimplementedIonscaleServiceHandler) ListMachines(context.Context, *connec
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("ionscale.v1.IonscaleService.ListMachines is not implemented"))
}
func (UnimplementedIonscaleServiceHandler) SetMachineName(context.Context, *connect_go.Request[v1.SetMachineNameRequest]) (*connect_go.Response[v1.SetMachineNameResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("ionscale.v1.IonscaleService.SetMachineName is not implemented"))
}
func (UnimplementedIonscaleServiceHandler) AuthorizeMachine(context.Context, *connect_go.Request[v1.AuthorizeMachineRequest]) (*connect_go.Response[v1.AuthorizeMachineResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("ionscale.v1.IonscaleService.AuthorizeMachine is not implemented"))
}
+244 -345
View File
@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.32.0
// protoc-gen-go v1.36.5
// protoc (unknown)
// source: ionscale/v1/machines.proto
@@ -12,6 +12,7 @@ import (
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
@@ -22,21 +23,18 @@ const (
)
type ListMachinesRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
TailnetId uint64 `protobuf:"varint,1,opt,name=tailnet_id,json=tailnetId,proto3" json:"tailnet_id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListMachinesRequest) Reset() {
*x = ListMachinesRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_machines_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ListMachinesRequest) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -46,7 +44,7 @@ func (*ListMachinesRequest) ProtoMessage() {}
func (x *ListMachinesRequest) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_machines_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -69,21 +67,18 @@ func (x *ListMachinesRequest) GetTailnetId() uint64 {
}
type ListMachinesResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
Machines []*Machine `protobuf:"bytes,1,rep,name=machines,proto3" json:"machines,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListMachinesResponse) Reset() {
*x = ListMachinesResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_machines_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ListMachinesResponse) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -93,7 +88,7 @@ func (*ListMachinesResponse) ProtoMessage() {}
func (x *ListMachinesResponse) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_machines_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -116,21 +111,18 @@ func (x *ListMachinesResponse) GetMachines() []*Machine {
}
type DeleteMachineRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
MachineId uint64 `protobuf:"varint,1,opt,name=machine_id,json=machineId,proto3" json:"machine_id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *DeleteMachineRequest) Reset() {
*x = DeleteMachineRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_machines_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DeleteMachineRequest) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -140,7 +132,7 @@ func (*DeleteMachineRequest) ProtoMessage() {}
func (x *DeleteMachineRequest) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_machines_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -163,19 +155,17 @@ func (x *DeleteMachineRequest) GetMachineId() uint64 {
}
type DeleteMachineResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *DeleteMachineResponse) Reset() {
*x = DeleteMachineResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_machines_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DeleteMachineResponse) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -185,7 +175,7 @@ func (*DeleteMachineResponse) ProtoMessage() {}
func (x *DeleteMachineResponse) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_machines_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -201,21 +191,18 @@ func (*DeleteMachineResponse) Descriptor() ([]byte, []int) {
}
type ExpireMachineRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
MachineId uint64 `protobuf:"varint,1,opt,name=machine_id,json=machineId,proto3" json:"machine_id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ExpireMachineRequest) Reset() {
*x = ExpireMachineRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_machines_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ExpireMachineRequest) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -225,7 +212,7 @@ func (*ExpireMachineRequest) ProtoMessage() {}
func (x *ExpireMachineRequest) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_machines_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -248,19 +235,17 @@ func (x *ExpireMachineRequest) GetMachineId() uint64 {
}
type ExpireMachineResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ExpireMachineResponse) Reset() {
*x = ExpireMachineResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_machines_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ExpireMachineResponse) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -270,7 +255,7 @@ func (*ExpireMachineResponse) ProtoMessage() {}
func (x *ExpireMachineResponse) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_machines_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -286,22 +271,19 @@ func (*ExpireMachineResponse) Descriptor() ([]byte, []int) {
}
type SetMachineKeyExpiryRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
MachineId uint64 `protobuf:"varint,1,opt,name=machine_id,json=machineId,proto3" json:"machine_id,omitempty"`
Disabled bool `protobuf:"varint,2,opt,name=disabled,proto3" json:"disabled,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SetMachineKeyExpiryRequest) Reset() {
*x = SetMachineKeyExpiryRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_machines_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *SetMachineKeyExpiryRequest) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -311,7 +293,7 @@ func (*SetMachineKeyExpiryRequest) ProtoMessage() {}
func (x *SetMachineKeyExpiryRequest) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_machines_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -341,19 +323,17 @@ func (x *SetMachineKeyExpiryRequest) GetDisabled() bool {
}
type SetMachineKeyExpiryResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SetMachineKeyExpiryResponse) Reset() {
*x = SetMachineKeyExpiryResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_machines_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *SetMachineKeyExpiryResponse) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -363,7 +343,7 @@ func (*SetMachineKeyExpiryResponse) ProtoMessage() {}
func (x *SetMachineKeyExpiryResponse) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_machines_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -379,21 +359,18 @@ func (*SetMachineKeyExpiryResponse) Descriptor() ([]byte, []int) {
}
type GetMachineRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
MachineId uint64 `protobuf:"varint,1,opt,name=machine_id,json=machineId,proto3" json:"machine_id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetMachineRequest) Reset() {
*x = GetMachineRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_machines_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetMachineRequest) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -403,7 +380,7 @@ func (*GetMachineRequest) ProtoMessage() {}
func (x *GetMachineRequest) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_machines_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -426,21 +403,18 @@ func (x *GetMachineRequest) GetMachineId() uint64 {
}
type GetMachineResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
Machine *Machine `protobuf:"bytes,1,opt,name=machine,proto3" json:"machine,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetMachineResponse) Reset() {
*x = GetMachineResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_machines_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetMachineResponse) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -450,7 +424,7 @@ func (*GetMachineResponse) ProtoMessage() {}
func (x *GetMachineResponse) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_machines_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -473,21 +447,18 @@ func (x *GetMachineResponse) GetMachine() *Machine {
}
type AuthorizeMachineRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
MachineId uint64 `protobuf:"varint,1,opt,name=machine_id,json=machineId,proto3" json:"machine_id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *AuthorizeMachineRequest) Reset() {
*x = AuthorizeMachineRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_machines_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *AuthorizeMachineRequest) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -497,7 +468,7 @@ func (*AuthorizeMachineRequest) ProtoMessage() {}
func (x *AuthorizeMachineRequest) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_machines_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -520,19 +491,17 @@ func (x *AuthorizeMachineRequest) GetMachineId() uint64 {
}
type AuthorizeMachineResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *AuthorizeMachineResponse) Reset() {
*x = AuthorizeMachineResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_machines_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *AuthorizeMachineResponse) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -542,7 +511,7 @@ func (*AuthorizeMachineResponse) ProtoMessage() {}
func (x *AuthorizeMachineResponse) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_machines_proto_msgTypes[11]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -557,11 +526,104 @@ func (*AuthorizeMachineResponse) Descriptor() ([]byte, []int) {
return file_ionscale_v1_machines_proto_rawDescGZIP(), []int{11}
}
type Machine struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
type SetMachineNameRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
MachineId uint64 `protobuf:"varint,1,opt,name=machine_id,json=machineId,proto3" json:"machine_id,omitempty"`
UseOsHostname bool `protobuf:"varint,2,opt,name=use_os_hostname,json=useOsHostname,proto3" json:"use_os_hostname,omitempty"`
Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SetMachineNameRequest) Reset() {
*x = SetMachineNameRequest{}
mi := &file_ionscale_v1_machines_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *SetMachineNameRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SetMachineNameRequest) ProtoMessage() {}
func (x *SetMachineNameRequest) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_machines_proto_msgTypes[12]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use SetMachineNameRequest.ProtoReflect.Descriptor instead.
func (*SetMachineNameRequest) Descriptor() ([]byte, []int) {
return file_ionscale_v1_machines_proto_rawDescGZIP(), []int{12}
}
func (x *SetMachineNameRequest) GetMachineId() uint64 {
if x != nil {
return x.MachineId
}
return 0
}
func (x *SetMachineNameRequest) GetUseOsHostname() bool {
if x != nil {
return x.UseOsHostname
}
return false
}
func (x *SetMachineNameRequest) GetName() string {
if x != nil {
return x.Name
}
return ""
}
type SetMachineNameResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SetMachineNameResponse) Reset() {
*x = SetMachineNameResponse{}
mi := &file_ionscale_v1_machines_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *SetMachineNameResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SetMachineNameResponse) ProtoMessage() {}
func (x *SetMachineNameResponse) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_machines_proto_msgTypes[13]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use SetMachineNameResponse.ProtoReflect.Descriptor instead.
func (*SetMachineNameResponse) Descriptor() ([]byte, []int) {
return file_ionscale_v1_machines_proto_rawDescGZIP(), []int{13}
}
type Machine struct {
state protoimpl.MessageState `protogen:"open.v1"`
Id uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
Ipv4 string `protobuf:"bytes,3,opt,name=ipv4,proto3" json:"ipv4,omitempty"`
@@ -583,16 +645,16 @@ type Machine struct {
AdvertisedExitNode bool `protobuf:"varint,19,opt,name=advertised_exit_node,json=advertisedExitNode,proto3" json:"advertised_exit_node,omitempty"`
EnabledExitNode bool `protobuf:"varint,20,opt,name=enabled_exit_node,json=enabledExitNode,proto3" json:"enabled_exit_node,omitempty"`
Authorized bool `protobuf:"varint,21,opt,name=authorized,proto3" json:"authorized,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *Machine) Reset() {
*x = Machine{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_machines_proto_msgTypes[12]
mi := &file_ionscale_v1_machines_proto_msgTypes[14]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Machine) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -601,8 +663,8 @@ func (x *Machine) String() string {
func (*Machine) ProtoMessage() {}
func (x *Machine) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_machines_proto_msgTypes[12]
if protoimpl.UnsafeEnabled && x != nil {
mi := &file_ionscale_v1_machines_proto_msgTypes[14]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -614,7 +676,7 @@ func (x *Machine) ProtoReflect() protoreflect.Message {
// Deprecated: Use Machine.ProtoReflect.Descriptor instead.
func (*Machine) Descriptor() ([]byte, []int) {
return file_ionscale_v1_machines_proto_rawDescGZIP(), []int{12}
return file_ionscale_v1_machines_proto_rawDescGZIP(), []int{14}
}
func (x *Machine) GetId() uint64 {
@@ -765,21 +827,18 @@ func (x *Machine) GetAuthorized() bool {
}
type ClientConnectivity struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
Endpoints []string `protobuf:"bytes,1,rep,name=endpoints,proto3" json:"endpoints,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ClientConnectivity) Reset() {
*x = ClientConnectivity{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_machines_proto_msgTypes[13]
mi := &file_ionscale_v1_machines_proto_msgTypes[15]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ClientConnectivity) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -788,8 +847,8 @@ func (x *ClientConnectivity) String() string {
func (*ClientConnectivity) ProtoMessage() {}
func (x *ClientConnectivity) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_machines_proto_msgTypes[13]
if protoimpl.UnsafeEnabled && x != nil {
mi := &file_ionscale_v1_machines_proto_msgTypes[15]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -801,7 +860,7 @@ func (x *ClientConnectivity) ProtoReflect() protoreflect.Message {
// Deprecated: Use ClientConnectivity.ProtoReflect.Descriptor instead.
func (*ClientConnectivity) Descriptor() ([]byte, []int) {
return file_ionscale_v1_machines_proto_rawDescGZIP(), []int{13}
return file_ionscale_v1_machines_proto_rawDescGZIP(), []int{15}
}
func (x *ClientConnectivity) GetEndpoints() []string {
@@ -813,7 +872,7 @@ func (x *ClientConnectivity) GetEndpoints() []string {
var File_ionscale_v1_machines_proto protoreflect.FileDescriptor
var file_ionscale_v1_machines_proto_rawDesc = []byte{
var file_ionscale_v1_machines_proto_rawDesc = string([]byte{
0x0a, 0x1a, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61,
0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x69, 0x6f,
0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
@@ -858,82 +917,91 @@ var file_ionscale_v1_machines_proto_rawDesc = []byte{
0x0a, 0x0a, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x04, 0x52, 0x09, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x22, 0x1a, 0x0a,
0x18, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e,
0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xb1, 0x06, 0x0a, 0x07, 0x4d, 0x61,
0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
0x04, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x70, 0x76,
0x34, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x69, 0x70, 0x76, 0x34, 0x12, 0x12, 0x0a,
0x04, 0x69, 0x70, 0x76, 0x36, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x69, 0x70, 0x76,
0x36, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x18, 0x05,
0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x65, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x12,
0x37, 0x0a, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x65, 0x6e, 0x18, 0x06, 0x20, 0x01,
0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x72, 0x0a, 0x15, 0x53, 0x65, 0x74,
0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64,
0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49,
0x64, 0x12, 0x26, 0x0a, 0x0f, 0x75, 0x73, 0x65, 0x5f, 0x6f, 0x73, 0x5f, 0x68, 0x6f, 0x73, 0x74,
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x75, 0x73, 0x65, 0x4f,
0x73, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x18, 0x0a,
0x16, 0x53, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xb1, 0x06, 0x0a, 0x07, 0x4d, 0x61, 0x63, 0x68,
0x69, 0x6e, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52,
0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x70, 0x76, 0x34, 0x18,
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x69, 0x70, 0x76, 0x34, 0x12, 0x12, 0x0a, 0x04, 0x69,
0x70, 0x76, 0x36, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x69, 0x70, 0x76, 0x36, 0x12,
0x1c, 0x0a, 0x09, 0x65, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x18, 0x05, 0x20, 0x01,
0x28, 0x08, 0x52, 0x09, 0x65, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x12, 0x37, 0x0a,
0x09, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x65, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x6c, 0x61,
0x73, 0x74, 0x53, 0x65, 0x65, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
0x74, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x6e, 0x65,
0x63, 0x74, 0x65, 0x64, 0x12, 0x2a, 0x0a, 0x07, 0x74, 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74, 0x18,
0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65,
0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x66, 0x52, 0x07, 0x74, 0x61, 0x69, 0x6c, 0x6e, 0x65, 0x74,
0x12, 0x24, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10,
0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x66,
0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x0a,
0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6c,
0x69, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0b, 0x20, 0x01,
0x28, 0x09, 0x52, 0x0d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f,
0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x6f,
0x73, 0x12, 0x50, 0x0a, 0x13, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x6e,
0x65, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f,
0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x69,
0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52,
0x12, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x76,
0x69, 0x74, 0x79, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61,
0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74,
0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39,
0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, 0x74, 0x18, 0x0f, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08,
0x6c, 0x61, 0x73, 0x74, 0x53, 0x65, 0x65, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x6e,
0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x63, 0x6f, 0x6e,
0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x2a, 0x0a, 0x07, 0x74, 0x61, 0x69, 0x6c, 0x6e, 0x65,
0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61,
0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x66, 0x52, 0x07, 0x74, 0x61, 0x69, 0x6c, 0x6e,
0x65, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x10, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52,
0x65, 0x66, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73,
0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x25, 0x0a, 0x0e,
0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0b,
0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x56, 0x65, 0x72, 0x73,
0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52,
0x02, 0x6f, 0x73, 0x12, 0x50, 0x0a, 0x13, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f,
0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x1f, 0x2e, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43,
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09,
0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x12, 0x2e, 0x0a, 0x13, 0x6b, 0x65, 0x79,
0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x5f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64,
0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x6b, 0x65, 0x79, 0x45, 0x78, 0x70, 0x69, 0x72,
0x79, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x6e, 0x61,
0x62, 0x6c, 0x65, 0x64, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, 0x11, 0x20, 0x03, 0x28,
0x09, 0x52, 0x0d, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73,
0x12, 0x2b, 0x0a, 0x11, 0x61, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x64, 0x5f, 0x72,
0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, 0x12, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x61, 0x64, 0x76,
0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x64, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x30, 0x0a,
0x14, 0x61, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x64, 0x5f, 0x65, 0x78, 0x69, 0x74,
0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x13, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x61, 0x64, 0x76,
0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x64, 0x45, 0x78, 0x69, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x12,
0x2a, 0x0a, 0x11, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x5f,
0x6e, 0x6f, 0x64, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x65, 0x6e, 0x61, 0x62,
0x6c, 0x65, 0x64, 0x45, 0x78, 0x69, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x61,
0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x15, 0x20, 0x01, 0x28, 0x08, 0x52,
0x0a, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x22, 0x32, 0x0a, 0x12, 0x43,
0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74,
0x79, 0x52, 0x12, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74,
0x69, 0x76, 0x69, 0x74, 0x79, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64,
0x5f, 0x61, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65,
0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74,
0x12, 0x39, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, 0x74, 0x18, 0x0f,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
0x52, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x12, 0x2e, 0x0a, 0x13, 0x6b,
0x65, 0x79, 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x5f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c,
0x65, 0x64, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x6b, 0x65, 0x79, 0x45, 0x78, 0x70,
0x69, 0x72, 0x79, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x65,
0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, 0x11, 0x20,
0x03, 0x28, 0x09, 0x52, 0x0d, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x52, 0x6f, 0x75, 0x74,
0x65, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x61, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x64,
0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, 0x12, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x61,
0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x64, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12,
0x30, 0x0a, 0x14, 0x61, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x64, 0x5f, 0x65, 0x78,
0x69, 0x74, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x13, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x61,
0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x64, 0x45, 0x78, 0x69, 0x74, 0x4e, 0x6f, 0x64,
0x65, 0x12, 0x2a, 0x0a, 0x11, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x65, 0x78, 0x69,
0x74, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x65, 0x6e,
0x61, 0x62, 0x6c, 0x65, 0x64, 0x45, 0x78, 0x69, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x1e, 0x0a,
0x0a, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x15, 0x20, 0x01, 0x28,
0x08, 0x52, 0x0a, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x22, 0x32, 0x0a,
0x12, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x76,
0x69, 0x74, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73,
0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74,
0x73, 0x42, 0x3d, 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
0x6a, 0x73, 0x69, 0x65, 0x62, 0x65, 0x6e, 0x73, 0x2f, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c,
0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61,
0x6c, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x76, 0x31,
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
0x79, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x01,
0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x42,
0x3d, 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6a, 0x73,
0x69, 0x65, 0x62, 0x65, 0x6e, 0x73, 0x2f, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f,
0x70, 0x6b, 0x67, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65,
0x2f, 0x76, 0x31, 0x3b, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x76, 0x31, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
})
var (
file_ionscale_v1_machines_proto_rawDescOnce sync.Once
file_ionscale_v1_machines_proto_rawDescData = file_ionscale_v1_machines_proto_rawDesc
file_ionscale_v1_machines_proto_rawDescData []byte
)
func file_ionscale_v1_machines_proto_rawDescGZIP() []byte {
file_ionscale_v1_machines_proto_rawDescOnce.Do(func() {
file_ionscale_v1_machines_proto_rawDescData = protoimpl.X.CompressGZIP(file_ionscale_v1_machines_proto_rawDescData)
file_ionscale_v1_machines_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_ionscale_v1_machines_proto_rawDesc), len(file_ionscale_v1_machines_proto_rawDesc)))
})
return file_ionscale_v1_machines_proto_rawDescData
}
var file_ionscale_v1_machines_proto_msgTypes = make([]protoimpl.MessageInfo, 14)
var file_ionscale_v1_machines_proto_goTypes = []interface{}{
var file_ionscale_v1_machines_proto_msgTypes = make([]protoimpl.MessageInfo, 16)
var file_ionscale_v1_machines_proto_goTypes = []any{
(*ListMachinesRequest)(nil), // 0: ionscale.v1.ListMachinesRequest
(*ListMachinesResponse)(nil), // 1: ionscale.v1.ListMachinesResponse
(*DeleteMachineRequest)(nil), // 2: ionscale.v1.DeleteMachineRequest
@@ -946,20 +1014,22 @@ var file_ionscale_v1_machines_proto_goTypes = []interface{}{
(*GetMachineResponse)(nil), // 9: ionscale.v1.GetMachineResponse
(*AuthorizeMachineRequest)(nil), // 10: ionscale.v1.AuthorizeMachineRequest
(*AuthorizeMachineResponse)(nil), // 11: ionscale.v1.AuthorizeMachineResponse
(*Machine)(nil), // 12: ionscale.v1.Machine
(*ClientConnectivity)(nil), // 13: ionscale.v1.ClientConnectivity
(*timestamppb.Timestamp)(nil), // 14: google.protobuf.Timestamp
(*Ref)(nil), // 15: ionscale.v1.Ref
(*SetMachineNameRequest)(nil), // 12: ionscale.v1.SetMachineNameRequest
(*SetMachineNameResponse)(nil), // 13: ionscale.v1.SetMachineNameResponse
(*Machine)(nil), // 14: ionscale.v1.Machine
(*ClientConnectivity)(nil), // 15: ionscale.v1.ClientConnectivity
(*timestamppb.Timestamp)(nil), // 16: google.protobuf.Timestamp
(*Ref)(nil), // 17: ionscale.v1.Ref
}
var file_ionscale_v1_machines_proto_depIdxs = []int32{
12, // 0: ionscale.v1.ListMachinesResponse.machines:type_name -> ionscale.v1.Machine
12, // 1: ionscale.v1.GetMachineResponse.machine:type_name -> ionscale.v1.Machine
14, // 2: ionscale.v1.Machine.last_seen:type_name -> google.protobuf.Timestamp
15, // 3: ionscale.v1.Machine.tailnet:type_name -> ionscale.v1.Ref
15, // 4: ionscale.v1.Machine.user:type_name -> ionscale.v1.Ref
13, // 5: ionscale.v1.Machine.client_connectivity:type_name -> ionscale.v1.ClientConnectivity
14, // 6: ionscale.v1.Machine.created_at:type_name -> google.protobuf.Timestamp
14, // 7: ionscale.v1.Machine.expires_at:type_name -> google.protobuf.Timestamp
14, // 0: ionscale.v1.ListMachinesResponse.machines:type_name -> ionscale.v1.Machine
14, // 1: ionscale.v1.GetMachineResponse.machine:type_name -> ionscale.v1.Machine
16, // 2: ionscale.v1.Machine.last_seen:type_name -> google.protobuf.Timestamp
17, // 3: ionscale.v1.Machine.tailnet:type_name -> ionscale.v1.Ref
17, // 4: ionscale.v1.Machine.user:type_name -> ionscale.v1.Ref
15, // 5: ionscale.v1.Machine.client_connectivity:type_name -> ionscale.v1.ClientConnectivity
16, // 6: ionscale.v1.Machine.created_at:type_name -> google.protobuf.Timestamp
16, // 7: ionscale.v1.Machine.expires_at:type_name -> google.protobuf.Timestamp
8, // [8:8] is the sub-list for method output_type
8, // [8:8] is the sub-list for method input_type
8, // [8:8] is the sub-list for extension type_name
@@ -973,183 +1043,13 @@ func file_ionscale_v1_machines_proto_init() {
return
}
file_ionscale_v1_ref_proto_init()
if !protoimpl.UnsafeEnabled {
file_ionscale_v1_machines_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListMachinesRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_machines_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListMachinesResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_machines_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeleteMachineRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_machines_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeleteMachineResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_machines_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ExpireMachineRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_machines_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ExpireMachineResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_machines_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SetMachineKeyExpiryRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_machines_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SetMachineKeyExpiryResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_machines_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetMachineRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_machines_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetMachineResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_machines_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*AuthorizeMachineRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_machines_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*AuthorizeMachineResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_machines_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Machine); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_machines_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ClientConnectivity); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_ionscale_v1_machines_proto_rawDesc,
RawDescriptor: unsafe.Slice(unsafe.StringData(file_ionscale_v1_machines_proto_rawDesc), len(file_ionscale_v1_machines_proto_rawDesc)),
NumEnums: 0,
NumMessages: 14,
NumMessages: 16,
NumExtensions: 0,
NumServices: 0,
},
@@ -1158,7 +1058,6 @@ func file_ionscale_v1_machines_proto_init() {
MessageInfos: file_ionscale_v1_machines_proto_msgTypes,
}.Build()
File_ionscale_v1_machines_proto = out.File
file_ionscale_v1_machines_proto_rawDesc = nil
file_ionscale_v1_machines_proto_goTypes = nil
file_ionscale_v1_machines_proto_depIdxs = nil
}
+12 -29
View File
@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.32.0
// protoc-gen-go v1.36.5
// protoc (unknown)
// source: ionscale/v1/ref.proto
@@ -11,6 +11,7 @@ import (
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
@@ -21,22 +22,19 @@ const (
)
type Ref struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
Id uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *Ref) Reset() {
*x = Ref{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_ref_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Ref) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -46,7 +44,7 @@ func (*Ref) ProtoMessage() {}
func (x *Ref) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_ref_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -77,7 +75,7 @@ func (x *Ref) GetName() string {
var File_ionscale_v1_ref_proto protoreflect.FileDescriptor
var file_ionscale_v1_ref_proto_rawDesc = []byte{
var file_ionscale_v1_ref_proto_rawDesc = string([]byte{
0x0a, 0x15, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65,
0x66, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c,
0x65, 0x2e, 0x76, 0x31, 0x22, 0x29, 0x0a, 0x03, 0x52, 0x65, 0x66, 0x12, 0x0e, 0x0a, 0x02, 0x69,
@@ -88,22 +86,22 @@ var file_ionscale_v1_ref_proto_rawDesc = []byte{
0x70, 0x6b, 0x67, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65,
0x2f, 0x76, 0x31, 0x3b, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x76, 0x31, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
})
var (
file_ionscale_v1_ref_proto_rawDescOnce sync.Once
file_ionscale_v1_ref_proto_rawDescData = file_ionscale_v1_ref_proto_rawDesc
file_ionscale_v1_ref_proto_rawDescData []byte
)
func file_ionscale_v1_ref_proto_rawDescGZIP() []byte {
file_ionscale_v1_ref_proto_rawDescOnce.Do(func() {
file_ionscale_v1_ref_proto_rawDescData = protoimpl.X.CompressGZIP(file_ionscale_v1_ref_proto_rawDescData)
file_ionscale_v1_ref_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_ionscale_v1_ref_proto_rawDesc), len(file_ionscale_v1_ref_proto_rawDesc)))
})
return file_ionscale_v1_ref_proto_rawDescData
}
var file_ionscale_v1_ref_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_ionscale_v1_ref_proto_goTypes = []interface{}{
var file_ionscale_v1_ref_proto_goTypes = []any{
(*Ref)(nil), // 0: ionscale.v1.Ref
}
var file_ionscale_v1_ref_proto_depIdxs = []int32{
@@ -119,25 +117,11 @@ func file_ionscale_v1_ref_proto_init() {
if File_ionscale_v1_ref_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_ionscale_v1_ref_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Ref); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_ionscale_v1_ref_proto_rawDesc,
RawDescriptor: unsafe.Slice(unsafe.StringData(file_ionscale_v1_ref_proto_rawDesc), len(file_ionscale_v1_ref_proto_rawDesc)),
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
@@ -148,7 +132,6 @@ func file_ionscale_v1_ref_proto_init() {
MessageInfos: file_ionscale_v1_ref_proto_msgTypes,
}.Build()
File_ionscale_v1_ref_proto = out.File
file_ionscale_v1_ref_proto_rawDesc = nil
file_ionscale_v1_ref_proto_goTypes = nil
file_ionscale_v1_ref_proto_depIdxs = nil
}
+52 -219
View File
@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.32.0
// protoc-gen-go v1.36.5
// protoc (unknown)
// source: ionscale/v1/routes.proto
@@ -11,6 +11,7 @@ import (
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
@@ -21,21 +22,18 @@ const (
)
type GetMachineRoutesRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
MachineId uint64 `protobuf:"varint,1,opt,name=machine_id,json=machineId,proto3" json:"machine_id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetMachineRoutesRequest) Reset() {
*x = GetMachineRoutesRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_routes_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetMachineRoutesRequest) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -45,7 +43,7 @@ func (*GetMachineRoutesRequest) ProtoMessage() {}
func (x *GetMachineRoutesRequest) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_routes_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -68,22 +66,19 @@ func (x *GetMachineRoutesRequest) GetMachineId() uint64 {
}
type GetMachineRoutesResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
MachineId uint64 `protobuf:"varint,1,opt,name=machine_id,json=machineId,proto3" json:"machine_id,omitempty"`
Routes *MachineRoutes `protobuf:"bytes,2,opt,name=routes,proto3" json:"routes,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetMachineRoutesResponse) Reset() {
*x = GetMachineRoutesResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_routes_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetMachineRoutesResponse) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -93,7 +88,7 @@ func (*GetMachineRoutesResponse) ProtoMessage() {}
func (x *GetMachineRoutesResponse) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_routes_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -123,23 +118,20 @@ func (x *GetMachineRoutesResponse) GetRoutes() *MachineRoutes {
}
type EnableMachineRoutesRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
MachineId uint64 `protobuf:"varint,1,opt,name=machine_id,json=machineId,proto3" json:"machine_id,omitempty"`
Routes []string `protobuf:"bytes,2,rep,name=routes,proto3" json:"routes,omitempty"`
Replace bool `protobuf:"varint,3,opt,name=replace,proto3" json:"replace,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *EnableMachineRoutesRequest) Reset() {
*x = EnableMachineRoutesRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_routes_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *EnableMachineRoutesRequest) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -149,7 +141,7 @@ func (*EnableMachineRoutesRequest) ProtoMessage() {}
func (x *EnableMachineRoutesRequest) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_routes_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -186,22 +178,19 @@ func (x *EnableMachineRoutesRequest) GetReplace() bool {
}
type EnableMachineRoutesResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
MachineId uint64 `protobuf:"varint,1,opt,name=machine_id,json=machineId,proto3" json:"machine_id,omitempty"`
Routes *MachineRoutes `protobuf:"bytes,2,opt,name=routes,proto3" json:"routes,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *EnableMachineRoutesResponse) Reset() {
*x = EnableMachineRoutesResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_routes_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *EnableMachineRoutesResponse) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -211,7 +200,7 @@ func (*EnableMachineRoutesResponse) ProtoMessage() {}
func (x *EnableMachineRoutesResponse) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_routes_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -241,22 +230,19 @@ func (x *EnableMachineRoutesResponse) GetRoutes() *MachineRoutes {
}
type DisableMachineRoutesRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
MachineId uint64 `protobuf:"varint,1,opt,name=machine_id,json=machineId,proto3" json:"machine_id,omitempty"`
Routes []string `protobuf:"bytes,2,rep,name=routes,proto3" json:"routes,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *DisableMachineRoutesRequest) Reset() {
*x = DisableMachineRoutesRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_routes_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DisableMachineRoutesRequest) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -266,7 +252,7 @@ func (*DisableMachineRoutesRequest) ProtoMessage() {}
func (x *DisableMachineRoutesRequest) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_routes_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -296,22 +282,19 @@ func (x *DisableMachineRoutesRequest) GetRoutes() []string {
}
type DisableMachineRoutesResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
MachineId uint64 `protobuf:"varint,1,opt,name=machine_id,json=machineId,proto3" json:"machine_id,omitempty"`
Routes *MachineRoutes `protobuf:"bytes,2,opt,name=routes,proto3" json:"routes,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *DisableMachineRoutesResponse) Reset() {
*x = DisableMachineRoutesResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_routes_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DisableMachineRoutesResponse) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -321,7 +304,7 @@ func (*DisableMachineRoutesResponse) ProtoMessage() {}
func (x *DisableMachineRoutesResponse) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_routes_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -351,21 +334,18 @@ func (x *DisableMachineRoutesResponse) GetRoutes() *MachineRoutes {
}
type EnableExitNodeRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
MachineId uint64 `protobuf:"varint,1,opt,name=machine_id,json=machineId,proto3" json:"machine_id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *EnableExitNodeRequest) Reset() {
*x = EnableExitNodeRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_routes_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *EnableExitNodeRequest) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -375,7 +355,7 @@ func (*EnableExitNodeRequest) ProtoMessage() {}
func (x *EnableExitNodeRequest) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_routes_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -398,22 +378,19 @@ func (x *EnableExitNodeRequest) GetMachineId() uint64 {
}
type EnableExitNodeResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
MachineId uint64 `protobuf:"varint,1,opt,name=machine_id,json=machineId,proto3" json:"machine_id,omitempty"`
Routes *MachineRoutes `protobuf:"bytes,2,opt,name=routes,proto3" json:"routes,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *EnableExitNodeResponse) Reset() {
*x = EnableExitNodeResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_routes_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *EnableExitNodeResponse) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -423,7 +400,7 @@ func (*EnableExitNodeResponse) ProtoMessage() {}
func (x *EnableExitNodeResponse) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_routes_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -453,21 +430,18 @@ func (x *EnableExitNodeResponse) GetRoutes() *MachineRoutes {
}
type DisableExitNodeRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
MachineId uint64 `protobuf:"varint,1,opt,name=machine_id,json=machineId,proto3" json:"machine_id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *DisableExitNodeRequest) Reset() {
*x = DisableExitNodeRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_routes_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DisableExitNodeRequest) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -477,7 +451,7 @@ func (*DisableExitNodeRequest) ProtoMessage() {}
func (x *DisableExitNodeRequest) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_routes_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -500,22 +474,19 @@ func (x *DisableExitNodeRequest) GetMachineId() uint64 {
}
type DisableExitNodeResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
MachineId uint64 `protobuf:"varint,1,opt,name=machine_id,json=machineId,proto3" json:"machine_id,omitempty"`
Routes *MachineRoutes `protobuf:"bytes,2,opt,name=routes,proto3" json:"routes,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *DisableExitNodeResponse) Reset() {
*x = DisableExitNodeResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_routes_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DisableExitNodeResponse) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -525,7 +496,7 @@ func (*DisableExitNodeResponse) ProtoMessage() {}
func (x *DisableExitNodeResponse) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_routes_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -555,24 +526,21 @@ func (x *DisableExitNodeResponse) GetRoutes() *MachineRoutes {
}
type MachineRoutes struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
AdvertisedRoutes []string `protobuf:"bytes,1,rep,name=advertised_routes,json=advertisedRoutes,proto3" json:"advertised_routes,omitempty"`
EnabledRoutes []string `protobuf:"bytes,2,rep,name=enabled_routes,json=enabledRoutes,proto3" json:"enabled_routes,omitempty"`
AdvertisedExitNode bool `protobuf:"varint,3,opt,name=advertised_exit_node,json=advertisedExitNode,proto3" json:"advertised_exit_node,omitempty"`
EnabledExitNode bool `protobuf:"varint,4,opt,name=enabled_exit_node,json=enabledExitNode,proto3" json:"enabled_exit_node,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *MachineRoutes) Reset() {
*x = MachineRoutes{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_routes_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *MachineRoutes) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -582,7 +550,7 @@ func (*MachineRoutes) ProtoMessage() {}
func (x *MachineRoutes) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_routes_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -627,7 +595,7 @@ func (x *MachineRoutes) GetEnabledExitNode() bool {
var File_ionscale_v1_routes_proto protoreflect.FileDescriptor
var file_ionscale_v1_routes_proto_rawDesc = []byte{
var file_ionscale_v1_routes_proto_rawDesc = string([]byte{
0x0a, 0x18, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f,
0x75, 0x74, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x69, 0x6f, 0x6e, 0x73,
0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x22, 0x38, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x4d, 0x61,
@@ -706,22 +674,22 @@ var file_ionscale_v1_routes_proto_rawDesc = []byte{
0x65, 0x6e, 0x2f, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x69,
0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x33,
}
})
var (
file_ionscale_v1_routes_proto_rawDescOnce sync.Once
file_ionscale_v1_routes_proto_rawDescData = file_ionscale_v1_routes_proto_rawDesc
file_ionscale_v1_routes_proto_rawDescData []byte
)
func file_ionscale_v1_routes_proto_rawDescGZIP() []byte {
file_ionscale_v1_routes_proto_rawDescOnce.Do(func() {
file_ionscale_v1_routes_proto_rawDescData = protoimpl.X.CompressGZIP(file_ionscale_v1_routes_proto_rawDescData)
file_ionscale_v1_routes_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_ionscale_v1_routes_proto_rawDesc), len(file_ionscale_v1_routes_proto_rawDesc)))
})
return file_ionscale_v1_routes_proto_rawDescData
}
var file_ionscale_v1_routes_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
var file_ionscale_v1_routes_proto_goTypes = []interface{}{
var file_ionscale_v1_routes_proto_goTypes = []any{
(*GetMachineRoutesRequest)(nil), // 0: ionscale.v1.GetMachineRoutesRequest
(*GetMachineRoutesResponse)(nil), // 1: ionscale.v1.GetMachineRoutesResponse
(*EnableMachineRoutesRequest)(nil), // 2: ionscale.v1.EnableMachineRoutesRequest
@@ -752,145 +720,11 @@ func file_ionscale_v1_routes_proto_init() {
if File_ionscale_v1_routes_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_ionscale_v1_routes_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetMachineRoutesRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_routes_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetMachineRoutesResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_routes_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*EnableMachineRoutesRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_routes_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*EnableMachineRoutesResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_routes_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DisableMachineRoutesRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_routes_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DisableMachineRoutesResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_routes_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*EnableExitNodeRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_routes_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*EnableExitNodeResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_routes_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DisableExitNodeRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_routes_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DisableExitNodeResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_routes_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*MachineRoutes); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_ionscale_v1_routes_proto_rawDesc,
RawDescriptor: unsafe.Slice(unsafe.StringData(file_ionscale_v1_routes_proto_rawDesc), len(file_ionscale_v1_routes_proto_rawDesc)),
NumEnums: 0,
NumMessages: 11,
NumExtensions: 0,
@@ -901,7 +735,6 @@ func file_ionscale_v1_routes_proto_init() {
MessageInfos: file_ionscale_v1_routes_proto_msgTypes,
}.Build()
File_ionscale_v1_routes_proto = out.File
file_ionscale_v1_routes_proto_rawDesc = nil
file_ionscale_v1_routes_proto_goTypes = nil
file_ionscale_v1_routes_proto_depIdxs = nil
}
File diff suppressed because it is too large Load Diff
+27 -103
View File
@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.32.0
// protoc-gen-go v1.36.5
// protoc (unknown)
// source: ionscale/v1/users.proto
@@ -11,6 +11,7 @@ import (
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
@@ -21,23 +22,20 @@ const (
)
type User struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
Id uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
Role string `protobuf:"bytes,3,opt,name=role,proto3" json:"role,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *User) Reset() {
*x = User{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_users_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *User) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -47,7 +45,7 @@ func (*User) ProtoMessage() {}
func (x *User) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_users_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -84,21 +82,18 @@ func (x *User) GetRole() string {
}
type ListUsersRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
TailnetId uint64 `protobuf:"varint,1,opt,name=tailnet_id,json=tailnetId,proto3" json:"tailnet_id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListUsersRequest) Reset() {
*x = ListUsersRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_users_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ListUsersRequest) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -108,7 +103,7 @@ func (*ListUsersRequest) ProtoMessage() {}
func (x *ListUsersRequest) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_users_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -131,21 +126,18 @@ func (x *ListUsersRequest) GetTailnetId() uint64 {
}
type ListUsersResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
Users []*User `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListUsersResponse) Reset() {
*x = ListUsersResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_users_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ListUsersResponse) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -155,7 +147,7 @@ func (*ListUsersResponse) ProtoMessage() {}
func (x *ListUsersResponse) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_users_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -178,21 +170,18 @@ func (x *ListUsersResponse) GetUsers() []*User {
}
type DeleteUserRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
UserId uint64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *DeleteUserRequest) Reset() {
*x = DeleteUserRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_users_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DeleteUserRequest) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -202,7 +191,7 @@ func (*DeleteUserRequest) ProtoMessage() {}
func (x *DeleteUserRequest) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_users_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -225,19 +214,17 @@ func (x *DeleteUserRequest) GetUserId() uint64 {
}
type DeleteUserResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *DeleteUserResponse) Reset() {
*x = DeleteUserResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_users_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DeleteUserResponse) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -247,7 +234,7 @@ func (*DeleteUserResponse) ProtoMessage() {}
func (x *DeleteUserResponse) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_users_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -264,7 +251,7 @@ func (*DeleteUserResponse) Descriptor() ([]byte, []int) {
var File_ionscale_v1_users_proto protoreflect.FileDescriptor
var file_ionscale_v1_users_proto_rawDesc = []byte{
var file_ionscale_v1_users_proto_rawDesc = string([]byte{
0x0a, 0x17, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73,
0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x69, 0x6f, 0x6e, 0x73, 0x63,
0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x22, 0x3e, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x0e,
@@ -288,22 +275,22 @@ var file_ionscale_v1_users_proto_rawDesc = []byte{
0x67, 0x65, 0x6e, 0x2f, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x3b,
0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
}
})
var (
file_ionscale_v1_users_proto_rawDescOnce sync.Once
file_ionscale_v1_users_proto_rawDescData = file_ionscale_v1_users_proto_rawDesc
file_ionscale_v1_users_proto_rawDescData []byte
)
func file_ionscale_v1_users_proto_rawDescGZIP() []byte {
file_ionscale_v1_users_proto_rawDescOnce.Do(func() {
file_ionscale_v1_users_proto_rawDescData = protoimpl.X.CompressGZIP(file_ionscale_v1_users_proto_rawDescData)
file_ionscale_v1_users_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_ionscale_v1_users_proto_rawDesc), len(file_ionscale_v1_users_proto_rawDesc)))
})
return file_ionscale_v1_users_proto_rawDescData
}
var file_ionscale_v1_users_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
var file_ionscale_v1_users_proto_goTypes = []interface{}{
var file_ionscale_v1_users_proto_goTypes = []any{
(*User)(nil), // 0: ionscale.v1.User
(*ListUsersRequest)(nil), // 1: ionscale.v1.ListUsersRequest
(*ListUsersResponse)(nil), // 2: ionscale.v1.ListUsersResponse
@@ -324,73 +311,11 @@ func file_ionscale_v1_users_proto_init() {
if File_ionscale_v1_users_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_ionscale_v1_users_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*User); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_users_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListUsersRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_users_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListUsersResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_users_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeleteUserRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_users_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeleteUserResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_ionscale_v1_users_proto_rawDesc,
RawDescriptor: unsafe.Slice(unsafe.StringData(file_ionscale_v1_users_proto_rawDesc), len(file_ionscale_v1_users_proto_rawDesc)),
NumEnums: 0,
NumMessages: 5,
NumExtensions: 0,
@@ -401,7 +326,6 @@ func file_ionscale_v1_users_proto_init() {
MessageInfos: file_ionscale_v1_users_proto_msgTypes,
}.Build()
File_ionscale_v1_users_proto = out.File
file_ionscale_v1_users_proto_rawDesc = nil
file_ionscale_v1_users_proto_goTypes = nil
file_ionscale_v1_users_proto_depIdxs = nil
}
+15 -46
View File
@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.32.0
// protoc-gen-go v1.36.5
// protoc (unknown)
// source: ionscale/v1/version.proto
@@ -11,6 +11,7 @@ import (
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
@@ -21,19 +22,17 @@ const (
)
type GetVersionRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetVersionRequest) Reset() {
*x = GetVersionRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_version_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetVersionRequest) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -43,7 +42,7 @@ func (*GetVersionRequest) ProtoMessage() {}
func (x *GetVersionRequest) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_version_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -59,22 +58,19 @@ func (*GetVersionRequest) Descriptor() ([]byte, []int) {
}
type GetVersionResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"`
Revision string `protobuf:"bytes,2,opt,name=revision,proto3" json:"revision,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetVersionResponse) Reset() {
*x = GetVersionResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_ionscale_v1_version_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetVersionResponse) String() string {
return protoimpl.X.MessageStringOf(x)
@@ -84,7 +80,7 @@ func (*GetVersionResponse) ProtoMessage() {}
func (x *GetVersionResponse) ProtoReflect() protoreflect.Message {
mi := &file_ionscale_v1_version_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -115,7 +111,7 @@ func (x *GetVersionResponse) GetRevision() string {
var File_ionscale_v1_version_proto protoreflect.FileDescriptor
var file_ionscale_v1_version_proto_rawDesc = []byte{
var file_ionscale_v1_version_proto_rawDesc = string([]byte{
0x0a, 0x19, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x65,
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x69, 0x6f, 0x6e,
0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x22, 0x13, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x56,
@@ -129,22 +125,22 @@ var file_ionscale_v1_version_proto_rawDesc = []byte{
0x2f, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x65,
0x6e, 0x2f, 0x69, 0x6f, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x69, 0x6f,
0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
})
var (
file_ionscale_v1_version_proto_rawDescOnce sync.Once
file_ionscale_v1_version_proto_rawDescData = file_ionscale_v1_version_proto_rawDesc
file_ionscale_v1_version_proto_rawDescData []byte
)
func file_ionscale_v1_version_proto_rawDescGZIP() []byte {
file_ionscale_v1_version_proto_rawDescOnce.Do(func() {
file_ionscale_v1_version_proto_rawDescData = protoimpl.X.CompressGZIP(file_ionscale_v1_version_proto_rawDescData)
file_ionscale_v1_version_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_ionscale_v1_version_proto_rawDesc), len(file_ionscale_v1_version_proto_rawDesc)))
})
return file_ionscale_v1_version_proto_rawDescData
}
var file_ionscale_v1_version_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_ionscale_v1_version_proto_goTypes = []interface{}{
var file_ionscale_v1_version_proto_goTypes = []any{
(*GetVersionRequest)(nil), // 0: ionscale.v1.GetVersionRequest
(*GetVersionResponse)(nil), // 1: ionscale.v1.GetVersionResponse
}
@@ -161,37 +157,11 @@ func file_ionscale_v1_version_proto_init() {
if File_ionscale_v1_version_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_ionscale_v1_version_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetVersionRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_ionscale_v1_version_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetVersionResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_ionscale_v1_version_proto_rawDesc,
RawDescriptor: unsafe.Slice(unsafe.StringData(file_ionscale_v1_version_proto_rawDesc), len(file_ionscale_v1_version_proto_rawDesc)),
NumEnums: 0,
NumMessages: 2,
NumExtensions: 0,
@@ -202,7 +172,6 @@ func file_ionscale_v1_version_proto_init() {
MessageInfos: file_ionscale_v1_version_proto_msgTypes,
}.Build()
File_ionscale_v1_version_proto = out.File
file_ionscale_v1_version_proto_rawDesc = nil
file_ionscale_v1_version_proto_goTypes = nil
file_ionscale_v1_version_proto_depIdxs = nil
}
+1
View File
@@ -59,6 +59,7 @@ service IonscaleService {
rpc GetMachine(GetMachineRequest) returns (GetMachineResponse) {}
rpc ListMachines(ListMachinesRequest) returns (ListMachinesResponse) {}
rpc SetMachineName(SetMachineNameRequest) returns (SetMachineNameResponse) {}
rpc AuthorizeMachine(AuthorizeMachineRequest) returns (AuthorizeMachineResponse) {}
rpc ExpireMachine(ExpireMachineRequest) returns (ExpireMachineResponse) {}
rpc DeleteMachine(DeleteMachineRequest) returns (DeleteMachineResponse) {}
+8
View File
@@ -48,6 +48,14 @@ message AuthorizeMachineRequest {
message AuthorizeMachineResponse {}
message SetMachineNameRequest {
uint64 machine_id = 1;
bool use_os_hostname = 2;
string name = 3;
}
message SetMachineNameResponse {}
message Machine {
uint64 id = 1;
string name = 2;
+155 -59
View File
@@ -1,166 +1,262 @@
#!/bin/bash
set -e
# ionscale linux installation script
# This script automates the installation of ionscale on a Linux server with systemd
# Display functions
info() {
echo '[INFO] ->' "$@"
echo "===> [INFO]" "$@"
}
warn() {
echo "===> [WARN]" "$@"
}
fatal() {
echo '[ERROR] ->' "$@"
echo "===> [ERROR]" "$@"
exit 1
}
verify_system() {
if ! [ -d /run/systemd ]; then
fatal 'Can not find systemd to use as a process supervisor for ionscale'
fi
}
# Welcome message
echo "===================================================="
echo "ionscale Installation Script"
echo "===================================================="
setup_env() {
# Check for systemd
if ! [ -d /run/systemd ]; then
fatal "Cannot find systemd to use as a process supervisor for ionscale"
fi
# Check for root or sudo privileges
SUDO=sudo
if [ "$(id -u)" -eq 0 ]; then
SUDO=
info "Running as root"
else
info "Running with sudo"
fi
# Get required input
if [ -z "${IONSCALE_DOMAIN}" ]; then
fatal "env variable IONSCALE_DOMAIN is undefined"
read -p "Enter your ionscale domain (e.g. ionscale.example.com): " IONSCALE_DOMAIN
if [ -z "${IONSCALE_DOMAIN}" ]; then
fatal "Domain is required"
fi
fi
if [ -z "${IONSCALE_ACME_EMAIL}" ]; then
fatal "env variable IONSCALE_ACME_EMAIL is undefined"
read -p "Enter your email address (for Let's Encrypt notifications): " IONSCALE_ACME_EMAIL
if [ -z "${IONSCALE_ACME_EMAIL}" ]; then
fatal "Email address is required"
fi
fi
IONSCALE_VERSION=v0.12.0
# Set up directories and paths
IONSCALE_VERSION=v0.17.0
IONSCALE_DATA_DIR=/var/lib/ionscale
IONSCALE_CONFIG_DIR=/etc/ionscale
IONSCALE_SERVICE_FILE=/etc/systemd/system/ionscale.service
IONSCALE_ENV_FILE=/etc/default/ionscale
BIN_DIR=/usr/local/bin
}
# --- set arch and suffix, fatal if architecture not supported ---
setup_verify_arch() {
# --- Architecture detection ---
setup_arch() {
info "Detecting architecture"
if [ -z "$ARCH" ]; then
ARCH=$(uname -m)
fi
case $ARCH in
amd64)
amd64|x86_64)
SUFFIX=amd64
;;
x86_64)
SUFFIX=amd64
;;
arm64)
SUFFIX=arm64
;;
aarch64)
arm64|aarch64)
SUFFIX=arm64
;;
*)
fatal "Unsupported architecture $ARCH"
;;
esac
info "Architecture: $ARCH (using $SUFFIX)"
}
has_yum() {
[ -n "$(command -v yum)" ]
}
has_apt_get() {
[ -n "$(command -v apt-get)" ]
}
# --- Dependencies check ---
install_dependencies() {
info "Checking for dependencies"
if ! [ -x "$(command -v curl)" ]; then
if $(has_apt_get); then
info "Installing curl"
if [ -n "$(command -v apt-get)" ]; then
$SUDO apt-get update
$SUDO apt-get install -y curl
elif $(has_yum); then
elif [ -n "$(command -v yum)" ]; then
$SUDO yum install -y curl
else
fatal "Could not find apt-get or yum. Cannot install dependencies on this OS"
exit 1
fi
fi
}
# --- Create service user ---
create_service_user() {
info "Creating service user"
# Only create user if it doesn't exist
if ! id ionscale &>/dev/null; then
$SUDO useradd --system --no-create-home --shell /bin/false ionscale
info "Created user 'ionscale'"
else
fatal "User 'ionscale' already exists"
fi
}
# --- Binary installation ---
download_and_install() {
info "Downloading ionscale binary"
info "Downloading ionscale binary $IONSCALE_VERSION"
$SUDO curl -o "$BIN_DIR/ionscale" -sfL "https://github.com/jsiebens/ionscale/releases/download/${IONSCALE_VERSION}/ionscale_linux_${SUFFIX}"
$SUDO chmod +x "$BIN_DIR/ionscale"
# Verify installation
if [ -x "$BIN_DIR/ionscale" ]; then
info "ionscale binary installed successfully"
$SUDO $BIN_DIR/ionscale version
else
fatal "Failed to install ionscale binary"
fi
}
# --- Create configuration files ---
create_folders_and_config() {
$SUDO mkdir --parents ${IONSCALE_DATA_DIR}
$SUDO mkdir --parents ${IONSCALE_CONFIG_DIR}
info "Creating directories"
$SUDO mkdir -p ${IONSCALE_DATA_DIR}
$SUDO mkdir -p ${IONSCALE_CONFIG_DIR}
if [ ! -f "/etc/default/ionscale" ]; then
$SUDO tee /etc/default/ionscale >/dev/null <<EOF
IONSCALE_KEYS_SYSTEM_ADMIN_KEY=$($BIN_DIR/ionscale genkey -n)
# Set appropriate ownership
$SUDO chown ionscale:ionscale ${IONSCALE_DATA_DIR}
$SUDO chown ionscale:ionscale ${IONSCALE_CONFIG_DIR}
info "Generating system admin key"
ADMIN_KEY=$($BIN_DIR/ionscale genkey -n)
$SUDO tee $IONSCALE_ENV_FILE >/dev/null <<EOF
IONSCALE_KEYS_SYSTEM_ADMIN_KEY=$ADMIN_KEY
EOF
fi
info "Generated system admin key:"
echo "$ADMIN_KEY"
echo "IMPORTANT: Save this key securely. You'll need it to administer ionscale."
info "Creating configuration file"
$SUDO tee ${IONSCALE_CONFIG_DIR}/config.yaml >/dev/null <<EOF
http_listen_addr: ":80"
https_listen_addr: ":443"
metrics_listen_addr: 127.0.0.1:9090
server_url: "https://${IONSCALE_DOMAIN}"
listen_addr: ":443"
public_addr: "${IONSCALE_DOMAIN}:443"
stun_listen_addr: ":3478"
stun_public_addr: "${IONSCALE_DOMAIN}:3478"
tls:
acme: true
acme_email: "${IONSCALE_ACME_EMAIL}"
acme_path: "${IONSCALE_DATA_DIR}/acme"
database:
type: sqlite
url: "${IONSCALE_DATA_DIR}/ionscale.db?_pragma=busy_timeout(5000)&_pragma=journal_mode(WAL)&_pragma=foreign_keys(ON)"
keys:
system_admin_key: "\${IONSCALE_KEYS_SYSTEM_ADMIN_KEY}"
logging:
level: info
EOF
info "Configuration created at ${IONSCALE_CONFIG_DIR}/config.yaml"
}
# --- write systemd service file ---
# --- Create systemd service file ---
create_systemd_service_file() {
info "Adding systemd service file ${IONSCALE_SERVICE_FILE}"
info "Creating systemd service file ${IONSCALE_SERVICE_FILE}"
$SUDO tee ${IONSCALE_SERVICE_FILE} >/dev/null <<EOF
[Unit]
Description=ionscale - a Tailscale Controller server
After=syslog.target
Description=ionscale - a Tailscale control server
Requires=network-online.target
After=network.target
[Service]
EnvironmentFile=/etc/default/ionscale
User=ionscale
Group=ionscale
ExecStart=${BIN_DIR}/ionscale server --config ${IONSCALE_CONFIG_DIR}/config.yaml
Restart=on-failure
RestartSec=10s
AmbientCapabilities=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target
EOF
}
# --- startup systemd service ---
# --- Enable and start service ---
systemd_enable_and_start() {
[ "${SKIP_ENABLE}" = true ] && return
if [ "${SKIP_ENABLE}" = true ]; then
info "Skipping service enablement (SKIP_ENABLE=true)"
return
fi
info "Enabling systemd service"
$SUDO systemctl enable ${IONSCALE_SERVICE_FILE} >/dev/null
$SUDO systemctl daemon-reload >/dev/null
$SUDO systemctl enable ${IONSCALE_SERVICE_FILE} >/dev/null
[ "${SKIP_START}" = true ] && return
if [ "${SKIP_START}" = true ]; then
info "Skipping service start (SKIP_START=true)"
return
fi
info "Starting systemd service"
info "Starting ionscale service"
$SUDO systemctl restart ionscale
return 0
# Check service status
ATTEMPTS=0
MAX_ATTEMPTS=5
DELAY=2
while [ $ATTEMPTS -lt $MAX_ATTEMPTS ]; do
if $SUDO systemctl is-active --quiet ionscale; then
info "ionscale service is running"
break
else
ATTEMPTS=$((ATTEMPTS + 1))
if [ $ATTEMPTS -eq $MAX_ATTEMPTS ]; then
warn "ionscale service failed to start. Check status with: sudo systemctl status ionscale"
else
info "Waiting for service to start ($ATTEMPTS/$MAX_ATTEMPTS)..."
sleep $DELAY
fi
fi
done
}
setup_env
setup_verify_arch
verify_system
# Main execution sequence
setup_arch
install_dependencies
create_service_user
download_and_install
create_folders_and_config
create_systemd_service_file
systemd_enable_and_start
# Completion message
echo
echo "===================================================="
echo "ionscale installation complete!"
echo "===================================================="
echo
echo "Your ionscale instance is now available at: https://${IONSCALE_DOMAIN}"
echo
echo "Next steps:"
echo "1. Configure OIDC authentication if needed"
echo "2. Set up DNS provider if needed"
echo "3. Create your first tailnet"
echo
echo "To view logs: sudo journalctl -u ionscale -f"
echo "To restart the service: sudo systemctl restart ionscale"
echo
echo "Configure ionscale CLI:"
echo "export IONSCALE_ADDR=https://${IONSCALE_DOMAIN}"
echo "export IONSCALE_SYSTEM_ADMIN_KEY=${ADMIN_KEY}"
echo "Then you can run: ionscale tailnets list"
+136
View File
@@ -0,0 +1,136 @@
package tests
import (
"github.com/jsiebens/ionscale/pkg/client/ionscale"
"github.com/jsiebens/ionscale/pkg/defaults"
"github.com/jsiebens/ionscale/tests/sc"
"github.com/jsiebens/ionscale/tests/tsn"
"github.com/stretchr/testify/require"
"net/netip"
"testing"
)
func TestAdvertiseRoutesAutoApprovedOnNewNode(t *testing.T) {
route1 := netip.MustParsePrefix("10.1.0.0/24")
route2 := netip.MustParsePrefix("10.2.0.0/24")
sc.Run(t, func(s *sc.Scenario) {
aclPolicy := defaults.DefaultACLPolicy()
aclPolicy.AutoApprovers = &ionscale.ACLAutoApprovers{
Routes: map[string][]string{
route1.String(): {"tag:test-route"},
},
}
tailnet := s.CreateTailnet()
s.SetACLPolicy(tailnet.Id, aclPolicy)
testNode := s.NewTailscaleNode()
require.NoError(t, testNode.Up(
s.CreateAuthKey(tailnet.Id, true, "tag:test-route"),
tsn.WithAdvertiseTags("tag:test-route"),
tsn.WithAdvertiseRoutes([]string{
route1.String(),
route2.String()},
),
))
require.NoError(t, testNode.WaitFor(tsn.HasTailnet(tailnet.Name)))
mid, err := s.FindMachine(tailnet.Id, testNode.Hostname())
require.NoError(t, err)
machineRoutes := s.GetMachineRoutes(mid)
require.NoError(t, err)
require.Equal(t, []string{route1.String(), route2.String()}, machineRoutes.AdvertisedRoutes)
require.Equal(t, []string{route1.String()}, machineRoutes.EnabledRoutes)
require.NoError(t, testNode.Check(tsn.HasAllowedIP(route1)))
require.NoError(t, testNode.Check(tsn.IsMissingAllowedIP(route2)))
})
}
func TestAdvertiseRoutesAutoApprovedOnExistingNode(t *testing.T) {
route1 := netip.MustParsePrefix("10.1.0.0/24")
route2 := netip.MustParsePrefix("10.2.0.0/24")
route3 := netip.MustParsePrefix("10.3.0.0/24")
sc.Run(t, func(s *sc.Scenario) {
aclPolicy := defaults.DefaultACLPolicy()
aclPolicy.AutoApprovers = &ionscale.ACLAutoApprovers{
Routes: map[string][]string{
route1.String(): {"tag:test-route"},
route3.String(): {"tag:test-route"},
},
}
tailnet := s.CreateTailnet()
s.SetACLPolicy(tailnet.Id, aclPolicy)
testNode := s.NewTailscaleNode()
require.NoError(t, testNode.Up(
s.CreateAuthKey(tailnet.Id, true, "tag:test-route"),
tsn.WithAdvertiseTags("tag:test-route"),
))
require.NoError(t, testNode.Check(tsn.HasTailnet(tailnet.Name)))
testNode.Set(tsn.WithAdvertiseRoutes([]string{
route3.String(),
route1.String(),
route2.String()},
))
require.NoError(t, testNode.WaitFor(tsn.HasAllowedIP(route1)))
require.NoError(t, testNode.WaitFor(tsn.HasAllowedIP(route3)))
require.NoError(t, testNode.WaitFor(tsn.IsMissingAllowedIP(route2)))
mid, err := s.FindMachine(tailnet.Id, testNode.Hostname())
require.NoError(t, err)
machineRoutes := s.GetMachineRoutes(mid)
require.NoError(t, err)
require.Equal(t, []string{route1.String(), route2.String(), route3.String()}, machineRoutes.AdvertisedRoutes)
require.Equal(t, []string{route1.String(), route3.String()}, machineRoutes.EnabledRoutes)
})
}
func TestAdvertiseRemoveRoutesAutoApprovedOnExistingNode(t *testing.T) {
route1 := netip.MustParsePrefix("10.1.0.0/24")
route2 := netip.MustParsePrefix("10.2.0.0/24")
sc.Run(t, func(s *sc.Scenario) {
aclPolicy := defaults.DefaultACLPolicy()
aclPolicy.AutoApprovers = &ionscale.ACLAutoApprovers{
Routes: map[string][]string{
route1.String(): {"tag:test-route"},
route2.String(): {"tag:test-route"},
},
}
tailnet := s.CreateTailnet()
s.SetACLPolicy(tailnet.Id, aclPolicy)
testNode := s.NewTailscaleNode()
require.NoError(t, testNode.Up(
s.CreateAuthKey(tailnet.Id, true, "tag:test-route"),
tsn.WithAdvertiseTags("tag:test-route"),
tsn.WithAdvertiseRoutes([]string{
route1.String(),
route2.String()},
),
))
require.NoError(t, testNode.WaitFor(tsn.HasTailnet(tailnet.Name)))
require.NoError(t, testNode.Check(tsn.HasAllowedIP(route1)))
require.NoError(t, testNode.Check(tsn.HasAllowedIP(route2)))
testNode.Set(tsn.WithAdvertiseRoutes([]string{
route1.String(),
}))
require.NoError(t, testNode.WaitFor(tsn.IsMissingAllowedIP(route2)))
})
}
+1 -1
View File
@@ -1,4 +1,4 @@
FROM golang:1.22-bullseye as builder
FROM golang:1.24-bullseye as builder
WORKDIR /app
+13
View File
@@ -80,3 +80,16 @@ func TestNodeWithSameHostname(t *testing.T) {
}, machines)
})
}
func TestNodeShouldSeeAssignedTags(t *testing.T) {
sc.Run(t, func(s *sc.Scenario) {
tailnet := s.CreateTailnet()
key := s.CreateAuthKey(tailnet.Id, true, "tag:server")
nodeA := s.NewTailscaleNode()
require.NoError(t, nodeA.Up(key, tsn.WithAdvertiseTags("tag:test")))
require.NoError(t, nodeA.WaitFor(tsn.HasTag("tag:server")))
require.NoError(t, nodeA.WaitFor(tsn.HasTag("tag:test")))
})
}
+27
View File
@@ -85,6 +85,23 @@ func (s *Scenario) ExpireMachines(tailnetID uint64) {
}
}
func (s *Scenario) FindMachine(tailnetID uint64, name string) (uint64, error) {
machines := s.ListMachines(tailnetID)
for _, m := range machines {
if m.Name == name {
return m.Id, nil
}
}
return 0, fmt.Errorf("machine %s not found", name)
}
func (s *Scenario) SetMachineName(machineID uint64, useOSHostname bool, name string) error {
req := &api.SetMachineNameRequest{MachineId: machineID, UseOsHostname: useOSHostname, Name: name}
_, err := s.ionscaleClient.SetMachineName(context.Background(), connect.NewRequest(req))
return err
}
func (s *Scenario) SetACLPolicy(tailnetID uint64, policy *ionscaleclt.ACLPolicy) {
_, err := s.ionscaleClient.SetACLPolicy(context.Background(), connect.NewRequest(&api.SetACLPolicyRequest{TailnetId: tailnetID, Policy: policy.Marshal()}))
require.NoError(s.t, err)
@@ -100,6 +117,12 @@ func (s *Scenario) EnableMachineAutorization(tailnetID uint64) {
require.NoError(s.t, err)
}
func (s *Scenario) GetMachineRoutes(machineID uint64) *api.MachineRoutes {
routes, err := s.ionscaleClient.GetMachineRoutes(context.Background(), connect.NewRequest(&api.GetMachineRoutesRequest{MachineId: machineID}))
require.NoError(s.t, err)
return routes.Msg.Routes
}
func (s *Scenario) PushOIDCUser(sub, email, preferredUsername string) {
_, err := s.mockoidcClient.PushUser(context.Background(), connect.NewRequest(&mockoidcv1.PushUserRequest{Subject: sub, Email: email, PreferredUsername: preferredUsername}))
require.NoError(s.t, err)
@@ -136,6 +159,10 @@ type TailscaleNodeConfig struct {
type TailscaleNodeOpt = func(*TailscaleNodeConfig)
func RandomName() string {
return petname.Generate(3, "-")
}
func WithName(name string) TailscaleNodeOpt {
return func(config *TailscaleNodeConfig) {
config.Hostname = name
+89
View File
@@ -0,0 +1,89 @@
package tests
import (
"github.com/jsiebens/ionscale/tests/sc"
"github.com/jsiebens/ionscale/tests/tsn"
"github.com/stretchr/testify/require"
"testing"
)
func TestNewHostnameShouldPropagateToPeersWhenSet(t *testing.T) {
sc.Run(t, func(s *sc.Scenario) {
tailnet := s.CreateTailnet()
key := s.CreateAuthKey(tailnet.Id, true)
initialName := sc.RandomName()
nodeA := s.NewTailscaleNode()
nodeB := s.NewTailscaleNode(sc.WithName(initialName))
require.NoError(t, nodeA.Up(key))
require.NoError(t, nodeB.Up(key))
require.NoError(t, nodeA.WaitFor(tsn.HasPeer(initialName)))
newName := sc.RandomName()
require.NoError(t, nodeB.SetHostname(newName))
require.NoError(t, nodeA.WaitFor(tsn.HasPeer(newName)))
})
}
func TestSetHostname(t *testing.T) {
sc.Run(t, func(s *sc.Scenario) {
tailnet := s.CreateTailnet()
key := s.CreateAuthKey(tailnet.Id, true)
initialName := sc.RandomName()
nodeA := s.NewTailscaleNode()
nodeB := s.NewTailscaleNode(sc.WithName(initialName))
require.NoError(t, nodeA.Up(key))
require.NoError(t, nodeB.Up(key))
require.NoError(t, nodeA.WaitFor(tsn.HasPeer(initialName)))
mid, err := s.FindMachine(tailnet.Id, initialName)
require.NoError(t, err)
newName := sc.RandomName()
require.NoError(t, s.SetMachineName(mid, false, newName))
require.NoError(t, nodeA.WaitFor(tsn.HasPeer(newName)))
require.NoError(t, s.SetMachineName(mid, true, ""))
require.NoError(t, nodeA.WaitFor(tsn.HasPeer(initialName)))
})
}
func TestSetHostnameWhenNameAlreadyInUse(t *testing.T) {
sc.Run(t, func(s *sc.Scenario) {
tailnet := s.CreateTailnet()
key := s.CreateAuthKey(tailnet.Id, true)
nodeA := s.NewTailscaleNode(sc.WithName("node-a"))
nodeB := s.NewTailscaleNode(sc.WithName("node-b"))
require.NoError(t, nodeA.Up(key))
require.NoError(t, nodeB.Up(key))
require.NoError(t, nodeA.WaitFor(tsn.PeerCount(1)))
require.NoError(t, nodeB.WaitFor(tsn.PeerCount(1)))
mida, err := s.FindMachine(tailnet.Id, "node-a")
require.NoError(t, err)
midb, err := s.FindMachine(tailnet.Id, "node-b")
require.NoError(t, err)
newName := sc.RandomName()
require.NoError(t, s.SetMachineName(mida, false, newName))
require.NoError(t, nodeB.WaitFor(tsn.HasPeer(newName)))
err = s.SetMachineName(midb, false, newName)
require.ErrorContains(t, err, "machine name already in use")
})
}
+30
View File
@@ -1,6 +1,7 @@
package tsn
import (
"net/netip"
"slices"
"strings"
"tailscale.com/ipn/ipnstate"
@@ -60,6 +61,24 @@ func HasUser(email string) Condition {
}
}
func HasAllowedIP(route netip.Prefix) Condition {
return func(status *ipnstate.Status) bool {
if status.Self == nil || status.Self.AllowedIPs.Len() == 0 {
return false
}
return slices.Contains(status.Self.AllowedIPs.AsSlice(), route)
}
}
func IsMissingAllowedIP(route netip.Prefix) Condition {
return func(status *ipnstate.Status) bool {
if status.Self == nil || status.Self.AllowedIPs.Len() == 0 {
return true
}
return !slices.Contains(status.Self.AllowedIPs.AsSlice(), route)
}
}
func PeerCount(expected int) Condition {
return func(status *ipnstate.Status) bool {
return len(status.Peers()) == expected
@@ -77,6 +96,17 @@ func HasExpiredPeer(name string) Condition {
}
}
func HasPeer(name string) Condition {
return func(status *ipnstate.Status) bool {
for _, peer := range status.Peer {
if strings.HasPrefix(peer.DNSName, name) {
return true
}
}
return false
}
}
func HasCapability(capability tailcfg.NodeCapability) Condition {
return func(status *ipnstate.Status) bool {
self := status.Self
+24 -2
View File
@@ -38,11 +38,25 @@ func (t *TailscaleNode) Hostname() string {
return t.hostname
}
func (t *TailscaleNode) Up(authkey string) error {
t.mustExecTailscaleCmd("up", "--login-server", t.loginServer, "--authkey", authkey)
func (t *TailscaleNode) Up(authkey string, flags ...UpFlag) error {
cmd := []string{"up", "--login-server", t.loginServer, "--authkey", authkey}
for _, f := range flags {
cmd = append(cmd, f...)
}
t.mustExecTailscaleCmd(cmd...)
return t.WaitFor(Connected())
}
func (t *TailscaleNode) Set(flags ...UpFlag) string {
cmd := []string{"set"}
for _, f := range flags {
cmd = append(cmd, f...)
}
return t.mustExecTailscaleCmd(cmd...)
}
func (t *TailscaleNode) LoginWithOidc(flags ...UpFlag) (int, error) {
check := func(stdout, stderr string) bool {
return strings.Contains(stderr, "To authenticate, visit:")
@@ -148,6 +162,14 @@ func (t *TailscaleNode) Ping(target string) error {
return nil
}
func (t *TailscaleNode) SetHostname(hostname string) error {
_, _, err := t.execTailscaleCmd("set", "--hostname", hostname)
if err != nil {
return err
}
return nil
}
func (t *TailscaleNode) NetCheck() (*netcheck.Report, error) {
result, _, err := t.execTailscaleCmd("netcheck", "--format=json")
if err != nil {
+6
View File
@@ -1,7 +1,13 @@
package tsn
import "strings"
type UpFlag = []string
func WithAdvertiseTags(tags string) UpFlag {
return []string{"--advertise-tags", tags}
}
func WithAdvertiseRoutes(routes []string) UpFlag {
return []string{"--advertise-routes", strings.Join(routes, ",")}
}