Compare commits
1 Commits
v2023.3.27
...
auth
Author | SHA1 | Date | |
---|---|---|---|
ee69644699 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -9,4 +9,3 @@ dist/
|
||||
/agent-key.json
|
||||
/apps
|
||||
/server-key.json
|
||||
/.emissary-token
|
@ -2,7 +2,6 @@ project_name: emissary
|
||||
before:
|
||||
hooks:
|
||||
- go mod tidy
|
||||
- go generate ./...
|
||||
builds:
|
||||
- id: emissary-server
|
||||
env:
|
||||
@ -46,9 +45,6 @@ builds:
|
||||
- arm64
|
||||
- arm
|
||||
- "386"
|
||||
goarm:
|
||||
- "6"
|
||||
- "7"
|
||||
main: ./cmd/agent
|
||||
archives:
|
||||
- id: server
|
||||
@ -67,7 +63,7 @@ archives:
|
||||
checksum:
|
||||
name_template: 'checksums.txt'
|
||||
snapshot:
|
||||
name_template: "{{ .Version }}"
|
||||
name_template: "{{ incpatch .Version }}-next"
|
||||
changelog:
|
||||
sort: asc
|
||||
filters:
|
||||
|
21
Makefile
21
Makefile
@ -1,16 +1,14 @@
|
||||
LINT_ARGS ?= --timeout 5m
|
||||
GORELEASER_VERSION ?= v1.13.1
|
||||
GORELEASER_ARGS ?= release --snapshot --rm-dist
|
||||
GORELEASER_ARGS ?= release --auto-snapshot --snapshot --rm-dist
|
||||
GITCHLOG_ARGS ?=
|
||||
SHELL := /bin/bash
|
||||
|
||||
EMISSARY_VERSION ?=
|
||||
GIT_VERSION := $(shell git describe --always)
|
||||
DATE_VERSION := $(shell date +%Y.%-m.%-d)
|
||||
FULL_VERSION := v$(DATE_VERSION)-$(GIT_VERSION)$(if $(shell git diff --stat),-dirty,)
|
||||
GIT_VERSION ?= $(shell git describe --always)
|
||||
|
||||
DOCKER_IMAGE_NAME ?= bornholm/emissary
|
||||
DOCKER_IMAGE_TAG ?= $(FULL_VERSION)
|
||||
DOCKER_IMAGE_TAG ?= $(GIT_VERSION)$(if $(shell git diff --stat),-dirty,)
|
||||
|
||||
GOTEST_ARGS ?= -short
|
||||
|
||||
@ -45,7 +43,7 @@ build-emissary-%: deps ## Build executable
|
||||
-v \
|
||||
-ldflags "\
|
||||
-X 'main.GitRef=$(shell git rev-parse --short HEAD)' \
|
||||
-X 'main.ProjectVersion=$(FULL_VERSION)' \
|
||||
-X 'main.ProjectVersion=$(shell git describe --always)' \
|
||||
-X 'main.BuildDate=$(shell date --utc --rfc-3339=seconds)' \
|
||||
" \
|
||||
-o ./bin/$* \
|
||||
@ -75,7 +73,7 @@ dump-config: build-emissary
|
||||
|
||||
.PHONY: goreleaser
|
||||
goreleaser: deps
|
||||
( set -o allexport && source .env && set +o allexport && VERSION=$(GORELEASER_VERSION) curl -sfL https://goreleaser.com/static/run | GORELEASER_CURRENT_TAG="$(FULL_VERSION)" bash /dev/stdin $(GORELEASER_ARGS) )
|
||||
( set -o allexport && source .env && set +o allexport && VERSION=$(GORELEASER_VERSION) curl -sfL https://goreleaser.com/static/run | bash /dev/stdin $(GORELEASER_ARGS) )
|
||||
|
||||
.PHONY: start-release
|
||||
start-release:
|
||||
@ -124,14 +122,12 @@ gitea-release: tools/gitea-release/bin/gitea-release.sh goreleaser
|
||||
rm -rf .gitea-release/*
|
||||
|
||||
cp dist/*.tar.gz .gitea-release/
|
||||
cp dist/*.apk .gitea-release/
|
||||
cp dist/*.deb .gitea-release/
|
||||
|
||||
GITEA_RELEASE_PROJECT="emissary" \
|
||||
GITEA_RELEASE_ORG="arcad" \
|
||||
GITEA_RELEASE_BASE_URL="https://forge.cadoles.com" \
|
||||
GITEA_RELEASE_VERSION="$(FULL_VERSION)" \
|
||||
GITEA_RELEASE_NAME="$(FULL_VERSION)" \
|
||||
GITEA_RELEASE_VERSION="$(GIT_VERSION)" \
|
||||
GITEA_RELEASE_NAME="$(GIT_VERSION)" \
|
||||
GITEA_RELEASE_COMMITISH_TARGET="$(GIT_VERSION)" \
|
||||
GITEA_RELEASE_IS_DRAFT="false" \
|
||||
GITEA_RELEASE_BODY="" \
|
||||
@ -142,6 +138,3 @@ tools/gitea-release/bin/gitea-release.sh:
|
||||
mkdir -p tools/gitea-release/bin
|
||||
curl --output tools/gitea-release/bin/gitea-release.sh https://forge.cadoles.com/Cadoles/Jenkins/raw/branch/master/resources/com/cadoles/gitea/gitea-release.sh
|
||||
chmod +x tools/gitea-release/bin/gitea-release.sh
|
||||
|
||||
.emissary-token:
|
||||
$(MAKE) run-emissary-server EMISSARY_CMD="--debug --config tmp/server.yml server auth create-token --role writer > .emissary-token"
|
@ -5,9 +5,7 @@ import (
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/agent"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/api"
|
||||
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/imports/spec"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/client"
|
||||
)
|
||||
|
||||
// nolint: gochecknoglobals
|
||||
@ -19,5 +17,5 @@ var (
|
||||
)
|
||||
|
||||
func main() {
|
||||
command.Main(BuildDate, ProjectVersion, GitRef, DefaultConfigPath, agent.Root(), api.Root())
|
||||
command.Main(BuildDate, ProjectVersion, GitRef, DefaultConfigPath, agent.Root(), client.Root())
|
||||
}
|
||||
|
@ -4,12 +4,11 @@ import (
|
||||
"time"
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/api"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/client"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/server"
|
||||
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/imports/format"
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/imports/spec"
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/imports/sql"
|
||||
_ "github.com/jackc/pgx/v5/stdlib"
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
||||
|
||||
// nolint: gochecknoglobals
|
||||
@ -21,5 +20,5 @@ var (
|
||||
)
|
||||
|
||||
func main() {
|
||||
command.Main(BuildDate, ProjectVersion, GitRef, DefaultConfigPath, server.Root(), api.Root())
|
||||
command.Main(BuildDate, ProjectVersion, GitRef, DefaultConfigPath, server.Root(), client.Root())
|
||||
}
|
||||
|
@ -10,12 +10,6 @@
|
||||
|
||||
[See `misc/rest/server.rest`](../misc/rest/server.rest)
|
||||
|
||||
### Spécifications
|
||||
|
||||
- [Schéma `app.emissary.cadoles.com`](../internal/spec/app/schema.json)
|
||||
- [Schéma `uci.emissary.cadoles.com`](../internal/spec/uci/schema.json)
|
||||
- [Schéma `gateway.emissary.cadoles.com`](../internal/spec/gateway/schema.json)
|
||||
|
||||
### Configuration
|
||||
|
||||
See:
|
||||
|
32
go.mod
32
go.mod
@ -3,25 +3,23 @@ module forge.cadoles.com/Cadoles/emissary
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
forge.cadoles.com/arcad/edge v0.0.0-20230322170544-cf8a3f8ac077
|
||||
forge.cadoles.com/arcad/edge v0.0.0-20230303153719-6399196fe5c9
|
||||
github.com/alecthomas/participle/v2 v2.0.0-beta.5
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883
|
||||
github.com/btcsuite/btcd/btcutil v1.1.3
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/denisbrodbeck/machineid v1.0.1
|
||||
github.com/dop251/goja v0.0.0-20230304130813-e2f543bf4b4c
|
||||
github.com/evanphx/json-patch/v5 v5.6.0
|
||||
github.com/go-chi/chi v4.1.2+incompatible
|
||||
github.com/go-chi/cors v1.2.1
|
||||
github.com/golang-migrate/migrate/v4 v4.15.2
|
||||
github.com/jackc/pgx/v5 v5.3.1
|
||||
github.com/jedib0t/go-pretty/v6 v6.4.4
|
||||
github.com/lestrrat-go/jwx/v2 v2.0.9
|
||||
github.com/lithammer/shortuuid/v4 v4.0.0
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2
|
||||
github.com/lestrrat-go/jwx/v2 v2.0.8
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/qri-io/jsonschema v0.2.1
|
||||
github.com/santhosh-tekuri/jsonschema/v5 v5.1.1
|
||||
github.com/urfave/cli/v2 v2.24.4
|
||||
gitlab.com/wpetit/goweb v0.0.0-20230227162855-a1f09bafccb3
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
@ -30,34 +28,34 @@ require (
|
||||
|
||||
require (
|
||||
github.com/barnybug/go-cast v0.0.0-20201201064555-a87ccbc26692 // indirect
|
||||
github.com/dop251/goja_nodejs v0.0.0-20230320130059-dcf93ba651dd // indirect
|
||||
github.com/dop251/goja v0.0.0-20230226152633-7c93113e17ac // indirect
|
||||
github.com/dop251/goja_nodejs v0.0.0-20230226152057-060fa99b809f // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.1 // indirect
|
||||
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/google/pprof v0.0.0-20230309165930-d61513b1440d // indirect
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/hashicorp/mdns v1.0.5 // indirect
|
||||
github.com/igm/sockjs-go/v3 v3.0.2 // indirect
|
||||
github.com/miekg/dns v1.1.51 // indirect
|
||||
github.com/oklog/ulid/v2 v2.1.0 // indirect
|
||||
github.com/orcaman/concurrent-map v1.0.0 // indirect
|
||||
golang.org/x/net v0.8.0 // indirect
|
||||
golang.org/x/net v0.7.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20220728213248-dd149ef739b9 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
cdr.dev/slog v1.4.2 // indirect
|
||||
cdr.dev/slog v1.4.1 // indirect
|
||||
github.com/alecthomas/chroma v0.10.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect
|
||||
github.com/dlclark/regexp2 v1.8.1 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/fatih/color v1.15.0 // indirect
|
||||
github.com/fatih/color v1.14.1 // indirect
|
||||
github.com/go-chi/chi/v5 v5.0.8
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/goccy/go-json v0.9.11 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
@ -71,7 +69,7 @@ require (
|
||||
github.com/lestrrat-go/httpcc v1.0.1 // indirect
|
||||
github.com/lestrrat-go/httprc v1.0.4 // indirect
|
||||
github.com/lestrrat-go/iter v1.0.2 // indirect
|
||||
github.com/lestrrat-go/option v1.0.1 // indirect
|
||||
github.com/lestrrat-go/option v1.0.0 // indirect
|
||||
github.com/lib/pq v1.10.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||
@ -85,12 +83,12 @@ require (
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.uber.org/atomic v1.10.0 // indirect
|
||||
golang.org/x/crypto v0.7.0 // indirect
|
||||
golang.org/x/crypto v0.6.0 // indirect
|
||||
golang.org/x/mod v0.8.0 // indirect
|
||||
golang.org/x/sync v0.1.0 // indirect
|
||||
golang.org/x/sys v0.6.0 // indirect
|
||||
golang.org/x/term v0.6.0 // indirect
|
||||
golang.org/x/text v0.8.0 // indirect
|
||||
golang.org/x/sys v0.5.0 // indirect
|
||||
golang.org/x/term v0.5.0 // indirect
|
||||
golang.org/x/text v0.7.0 // indirect
|
||||
golang.org/x/tools v0.6.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
@ -105,5 +103,3 @@ require (
|
||||
modernc.org/strutil v1.1.3 // indirect
|
||||
modernc.org/token v1.1.0 // indirect
|
||||
)
|
||||
|
||||
// replace forge.cadoles.com/arcad/edge => ../edge
|
||||
|
76
go.sum
76
go.sum
@ -1,8 +1,8 @@
|
||||
bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
|
||||
bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM=
|
||||
cdr.dev/slog v1.4.0/go.mod h1:C5OL99WyuOK8YHZdYY57dAPN1jK2WJlCdq2VP6xeQns=
|
||||
cdr.dev/slog v1.4.2 h1:fIfiqASYQFJBZiASwL825atyzeA96NsqSxx2aL61P8I=
|
||||
cdr.dev/slog v1.4.2/go.mod h1:0EkH+GkFNxizNR+GAXUEdUHanxUH5t9zqPILmPM/Vn8=
|
||||
cdr.dev/slog v1.4.1 h1:Q8+X63m8/WB4geelMTDO8t4CTwVh1f7+5Cxi7kS/SZg=
|
||||
cdr.dev/slog v1.4.1/go.mod h1:O76C6gZJxa5HK1SXMrjd48V2kJxYZKFRTcFfn/V9OhA=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
@ -54,8 +54,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
|
||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
forge.cadoles.com/arcad/edge v0.0.0-20230322170544-cf8a3f8ac077 h1:vsYcNHZevZrs0VeOTasvJoqvPynb8OvH+MMpIUvNT6Q=
|
||||
forge.cadoles.com/arcad/edge v0.0.0-20230322170544-cf8a3f8ac077/go.mod h1:ONd6vyQ0IM0vHi1i+bmZBRc1Fd0BoXMuDdY/+0sZefw=
|
||||
forge.cadoles.com/arcad/edge v0.0.0-20230303153719-6399196fe5c9 h1:dleaaf/rV2GWtGvrPunRakjrKVDfXoANxAy8/1ctMVs=
|
||||
forge.cadoles.com/arcad/edge v0.0.0-20230303153719-6399196fe5c9/go.mod h1:pl9EMtSLSVr4wbDgQBDjr4aizwtmwasE686dm5arYPw=
|
||||
gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8/go.mod h1:CzsSbkDixRphAF5hS6wbMKq0eI6ccJRb7/A0M6JBnwg=
|
||||
github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k=
|
||||
@ -123,11 +123,13 @@ github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 h1:smF2tmSOzy2Mm
|
||||
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI=
|
||||
github.com/alecthomas/assert/v2 v2.0.3 h1:WKqJODfOiQG0nEJKFKzDIG3E29CN2/4zR9XGJzKIkbg=
|
||||
github.com/alecthomas/chroma v0.7.0/go.mod h1:1U/PfCsTALWWYHDnsIQkxEBM0+6LLe0v8+RSVMOwxeY=
|
||||
github.com/alecthomas/chroma v0.9.1/go.mod h1:eMuEnpA18XbG/WhOWtCzJHS7WqEtDAI+HxdwoW0nVSk=
|
||||
github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek=
|
||||
github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s=
|
||||
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0=
|
||||
github.com/alecthomas/kong v0.1.17-0.20190424132513-439c674f7ae0/go.mod h1:+inYUSluD+p4L8KdviBSgzcqEjUQOfC5fQDRFuc36lI=
|
||||
github.com/alecthomas/kong v0.2.1-0.20190708041108-0548c6b1afae/go.mod h1:+inYUSluD+p4L8KdviBSgzcqEjUQOfC5fQDRFuc36lI=
|
||||
github.com/alecthomas/kong v0.2.4/go.mod h1:kQOmtJgV+Lb4aj+I2LEn40cbtawdWJ9Y8QLq+lElKxE=
|
||||
github.com/alecthomas/kong-hcl v0.1.8-0.20190615233001-b21fea9723c8/go.mod h1:MRgZdU3vrFd05IQ89AxUZ0aYdF39BYoNFa324SodPCA=
|
||||
github.com/alecthomas/participle/v2 v2.0.0-beta.5 h1:y6dsSYVb1G5eK6mgmy+BgI3Mw35a3WghArZ/Hbebrjo=
|
||||
github.com/alecthomas/participle/v2 v2.0.0-beta.5/go.mod h1:RC764t6n4L8D8ITAJv0qdokritYSNR3wV5cVwmIEaMM=
|
||||
@ -234,11 +236,8 @@ github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOo
|
||||
github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
|
||||
github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg=
|
||||
github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc=
|
||||
github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
|
||||
@ -444,12 +443,12 @@ github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZ
|
||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
||||
github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk=
|
||||
github.com/dop251/goja v0.0.0-20221118162653-d4bf6fde1b86/go.mod h1:yRkwfj0CBpOGre+TwBsqPV0IH0Pk73e4PXJOeNDboGs=
|
||||
github.com/dop251/goja v0.0.0-20230304130813-e2f543bf4b4c h1:/utv6nmTctV6OVgfk5+O6lEMEWL+6KJy4h9NZ5fnkQQ=
|
||||
github.com/dop251/goja v0.0.0-20230304130813-e2f543bf4b4c/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4=
|
||||
github.com/dop251/goja v0.0.0-20230226152633-7c93113e17ac h1:NGu46Adk2oPN3tinGFItahy4W9l+9uhEf03ZxbwmdVE=
|
||||
github.com/dop251/goja v0.0.0-20230226152633-7c93113e17ac/go.mod h1:yRkwfj0CBpOGre+TwBsqPV0IH0Pk73e4PXJOeNDboGs=
|
||||
github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y=
|
||||
github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM=
|
||||
github.com/dop251/goja_nodejs v0.0.0-20230320130059-dcf93ba651dd h1:8FguYHL/davT0sAfVoi84iRI4MCVTVFtlnmZqIoAXDQ=
|
||||
github.com/dop251/goja_nodejs v0.0.0-20230320130059-dcf93ba651dd/go.mod h1:0tlktQL7yHfYEtjcRGi/eiOkbDR5XF7gyFFvbC5//E0=
|
||||
github.com/dop251/goja_nodejs v0.0.0-20230226152057-060fa99b809f h1:mmnNidRg3cMfcgyeNtIBSDZgjf/85lA/2pplccwSxYg=
|
||||
github.com/dop251/goja_nodejs v0.0.0-20230226152057-060fa99b809f/go.mod h1:0tlktQL7yHfYEtjcRGi/eiOkbDR5XF7gyFFvbC5//E0=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
@ -474,9 +473,9 @@ github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQL
|
||||
github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww=
|
||||
github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
|
||||
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
|
||||
github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w=
|
||||
github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg=
|
||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
||||
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
||||
@ -577,8 +576,8 @@ github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWe
|
||||
github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ=
|
||||
github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0=
|
||||
github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk=
|
||||
github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/gocql/gocql v0.0.0-20210515062232-b7ef815b4556/go.mod h1:DL0ekTmBSTdlNF25Orwt/JMzqIq3EJ4MVa/J/uK64OY=
|
||||
github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
||||
github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
||||
@ -688,9 +687,7 @@ github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLe
|
||||
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg=
|
||||
github.com/google/pprof v0.0.0-20230309165930-d61513b1440d h1:um9/pc7tKMINFfP1eE7Wv6PRGXlcCSJkVajF7KJw3uQ=
|
||||
github.com/google/pprof v0.0.0-20230309165930-d61513b1440d/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk=
|
||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
@ -764,7 +761,6 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
|
||||
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
|
||||
github.com/igm/sockjs-go/v3 v3.0.2 h1:2m0k53w0DBiGozeQUIEPR6snZFmpFpYvVsGnfLPNXbE=
|
||||
github.com/igm/sockjs-go/v3 v3.0.2/go.mod h1:UqchsOjeagIBFHvd+RZpLaVRbCwGilEC08EDHsD1jYE=
|
||||
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
@ -904,11 +900,10 @@ github.com/lestrrat-go/httprc v1.0.4 h1:bAZymwoZQb+Oq8MEbyipag7iSq6YIga8Wj6GOiJG
|
||||
github.com/lestrrat-go/httprc v1.0.4/go.mod h1:mwwz3JMTPBjHUkkDv/IGJ39aALInZLrhBp0X7KGUZlo=
|
||||
github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI=
|
||||
github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4=
|
||||
github.com/lestrrat-go/jwx/v2 v2.0.9 h1:TRX4Q630UXxPVLvP5vGaqVJO7S+0PE6msRZUsFSBoC8=
|
||||
github.com/lestrrat-go/jwx/v2 v2.0.9/go.mod h1:K68euYaR95FnL0hIQB8VvzL70vB7pSifbJUydCTPmgM=
|
||||
github.com/lestrrat-go/jwx/v2 v2.0.8 h1:jCFT8oc0hEDVjgUgsBy1F9cbjsjAVZSXNi7JaU9HR/Q=
|
||||
github.com/lestrrat-go/jwx/v2 v2.0.8/go.mod h1:zLxnyv9rTlEvOUHbc48FAfIL8iYu2hHvIRaTFGc8mT0=
|
||||
github.com/lestrrat-go/option v1.0.0 h1:WqAWL8kh8VcSoD6xjSH34/1m8yxluXQbDeKNfvFeEO4=
|
||||
github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
||||
github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
|
||||
github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
@ -918,8 +913,6 @@ github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
|
||||
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo=
|
||||
github.com/lithammer/shortuuid/v4 v4.0.0 h1:QRbbVkfgNippHOS8PXDkti4NaWeyYfcBTHtw7k08o4c=
|
||||
github.com/lithammer/shortuuid/v4 v4.0.0/go.mod h1:Zs8puNcrvf2rV9rTH51ZLLcj7ZXqQI3lv67aw4KiB1Y=
|
||||
github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
@ -937,7 +930,7 @@ github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcncea
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E=
|
||||
@ -949,7 +942,6 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
|
||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
||||
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
@ -978,8 +970,6 @@ github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
@ -1169,6 +1159,8 @@ github.com/rwtodd/Go.Sed v0.0.0-20210816025313-55464686f9ef/go.mod h1:8AEUvGVi2u
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
|
||||
github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
|
||||
github.com/santhosh-tekuri/jsonschema/v5 v5.1.1 h1:lEOLY2vyGIqKWUI9nzsOJRV3mb3WC9dXYORsLEUcoeY=
|
||||
github.com/santhosh-tekuri/jsonschema/v5 v5.1.1/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
|
||||
github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U=
|
||||
@ -1345,7 +1337,6 @@ go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
||||
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||
go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
@ -1379,8 +1370,9 @@ golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWP
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=
|
||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
@ -1498,6 +1490,7 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220111093109-d55c255bac03/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
@ -1506,9 +1499,8 @@ golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
@ -1599,6 +1591,7 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -1664,16 +1657,14 @@ golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220317061510-51cd9980dadf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
@ -1681,9 +1672,8 @@ golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuX
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
|
||||
golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@ -1693,12 +1683,10 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
@ -30,6 +30,7 @@ func (a *Agent) Run(ctx context.Context) error {
|
||||
ticker := time.NewTicker(a.interval)
|
||||
defer ticker.Stop()
|
||||
|
||||
logger.Info(ctx, "generating token")
|
||||
token, err := agent.GenerateToken(a.privateKey, a.thumbprint)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
@ -39,13 +40,16 @@ func (a *Agent) Run(ctx context.Context) error {
|
||||
|
||||
ctx = withClient(ctx, client)
|
||||
|
||||
tick := func() {
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
|
||||
logger.Debug(ctx, "registering agent")
|
||||
|
||||
if err := a.registerAgent(ctx, client, state); err != nil {
|
||||
logger.Error(ctx, "could not register agent", logger.E(errors.WithStack(err)))
|
||||
|
||||
return
|
||||
continue
|
||||
}
|
||||
|
||||
logger.Debug(ctx, "state before reconciliation", logger.F("state", state))
|
||||
@ -53,18 +57,11 @@ func (a *Agent) Run(ctx context.Context) error {
|
||||
if err := a.Reconcile(ctx, state); err != nil {
|
||||
logger.Error(ctx, "could not reconcile node with state", logger.E(errors.WithStack(err)))
|
||||
|
||||
return
|
||||
continue
|
||||
}
|
||||
|
||||
logger.Debug(ctx, "state after reconciliation", logger.F("state", state))
|
||||
}
|
||||
|
||||
tick()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
tick()
|
||||
case <-ctx.Done():
|
||||
return errors.WithStack(ctx.Err())
|
||||
}
|
||||
|
@ -11,21 +11,16 @@ import (
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/spec/app"
|
||||
"forge.cadoles.com/arcad/edge/pkg/bundle"
|
||||
"forge.cadoles.com/arcad/edge/pkg/storage/sqlite"
|
||||
"github.com/mitchellh/hashstructure/v2"
|
||||
"github.com/pkg/errors"
|
||||
"gitlab.com/wpetit/goweb/logger"
|
||||
)
|
||||
|
||||
type serverEntry struct {
|
||||
SpecHash uint64
|
||||
Server *Server
|
||||
}
|
||||
|
||||
type Controller struct {
|
||||
currentSpecRevision int
|
||||
client *http.Client
|
||||
downloadDir string
|
||||
dataDir string
|
||||
servers map[string]*serverEntry
|
||||
servers map[string]*Server
|
||||
}
|
||||
|
||||
// Name implements node.Controller.
|
||||
@ -39,9 +34,9 @@ func (c *Controller) Reconcile(ctx context.Context, state *agent.State) error {
|
||||
|
||||
if err := state.GetSpec(app.NameApp, appSpec); err != nil {
|
||||
if errors.Is(err, agent.ErrSpecNotFound) {
|
||||
logger.Info(ctx, "could not find app spec")
|
||||
logger.Info(ctx, "could not find app spec, stopping all remaining apps")
|
||||
|
||||
c.stopAllApps(ctx, appSpec)
|
||||
c.stopAllApps(ctx)
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -51,20 +46,22 @@ func (c *Controller) Reconcile(ctx context.Context, state *agent.State) error {
|
||||
|
||||
logger.Info(ctx, "retrieved spec", logger.F("spec", appSpec.SpecName()), logger.F("revision", appSpec.SpecRevision()))
|
||||
|
||||
if c.currentSpecRevision == appSpec.SpecRevision() {
|
||||
logger.Info(ctx, "spec revision did not change, doing nothing")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
c.updateApps(ctx, appSpec)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Controller) stopAllApps(ctx context.Context, spec *app.Spec) {
|
||||
if len(c.servers) > 0 {
|
||||
logger.Info(ctx, "stopping all apps")
|
||||
}
|
||||
|
||||
for appID, entry := range c.servers {
|
||||
func (c *Controller) stopAllApps(ctx context.Context) {
|
||||
for appID, server := range c.servers {
|
||||
logger.Info(ctx, "stopping app", logger.F("appID", appID))
|
||||
|
||||
if err := entry.Server.Stop(); err != nil {
|
||||
if err := server.Stop(); err != nil {
|
||||
logger.Error(
|
||||
ctx, "error while stopping app",
|
||||
logger.F("appID", appID),
|
||||
@ -77,15 +74,17 @@ func (c *Controller) stopAllApps(ctx context.Context, spec *app.Spec) {
|
||||
}
|
||||
|
||||
func (c *Controller) updateApps(ctx context.Context, spec *app.Spec) {
|
||||
hadError := false
|
||||
|
||||
// Stop and remove obsolete apps
|
||||
for appID, entry := range c.servers {
|
||||
for appID, server := range c.servers {
|
||||
if _, exists := spec.Apps[appID]; exists {
|
||||
continue
|
||||
}
|
||||
|
||||
logger.Info(ctx, "stopping app", logger.F("appID", appID))
|
||||
|
||||
if err := entry.Server.Stop(); err != nil {
|
||||
if err := server.Stop(); err != nil {
|
||||
logger.Error(
|
||||
ctx, "error while stopping app",
|
||||
logger.F("gatewayID", appID),
|
||||
@ -93,6 +92,8 @@ func (c *Controller) updateApps(ctx context.Context, spec *app.Spec) {
|
||||
)
|
||||
|
||||
delete(c.servers, appID)
|
||||
|
||||
hadError = true
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,19 +101,22 @@ func (c *Controller) updateApps(ctx context.Context, spec *app.Spec) {
|
||||
for appID, appSpec := range spec.Apps {
|
||||
appCtx := logger.With(ctx, logger.F("appID", appID))
|
||||
|
||||
if err := c.updateApp(ctx, appID, appSpec, spec.Auth); err != nil {
|
||||
if err := c.updateApp(ctx, appID, appSpec); err != nil {
|
||||
logger.Error(appCtx, "could not update app", logger.E(errors.WithStack(err)))
|
||||
|
||||
hadError = true
|
||||
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if !hadError {
|
||||
c.currentSpecRevision = spec.SpecRevision()
|
||||
logger.Info(ctx, "updating current spec revision", logger.F("revision", c.currentSpecRevision))
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) updateApp(ctx context.Context, appID string, appSpec app.AppEntry, auth *app.Auth) (err error) {
|
||||
newAppSpecHash, err := hashstructure.Hash(appSpec, hashstructure.FormatV2, nil)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
func (c *Controller) updateApp(ctx context.Context, appID string, appSpec app.AppEntry) error {
|
||||
bundle, sha256sum, err := c.ensureAppBundle(ctx, appID, appSpec)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not download app bundle")
|
||||
@ -123,9 +127,7 @@ func (c *Controller) updateApp(ctx context.Context, appID string, appSpec app.Ap
|
||||
return errors.Wrap(err, "could not retrieve app data dir")
|
||||
}
|
||||
|
||||
var entry *serverEntry
|
||||
|
||||
entry, exists := c.servers[appID]
|
||||
server, exists := c.servers[appID]
|
||||
if !exists {
|
||||
logger.Info(ctx, "app currently not running")
|
||||
} else if sha256sum != appSpec.SHA256Sum {
|
||||
@ -135,54 +137,35 @@ func (c *Controller) updateApp(ctx context.Context, appID string, appSpec app.Ap
|
||||
logger.F("specHash", appSpec.SHA256Sum),
|
||||
)
|
||||
|
||||
if err := entry.Server.Stop(); err != nil {
|
||||
if err := server.Stop(); err != nil {
|
||||
return errors.Wrap(err, "could not stop app")
|
||||
}
|
||||
|
||||
entry = nil
|
||||
server = nil
|
||||
}
|
||||
|
||||
if entry == nil {
|
||||
if server == nil {
|
||||
dbFile := filepath.Join(dataDir, appID+".sqlite")
|
||||
db, err := sqlite.Open(dbFile)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not opend database file '%s'", dbFile)
|
||||
}
|
||||
|
||||
entry = &serverEntry{
|
||||
Server: NewServer(bundle, db, auth),
|
||||
SpecHash: 0,
|
||||
server = NewServer(bundle, db)
|
||||
c.servers[appID] = server
|
||||
}
|
||||
|
||||
c.servers[appID] = entry
|
||||
}
|
||||
|
||||
specChanged := newAppSpecHash != entry.SpecHash
|
||||
|
||||
if entry.Server.Running() && !specChanged {
|
||||
return nil
|
||||
}
|
||||
|
||||
if specChanged && entry.SpecHash != 0 {
|
||||
logger.Info(
|
||||
ctx, "restarting app",
|
||||
logger.F("address", appSpec.Address),
|
||||
)
|
||||
} else {
|
||||
logger.Info(
|
||||
ctx, "starting app",
|
||||
logger.F("address", appSpec.Address),
|
||||
)
|
||||
}
|
||||
|
||||
if err := entry.Server.Start(ctx, appSpec.Address); err != nil {
|
||||
if err := server.Start(ctx, appSpec.Address); err != nil {
|
||||
delete(c.servers, appID)
|
||||
|
||||
return errors.Wrap(err, "could not start app")
|
||||
}
|
||||
|
||||
entry.SpecHash = newAppSpecHash
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -295,7 +278,8 @@ func NewController(funcs ...OptionFunc) *Controller {
|
||||
client: opts.Client,
|
||||
downloadDir: opts.DownloadDir,
|
||||
dataDir: opts.DataDir,
|
||||
servers: make(map[string]*serverEntry),
|
||||
currentSpecRevision: -1,
|
||||
servers: make(map[string]*Server),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,43 +4,30 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
appSpec "forge.cadoles.com/Cadoles/emissary/internal/spec/app"
|
||||
"forge.cadoles.com/arcad/edge/pkg/app"
|
||||
"forge.cadoles.com/arcad/edge/pkg/bus"
|
||||
"forge.cadoles.com/arcad/edge/pkg/bus/memory"
|
||||
edgeHTTP "forge.cadoles.com/arcad/edge/pkg/http"
|
||||
"forge.cadoles.com/arcad/edge/pkg/module"
|
||||
"forge.cadoles.com/arcad/edge/pkg/module/auth"
|
||||
authHTTP "forge.cadoles.com/arcad/edge/pkg/module/auth/http"
|
||||
"forge.cadoles.com/arcad/edge/pkg/module/cast"
|
||||
"forge.cadoles.com/arcad/edge/pkg/module/net"
|
||||
"forge.cadoles.com/arcad/edge/pkg/storage"
|
||||
"forge.cadoles.com/arcad/edge/pkg/storage/sqlite"
|
||||
"gitlab.com/wpetit/goweb/logger"
|
||||
|
||||
"forge.cadoles.com/arcad/edge/pkg/bundle"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/go-chi/chi/middleware"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/lestrrat-go/jwx/v2/jwa"
|
||||
"github.com/lestrrat-go/jwx/v2/jwk"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/imports/passwd"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
bundle bundle.Bundle
|
||||
db *sql.DB
|
||||
server *http.Server
|
||||
serverMutex sync.RWMutex
|
||||
auth *appSpec.Auth
|
||||
keySet jwk.Set
|
||||
}
|
||||
|
||||
func (s *Server) Start(ctx context.Context, addr string) (err error) {
|
||||
func (s *Server) Start(ctx context.Context, addr string) error {
|
||||
if s.server != nil {
|
||||
if err := s.Stop(); err != nil {
|
||||
return errors.WithStack(err)
|
||||
@ -63,37 +50,6 @@ func (s *Server) Start(ctx context.Context, addr string) (err error) {
|
||||
return errors.Wrap(err, "could not load app bundle")
|
||||
}
|
||||
|
||||
if s.auth != nil {
|
||||
if s.auth.Local != nil {
|
||||
var rawKey any = s.auth.Local.Key
|
||||
if strKey, ok := rawKey.(string); ok {
|
||||
rawKey = []byte(strKey)
|
||||
}
|
||||
|
||||
key, err := jwk.FromRaw(rawKey)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
if err := key.Set(jwk.AlgorithmKey, jwa.HS256); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
keySet := jwk.NewSet()
|
||||
if err := keySet.AddKey(key); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
s.keySet = keySet
|
||||
|
||||
router.Handle("/auth/*", authHTTP.NewLocalHandler(
|
||||
jwa.HS256, key,
|
||||
authHTTP.WithRoutePrefix("/auth"),
|
||||
authHTTP.WithAccounts(s.auth.Local.Accounts...),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
router.Handle("/*", handler)
|
||||
|
||||
server := &http.Server{
|
||||
@ -102,18 +58,6 @@ func (s *Server) Start(ctx context.Context, addr string) (err error) {
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer func() {
|
||||
if recovered := recover(); recovered != nil {
|
||||
if err, ok := recovered.(error); ok {
|
||||
logger.Error(ctx, err.Error(), logger.E(errors.WithStack(err)))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
panic(recovered)
|
||||
}
|
||||
}()
|
||||
|
||||
defer func() {
|
||||
if err := s.Stop(); err != nil {
|
||||
panic(errors.WithStack(err))
|
||||
@ -125,29 +69,18 @@ func (s *Server) Start(ctx context.Context, addr string) (err error) {
|
||||
}
|
||||
}()
|
||||
|
||||
s.serverMutex.Lock()
|
||||
s.server = server
|
||||
s.serverMutex.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) Running() bool {
|
||||
s.serverMutex.RLock()
|
||||
defer s.serverMutex.RUnlock()
|
||||
|
||||
return s.server != nil
|
||||
}
|
||||
|
||||
func (s *Server) Stop() error {
|
||||
if s.server == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
defer func() {
|
||||
s.serverMutex.Lock()
|
||||
s.server = nil
|
||||
s.serverMutex.Unlock()
|
||||
}()
|
||||
|
||||
if err := s.server.Close(); err != nil {
|
||||
@ -167,39 +100,26 @@ func (s *Server) getAppModules(bus bus.Bus, ds storage.DocumentStore, bs storage
|
||||
module.RPCModuleFactory(bus),
|
||||
module.StoreModuleFactory(ds),
|
||||
module.BlobModuleFactory(bus, bs),
|
||||
module.Extends(
|
||||
auth.ModuleFactory(
|
||||
auth.WithJWT(s.getJWTKeySet),
|
||||
),
|
||||
func(o *goja.Object) {
|
||||
if err := o.Set("CLAIM_TENANT", "arcad_tenant"); err != nil {
|
||||
panic(errors.New("could not set 'CLAIM_TENANT' property"))
|
||||
}
|
||||
// module.Extends(
|
||||
// auth.ModuleFactory(
|
||||
// auth.WithJWT(dummyKeyFunc),
|
||||
// ),
|
||||
// func(o *goja.Object) {
|
||||
// if err := o.Set("CLAIM_ROLE", "role"); err != nil {
|
||||
// panic(errors.New("could not set 'CLAIM_ROLE' property"))
|
||||
// }
|
||||
|
||||
if err := o.Set("CLAIM_ENTRYPOINT", "arcad_entrypoint"); err != nil {
|
||||
panic(errors.New("could not set 'CLAIM_ENTRYPOINT' property"))
|
||||
}
|
||||
|
||||
if err := o.Set("CLAIM_ROLE", "arcad_role"); err != nil {
|
||||
panic(errors.New("could not set 'CLAIM_ROLE' property"))
|
||||
}
|
||||
|
||||
if err := o.Set("CLAIM_PREFERRED_USERNAME", "preferred_username"); err != nil {
|
||||
panic(errors.New("could not set 'CLAIM_PREFERRED_USERNAME' property"))
|
||||
}
|
||||
},
|
||||
),
|
||||
// if err := o.Set("CLAIM_PREFERRED_USERNAME", "preferred_username"); err != nil {
|
||||
// panic(errors.New("could not set 'CLAIM_PREFERRED_USERNAME' property"))
|
||||
// }
|
||||
// },
|
||||
// ),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) getJWTKeySet() (jwk.Set, error) {
|
||||
return s.keySet, nil
|
||||
}
|
||||
|
||||
func NewServer(bundle bundle.Bundle, db *sql.DB, auth *appSpec.Auth) *Server {
|
||||
func NewServer(bundle bundle.Bundle, db *sql.DB) *Server {
|
||||
return &Server{
|
||||
bundle: bundle,
|
||||
db: db,
|
||||
auth: auth,
|
||||
}
|
||||
}
|
||||
|
124
internal/agent/controller/gateway/controller.go
Normal file
124
internal/agent/controller/gateway/controller.go
Normal file
@ -0,0 +1,124 @@
|
||||
package gateway
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/agent"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/spec/gateway"
|
||||
"github.com/pkg/errors"
|
||||
"gitlab.com/wpetit/goweb/logger"
|
||||
)
|
||||
|
||||
type Controller struct {
|
||||
proxies map[gateway.ID]*ReverseProxy
|
||||
currentSpecRevision int
|
||||
}
|
||||
|
||||
// Name implements node.Controller.
|
||||
func (c *Controller) Name() string {
|
||||
return "gateway-controller"
|
||||
}
|
||||
|
||||
// Reconcile implements node.Controller.
|
||||
func (c *Controller) Reconcile(ctx context.Context, state *agent.State) error {
|
||||
gatewaySpec := gateway.NewSpec()
|
||||
|
||||
if err := state.GetSpec(gateway.NameGateway, gatewaySpec); err != nil {
|
||||
if errors.Is(err, agent.ErrSpecNotFound) {
|
||||
logger.Info(ctx, "could not find gateway spec, stopping all remaining proxies")
|
||||
|
||||
c.stopAllProxies(ctx)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
logger.Info(ctx, "retrieved spec", logger.F("spec", gatewaySpec.SpecName()), logger.F("revision", gatewaySpec.SpecRevision()))
|
||||
|
||||
if c.currentSpecRevision == gatewaySpec.SpecRevision() {
|
||||
logger.Info(ctx, "spec revision did not change, doing nothing")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
c.updateProxies(ctx, gatewaySpec)
|
||||
|
||||
c.currentSpecRevision = gatewaySpec.SpecRevision()
|
||||
logger.Info(ctx, "updating current spec revision", logger.F("revision", c.currentSpecRevision))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Controller) stopAllProxies(ctx context.Context) {
|
||||
for gatewayID, proxy := range c.proxies {
|
||||
logger.Info(ctx, "stopping proxy", logger.F("gatewayID", gatewayID))
|
||||
|
||||
if err := proxy.Stop(); err != nil {
|
||||
logger.Error(
|
||||
ctx, "error while stopping proxy",
|
||||
logger.F("gatewayID", gatewayID),
|
||||
logger.E(errors.WithStack(err)),
|
||||
)
|
||||
|
||||
delete(c.proxies, gatewayID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) updateProxies(ctx context.Context, spec *gateway.Spec) {
|
||||
// Stop and remove obsolete gateways
|
||||
for gatewayID, proxy := range c.proxies {
|
||||
if _, exists := spec.Gateways[gatewayID]; exists {
|
||||
continue
|
||||
}
|
||||
|
||||
logger.Info(ctx, "stopping proxy", logger.F("gatewayID", gatewayID))
|
||||
|
||||
if err := proxy.Stop(); err != nil {
|
||||
logger.Error(
|
||||
ctx, "error while stopping proxy",
|
||||
logger.F("gatewayID", gatewayID),
|
||||
logger.E(errors.WithStack(err)),
|
||||
)
|
||||
|
||||
delete(c.proxies, gatewayID)
|
||||
}
|
||||
}
|
||||
|
||||
// (Re)start gateways
|
||||
for gatewayID, gatewaySpec := range spec.Gateways {
|
||||
proxy, exists := c.proxies[gatewayID]
|
||||
if !exists {
|
||||
proxy = NewReverseProxy()
|
||||
c.proxies[gatewayID] = proxy
|
||||
}
|
||||
|
||||
logger.Info(
|
||||
ctx, "starting proxy",
|
||||
logger.F("gatewayID", gatewayID),
|
||||
logger.F("addr", gatewaySpec.Address),
|
||||
logger.F("target", gatewaySpec.Target),
|
||||
)
|
||||
|
||||
if err := proxy.Start(ctx, gatewaySpec.Address, gatewaySpec.Target); err != nil {
|
||||
logger.Error(
|
||||
ctx, "error while starting proxy",
|
||||
logger.F("gatewayID", gatewayID),
|
||||
logger.E(errors.WithStack(err)),
|
||||
)
|
||||
|
||||
delete(c.proxies, gatewayID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func NewController() *Controller {
|
||||
return &Controller{
|
||||
proxies: make(map[gateway.ID]*ReverseProxy),
|
||||
currentSpecRevision: -1,
|
||||
}
|
||||
}
|
||||
|
||||
var _ agent.Controller = &Controller{}
|
@ -1,23 +1,28 @@
|
||||
package proxy
|
||||
package gateway
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"sync"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gitlab.com/wpetit/goweb/logger"
|
||||
|
||||
"forge.cadoles.com/arcad/edge/pkg/proxy"
|
||||
)
|
||||
|
||||
type ReverseProxy struct {
|
||||
addr string
|
||||
target string
|
||||
server *http.Server
|
||||
mutex sync.RWMutex
|
||||
}
|
||||
|
||||
func (p *ReverseProxy) Start(ctx context.Context, addr string, funcs ...proxy.OptionFunc) error {
|
||||
func (p *ReverseProxy) Start(ctx context.Context, addr, target string) error {
|
||||
alreadyRunning := p.server != nil && target == p.target && addr == p.target
|
||||
|
||||
if alreadyRunning {
|
||||
return nil
|
||||
}
|
||||
|
||||
if p.server != nil {
|
||||
if err := p.Stop(); err != nil {
|
||||
return errors.WithStack(err)
|
||||
@ -28,40 +33,33 @@ func (p *ReverseProxy) Start(ctx context.Context, addr string, funcs ...proxy.Op
|
||||
Addr: addr,
|
||||
}
|
||||
|
||||
proxy := proxy.New(funcs...)
|
||||
url, err := url.Parse(target)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
proxy := httputil.NewSingleHostReverseProxy(url)
|
||||
|
||||
server.Handler = proxy
|
||||
|
||||
p.mutex.Lock()
|
||||
p.server = server
|
||||
p.addr = addr
|
||||
p.mutex.Unlock()
|
||||
p.target = target
|
||||
|
||||
go func() {
|
||||
defer func() {
|
||||
if err := p.Stop(); err != nil {
|
||||
logger.Error(ctx, "error while stopping gateway", logger.E(errors.WithStack(err)))
|
||||
}
|
||||
}()
|
||||
|
||||
if err := server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||
logger.Error(ctx, "error while listening", logger.E(errors.WithStack(err)))
|
||||
}
|
||||
|
||||
if err := p.Stop(); err != nil {
|
||||
logger.Error(ctx, "error while stopping gateway", logger.E(errors.WithStack(err)))
|
||||
}
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *ReverseProxy) Running() bool {
|
||||
p.mutex.RLock()
|
||||
defer p.mutex.RUnlock()
|
||||
|
||||
return p.server != nil
|
||||
}
|
||||
|
||||
func (p *ReverseProxy) Stop() error {
|
||||
p.mutex.Lock()
|
||||
defer p.mutex.Unlock()
|
||||
|
||||
if p.server == nil {
|
||||
return nil
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
package openwrt
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func hash(path string) (string, error) {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return "", errors.WithStack(err)
|
||||
}
|
||||
|
||||
hasher := sha256.New()
|
||||
|
||||
defer func() {
|
||||
if err := file.Close(); err != nil {
|
||||
panic(errors.WithStack(err))
|
||||
}
|
||||
}()
|
||||
|
||||
if _, err := io.Copy(hasher, file); err != nil {
|
||||
return "", errors.WithStack(err)
|
||||
}
|
||||
|
||||
return hex.EncodeToString(hasher.Sum(nil)), nil
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://sysupgrade.openwrt.emissary.cadoles.com/spec.json",
|
||||
"title": "SysUpgradeSpec",
|
||||
"description": "Emissary 'SysUpgrade' specification",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string"
|
||||
},
|
||||
"sha256sum": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["url", "sha256sum", "version"],
|
||||
"additionalProperties": false
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
package sysupgrade
|
||||
|
||||
import (
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/spec"
|
||||
)
|
||||
|
||||
const Name spec.Name = "sysupgrade.openwrt.emissary.cadoles.com"
|
||||
|
||||
type Spec struct {
|
||||
Revision int `json:"revision"`
|
||||
URL string `json:"url"`
|
||||
SHA256Sum string `json:"sha256sum"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
func (s *Spec) SpecName() spec.Name {
|
||||
return Name
|
||||
}
|
||||
|
||||
func (s *Spec) SpecRevision() int {
|
||||
return s.Revision
|
||||
}
|
||||
|
||||
func (s *Spec) SpecData() map[string]any {
|
||||
return map[string]any{
|
||||
"url": s.URL,
|
||||
"version": s.Version,
|
||||
"sha256sum": s.SHA256Sum,
|
||||
}
|
||||
}
|
||||
|
||||
func NewSpec() *Spec {
|
||||
return &Spec{
|
||||
Revision: -1,
|
||||
}
|
||||
}
|
||||
|
||||
var _ spec.Spec = &Spec{}
|
@ -1,9 +0,0 @@
|
||||
{
|
||||
"name": "sysupgrade.openwrt.emissary.cadoles.com",
|
||||
"data": {
|
||||
"url": "http://example.com/firmware.img",
|
||||
"sha256sum": "58019192dacdae17755707719707db007e26dac856102280583fbd18427dd352",
|
||||
"version": "0.0.0"
|
||||
},
|
||||
"revision": 0
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
package sysupgrade
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/spec"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type validatorTestCase struct {
|
||||
Name string
|
||||
Source string
|
||||
ShouldFail bool
|
||||
}
|
||||
|
||||
var validatorTestCases = []validatorTestCase{
|
||||
{
|
||||
Name: "SpecOK",
|
||||
Source: "testdata/spec-ok.json",
|
||||
ShouldFail: false,
|
||||
},
|
||||
}
|
||||
|
||||
func TestValidator(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
validator := spec.NewValidator()
|
||||
if err := validator.Register(Name, schema); err != nil {
|
||||
t.Fatalf("+%v", errors.WithStack(err))
|
||||
}
|
||||
|
||||
for _, tc := range validatorTestCases {
|
||||
func(tc validatorTestCase) {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
rawSpec, err := ioutil.ReadFile(tc.Source)
|
||||
if err != nil {
|
||||
t.Fatalf("+%v", errors.WithStack(err))
|
||||
}
|
||||
|
||||
var spec spec.RawSpec
|
||||
|
||||
if err := json.Unmarshal(rawSpec, &spec); err != nil {
|
||||
t.Fatalf("+%v", errors.WithStack(err))
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
err = validator.Validate(ctx, &spec)
|
||||
|
||||
if !tc.ShouldFail && err != nil {
|
||||
t.Errorf("+%v", errors.WithStack(err))
|
||||
}
|
||||
|
||||
if tc.ShouldFail && err == nil {
|
||||
t.Error("validation should have failed")
|
||||
}
|
||||
})
|
||||
}(tc)
|
||||
}
|
||||
}
|
@ -1,177 +0,0 @@
|
||||
package openwrt
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/agent"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/agent/controller/openwrt/spec/sysupgrade"
|
||||
"github.com/pkg/errors"
|
||||
"gitlab.com/wpetit/goweb/logger"
|
||||
)
|
||||
|
||||
type SysUpgradeController struct {
|
||||
client *http.Client
|
||||
command string
|
||||
args []string
|
||||
firmwareVersion FirmwareVersion
|
||||
}
|
||||
|
||||
// Name implements agent.Controller
|
||||
func (*SysUpgradeController) Name() string {
|
||||
return "sysupgrade-controller"
|
||||
}
|
||||
|
||||
// Reconcile implements agent.Controller
|
||||
func (c *SysUpgradeController) Reconcile(ctx context.Context, state *agent.State) error {
|
||||
sysSpec := sysupgrade.NewSpec()
|
||||
|
||||
if err := state.GetSpec(sysupgrade.Name, sysSpec); err != nil {
|
||||
if errors.Is(err, agent.ErrSpecNotFound) {
|
||||
logger.Info(ctx, "could not find sysupgrade spec, doing nothing")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
firmwareVersion, err := c.firmwareVersion.FirmwareVersion(ctx)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
ctx = logger.With(ctx,
|
||||
logger.F("currentFirmwareVersion", firmwareVersion),
|
||||
logger.F("newFirmwareVersion", sysSpec.Version),
|
||||
)
|
||||
|
||||
if firmwareVersion == sysSpec.Version {
|
||||
logger.Info(ctx, "firmware version did not change, doing nothing")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
downloadDir, err := os.MkdirTemp(os.TempDir(), "emissary_sysupgrade_*")
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := os.RemoveAll(downloadDir); err != nil {
|
||||
logger.Error(
|
||||
ctx, "could not remove download direction",
|
||||
logger.E(errors.WithStack(err)),
|
||||
logger.F("downloadDir", downloadDir),
|
||||
)
|
||||
}
|
||||
}()
|
||||
|
||||
firmwareFile := filepath.Join(downloadDir, "firmware.bin")
|
||||
|
||||
logger.Info(
|
||||
ctx, "downloading firmware",
|
||||
logger.F("url", sysSpec.URL), logger.F("sha256sum", sysSpec.SHA256Sum),
|
||||
)
|
||||
|
||||
if err := c.downloadFile(ctx, sysSpec.URL, sysSpec.SHA256Sum, firmwareFile); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
logger.Info(ctx, "upgrading firmware")
|
||||
|
||||
if err := c.upgradeFirmware(ctx, firmwareFile); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *SysUpgradeController) downloadFile(ctx context.Context, url string, sha256sum string, dest string) error {
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
res, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := res.Body.Close(); err != nil && !errors.Is(err, os.ErrClosed) {
|
||||
panic(errors.WithStack(err))
|
||||
}
|
||||
}()
|
||||
|
||||
tmp, err := os.CreateTemp(filepath.Dir(dest), "download_")
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := os.Remove(tmp.Name()); err != nil && !os.IsNotExist(err) {
|
||||
panic(errors.WithStack(err))
|
||||
}
|
||||
}()
|
||||
|
||||
if _, err := io.Copy(tmp, res.Body); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
tmpFileHash, err := hash(tmp.Name())
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
if tmpFileHash != sha256sum {
|
||||
return errors.Errorf("sha256 sum mismatch: expected '%s', got '%s'", sha256sum, tmpFileHash)
|
||||
}
|
||||
|
||||
if err := os.Rename(tmp.Name(), dest); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *SysUpgradeController) upgradeFirmware(ctx context.Context, firmwareFile string) error {
|
||||
templatizedArgs := make([]string, len(c.args))
|
||||
for i, a := range c.args {
|
||||
templatizedArgs[i] = strings.Replace(a, FirmwareFileTemplate, firmwareFile, 1)
|
||||
}
|
||||
|
||||
command := exec.CommandContext(ctx, c.command, templatizedArgs...)
|
||||
|
||||
command.Stdout = os.Stdout
|
||||
command.Stderr = os.Stderr
|
||||
|
||||
logger.Debug(ctx, "executing command", logger.F("command", c.command), logger.F("args", templatizedArgs))
|
||||
|
||||
if err := command.Run(); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewSysUpgradeController(funcs ...SysUpgradeOptionFunc) *SysUpgradeController {
|
||||
opts := defaultSysUpgradeOptions()
|
||||
for _, fn := range funcs {
|
||||
fn(opts)
|
||||
}
|
||||
|
||||
return &SysUpgradeController{
|
||||
command: opts.Command,
|
||||
args: opts.Args,
|
||||
client: opts.Client,
|
||||
firmwareVersion: opts.FirmwareVersion,
|
||||
}
|
||||
}
|
||||
|
||||
var _ agent.Controller = &SysUpgradeController{}
|
@ -1,46 +0,0 @@
|
||||
package openwrt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gitlab.com/wpetit/goweb/logger"
|
||||
)
|
||||
|
||||
type ShellFirmwareVersion struct {
|
||||
command string
|
||||
args []string
|
||||
}
|
||||
|
||||
// FirmwareVersion implements FirmwareVersion
|
||||
func (fv *ShellFirmwareVersion) FirmwareVersion(ctx context.Context) (string, error) {
|
||||
command := exec.CommandContext(ctx, fv.command, fv.args...)
|
||||
|
||||
var buf bytes.Buffer
|
||||
|
||||
command.Stdout = &buf
|
||||
command.Stderr = os.Stderr
|
||||
|
||||
logger.Debug(ctx, "executing command", logger.F("command", fv.command), logger.F("args", fv.args))
|
||||
|
||||
if err := command.Run(); err != nil {
|
||||
return "", errors.WithStack(err)
|
||||
}
|
||||
|
||||
version := strings.TrimSpace(buf.String())
|
||||
|
||||
return version, nil
|
||||
}
|
||||
|
||||
func NewShellFirmwareVersion(command string, args ...string) *ShellFirmwareVersion {
|
||||
return &ShellFirmwareVersion{
|
||||
command: command,
|
||||
args: args,
|
||||
}
|
||||
}
|
||||
|
||||
var _ FirmwareVersion = &ShellFirmwareVersion{}
|
@ -1,58 +0,0 @@
|
||||
package openwrt
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
const FirmwareFileTemplate = "%FIRMWARE%"
|
||||
|
||||
type FirmwareVersion interface {
|
||||
FirmwareVersion(context.Context) (string, error)
|
||||
}
|
||||
|
||||
type SysUpgradeOptions struct {
|
||||
Command string
|
||||
Args []string
|
||||
FirmwareVersion FirmwareVersion
|
||||
Client *http.Client
|
||||
}
|
||||
|
||||
func defaultSysUpgradeOptions() *SysUpgradeOptions {
|
||||
return &SysUpgradeOptions{
|
||||
Command: `echo`,
|
||||
Args: []string{`[DUMMY UPGRADE]`, FirmwareFileTemplate},
|
||||
Client: &http.Client{
|
||||
Timeout: 30 * time.Second,
|
||||
},
|
||||
FirmwareVersion: NewShellFirmwareVersion(`echo`, "0.0.0-dummy"),
|
||||
}
|
||||
}
|
||||
|
||||
type SysUpgradeOptionFunc func(*SysUpgradeOptions)
|
||||
|
||||
func WithSysUpgradeCommand(command string, args ...string) SysUpgradeOptionFunc {
|
||||
return func(opts *SysUpgradeOptions) {
|
||||
opts.Command = command
|
||||
opts.Args = args
|
||||
}
|
||||
}
|
||||
|
||||
func WithSysUpgradeFirmwareVersion(firmwareVersion FirmwareVersion) SysUpgradeOptionFunc {
|
||||
return func(opts *SysUpgradeOptions) {
|
||||
opts.FirmwareVersion = firmwareVersion
|
||||
}
|
||||
}
|
||||
|
||||
func WithSysUpgradeShellFirmwareVersion(command string, args ...string) SysUpgradeOptionFunc {
|
||||
return func(opts *SysUpgradeOptions) {
|
||||
opts.FirmwareVersion = NewShellFirmwareVersion(command, args...)
|
||||
}
|
||||
}
|
||||
|
||||
func WithSysUpgradeClient(client *http.Client) SysUpgradeOptionFunc {
|
||||
return func(opts *SysUpgradeOptions) {
|
||||
opts.Client = client
|
||||
}
|
||||
}
|
@ -1,180 +0,0 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/agent"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/spec/proxy"
|
||||
edgeProxy "forge.cadoles.com/arcad/edge/pkg/proxy"
|
||||
"github.com/mitchellh/hashstructure/v2"
|
||||
"github.com/pkg/errors"
|
||||
"gitlab.com/wpetit/goweb/logger"
|
||||
)
|
||||
|
||||
type proxyEntry struct {
|
||||
SpecHash uint64
|
||||
Proxy *ReverseProxy
|
||||
}
|
||||
|
||||
type Controller struct {
|
||||
proxies map[proxy.ID]*proxyEntry
|
||||
}
|
||||
|
||||
// Name implements node.Controller.
|
||||
func (c *Controller) Name() string {
|
||||
return "proxy-controller"
|
||||
}
|
||||
|
||||
// Reconcile implements node.Controller.
|
||||
func (c *Controller) Reconcile(ctx context.Context, state *agent.State) error {
|
||||
proxySpec := proxy.NewSpec()
|
||||
|
||||
if err := state.GetSpec(proxy.NameProxy, proxySpec); err != nil {
|
||||
if errors.Is(err, agent.ErrSpecNotFound) {
|
||||
logger.Info(ctx, "could not find proxy spec")
|
||||
|
||||
c.stopAllProxies(ctx)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
logger.Info(ctx, "retrieved spec", logger.F("spec", proxySpec.SpecName()), logger.F("revision", proxySpec.SpecRevision()))
|
||||
|
||||
c.updateProxies(ctx, proxySpec)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Controller) stopAllProxies(ctx context.Context) {
|
||||
if len(c.proxies) > 0 {
|
||||
logger.Info(ctx, "stopping all proxies")
|
||||
}
|
||||
|
||||
for proxyID, entry := range c.proxies {
|
||||
logger.Info(ctx, "stopping proxy", logger.F("proxyID", proxyID))
|
||||
|
||||
if err := entry.Proxy.Stop(); err != nil {
|
||||
logger.Error(
|
||||
ctx, "error while stopping proxy",
|
||||
logger.F("proxyID", proxyID),
|
||||
logger.E(errors.WithStack(err)),
|
||||
)
|
||||
|
||||
delete(c.proxies, proxyID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) updateProxies(ctx context.Context, spec *proxy.Spec) {
|
||||
// Stop and remove obsolete proxys
|
||||
for proxyID, entry := range c.proxies {
|
||||
if _, exists := spec.Proxies[proxyID]; exists {
|
||||
continue
|
||||
}
|
||||
|
||||
logger.Info(ctx, "stopping proxy", logger.F("proxyID", proxyID))
|
||||
|
||||
if err := entry.Proxy.Stop(); err != nil {
|
||||
logger.Error(
|
||||
ctx, "error while stopping proxy",
|
||||
logger.F("proxyID", proxyID),
|
||||
logger.E(errors.WithStack(err)),
|
||||
)
|
||||
|
||||
delete(c.proxies, proxyID)
|
||||
}
|
||||
}
|
||||
|
||||
// (Re)start proxys
|
||||
for proxyID, proxySpec := range spec.Proxies {
|
||||
proxyCtx := logger.With(ctx, logger.F("proxyID", proxyID))
|
||||
|
||||
if err := c.updateProxy(ctx, proxyID, proxySpec); err != nil {
|
||||
logger.Error(proxyCtx, "could not update proxy", logger.E(errors.WithStack(err)))
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) updateProxy(ctx context.Context, proxyID proxy.ID, proxySpec proxy.ProxyEntry) (err error) {
|
||||
newProxySpecHash, err := hashstructure.Hash(proxySpec, hashstructure.FormatV2, nil)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
var entry *proxyEntry
|
||||
|
||||
entry, exists := c.proxies[proxyID]
|
||||
if !exists {
|
||||
logger.Info(ctx, "proxy currently not running")
|
||||
}
|
||||
|
||||
if entry == nil {
|
||||
entry = &proxyEntry{
|
||||
Proxy: NewReverseProxy(),
|
||||
SpecHash: 0,
|
||||
}
|
||||
|
||||
c.proxies[proxyID] = entry
|
||||
}
|
||||
|
||||
specChanged := newProxySpecHash != entry.SpecHash
|
||||
|
||||
if entry.Proxy.Running() && !specChanged {
|
||||
return nil
|
||||
}
|
||||
|
||||
if specChanged && entry.SpecHash != 0 {
|
||||
logger.Info(
|
||||
ctx, "restarting proxy",
|
||||
logger.F("address", proxySpec.Address),
|
||||
)
|
||||
} else {
|
||||
logger.Info(
|
||||
ctx, "starting proxy",
|
||||
logger.F("address", proxySpec.Address),
|
||||
)
|
||||
}
|
||||
|
||||
options := make([]edgeProxy.OptionFunc, 0)
|
||||
allowedHosts := make([]string, len(proxySpec.Mappings))
|
||||
mappings := make(map[string]*url.URL, len(proxySpec.Mappings))
|
||||
|
||||
for _, m := range proxySpec.Mappings {
|
||||
target, err := url.Parse(m.Target)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
mappings[m.HostPattern] = target
|
||||
allowedHosts = append(allowedHosts, m.HostPattern)
|
||||
}
|
||||
|
||||
options = append(
|
||||
options,
|
||||
edgeProxy.WithAllowedHosts(allowedHosts...),
|
||||
edgeProxy.WithRewriteHosts(mappings),
|
||||
)
|
||||
|
||||
if err := entry.Proxy.Start(ctx, proxySpec.Address, options...); err != nil {
|
||||
delete(c.proxies, proxyID)
|
||||
|
||||
return errors.Wrap(err, "could not start app")
|
||||
}
|
||||
|
||||
entry.SpecHash = newProxySpecHash
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewController() *Controller {
|
||||
return &Controller{
|
||||
proxies: make(map[proxy.ID]*proxyEntry),
|
||||
}
|
||||
}
|
||||
|
||||
var _ agent.Controller = &Controller{}
|
@ -21,15 +21,22 @@ func (c *Controller) Name() string {
|
||||
func (c *Controller) Reconcile(ctx context.Context, state *agent.State) error {
|
||||
cl := agent.Client(ctx)
|
||||
|
||||
agent, err := cl.GetAgent(
|
||||
agents, _, err := cl.QueryAgents(
|
||||
ctx,
|
||||
state.AgentID(),
|
||||
client.WithQueryAgentsLimit(1),
|
||||
client.WithQueryAgentsID(state.AgentID()),
|
||||
)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
if err := c.reconcileAgent(ctx, cl, state, agent); err != nil {
|
||||
if len(agents) == 0 {
|
||||
logger.Error(ctx, "could not find remote matching agent")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := c.reconcileAgent(ctx, cl, state, agents[0]); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ type User struct {
|
||||
|
||||
// Subject implements auth.User
|
||||
func (u *User) Subject() string {
|
||||
return fmt.Sprintf("agent-%d", u.agent.ID)
|
||||
return fmt.Sprintf("agent#%d", u.agent.ID)
|
||||
}
|
||||
|
||||
func (u *User) Agent() *datastore.Agent {
|
||||
|
@ -20,8 +20,8 @@ const (
|
||||
contextKeyUser contextKey = "user"
|
||||
)
|
||||
|
||||
func CtxUser(ctx context.Context) (User, error) {
|
||||
user, ok := ctx.Value(contextKeyUser).(User)
|
||||
func CtxUser(ctx context.Context) (*User, error) {
|
||||
user, ok := ctx.Value(contextKeyUser).(*User)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("unexpected user type: expected '%T', got '%T'", new(User), ctx.Value(contextKeyUser))
|
||||
}
|
||||
@ -29,7 +29,10 @@ func CtxUser(ctx context.Context) (User, error) {
|
||||
return user, nil
|
||||
}
|
||||
|
||||
var ErrUnauthenticated = errors.New("unauthenticated")
|
||||
var (
|
||||
ErrUnauthenticated = errors.New("unauthenticated")
|
||||
ErrForbidden = errors.New("forbidden")
|
||||
)
|
||||
|
||||
type User interface {
|
||||
Subject() string
|
||||
@ -52,7 +55,7 @@ func Middleware(authenticators ...Authenticator) func(http.Handler) http.Handler
|
||||
for _, auth := range authenticators {
|
||||
user, err = auth.Authenticate(ctx, r)
|
||||
if err != nil {
|
||||
logger.Debug(ctx, "could not authenticate request", logger.E(errors.WithStack(err)))
|
||||
logger.Warn(ctx, "could not authenticate request", logger.E(errors.WithStack(err)))
|
||||
|
||||
continue
|
||||
}
|
||||
@ -68,7 +71,6 @@ func Middleware(authenticators ...Authenticator) func(http.Handler) http.Handler
|
||||
return
|
||||
}
|
||||
|
||||
ctx = logger.With(ctx, logger.F("user", user.Subject()))
|
||||
ctx = context.WithValue(ctx, contextKeyUser, user)
|
||||
|
||||
h.ServeHTTP(w, r.WithContext(ctx))
|
||||
|
@ -1,4 +1,4 @@
|
||||
package thirdparty
|
||||
package user
|
||||
|
||||
import (
|
||||
"context"
|
@ -1,4 +1,4 @@
|
||||
package thirdparty
|
||||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -27,17 +27,9 @@ func parseToken(ctx context.Context, keys jwk.Set, issuer string, rawToken strin
|
||||
return token, nil
|
||||
}
|
||||
|
||||
func GenerateToken(ctx context.Context, key jwk.Key, issuer, subject string, role Role) (string, error) {
|
||||
func GenerateToken(ctx context.Context, key jwk.Key, role Role) (string, error) {
|
||||
token := jwt.New()
|
||||
|
||||
if err := token.Set(jwt.SubjectKey, subject); err != nil {
|
||||
return "", errors.WithStack(err)
|
||||
}
|
||||
|
||||
if err := token.Set(jwt.IssuerKey, issuer); err != nil {
|
||||
return "", errors.WithStack(err)
|
||||
}
|
||||
|
||||
if err := token.Set(keyRole, role); err != nil {
|
||||
return "", errors.WithStack(err)
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package thirdparty
|
||||
package user
|
||||
|
||||
import "forge.cadoles.com/Cadoles/emissary/internal/auth"
|
||||
|
@ -1,27 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/datastore"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func (c *Client) DeleteAgent(ctx context.Context, agentID datastore.AgentID, funcs ...OptionFunc) (datastore.AgentID, error) {
|
||||
response := withResponse[struct {
|
||||
AgentID int64 `json:"agentId"`
|
||||
}]()
|
||||
|
||||
path := fmt.Sprintf("/api/v1/agents/%d", agentID)
|
||||
|
||||
if err := c.apiDelete(ctx, path, nil, &response, funcs...); err != nil {
|
||||
return 0, errors.WithStack(err)
|
||||
}
|
||||
|
||||
if response.Error != nil {
|
||||
return 0, errors.WithStack(response.Error)
|
||||
}
|
||||
|
||||
return datastore.AgentID(response.Data.AgentID), nil
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/datastore"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/spec"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func (c *Client) DeleteAgentSpec(ctx context.Context, agentID datastore.AgentID, name spec.Name, funcs ...OptionFunc) (spec.Name, error) {
|
||||
payload := struct {
|
||||
Name spec.Name `json:"name"`
|
||||
}{
|
||||
Name: name,
|
||||
}
|
||||
|
||||
response := withResponse[struct {
|
||||
Name spec.Name `json:"name"`
|
||||
}]()
|
||||
|
||||
path := fmt.Sprintf("/api/v1/agents/%d/specs", agentID)
|
||||
|
||||
if err := c.apiDelete(ctx, path, payload, &response, funcs...); err != nil {
|
||||
return "", errors.WithStack(err)
|
||||
}
|
||||
|
||||
if response.Error != nil {
|
||||
return "", errors.WithStack(response.Error)
|
||||
}
|
||||
|
||||
return response.Data.Name, nil
|
||||
}
|
@ -10,6 +10,7 @@ import (
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/common"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/openwrt/uci"
|
||||
"github.com/pkg/errors"
|
||||
_ "github.com/santhosh-tekuri/jsonschema/v5/httploader"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
|
@ -14,7 +14,6 @@ func Root() *cli.Command {
|
||||
openwrt.Root(),
|
||||
config.Root(),
|
||||
RunCommand(),
|
||||
ShowThumbprintCommand(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -5,9 +5,9 @@ import (
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/agent"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/agent/controller/app"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/agent/controller/gateway"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/agent/controller/openwrt"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/agent/controller/persistence"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/agent/controller/proxy"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/agent/controller/spec"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/agent/metadata"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/agent/metadata/collector/buildinfo"
|
||||
@ -17,6 +17,7 @@ import (
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/jwk"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/machineid"
|
||||
"github.com/pkg/errors"
|
||||
_ "github.com/santhosh-tekuri/jsonschema/v5/httploader"
|
||||
"github.com/urfave/cli/v2"
|
||||
"gitlab.com/wpetit/goweb/logger"
|
||||
)
|
||||
@ -49,8 +50,8 @@ func RunCommand() *cli.Command {
|
||||
controllers = append(controllers, spec.NewController())
|
||||
}
|
||||
|
||||
if ctrlConf.Proxy.Enabled {
|
||||
controllers = append(controllers, proxy.NewController())
|
||||
if ctrlConf.Gateway.Enabled {
|
||||
controllers = append(controllers, gateway.NewController())
|
||||
}
|
||||
|
||||
if ctrlConf.UCI.Enabled {
|
||||
@ -66,29 +67,6 @@ func RunCommand() *cli.Command {
|
||||
))
|
||||
}
|
||||
|
||||
if ctrlConf.SysUpgrade.Enabled {
|
||||
sysUpgradeArgs := make([]string, 0)
|
||||
if len(ctrlConf.SysUpgrade.SysUpgradeCommand) > 1 {
|
||||
sysUpgradeArgs = ctrlConf.SysUpgrade.SysUpgradeCommand[1:]
|
||||
}
|
||||
|
||||
firmwareVersionArgs := make([]string, 0)
|
||||
if len(ctrlConf.SysUpgrade.FirmwareVersionCommand) > 1 {
|
||||
firmwareVersionArgs = ctrlConf.SysUpgrade.FirmwareVersionCommand[1:]
|
||||
}
|
||||
|
||||
controllers = append(controllers, openwrt.NewSysUpgradeController(
|
||||
openwrt.WithSysUpgradeCommand(
|
||||
ctrlConf.SysUpgrade.SysUpgradeCommand[0],
|
||||
sysUpgradeArgs...,
|
||||
),
|
||||
openwrt.WithSysUpgradeShellFirmwareVersion(
|
||||
ctrlConf.SysUpgrade.FirmwareVersionCommand[0],
|
||||
firmwareVersionArgs...,
|
||||
),
|
||||
))
|
||||
}
|
||||
|
||||
key, err := jwk.LoadOrGenerate(string(conf.Agent.PrivateKeyPath), jwk.DefaultKeySize)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
|
@ -1,30 +0,0 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/common"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/machineid"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func ShowThumbprintCommand() *cli.Command {
|
||||
flags := common.Flags()
|
||||
|
||||
return &cli.Command{
|
||||
Name: "show-thumbprint",
|
||||
Usage: "Show the current agent thumbprint",
|
||||
Flags: flags,
|
||||
Action: func(ctx *cli.Context) error {
|
||||
thumbprint, err := machineid.Get()
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
fmt.Println(thumbprint)
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/client"
|
||||
agentFlag "forge.cadoles.com/Cadoles/emissary/internal/command/api/agent/flag"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/api/apierr"
|
||||
clientFlag "forge.cadoles.com/Cadoles/emissary/internal/command/api/flag"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/datastore"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/format"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func DeleteCommand() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "delete",
|
||||
Usage: "Delete agent",
|
||||
Flags: agentFlag.WithAgentFlags(),
|
||||
Action: func(ctx *cli.Context) error {
|
||||
baseFlags := clientFlag.GetBaseFlags(ctx)
|
||||
|
||||
token, err := clientFlag.GetToken(baseFlags)
|
||||
if err != nil {
|
||||
return errors.WithStack(apierr.Wrap(err))
|
||||
}
|
||||
|
||||
agentID, err := agentFlag.AssertAgentID(ctx)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
client := client.New(baseFlags.ServerURL, client.WithToken(token))
|
||||
|
||||
agentID, err = client.DeleteAgent(ctx.Context, agentID)
|
||||
if err != nil {
|
||||
return errors.WithStack(apierr.Wrap(err))
|
||||
}
|
||||
|
||||
hints := format.Hints{
|
||||
OutputMode: baseFlags.OutputMode,
|
||||
}
|
||||
|
||||
if err := format.Write(baseFlags.Format, os.Stdout, hints, struct {
|
||||
ID datastore.AgentID `json:"id"`
|
||||
}{
|
||||
ID: agentID,
|
||||
}); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/client"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/api/apierr"
|
||||
clientFlag "forge.cadoles.com/Cadoles/emissary/internal/command/api/flag"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/datastore"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/format"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func QueryCommand() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "query",
|
||||
Usage: "Query agents",
|
||||
Flags: clientFlag.ComposeFlags(
|
||||
&cli.StringSliceFlag{
|
||||
Name: "thumbprints",
|
||||
Usage: "use `THUMBPRINTS` as query filter",
|
||||
Value: nil,
|
||||
},
|
||||
&cli.Int64SliceFlag{
|
||||
Name: "statuses",
|
||||
Usage: "use `STATUSES` as query filter",
|
||||
},
|
||||
&cli.Int64SliceFlag{
|
||||
Name: "ids",
|
||||
Usage: "use `IDS` as query filter",
|
||||
},
|
||||
),
|
||||
Action: func(ctx *cli.Context) error {
|
||||
baseFlags := clientFlag.GetBaseFlags(ctx)
|
||||
|
||||
token, err := clientFlag.GetToken(baseFlags)
|
||||
if err != nil {
|
||||
return errors.WithStack(apierr.Wrap(err))
|
||||
}
|
||||
|
||||
options := make([]client.QueryAgentsOptionFunc, 0)
|
||||
|
||||
thumbprints := ctx.StringSlice("thumbprints")
|
||||
if thumbprints != nil {
|
||||
options = append(options, client.WithQueryAgentsThumbprints(thumbprints...))
|
||||
}
|
||||
|
||||
rawIDs := ctx.Int64Slice("ids")
|
||||
if rawIDs != nil {
|
||||
agentIDs := func(ids []int64) []datastore.AgentID {
|
||||
agentIDs := make([]datastore.AgentID, len(ids))
|
||||
for i, id := range ids {
|
||||
agentIDs[i] = datastore.AgentID(id)
|
||||
}
|
||||
return agentIDs
|
||||
}(rawIDs)
|
||||
options = append(options, client.WithQueryAgentsID(agentIDs...))
|
||||
}
|
||||
|
||||
rawStatuses := ctx.Int64Slice("statuses")
|
||||
if rawStatuses != nil {
|
||||
statuses := func(rawStatuses []int64) []datastore.AgentStatus {
|
||||
statuses := make([]datastore.AgentStatus, len(rawStatuses))
|
||||
for i, status := range rawStatuses {
|
||||
statuses[i] = datastore.AgentStatus(status)
|
||||
}
|
||||
return statuses
|
||||
}(rawStatuses)
|
||||
options = append(options, client.WithQueryAgentsStatus(statuses...))
|
||||
}
|
||||
|
||||
client := client.New(baseFlags.ServerURL, client.WithToken(token))
|
||||
|
||||
agents, _, err := client.QueryAgents(ctx.Context, options...)
|
||||
if err != nil {
|
||||
return errors.WithStack(apierr.Wrap(err))
|
||||
}
|
||||
|
||||
hints := agentHints(baseFlags.OutputMode)
|
||||
|
||||
if err := format.Write(baseFlags.Format, os.Stdout, hints, clientFlag.AsAnySlice(agents)...); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
package spec
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/client"
|
||||
agentFlag "forge.cadoles.com/Cadoles/emissary/internal/command/api/agent/flag"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/api/apierr"
|
||||
clientFlag "forge.cadoles.com/Cadoles/emissary/internal/command/api/flag"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/format"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/spec"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func DeleteCommand() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "delete",
|
||||
Usage: "Delete spec",
|
||||
|
||||
Flags: agentFlag.WithAgentFlags(
|
||||
&cli.StringFlag{
|
||||
Name: "spec-name",
|
||||
Usage: "use `NAME` as specification's name",
|
||||
},
|
||||
),
|
||||
Action: func(ctx *cli.Context) error {
|
||||
baseFlags := clientFlag.GetBaseFlags(ctx)
|
||||
|
||||
token, err := clientFlag.GetToken(baseFlags)
|
||||
if err != nil {
|
||||
return errors.WithStack(apierr.Wrap(err))
|
||||
}
|
||||
|
||||
agentID, err := agentFlag.AssertAgentID(ctx)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
specName, err := assertSpecName(ctx)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
client := client.New(baseFlags.ServerURL, client.WithToken(token))
|
||||
|
||||
specName, err = client.DeleteAgentSpec(ctx.Context, agentID, specName)
|
||||
if err != nil {
|
||||
return errors.WithStack(apierr.Wrap(err))
|
||||
}
|
||||
|
||||
hints := format.Hints{
|
||||
OutputMode: baseFlags.OutputMode,
|
||||
}
|
||||
|
||||
if err := format.Write(baseFlags.Format, os.Stdout, hints, struct {
|
||||
Name spec.Name `json:"name"`
|
||||
}{
|
||||
Name: specName,
|
||||
}); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/api/agent"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func Root() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "api",
|
||||
Usage: "API related commands",
|
||||
Subcommands: []*cli.Command{
|
||||
agent.Root(),
|
||||
},
|
||||
}
|
||||
}
|
@ -4,8 +4,8 @@ import (
|
||||
"os"
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/client"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/api/apierr"
|
||||
clientFlag "forge.cadoles.com/Cadoles/emissary/internal/command/api/flag"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/client/apierr"
|
||||
clientFlag "forge.cadoles.com/Cadoles/emissary/internal/command/client/flag"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/format"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli/v2"
|
||||
@ -18,13 +18,7 @@ func CountCommand() *cli.Command {
|
||||
Flags: clientFlag.ComposeFlags(),
|
||||
Action: func(ctx *cli.Context) error {
|
||||
baseFlags := clientFlag.GetBaseFlags(ctx)
|
||||
|
||||
token, err := clientFlag.GetToken(baseFlags)
|
||||
if err != nil {
|
||||
return errors.WithStack(apierr.Wrap(err))
|
||||
}
|
||||
|
||||
client := client.New(baseFlags.ServerURL, client.WithToken(token))
|
||||
client := client.New(baseFlags.ServerURL)
|
||||
|
||||
_, total, err := client.QueryAgents(ctx.Context)
|
||||
if err != nil {
|
@ -3,7 +3,7 @@ package flag
|
||||
import (
|
||||
"errors"
|
||||
|
||||
clientFlag "forge.cadoles.com/Cadoles/emissary/internal/command/api/flag"
|
||||
clientFlag "forge.cadoles.com/Cadoles/emissary/internal/command/client/flag"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/datastore"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
@ -4,9 +4,9 @@ import (
|
||||
"os"
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/client"
|
||||
agentFlag "forge.cadoles.com/Cadoles/emissary/internal/command/api/agent/flag"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/api/apierr"
|
||||
clientFlag "forge.cadoles.com/Cadoles/emissary/internal/command/api/flag"
|
||||
agentFlag "forge.cadoles.com/Cadoles/emissary/internal/command/client/agent/flag"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/client/apierr"
|
||||
clientFlag "forge.cadoles.com/Cadoles/emissary/internal/command/client/flag"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/format"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli/v2"
|
||||
@ -20,17 +20,12 @@ func GetCommand() *cli.Command {
|
||||
Action: func(ctx *cli.Context) error {
|
||||
baseFlags := clientFlag.GetBaseFlags(ctx)
|
||||
|
||||
token, err := clientFlag.GetToken(baseFlags)
|
||||
if err != nil {
|
||||
return errors.WithStack(apierr.Wrap(err))
|
||||
}
|
||||
|
||||
agentID, err := agentFlag.AssertAgentID(ctx)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
client := client.New(baseFlags.ServerURL, client.WithToken(token))
|
||||
client := client.New(baseFlags.ServerURL)
|
||||
|
||||
agent, err := client.GetAgent(ctx.Context, agentID)
|
||||
if err != nil {
|
37
internal/command/client/agent/query.go
Normal file
37
internal/command/client/agent/query.go
Normal file
@ -0,0 +1,37 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/client"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/client/apierr"
|
||||
clientFlag "forge.cadoles.com/Cadoles/emissary/internal/command/client/flag"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/format"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func QueryCommand() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "query",
|
||||
Usage: "Query agents",
|
||||
Flags: clientFlag.ComposeFlags(),
|
||||
Action: func(ctx *cli.Context) error {
|
||||
baseFlags := clientFlag.GetBaseFlags(ctx)
|
||||
client := client.New(baseFlags.ServerURL)
|
||||
|
||||
agents, _, err := client.QueryAgents(ctx.Context)
|
||||
if err != nil {
|
||||
return errors.WithStack(apierr.Wrap(err))
|
||||
}
|
||||
|
||||
hints := agentHints(baseFlags.OutputMode)
|
||||
|
||||
if err := format.Write(baseFlags.Format, os.Stdout, hints, clientFlag.AsAnySlice(agents)...); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/api/agent/spec"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/client/agent/spec"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
@ -14,7 +14,6 @@ func Root() *cli.Command {
|
||||
CountCommand(),
|
||||
UpdateCommand(),
|
||||
GetCommand(),
|
||||
DeleteCommand(),
|
||||
spec.Root(),
|
||||
},
|
||||
}
|
@ -4,9 +4,9 @@ import (
|
||||
"os"
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/client"
|
||||
agentFlag "forge.cadoles.com/Cadoles/emissary/internal/command/api/agent/flag"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/api/apierr"
|
||||
clientFlag "forge.cadoles.com/Cadoles/emissary/internal/command/api/flag"
|
||||
agentFlag "forge.cadoles.com/Cadoles/emissary/internal/command/client/agent/flag"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/client/apierr"
|
||||
clientFlag "forge.cadoles.com/Cadoles/emissary/internal/command/client/flag"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/format"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli/v2"
|
||||
@ -24,12 +24,7 @@ func GetCommand() *cli.Command {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
token, err := clientFlag.GetToken(baseFlags)
|
||||
if err != nil {
|
||||
return errors.WithStack(apierr.Wrap(err))
|
||||
}
|
||||
|
||||
client := client.New(baseFlags.ServerURL, client.WithToken(token))
|
||||
client := client.New(baseFlags.ServerURL)
|
||||
|
||||
specs, err := client.GetAgentSpecs(ctx.Context, agentID)
|
||||
if err != nil {
|
@ -11,7 +11,6 @@ func Root() *cli.Command {
|
||||
Subcommands: []*cli.Command{
|
||||
GetCommand(),
|
||||
UpdateCommand(),
|
||||
DeleteCommand(),
|
||||
},
|
||||
}
|
||||
}
|
@ -5,14 +5,19 @@ import (
|
||||
"os"
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/client"
|
||||
agentFlag "forge.cadoles.com/Cadoles/emissary/internal/command/api/agent/flag"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/api/apierr"
|
||||
clientFlag "forge.cadoles.com/Cadoles/emissary/internal/command/api/flag"
|
||||
agentFlag "forge.cadoles.com/Cadoles/emissary/internal/command/client/agent/flag"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/client/apierr"
|
||||
clientFlag "forge.cadoles.com/Cadoles/emissary/internal/command/client/flag"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/format"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/spec"
|
||||
jsonpatch "github.com/evanphx/json-patch/v5"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
// Import specs
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/spec/app"
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/spec/gateway"
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/spec/uci"
|
||||
)
|
||||
|
||||
func UpdateCommand() *cli.Command {
|
||||
@ -22,11 +27,11 @@ func UpdateCommand() *cli.Command {
|
||||
Flags: agentFlag.WithAgentFlags(
|
||||
&cli.StringFlag{
|
||||
Name: "spec-name",
|
||||
Usage: "use `NAME` as specification's name",
|
||||
Usage: "use `NAME` as spec name",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "spec-data",
|
||||
Usage: "use `DATA` as specification's data, '-' to read from STDIN",
|
||||
Usage: "use `DATA` as spec data, '-' to read from STDIN",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "no-patch",
|
||||
@ -56,12 +61,7 @@ func UpdateCommand() *cli.Command {
|
||||
|
||||
noPatch := ctx.Bool("no-patch")
|
||||
|
||||
token, err := clientFlag.GetToken(baseFlags)
|
||||
if err != nil {
|
||||
return errors.WithStack(apierr.Wrap(err))
|
||||
}
|
||||
|
||||
client := client.New(baseFlags.ServerURL, client.WithToken(token))
|
||||
client := client.New(baseFlags.ServerURL)
|
||||
|
||||
specs, err := client.GetAgentSpecs(ctx.Context, agentID)
|
||||
if err != nil {
|
@ -4,9 +4,9 @@ import (
|
||||
"os"
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/client"
|
||||
agentFlag "forge.cadoles.com/Cadoles/emissary/internal/command/api/agent/flag"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/api/apierr"
|
||||
clientFlag "forge.cadoles.com/Cadoles/emissary/internal/command/api/flag"
|
||||
agentFlag "forge.cadoles.com/Cadoles/emissary/internal/command/client/agent/flag"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/client/apierr"
|
||||
clientFlag "forge.cadoles.com/Cadoles/emissary/internal/command/client/flag"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/format"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli/v2"
|
||||
@ -26,11 +26,6 @@ func UpdateCommand() *cli.Command {
|
||||
Action: func(ctx *cli.Context) error {
|
||||
baseFlags := clientFlag.GetBaseFlags(ctx)
|
||||
|
||||
token, err := clientFlag.GetToken(baseFlags)
|
||||
if err != nil {
|
||||
return errors.WithStack(apierr.Wrap(err))
|
||||
}
|
||||
|
||||
agentID, err := agentFlag.AssertAgentID(ctx)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
@ -43,7 +38,7 @@ func UpdateCommand() *cli.Command {
|
||||
options = append(options, client.WithAgentStatus(status))
|
||||
}
|
||||
|
||||
client := client.New(baseFlags.ServerURL, client.WithToken(token))
|
||||
client := client.New(baseFlags.ServerURL)
|
||||
|
||||
agent, err := client.UpdateAgent(ctx.Context, agentID, options...)
|
||||
if err != nil {
|
@ -2,13 +2,9 @@ package flag
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/format"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/format/table"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
@ -32,17 +28,6 @@ func ComposeFlags(flags ...cli.Flag) []cli.Flag {
|
||||
Usage: fmt.Sprintf("use `MODE` as output mode (available: %s)", []format.OutputMode{format.OutputModeCompact, format.OutputModeWide}),
|
||||
Value: string(format.OutputModeCompact),
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "token",
|
||||
Aliases: []string{"t"},
|
||||
Usage: "use `TOKEN` as authentication token",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "token-file",
|
||||
Usage: "use `TOKEN_FILE` as file containing the authentication token",
|
||||
Value: ".emissary-token",
|
||||
TakesFile: true,
|
||||
},
|
||||
}
|
||||
|
||||
flags = append(flags, baseFlags...)
|
||||
@ -54,43 +39,16 @@ type BaseFlags struct {
|
||||
ServerURL string
|
||||
Format format.Format
|
||||
OutputMode format.OutputMode
|
||||
Token string
|
||||
TokenFile string
|
||||
}
|
||||
|
||||
func GetBaseFlags(ctx *cli.Context) *BaseFlags {
|
||||
serverURL := ctx.String("server")
|
||||
rawFormat := ctx.String("format")
|
||||
rawOutputMode := ctx.String("output-mode")
|
||||
tokenFile := ctx.String("token-file")
|
||||
token := ctx.String("token")
|
||||
|
||||
return &BaseFlags{
|
||||
ServerURL: serverURL,
|
||||
Format: format.Format(rawFormat),
|
||||
OutputMode: format.OutputMode(rawOutputMode),
|
||||
Token: token,
|
||||
TokenFile: tokenFile,
|
||||
}
|
||||
}
|
||||
|
||||
func GetToken(flags *BaseFlags) (string, error) {
|
||||
if flags.Token != "" {
|
||||
return flags.Token, nil
|
||||
}
|
||||
|
||||
if flags.TokenFile == "" {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
rawToken, err := ioutil.ReadFile(flags.TokenFile)
|
||||
if err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||
return "", errors.WithStack(err)
|
||||
}
|
||||
|
||||
if rawToken == nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
return strings.TrimSpace(string(rawToken)), nil
|
||||
}
|
20
internal/command/client/root.go
Normal file
20
internal/command/client/root.go
Normal file
@ -0,0 +1,20 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/client/agent"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
// Output format
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/format/json"
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/format/table"
|
||||
)
|
||||
|
||||
func Root() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "client",
|
||||
Usage: "Client related commands",
|
||||
Subcommands: []*cli.Command{
|
||||
agent.Root(),
|
||||
},
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ import (
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/common"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/config"
|
||||
"github.com/pkg/errors"
|
||||
_ "github.com/santhosh-tekuri/jsonschema/v5/httploader"
|
||||
"github.com/urfave/cli/v2"
|
||||
"gitlab.com/wpetit/goweb/logger"
|
||||
)
|
||||
|
@ -9,6 +9,10 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
// Spec validation
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/spec/gateway"
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/spec/uci"
|
||||
)
|
||||
|
||||
func Main(buildDate, projectVersion, gitRef, defaultConfigPath string, commands ...*cli.Command) {
|
||||
|
@ -1,54 +0,0 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/auth/thirdparty"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/common"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/jwk"
|
||||
"github.com/lithammer/shortuuid/v4"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func CreateTokenCommand() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "create-token",
|
||||
Usage: "Create a new authentication token",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "role",
|
||||
Usage: fmt.Sprintf("associate `ROLE` to the token (available: %v)", []thirdparty.Role{thirdparty.RoleReader, thirdparty.RoleWriter}),
|
||||
Value: string(thirdparty.RoleReader),
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "subject",
|
||||
Usage: "associate `SUBJECT` to the token",
|
||||
Value: fmt.Sprintf("user-%s", shortuuid.New()),
|
||||
},
|
||||
},
|
||||
Action: func(ctx *cli.Context) error {
|
||||
conf, err := common.LoadConfig(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Could not load configuration")
|
||||
}
|
||||
|
||||
subject := ctx.String("subject")
|
||||
role := ctx.String("role")
|
||||
|
||||
key, err := jwk.LoadOrGenerate(string(conf.Server.PrivateKeyPath), jwk.DefaultKeySize)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
token, err := thirdparty.GenerateToken(ctx.Context, key, string(conf.Server.Issuer), subject, thirdparty.Role(role))
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
fmt.Println(token)
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
@ -8,8 +8,6 @@ func Root() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "auth",
|
||||
Usage: "Authentication related commands",
|
||||
Subcommands: []*cli.Command{
|
||||
CreateTokenCommand(),
|
||||
},
|
||||
Subcommands: []*cli.Command{},
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/common"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/server"
|
||||
"github.com/pkg/errors"
|
||||
_ "github.com/santhosh-tekuri/jsonschema/v5/httploader"
|
||||
"github.com/urfave/cli/v2"
|
||||
"gitlab.com/wpetit/goweb/logger"
|
||||
)
|
||||
|
@ -1,7 +1,5 @@
|
||||
package config
|
||||
|
||||
import "forge.cadoles.com/Cadoles/emissary/internal/agent/controller/openwrt"
|
||||
|
||||
type AgentConfig struct {
|
||||
ServerURL InterpolatedString `yaml:"serverUrl"`
|
||||
PrivateKeyPath InterpolatedString `yaml:"privateKeyPath"`
|
||||
@ -19,10 +17,9 @@ type ShellCollectorConfig struct {
|
||||
type ControllersConfig struct {
|
||||
Persistence PersistenceControllerConfig `yaml:"persistence"`
|
||||
Spec SpecControllerConfig `yaml:"spec"`
|
||||
Proxy ProxyControllerConfig `yaml:"proxy"`
|
||||
Gateway GatewayControllerConfig `yaml:"gateway"`
|
||||
UCI UCIControllerConfig `yaml:"uci"`
|
||||
App AppControllerConfig `yaml:"app"`
|
||||
SysUpgrade SysUpgradeControllerConfig `yaml:"sysupgrade"`
|
||||
}
|
||||
|
||||
type PersistenceControllerConfig struct {
|
||||
@ -33,7 +30,7 @@ type PersistenceControllerConfig struct {
|
||||
type SpecControllerConfig struct {
|
||||
Enabled InterpolatedBool `yaml:"enabled"`
|
||||
}
|
||||
type ProxyControllerConfig struct {
|
||||
type GatewayControllerConfig struct {
|
||||
Enabled InterpolatedBool `yaml:"enabled"`
|
||||
}
|
||||
|
||||
@ -49,12 +46,6 @@ type AppControllerConfig struct {
|
||||
DownloadDir InterpolatedString `yaml:"downloadDir"`
|
||||
}
|
||||
|
||||
type SysUpgradeControllerConfig struct {
|
||||
Enabled InterpolatedBool `yaml:"enabled"`
|
||||
SysUpgradeCommand InterpolatedStringSlice `yaml:"sysupgradeCommand"`
|
||||
FirmwareVersionCommand InterpolatedStringSlice `yaml:"firmwareVersionCommand"`
|
||||
}
|
||||
|
||||
func NewDefaultAgentConfig() AgentConfig {
|
||||
return AgentConfig{
|
||||
ServerURL: "http://127.0.0.1:3000",
|
||||
@ -68,7 +59,7 @@ func NewDefaultAgentConfig() AgentConfig {
|
||||
Enabled: true,
|
||||
StateFile: "state.json",
|
||||
},
|
||||
Proxy: ProxyControllerConfig{
|
||||
Gateway: GatewayControllerConfig{
|
||||
Enabled: true,
|
||||
},
|
||||
UCI: UCIControllerConfig{
|
||||
@ -81,11 +72,6 @@ func NewDefaultAgentConfig() AgentConfig {
|
||||
DataDir: "apps/data",
|
||||
DownloadDir: "apps/bundles",
|
||||
},
|
||||
SysUpgrade: SysUpgradeControllerConfig{
|
||||
Enabled: true,
|
||||
SysUpgradeCommand: InterpolatedStringSlice{"sysupgrade", "--force", "-u", "-v", openwrt.FirmwareFileTemplate},
|
||||
FirmwareVersionCommand: InterpolatedStringSlice{"sh", "-c", `source /etc/openwrt_release && echo "$DISTRIB_ID-$DISTRIB_RELEASE-$DISTRIB_REVISION"`},
|
||||
},
|
||||
},
|
||||
Collectors: []ShellCollectorConfig{
|
||||
{
|
||||
|
@ -269,25 +269,13 @@ func (r *AgentRepository) Create(ctx context.Context, thumbprint string, keySet
|
||||
|
||||
// Delete implements datastore.AgentRepository
|
||||
func (r *AgentRepository) Delete(ctx context.Context, id datastore.AgentID) error {
|
||||
err := r.withTx(ctx, func(tx *sql.Tx) error {
|
||||
query := `DELETE FROM agents WHERE id = $1`
|
||||
|
||||
_, err := r.db.ExecContext(ctx, query, id)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
query = `DELETE FROM specs WHERE agent_id = $1`
|
||||
_, err = r.db.ExecContext(ctx, query, id)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -1,6 +0,0 @@
|
||||
package format
|
||||
|
||||
import (
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/format/json"
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/format/table"
|
||||
)
|
@ -1,6 +0,0 @@
|
||||
package passwd
|
||||
|
||||
import (
|
||||
_ "forge.cadoles.com/arcad/edge/pkg/module/auth/http/passwd/argon2id"
|
||||
_ "forge.cadoles.com/arcad/edge/pkg/module/auth/http/passwd/plain"
|
||||
)
|
@ -1,8 +0,0 @@
|
||||
package spec
|
||||
|
||||
import (
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/agent/controller/openwrt/spec/sysupgrade"
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/spec/app"
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/spec/proxy"
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/spec/uci"
|
||||
)
|
@ -1,6 +0,0 @@
|
||||
package sql
|
||||
|
||||
import (
|
||||
_ "github.com/jackc/pgx/v5/stdlib"
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
@ -18,8 +18,7 @@ import (
|
||||
const (
|
||||
ErrCodeUnknownError api.ErrorCode = "unknown-error"
|
||||
ErrCodeNotFound api.ErrorCode = "not-found"
|
||||
ErrCodeInvalidSignature api.ErrorCode = "invalid-signature"
|
||||
ErrCodeConflict api.ErrorCode = "conflict"
|
||||
ErrInvalidSignature api.ErrorCode = "invalid-signature"
|
||||
)
|
||||
|
||||
type registerAgentRequest struct {
|
||||
@ -47,8 +46,6 @@ func (s *Server) registerAgent(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
ctx = logger.With(ctx, logger.F("agentThumbprint", registerAgentReq.Thumbprint))
|
||||
|
||||
// Validate that the existing signature validates the request
|
||||
|
||||
validSignature, err := jwk.Verify(keySet, registerAgentReq.Signature, registerAgentReq.Thumbprint, registerAgentReq.Metadata)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "could not validate signature", logger.E(errors.WithStack(err)))
|
||||
@ -58,8 +55,8 @@ func (s *Server) registerAgent(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if !validSignature {
|
||||
logger.Error(ctx, "conflicting signature", logger.F("signature", registerAgentReq.Signature))
|
||||
api.ErrorResponse(w, http.StatusConflict, ErrCodeConflict, nil)
|
||||
logger.Error(ctx, "invalid signature", logger.F("signature", registerAgentReq.Signature))
|
||||
api.ErrorResponse(w, http.StatusBadRequest, ErrInvalidSignature, nil)
|
||||
|
||||
return
|
||||
}
|
||||
@ -100,28 +97,6 @@ func (s *Server) registerAgent(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
agentID := agents[0].ID
|
||||
|
||||
agent, err = s.agentRepo.Get(ctx, agentID)
|
||||
if err != nil {
|
||||
logger.Error(
|
||||
ctx, "could not retrieve agent",
|
||||
logger.E(errors.WithStack(err)), logger.F("agentID", agentID),
|
||||
)
|
||||
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
validSignature, err = jwk.Verify(agent.KeySet.Set, registerAgentReq.Signature, registerAgentReq.Thumbprint, registerAgentReq.Metadata)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "could not validate signature using previous keyset", logger.E(errors.WithStack(err)))
|
||||
|
||||
api.ErrorResponse(w, http.StatusConflict, ErrCodeConflict, nil)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
agent, err = s.agentRepo.Update(
|
||||
ctx, agents[0].ID,
|
||||
datastore.WithAgentUpdateKeySet(keySet),
|
||||
|
@ -1,155 +0,0 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/auth"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/auth/agent"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/auth/thirdparty"
|
||||
"github.com/pkg/errors"
|
||||
"gitlab.com/wpetit/goweb/api"
|
||||
"gitlab.com/wpetit/goweb/logger"
|
||||
)
|
||||
|
||||
var ErrCodeForbidden api.ErrorCode = "forbidden"
|
||||
|
||||
func assertGlobalReadAccess(h http.Handler) http.Handler {
|
||||
fn := func(w http.ResponseWriter, r *http.Request) {
|
||||
reqUser, ok := assertRequestUser(w, r)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
switch user := reqUser.(type) {
|
||||
case *thirdparty.User:
|
||||
role := user.Role()
|
||||
if role == thirdparty.RoleReader || role == thirdparty.RoleWriter {
|
||||
h.ServeHTTP(w, r)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
case *agent.User:
|
||||
// Agents dont have global read access
|
||||
|
||||
default:
|
||||
logUnexpectedUserType(r.Context(), reqUser)
|
||||
}
|
||||
|
||||
forbidden(w, r)
|
||||
}
|
||||
|
||||
return http.HandlerFunc(fn)
|
||||
}
|
||||
|
||||
func assertAgentWriteAccess(h http.Handler) http.Handler {
|
||||
fn := func(w http.ResponseWriter, r *http.Request) {
|
||||
reqUser, ok := assertRequestUser(w, r)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
agentID, ok := getAgentID(w, r)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
switch user := reqUser.(type) {
|
||||
case *thirdparty.User:
|
||||
role := user.Role()
|
||||
if role == thirdparty.RoleWriter {
|
||||
h.ServeHTTP(w, r)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
case *agent.User:
|
||||
if user.Agent().ID == agentID {
|
||||
h.ServeHTTP(w, r)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
default:
|
||||
logUnexpectedUserType(r.Context(), reqUser)
|
||||
}
|
||||
|
||||
forbidden(w, r)
|
||||
}
|
||||
|
||||
return http.HandlerFunc(fn)
|
||||
}
|
||||
|
||||
func assertAgentReadAccess(h http.Handler) http.Handler {
|
||||
fn := func(w http.ResponseWriter, r *http.Request) {
|
||||
reqUser, ok := assertRequestUser(w, r)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
agentID, ok := getAgentID(w, r)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
switch user := reqUser.(type) {
|
||||
case *thirdparty.User:
|
||||
role := user.Role()
|
||||
if role == thirdparty.RoleReader || role == thirdparty.RoleWriter {
|
||||
h.ServeHTTP(w, r)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
case *agent.User:
|
||||
if user.Agent().ID == agentID {
|
||||
h.ServeHTTP(w, r)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
default:
|
||||
logUnexpectedUserType(r.Context(), reqUser)
|
||||
}
|
||||
|
||||
forbidden(w, r)
|
||||
}
|
||||
|
||||
return http.HandlerFunc(fn)
|
||||
}
|
||||
|
||||
func assertRequestUser(w http.ResponseWriter, r *http.Request) (auth.User, bool) {
|
||||
ctx := r.Context()
|
||||
user, err := auth.CtxUser(ctx)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "could not retrieve user", logger.E(errors.WithStack(err)))
|
||||
|
||||
forbidden(w, r)
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
if user == nil {
|
||||
forbidden(w, r)
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return user, true
|
||||
}
|
||||
|
||||
func forbidden(w http.ResponseWriter, r *http.Request) {
|
||||
logger.Warn(r.Context(), "forbidden", logger.F("path", r.URL.Path))
|
||||
|
||||
api.ErrorResponse(w, http.StatusForbidden, ErrCodeForbidden, nil)
|
||||
}
|
||||
|
||||
func logUnexpectedUserType(ctx context.Context, user auth.User) {
|
||||
logger.Error(
|
||||
ctx, "unexpected user type",
|
||||
logger.F("subject", user.Subject()),
|
||||
logger.F("type", fmt.Sprintf("%T", user)),
|
||||
)
|
||||
}
|
@ -9,7 +9,7 @@ import (
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/auth"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/auth/agent"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/auth/thirdparty"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/auth/user"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/config"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/datastore"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/jwk"
|
||||
@ -105,19 +105,19 @@ func (s *Server) run(parentCtx context.Context, addrs chan net.Addr, errs chan e
|
||||
|
||||
r.Group(func(r chi.Router) {
|
||||
r.Use(auth.Middleware(
|
||||
thirdparty.NewAuthenticator(keys, string(s.conf.Issuer)),
|
||||
user.NewAuthenticator(keys, string(s.conf.Issuer)),
|
||||
agent.NewAuthenticator(s.agentRepo),
|
||||
))
|
||||
|
||||
r.Route("/agents", func(r chi.Router) {
|
||||
r.With(assertGlobalReadAccess).Get("/", s.queryAgents)
|
||||
r.With(assertAgentReadAccess).Get("/{agentID}", s.getAgent)
|
||||
r.With(assertAgentWriteAccess).Put("/{agentID}", s.updateAgent)
|
||||
r.With(assertAgentWriteAccess).Delete("/{agentID}", s.deleteAgent)
|
||||
r.Get("/", s.queryAgents)
|
||||
r.Get("/{agentID}", s.getAgent)
|
||||
r.Put("/{agentID}", s.updateAgent)
|
||||
r.Delete("/{agentID}", s.deleteAgent)
|
||||
|
||||
r.With(assertAgentReadAccess).Get("/{agentID}/specs", s.getAgentSpecs)
|
||||
r.With(assertAgentWriteAccess).Post("/{agentID}/specs", s.updateSpec)
|
||||
r.With(assertAgentWriteAccess).Delete("/{agentID}/specs", s.deleteSpec)
|
||||
r.Get("/{agentID}/specs", s.getAgentSpecs)
|
||||
r.Post("/{agentID}/specs", s.updateSpec)
|
||||
r.Delete("/{agentID}/specs", s.deleteSpec)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -10,6 +10,11 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"gitlab.com/wpetit/goweb/api"
|
||||
"gitlab.com/wpetit/goweb/logger"
|
||||
|
||||
// Import specs
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/spec/app"
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/spec/gateway"
|
||||
_ "forge.cadoles.com/Cadoles/emissary/internal/spec/uci"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://app.edge.emissary.cadoles.com/spec.json",
|
||||
"$id": "https://app.emissary.cadoles.com/spec.json",
|
||||
"title": "AppSpec",
|
||||
"description": "Emissary 'App' specification",
|
||||
"type": "object",
|
||||
@ -22,66 +22,15 @@
|
||||
},
|
||||
"format": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"zip",
|
||||
"tar.gz"
|
||||
]
|
||||
"enum": ["zip", "tar.gz"]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"url",
|
||||
"sha256sum",
|
||||
"address",
|
||||
"format"
|
||||
],
|
||||
"required": ["url", "sha256sum", "address", "format"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"auth": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"local": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"key": {
|
||||
"type": ["object", "string"]
|
||||
},
|
||||
"accounts": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"username": {
|
||||
"type": "string"
|
||||
},
|
||||
"password": {
|
||||
"type": "string"
|
||||
},
|
||||
"algo": {
|
||||
"type": "string"
|
||||
},
|
||||
"claims": {
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"username",
|
||||
"password",
|
||||
"algo"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"key"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"apps"
|
||||
],
|
||||
"required": ["apps"],
|
||||
"additionalProperties": false
|
||||
}
|
@ -2,15 +2,13 @@ package app
|
||||
|
||||
import (
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/spec"
|
||||
edgeAuth "forge.cadoles.com/arcad/edge/pkg/module/auth/http"
|
||||
)
|
||||
|
||||
const NameApp spec.Name = "app.emissary.cadoles.com"
|
||||
|
||||
type Spec struct {
|
||||
Revision int `json:"revision"`
|
||||
Apps map[string]AppEntry `json:"apps"`
|
||||
Auth *Auth `json:"auth"`
|
||||
Revision int `json:"revisions"`
|
||||
Apps map[string]AppEntry
|
||||
}
|
||||
|
||||
type AppEntry struct {
|
||||
@ -20,15 +18,6 @@ type AppEntry struct {
|
||||
Format string `json:"format"`
|
||||
}
|
||||
|
||||
type Auth struct {
|
||||
Local *LocalAuth `json:"local,omitempty"`
|
||||
}
|
||||
|
||||
type LocalAuth struct {
|
||||
Key any `json:"key"`
|
||||
Accounts []edgeAuth.LocalAccount `json:"accounts"`
|
||||
}
|
||||
|
||||
func (s *Spec) SpecName() spec.Name {
|
||||
return NameApp
|
||||
}
|
||||
@ -40,14 +29,11 @@ func (s *Spec) SpecRevision() int {
|
||||
func (s *Spec) SpecData() map[string]any {
|
||||
return map[string]any{
|
||||
"apps": s.Apps,
|
||||
"auth": s.Auth,
|
||||
}
|
||||
}
|
||||
|
||||
func NewSpec() *Spec {
|
||||
return &Spec{
|
||||
Revision: -1,
|
||||
}
|
||||
return &Spec{}
|
||||
}
|
||||
|
||||
var _ spec.Spec = &Spec{}
|
||||
|
37
internal/spec/app/testdata/spec-ok.json
vendored
37
internal/spec/app/testdata/spec-ok.json
vendored
@ -1,42 +1,7 @@
|
||||
{
|
||||
"name": "app.emissary.cadoles.com",
|
||||
"data": {
|
||||
"apps": {
|
||||
"edge.sdk.client.test": {
|
||||
"url": "http://example.com/edge.sdk.client.test_0.0.0.zip",
|
||||
"sha256sum": "58019192dacdae17755707719707db007e26dac856102280583fbd18427dd352",
|
||||
"address": ":8081",
|
||||
"format": "zip"
|
||||
}
|
||||
},
|
||||
"auth": {
|
||||
"local": {
|
||||
"key": {
|
||||
"d": "YOre0WZefGfUGFvDg42oL5Oad5Zsb1N_hqPyLVM5ajpTZzcHpB3wT6In9tFO_VshB6lxVtPA9ckPkpMTFY7ygt1Yomc1HkoOKRtmIaqdr4VgNQifU-4yiLiJkSbdYSeMV-KkkN8mGR1keJpJeS34W1X0W6CkU2nw7F5VueBCJfWJA0funRfuWdI68MTUgT9kRZFp-SfvptvRL6jVYHV_5hqxzHCvgEdBSF6QKwx4M6P6QBMt7ft6uMLmFx9abKFw2V51hX3PkxiSepVB3w5CYg4HtS3AHX6bILL4m0R2pdTIkap7i3tkH_xAOuKWt8D6JhadI8X1rEAwXmCS5KrRgQ",
|
||||
"dp": "U0HfvBC6hk-SCpuotGIv3vbHCVt1aF3SHK0y32EYCOe8e_9G6YCEILfcvEJ5fiOCc2kvx6TasHQu4qj1uWRKenZlK1sJ6KDybGCkZL1D3jYnbeLZYBuWBL__YbZiST3ewbxzj_EDMWiZ8sUltahza_1weSgg8auSzTHS2LJBHIE",
|
||||
"dq": "hVom4ScDxgqhCsQNVpZlN7M3v0tgWjl_gTOHjOyzKCHQJeC0QmJJaMKkQZPWJ8jjLqy7VwVpqC2nZU7QDuX1Cq5eJDQcXi9XtaAfIBico9WcYDre6mDyhL588YHpekyRke8HnZ810iesr0G3gU1h0QvZVVuW-pXTJOXhZTt6nFc",
|
||||
"e": "AQAB",
|
||||
"kty": "RSA",
|
||||
"n": "vPnpkE3-HfNgJSru_K40LstkjiG2Bq_Tt-m0d_yUBBSbirFxF3qH4EXi7WrtZdeDahg2iV2BvpbVVj9GlmGo9OLol6jc7AP2yvZrkbABiiJhCbuPdkYbNpx6B7Itl8RT_bUSYAMZhmux5lpsn4weQ01fzjICi1rA-bIJpOfotdOjP4_lol-LxGZOGJQv9kndP8bgmssJb3Y_2s4gPtkmXySLrhpr5So-_6dVksyuBD9aLcnsMLDbywusjEMCdhqzQbvOjryomnmEXwyz_Ewb5HFK2PfgFtoHkdjqDz-mrEs3tw5g4TdYhCftzJxgbyNAEq4aEiOQrAncYyrXlotP_w",
|
||||
"p": "8TNMF0WUe7CEeNVUTsuEcBAAXRguNtpvVifIjlwzFRGOYVGIpKuHsqQPKlZL07I9gPr9LifQnyQus3oEmTOrVs6LB9sfbukbg43ZRKoGVM40JYF5Xjs7R3mEZhgU0WaYOVe3iLtBGMfXNWFwlbfQP-zEb-dPCBX1jWT3LdgNBcE",
|
||||
"q": "yJJLNc9w6O4y2icME8k99FugV9E7ObwUxF3v5JN3y1cmAT0h2njyE3iAGqaDZwcY1_jGCisjwoqX6i5E8xqhxX3Gcy3J7SmUAf8fhY8wU3zv9DK7skg2IdvanDb8Y1OM6GchbYZAOVPEg2IvVio8zI-Ih3DDwDk8Df0ufzoHRb8",
|
||||
"qi": "zOE-4R3cjPesm3MX-4PdwmsaF9QZLUVRUvvHJ08pKs6kAXP18hzjctAoOjhQDxlTYqNYNePfKzKwost3OJoPgRIc9w9qwUCK1gNOS4Z_xozCIaXgMddNFhkoAfZ4JaKjNCiinzjGfqG99Lf-yzmmREuuhRv7SdS3ST4VQjiJQew"
|
||||
},
|
||||
"accounts": [
|
||||
{
|
||||
"username": "foo",
|
||||
"algo": "plain",
|
||||
"password": "bar",
|
||||
"claims": {
|
||||
"arcad_role": "user",
|
||||
"arcad_tenant": "dev.cli",
|
||||
"preferred_username": "Foo",
|
||||
"sub": "foo"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
"apps": {}
|
||||
},
|
||||
"revision": 0
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
package spec
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/hashstructure/v2"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func Equals(a Spec, b Spec) (bool, error) {
|
||||
if a.SpecName() != b.SpecName() {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if a.SpecRevision() != b.SpecRevision() {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
hashA, err := hashstructure.Hash(a.SpecData(), hashstructure.FormatV2, nil)
|
||||
if err != nil {
|
||||
return false, errors.WithStack(err)
|
||||
}
|
||||
|
||||
hashB, err := hashstructure.Hash(b.SpecData(), hashstructure.FormatV2, nil)
|
||||
if err != nil {
|
||||
return false, errors.WithStack(err)
|
||||
}
|
||||
|
||||
return hashA == hashB, nil
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package sysupgrade
|
||||
package gateway
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
@ -11,7 +11,7 @@ import (
|
||||
var schema []byte
|
||||
|
||||
func init() {
|
||||
if err := spec.Register(Name, schema); err != nil {
|
||||
if err := spec.Register(NameGateway, schema); err != nil {
|
||||
panic(errors.WithStack(err))
|
||||
}
|
||||
}
|
29
internal/spec/gateway/schema.json
Normal file
29
internal/spec/gateway/schema.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://gateway.emissary.cadoles.com/spec.json",
|
||||
"title": "GatewaySpec",
|
||||
"description": "Emissary 'Gateway' specification",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"gateways": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
".*": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"address": {
|
||||
"type": "string"
|
||||
},
|
||||
"target": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["address", "target"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["gateways"],
|
||||
"additionalProperties": false
|
||||
}
|
39
internal/spec/gateway/spec.go
Normal file
39
internal/spec/gateway/spec.go
Normal file
@ -0,0 +1,39 @@
|
||||
package gateway
|
||||
|
||||
import "forge.cadoles.com/Cadoles/emissary/internal/spec"
|
||||
|
||||
const NameGateway spec.Name = "gateway.emissary.cadoles.com"
|
||||
|
||||
type ID string
|
||||
|
||||
type Spec struct {
|
||||
Revision int `json:"revision"`
|
||||
Gateways map[ID]GatewayEntry `json:"gateways"`
|
||||
}
|
||||
|
||||
type GatewayEntry struct {
|
||||
Address string `json:"address"`
|
||||
Target string `json:"target"`
|
||||
}
|
||||
|
||||
func (s *Spec) SpecName() spec.Name {
|
||||
return NameGateway
|
||||
}
|
||||
|
||||
func (s *Spec) SpecRevision() int {
|
||||
return s.Revision
|
||||
}
|
||||
|
||||
func (s *Spec) SpecData() map[string]any {
|
||||
return map[string]any{
|
||||
"gateways": s.Gateways,
|
||||
}
|
||||
}
|
||||
|
||||
func NewSpec() *Spec {
|
||||
return &Spec{
|
||||
Gateways: make(map[ID]GatewayEntry),
|
||||
}
|
||||
}
|
||||
|
||||
var _ spec.Spec = &Spec{}
|
13
internal/spec/gateway/testdata/spec-additional-prop.json
vendored
Normal file
13
internal/spec/gateway/testdata/spec-additional-prop.json
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "gateway.emissary.cadoles.com",
|
||||
"data": {
|
||||
"gateways": {
|
||||
"cadoles.com": {
|
||||
"address": ":3003",
|
||||
"target": "https://www.cadoles.com",
|
||||
"foo": "bar"
|
||||
}
|
||||
}
|
||||
},
|
||||
"revision": 0
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "proxy.emissary.cadoles.com",
|
||||
"name": "gateway.emissary.cadoles.com",
|
||||
"data": {
|
||||
"proxies": {
|
||||
"gateways": {
|
||||
"cadoles.com": {
|
||||
"address": ":3003"
|
||||
}
|
12
internal/spec/gateway/testdata/spec-ok.json
vendored
Normal file
12
internal/spec/gateway/testdata/spec-ok.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "gateway.emissary.cadoles.com",
|
||||
"data": {
|
||||
"gateways": {
|
||||
"cadoles.com": {
|
||||
"address": ":3003",
|
||||
"target": "https://www.cadoles.com"
|
||||
}
|
||||
}
|
||||
},
|
||||
"revision": 0
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package proxy
|
||||
package gateway
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -38,7 +38,7 @@ func TestValidator(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
validator := spec.NewValidator()
|
||||
if err := validator.Register(NameProxy, schema); err != nil {
|
||||
if err := validator.Register(NameGateway, schema); err != nil {
|
||||
t.Fatalf("+%v", errors.WithStack(err))
|
||||
}
|
||||
|
@ -1,17 +0,0 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/spec"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
//go:embed schema.json
|
||||
var schema []byte
|
||||
|
||||
func init() {
|
||||
if err := spec.Register(NameProxy, schema); err != nil {
|
||||
panic(errors.WithStack(err))
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://proxy.emissary.cadoles.com/spec.json",
|
||||
"title": "ProxySpec",
|
||||
"description": "Emissary 'Proxy' specification",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"proxies": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
".*": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"address": {
|
||||
"type": "string"
|
||||
},
|
||||
"mappings": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"hostPattern": {
|
||||
"type": "string"
|
||||
},
|
||||
"target": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["hostPattern", "target"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["address", "mappings"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["proxies"],
|
||||
"additionalProperties": false
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
package proxy
|
||||
|
||||
import "forge.cadoles.com/Cadoles/emissary/internal/spec"
|
||||
|
||||
const NameProxy spec.Name = "proxy.emissary.cadoles.com"
|
||||
|
||||
type ID string
|
||||
|
||||
type Spec struct {
|
||||
Revision int `json:"revision"`
|
||||
Proxies map[ID]ProxyEntry `json:"proxies"`
|
||||
}
|
||||
|
||||
type ProxyEntry struct {
|
||||
Address string `json:"address"`
|
||||
Mappings []ProxyMapping `json:"mappings"`
|
||||
}
|
||||
|
||||
type ProxyMapping struct {
|
||||
HostPattern string `json:"hostPattern"`
|
||||
Target string `json:"target"`
|
||||
}
|
||||
|
||||
func (s *Spec) SpecName() spec.Name {
|
||||
return NameProxy
|
||||
}
|
||||
|
||||
func (s *Spec) SpecRevision() int {
|
||||
return s.Revision
|
||||
}
|
||||
|
||||
func (s *Spec) SpecData() map[string]any {
|
||||
return map[string]any{
|
||||
"proxies": s.Proxies,
|
||||
}
|
||||
}
|
||||
|
||||
func NewSpec() *Spec {
|
||||
return &Spec{
|
||||
Revision: -1,
|
||||
Proxies: make(map[ID]ProxyEntry),
|
||||
}
|
||||
}
|
||||
|
||||
var _ spec.Spec = &Spec{}
|
@ -1,18 +0,0 @@
|
||||
{
|
||||
"name": "proxy.emissary.cadoles.com",
|
||||
"data": {
|
||||
"proxies": {
|
||||
"cadoles.com": {
|
||||
"address": ":3003",
|
||||
"mappings": [
|
||||
{
|
||||
"hostPattern": "localhost:3003",
|
||||
"target": "https://www.cadoles.com"
|
||||
}
|
||||
],
|
||||
"foo": "bar"
|
||||
}
|
||||
}
|
||||
},
|
||||
"revision": 0
|
||||
}
|
17
internal/spec/proxy/testdata/spec-ok.json
vendored
17
internal/spec/proxy/testdata/spec-ok.json
vendored
@ -1,17 +0,0 @@
|
||||
{
|
||||
"name": "proxy.emissary.cadoles.com",
|
||||
"data": {
|
||||
"proxies": {
|
||||
"cadoles.com": {
|
||||
"address": ":3003",
|
||||
"mappings": [
|
||||
{
|
||||
"hostPattern": "localhost:3003",
|
||||
"target": "https://www.cadoles.com"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"revision": 0
|
||||
}
|
@ -67,18 +67,13 @@
|
||||
"type": "string"
|
||||
},
|
||||
"options": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/option"
|
||||
}
|
||||
},
|
||||
{ "type": "null" }
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": ["name"],
|
||||
"required": ["name", "section", "options"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"option": {
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
const NameUCI spec.Name = "uci.emissary.cadoles.com"
|
||||
|
||||
type Spec struct {
|
||||
Revision int `json:"revision"`
|
||||
Revision int `json:"revisions"`
|
||||
Config *uci.UCI `json:"config"`
|
||||
PostImportCommands []*UCIPostImportCommand `json:"postImportCommands"`
|
||||
}
|
||||
@ -35,7 +35,6 @@ func (s *Spec) SpecData() map[string]any {
|
||||
|
||||
func NewSpec() *Spec {
|
||||
return &Spec{
|
||||
Revision: -1,
|
||||
PostImportCommands: make([]*UCIPostImportCommand, 0),
|
||||
}
|
||||
}
|
||||
|
1473
internal/spec/uci/testdata/spec-ok.json
vendored
1473
internal/spec/uci/testdata/spec-ok.json
vendored
@ -3,1475 +3,6 @@
|
||||
"data": {
|
||||
"config": {
|
||||
"packages": [
|
||||
{
|
||||
"name": "dhcp",
|
||||
"configs": [
|
||||
{
|
||||
"name": "dnsmasq",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "domainneeded",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "boguspriv",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "filterwin2k",
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "localise_queries",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "rebind_protection",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "rebind_localhost",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "local",
|
||||
"value": "/lan/"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "domain",
|
||||
"value": "lan"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "expandhosts",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "nonegcache",
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "authoritative",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "readethers",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "leasefile",
|
||||
"value": "/tmp/dhcp.leases"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "resolvfile",
|
||||
"value": "/tmp/resolv.conf.d/resolv.conf.auto"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "nonwildcard",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "localservice",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "ednspacket_max",
|
||||
"value": "1232"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "dhcp",
|
||||
"section": "lan",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "interface",
|
||||
"value": "lan"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "start",
|
||||
"value": "100"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "limit",
|
||||
"value": "150"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "leasetime",
|
||||
"value": "12h"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "dhcpv4",
|
||||
"value": "server"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "dhcpv6",
|
||||
"value": "server"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "ra",
|
||||
"value": "server"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "ra_slaac",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "ra_flags",
|
||||
"value": "managed-config"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "ra_flags",
|
||||
"value": "other-config"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "dhcp",
|
||||
"section": "wan",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "interface",
|
||||
"value": "wan"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "ignore",
|
||||
"value": "1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "odhcpd",
|
||||
"section": "odhcpd",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "maindhcp",
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "leasefile",
|
||||
"value": "/tmp/hosts/odhcpd"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "leasetrigger",
|
||||
"value": "/usr/sbin/odhcpd-update"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "loglevel",
|
||||
"value": "4"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "dropbear",
|
||||
"configs": [
|
||||
{
|
||||
"name": "dropbear",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "PasswordAuth",
|
||||
"value": "on"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "RootPasswordAuth",
|
||||
"value": "on"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "Port",
|
||||
"value": "22"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "emissary",
|
||||
"configs": [
|
||||
{
|
||||
"name": "main",
|
||||
"section": "agent",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "server_url",
|
||||
"value": "http://192.168.30.15:3000"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "reconciliation_interval",
|
||||
"value": "30"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "firewall",
|
||||
"configs": [
|
||||
{
|
||||
"name": "defaults",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "syn_flood",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "input",
|
||||
"value": "ACCEPT"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "output",
|
||||
"value": "ACCEPT"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "forward",
|
||||
"value": "REJECT"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "zone",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "name",
|
||||
"value": "lan"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "network",
|
||||
"value": "lan"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "input",
|
||||
"value": "ACCEPT"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "output",
|
||||
"value": "ACCEPT"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "forward",
|
||||
"value": "ACCEPT"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "zone",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "name",
|
||||
"value": "wan"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "network",
|
||||
"value": "wan"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "network",
|
||||
"value": "wan6"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "input",
|
||||
"value": "REJECT"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "output",
|
||||
"value": "ACCEPT"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "forward",
|
||||
"value": "REJECT"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "masq",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "mtu_fix",
|
||||
"value": "1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "forwarding",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "src",
|
||||
"value": "lan"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "dest",
|
||||
"value": "wan"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "rule",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "name",
|
||||
"value": "Allow-DHCP-Renew"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "src",
|
||||
"value": "wan"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "proto",
|
||||
"value": "udp"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "dest_port",
|
||||
"value": "68"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "target",
|
||||
"value": "ACCEPT"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "family",
|
||||
"value": "ipv4"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "rule",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "name",
|
||||
"value": "Allow-Ping"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "src",
|
||||
"value": "wan"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "proto",
|
||||
"value": "icmp"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "icmp_type",
|
||||
"value": "echo-request"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "family",
|
||||
"value": "ipv4"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "target",
|
||||
"value": "ACCEPT"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "rule",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "name",
|
||||
"value": "Allow-IGMP"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "src",
|
||||
"value": "wan"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "proto",
|
||||
"value": "igmp"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "family",
|
||||
"value": "ipv4"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "target",
|
||||
"value": "ACCEPT"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "rule",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "name",
|
||||
"value": "Allow-DHCPv6"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "src",
|
||||
"value": "wan"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "proto",
|
||||
"value": "udp"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "dest_port",
|
||||
"value": "546"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "family",
|
||||
"value": "ipv6"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "target",
|
||||
"value": "ACCEPT"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "rule",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "name",
|
||||
"value": "Allow-MLD"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "src",
|
||||
"value": "wan"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "proto",
|
||||
"value": "icmp"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "src_ip",
|
||||
"value": "fe80::/10"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "icmp_type",
|
||||
"value": "130/0"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "icmp_type",
|
||||
"value": "131/0"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "icmp_type",
|
||||
"value": "132/0"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "icmp_type",
|
||||
"value": "143/0"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "family",
|
||||
"value": "ipv6"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "target",
|
||||
"value": "ACCEPT"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "rule",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "name",
|
||||
"value": "Allow-ICMPv6-Input"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "src",
|
||||
"value": "wan"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "proto",
|
||||
"value": "icmp"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "icmp_type",
|
||||
"value": "echo-request"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "icmp_type",
|
||||
"value": "echo-reply"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "icmp_type",
|
||||
"value": "destination-unreachable"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "icmp_type",
|
||||
"value": "packet-too-big"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "icmp_type",
|
||||
"value": "time-exceeded"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "icmp_type",
|
||||
"value": "bad-header"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "icmp_type",
|
||||
"value": "unknown-header-type"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "icmp_type",
|
||||
"value": "router-solicitation"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "icmp_type",
|
||||
"value": "neighbour-solicitation"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "icmp_type",
|
||||
"value": "router-advertisement"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "icmp_type",
|
||||
"value": "neighbour-advertisement"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "limit",
|
||||
"value": "1000/sec"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "family",
|
||||
"value": "ipv6"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "target",
|
||||
"value": "ACCEPT"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "rule",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "name",
|
||||
"value": "Allow-ICMPv6-Forward"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "src",
|
||||
"value": "wan"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "dest",
|
||||
"value": "*"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "proto",
|
||||
"value": "icmp"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "icmp_type",
|
||||
"value": "echo-request"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "icmp_type",
|
||||
"value": "echo-reply"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "icmp_type",
|
||||
"value": "destination-unreachable"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "icmp_type",
|
||||
"value": "packet-too-big"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "icmp_type",
|
||||
"value": "time-exceeded"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "icmp_type",
|
||||
"value": "bad-header"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "icmp_type",
|
||||
"value": "unknown-header-type"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "limit",
|
||||
"value": "1000/sec"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "family",
|
||||
"value": "ipv6"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "target",
|
||||
"value": "ACCEPT"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "rule",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "name",
|
||||
"value": "Allow-IPSec-ESP"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "src",
|
||||
"value": "wan"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "dest",
|
||||
"value": "lan"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "proto",
|
||||
"value": "esp"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "target",
|
||||
"value": "ACCEPT"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "rule",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "name",
|
||||
"value": "Allow-ISAKMP"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "src",
|
||||
"value": "wan"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "dest",
|
||||
"value": "lan"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "dest_port",
|
||||
"value": "500"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "proto",
|
||||
"value": "udp"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "target",
|
||||
"value": "ACCEPT"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "rule",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "name",
|
||||
"value": "Allow SSH on WAN"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "src",
|
||||
"value": "wan"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "proto",
|
||||
"value": "tcp"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "dest_port",
|
||||
"value": "22"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "target",
|
||||
"value": "ACCEPT"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "rule",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "name",
|
||||
"value": "Allow HTTP on WAN"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "src",
|
||||
"value": "wan"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "proto",
|
||||
"value": "tcp"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "dest_port",
|
||||
"value": "80"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "target",
|
||||
"value": "ACCEPT"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "rule",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "name",
|
||||
"value": "Allow HTTPS on WAN"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "src",
|
||||
"value": "wan"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "proto",
|
||||
"value": "tcp"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "dest_port",
|
||||
"value": "443"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "target",
|
||||
"value": "ACCEPT"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "rule",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "name",
|
||||
"value": "Allow 8080 on WAN"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "src",
|
||||
"value": "wan"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "proto",
|
||||
"value": "tcp"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "dest_port",
|
||||
"value": "8080"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "target",
|
||||
"value": "ACCEPT"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "rule",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "name",
|
||||
"value": "Allow 8443 on WAN"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "src",
|
||||
"value": "wan"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "proto",
|
||||
"value": "tcp"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "dest_port",
|
||||
"value": "8443"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "target",
|
||||
"value": "ACCEPT"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "luci",
|
||||
"configs": [
|
||||
{
|
||||
"name": "core",
|
||||
"section": "main",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "lang",
|
||||
"value": "auto"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "mediaurlbase",
|
||||
"value": "/luci-static/bootstrap"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "resourcebase",
|
||||
"value": "/luci-static/resources"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "ubuspath",
|
||||
"value": "/ubus/"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "extern",
|
||||
"section": "flash_keep",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "uci",
|
||||
"value": "/etc/config/"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "dropbear",
|
||||
"value": "/etc/dropbear/"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "openvpn",
|
||||
"value": "/etc/openvpn/"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "passwd",
|
||||
"value": "/etc/passwd"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "opkg",
|
||||
"value": "/etc/opkg.conf"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "firewall",
|
||||
"value": "/etc/firewall.user"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "uploads",
|
||||
"value": "/lib/uci/upload/"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "internal",
|
||||
"section": "languages",
|
||||
"options": null
|
||||
},
|
||||
{
|
||||
"name": "internal",
|
||||
"section": "sauth",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "sessionpath",
|
||||
"value": "/tmp/luci-sessions"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "sessiontime",
|
||||
"value": "3600"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "internal",
|
||||
"section": "ccache",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "enable",
|
||||
"value": "1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "internal",
|
||||
"section": "themes",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "Bootstrap",
|
||||
"value": "/luci-static/bootstrap"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "BootstrapDark",
|
||||
"value": "/luci-static/bootstrap-dark"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "BootstrapLight",
|
||||
"value": "/luci-static/bootstrap-light"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "internal",
|
||||
"section": "apply",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "rollback",
|
||||
"value": "90"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "holdoff",
|
||||
"value": "4"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "timeout",
|
||||
"value": "5"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "display",
|
||||
"value": "1.5"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "internal",
|
||||
"section": "diag",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "dns",
|
||||
"value": "openwrt.org"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "ping",
|
||||
"value": "openwrt.org"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "route",
|
||||
"value": "openwrt.org"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "network",
|
||||
"configs": [
|
||||
{
|
||||
"name": "interface",
|
||||
"section": "loopback",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "ifname",
|
||||
"value": "lo"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "proto",
|
||||
"value": "static"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "ipaddr",
|
||||
"value": "127.0.0.1"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "netmask",
|
||||
"value": "255.0.0.0"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "interface",
|
||||
"section": "wan",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "ifname",
|
||||
"value": "eth0"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "proto",
|
||||
"value": "dhcp"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "rpcd",
|
||||
"configs": [
|
||||
{
|
||||
"name": "rpcd",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "socket",
|
||||
"value": "/var/run/ubus/ubus.sock"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "timeout",
|
||||
"value": "30"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "login",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "username",
|
||||
"value": "root"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "password",
|
||||
"value": "$p$root"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "read",
|
||||
"value": "*"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "write",
|
||||
"value": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "system",
|
||||
"configs": [
|
||||
{
|
||||
"name": "system",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "hostname",
|
||||
"value": "OpenWrt"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "timezone",
|
||||
"value": "UTC"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "ttylogin",
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "log_size",
|
||||
"value": "64"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "urandom_seed",
|
||||
"value": "0"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "timeserver",
|
||||
"section": "ntp",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "enabled",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "enable_server",
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "server",
|
||||
"value": "0.openwrt.pool.ntp.org"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "server",
|
||||
"value": "1.openwrt.pool.ntp.org"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "server",
|
||||
"value": "2.openwrt.pool.ntp.org"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "server",
|
||||
"value": "3.openwrt.pool.ntp.org"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ucitrack",
|
||||
"configs": [
|
||||
{
|
||||
"name": "network",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "init",
|
||||
"value": "network"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "affects",
|
||||
"value": "dhcp"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "wireless",
|
||||
"options": [
|
||||
{
|
||||
"type": "list",
|
||||
"name": "affects",
|
||||
"value": "network"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "firewall",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "init",
|
||||
"value": "firewall"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "affects",
|
||||
"value": "luci-splash"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "affects",
|
||||
"value": "qos"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "affects",
|
||||
"value": "miniupnpd"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "olsr",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "init",
|
||||
"value": "olsrd"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "dhcp",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "init",
|
||||
"value": "dnsmasq"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "affects",
|
||||
"value": "odhcpd"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "odhcpd",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "init",
|
||||
"value": "odhcpd"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "dropbear",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "init",
|
||||
"value": "dropbear"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "httpd",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "init",
|
||||
"value": "httpd"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "fstab",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "exec",
|
||||
"value": "/sbin/block mount"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "qos",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "init",
|
||||
"value": "qos"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "system",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "init",
|
||||
"value": "led"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
"name": "exec",
|
||||
"value": "/etc/init.d/log reload"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "affects",
|
||||
"value": "luci_statistics"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "affects",
|
||||
"value": "dhcp"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "luci_splash",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "init",
|
||||
"value": "luci_splash"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "upnpd",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "init",
|
||||
"value": "miniupnpd"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ntpclient",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "init",
|
||||
"value": "ntpclient"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "samba",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "init",
|
||||
"value": "samba"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "tinyproxy",
|
||||
"options": [
|
||||
{
|
||||
"type": "option",
|
||||
"name": "init",
|
||||
"value": "tinyproxy"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "uhttpd",
|
||||
"configs": [
|
||||
@ -1492,12 +23,12 @@
|
||||
{
|
||||
"type": "list",
|
||||
"name": "listen_https",
|
||||
"value": "0.0.0.0:4443"
|
||||
"value": "0.0.0.0:8443"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"name": "listen_https",
|
||||
"value": "[::]:4443"
|
||||
"value": "[::]:8443"
|
||||
},
|
||||
{
|
||||
"type": "option",
|
||||
|
@ -1,6 +1,3 @@
|
||||
logger:
|
||||
level: 1
|
||||
format: human
|
||||
agent:
|
||||
serverUrl: http://127.0.0.1:3000
|
||||
privateKeyPath: /var/lib/emissary/agent-key.json
|
||||
@ -11,28 +8,12 @@ agent:
|
||||
stateFile: /var/lib/emissary/state.json
|
||||
spec:
|
||||
enabled: true
|
||||
proxy:
|
||||
gateway:
|
||||
enabled: true
|
||||
uci:
|
||||
enabled: true
|
||||
binPath: uci
|
||||
configBackupFile: /var/lib/emissary/uci-backup.conf
|
||||
app:
|
||||
enabled: true
|
||||
dataDir: /var/lib/emissary/apps/data
|
||||
downloadDir: /var/lib/emissary/apps/bundles
|
||||
sysupgrade:
|
||||
enabled: true
|
||||
sysupgradeCommand:
|
||||
- sysupgrade
|
||||
- --force
|
||||
- -u
|
||||
- -v
|
||||
- '%FIRMWARE%'
|
||||
firmwareVersionCommand:
|
||||
- sh
|
||||
- -c
|
||||
- source /etc/openwrt_release && echo "$DISTRIB_ID-$DISTRIB_RELEASE-$DISTRIB_REVISION"
|
||||
collectors:
|
||||
- name: uname
|
||||
command: uname
|
||||
|
@ -1,12 +1,9 @@
|
||||
logger:
|
||||
level: 1
|
||||
format: human
|
||||
server:
|
||||
privateKeyPath: /var/lib/emissary/server-key.json
|
||||
issuer: http://127.0.0.1:3000
|
||||
http:
|
||||
host: 0.0.0.0
|
||||
port: 3000
|
||||
logger:
|
||||
level: 1
|
||||
format: human
|
||||
database:
|
||||
driver: sqlite
|
||||
dsn: sqlite:///var/lib/emissary/data.sqlite
|
||||
|
@ -1,5 +1,4 @@
|
||||
**/*.go
|
||||
**/*.json
|
||||
modd.conf
|
||||
tmp/config.yml
|
||||
.env {
|
||||
@ -7,8 +6,7 @@ tmp/config.yml
|
||||
prep: make build-emissary
|
||||
prep: make tmp/server.yml
|
||||
prep: make tmp/agent.yml
|
||||
prep: make run-emissary-server EMISSARY_CMD="--debug --config tmp/server.yml server database migrate"
|
||||
prep: make .emissary-token
|
||||
prep: make run-emissary-server EMISSARY_CMD="--debug --config tmp/agent.yml server database migrate"
|
||||
daemon: make run-emissary-server EMISSARY_CMD="--debug --config tmp/server.yml server run"
|
||||
daemon: make run-emissary-agent EMISSARY_CMD="--debug --config tmp/agent.yml agent run"
|
||||
}
|
Reference in New Issue
Block a user