Compare commits

..

1 Commits

Author SHA1 Message Date
c55c723868 chore: Create branch for project modifications testing
All checks were successful
arcad/emissary/pipeline/head This commit looks good
2023-08-28 11:26:44 +02:00
49 changed files with 218 additions and 2913 deletions

View File

@ -1,14 +0,0 @@
/apps
/bin
/dist
/out
/tmp
/tools
/.emissary-token
/.env
/agent-key.json
/server-key.json
/CHANGELOG.md
/state.json
/*.sqlite*
/.mktools

View File

@ -105,9 +105,6 @@ nfpms:
file_info:
mode: 0755
packager: apk
- src: misc/packaging/openrc/emissary-server.logrotate.conf
dst: /etc/logrotate.d/emissary-server
packager: apk
- dst: /var/lib/emissary
type: dir
file_info:
@ -150,8 +147,5 @@ nfpms:
file_info:
mode: 0755
packager: apk
- src: misc/packaging/openrc/emissary-agent.logrotate.conf
dst: /etc/logrotate.d/emissary-agent
packager: apk
scripts:
postinstall: "misc/packaging/common/postinstall-agent.sh"

View File

@ -1,12 +1,4 @@
FROM alpine as certs
RUN apk update && apk add ca-certificates curl openssl bash
RUN curl -k https://forge.cadoles.com/Cadoles/Jenkins/raw/branch/master/resources/com/cadoles/common/add-letsencrypt-ca.sh | bash
#####################################
# Emissary Server #
#####################################
FROM golang:1.21 AS build-emissary-server
FROM golang:1.19 AS BUILD
RUN apt-get update \
&& apt-get install -y make
@ -15,9 +7,9 @@ COPY . /src
WORKDIR /src
RUN make mktools && make GORELEASER_ARGS="build --snapshot --clean --single-target --id emissary-server" goreleaser
RUN make GORELEASER_ARGS='build --rm-dist --single-target --snapshot' release
FROM busybox:latest AS emissary-server
FROM busybox:latest AS RUNTIME
ARG DUMB_INIT_VERSION=1.2.5
@ -27,47 +19,11 @@ RUN mkdir -p /usr/local/bin \
ENTRYPOINT ["/usr/local/bin/dumb-init", "--"]
COPY --from=build-emissary-server /src/dist/emissary-server_linux_amd64_v1 /app
COPY misc/docker/server.yml /etc/emissary/server.yml
COPY --from=certs /etc/ssl/certs /etc/ssl/certs
COPY --from=BUILD /src/dist/emissary_linux_amd64_v1 /app
COPY --from=BUILD /src/tmp/config.yml /etc/emissary/config.yml
EXPOSE 3000
RUN mkdir -p /data
ENTRYPOINT ["/app/emissary"]
CMD [ "/app/emissary", "-c", "/etc/emissary/config.yml", "server", "run"]
#####################################
# Emissary Agent #
#####################################
FROM golang:1.21 AS build-emissary-agent
RUN apt-get update \
&& apt-get install -y make
COPY . /src
WORKDIR /src
RUN make mktools && make GORELEASER_ARGS="build --snapshot --clean --single-target --id emissary-agent" goreleaser
FROM busybox:latest AS emissary-agent
ARG DUMB_INIT_VERSION=1.2.5
RUN mkdir -p /usr/local/bin \
&& wget -O /usr/local/bin/dumb-init https://github.com/Yelp/dumb-init/releases/download/v${DUMB_INIT_VERSION}/dumb-init_${DUMB_INIT_VERSION}_x86_64 \
&& chmod +x /usr/local/bin/dumb-init
ENTRYPOINT ["/usr/local/bin/dumb-init", "--"]
COPY --from=build-emissary-agent /src/dist/emissary-agent_linux_amd64_v1 /app
COPY --chmod=777 misc/docker/docker-agent-wrapper.sh /usr/local/bin/docker-agent-wrapper
COPY misc/docker/agent.yml /etc/emissary/agent.yml
COPY --from=certs /etc/ssl/certs /etc/ssl/certs
RUN mkdir -p /data
CMD [ "/usr/local/bin/docker-agent-wrapper", "/app/emissary", "-c", "/etc/emissary/agent.yml", "agent", "run" ]
CMD ["server", "run", "-c", "/etc/emissary/config.yml"]

View File

@ -1,11 +1,12 @@
LINT_ARGS ?= --timeout 5m
GORELEASER_ARGS ?= release --snapshot --clean
GORELEASER_VERSION ?= v1.13.1
GORELEASER_ARGS ?= release --snapshot --rm-dist
GITCHLOG_ARGS ?=
SHELL := /bin/bash
EMISSARY_VERSION ?=
DOCKER_IMAGE_NAME ?= reg.cadoles.com/cadoles/emissary
DOCKER_IMAGE_NAME ?= bornholm/emissary
DOCKER_IMAGE_TAG ?= $(MKT_PROJECT_VERSION)
GOTEST_ARGS ?= -short
@ -70,23 +71,17 @@ dump-config: build-emissary
./bin/emissary config dump > tmp/config.yml
.PHONY: goreleaser
goreleaser: .env .mktools
( set -o allexport && source .env && set +o allexport && curl -sfL https://goreleaser.com/static/run | GORELEASER_CURRENT_TAG="$(MKT_PROJECT_VERSION)" bash /dev/stdin $(GORELEASER_ARGS) )
goreleaser: .mktools
( set -o allexport && source .env && set +o allexport && VERSION=$(GORELEASER_VERSION) curl -sfL https://goreleaser.com/static/run | GORELEASER_CURRENT_TAG="$(MKT_PROJECT_VERSION)" bash /dev/stdin $(GORELEASER_ARGS) )
install-git-hooks:
git config core.hooksPath .githooks
docker-build: docker-build-agent docker-build-server
docker-build:
docker build -t $(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG) .
docker-build-%:
docker build --target emissary-$* -t $(DOCKER_IMAGE_NAME)-$*:latest .
docker-release: docker-release-agent docker-release-server
docker-release-%:
docker tag $(DOCKER_IMAGE_NAME)-$*:latest $(DOCKER_IMAGE_NAME)-$*:$(DOCKER_IMAGE_TAG)
docker push $(DOCKER_IMAGE_NAME)-$*:latest
docker push $(DOCKER_IMAGE_NAME)-$*:$(DOCKER_IMAGE_TAG)
docker-release:
docker push $(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG)
deploy-openwrt-agent:
$(MAKE) GOARCH="arm" GORELEASER_ARGS='build --single-target --snapshot --clean' goreleaser
@ -131,15 +126,13 @@ load-sample-specs:
cat misc/spec-samples/app.emissary.cadoles.com.json | ./bin/server api agent spec update -a $(AGENT_ID) --no-patch --spec-data - --spec-name app.emissary.cadoles.com
cat misc/spec-samples/proxy.emissary.cadoles.com.json | ./bin/server api agent spec update -a $(AGENT_ID) --no-patch --spec-data - --spec-name proxy.emissary.cadoles.com
cat misc/spec-samples/mdns.emissary.cadoles.com.json | ./bin/server api agent spec update -a $(AGENT_ID) --no-patch --spec-data - --spec-name mdns.emissary.cadoles.com
cat misc/spec-samples/uci.emissary.cadoles.com.json | ./bin/server api agent spec update -a $(AGENT_ID) --no-patch --spec-data - --spec-name uci.emissary.cadoles.com
version: .mktools
@echo $(MKT_PROJECT_VERSION)
update-edge-lib:
git pull --rebase
go clean -modcache
GONOPROXY=forge.cadoles.com/arcad/edge GOPRIVATE=forge.cadoles.com/arcad/edge go get -v -u forge.cadoles.com/arcad/edge
GOPROXY=direct GOPRIVATE=forge.cadoles.com/arcad/edge go get -u forge.cadoles.com/arcad/edge
go mod tidy
$(MAKE) test
git add go.mod go.sum

View File

@ -7,7 +7,6 @@
- (FR) - [Premiers pas](./tutorials/fr/first-steps.md)
- (FR) - [Déployer un serveur mandataire inverse sur un agent](./tutorials/fr/deploy-reverse-proxy.md)
- (FR) - [Déployer une configuration UCI personnalisée sur un agent](./tutorials/fr/deploy-uci-configuration.md)
- (FR) - [Démarrer un agent avec Docker](./tutorials/fr/docker-agent.md)
## References

View File

@ -1,10 +0,0 @@
# Lancer un agent avec Docker
```shell
docker run \
--rm -it \
--network bridge \
-v emissary-agent-data:/data \
-e EMISSARY_AGENT_SERVER_URL=<server_url> \
reg.cadoles.com/cadoles/emissary-agent:latest
```

View File

@ -36,7 +36,7 @@
```bash
sudo nmap -sP 192.168.0.* # À modifier par le préfixe correspondant à votre réseau local
```
Une entrée équivalente à la suivante devrait être affichée:
```bash

28
go.mod
View File

@ -1,11 +1,9 @@
module forge.cadoles.com/Cadoles/emissary
go 1.21
toolchain go1.21.2
go 1.19
require (
forge.cadoles.com/arcad/edge v0.0.0-20231130180951-32f04af138d7
forge.cadoles.com/arcad/edge v0.0.0-20230426135323-17808d14c978
github.com/Masterminds/sprig/v3 v3.2.3
github.com/alecthomas/participle/v2 v2.0.0-beta.5
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883
@ -16,7 +14,7 @@ require (
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/getsentry/sentry-go v0.25.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
@ -28,7 +26,7 @@ require (
github.com/pkg/errors v0.9.1
github.com/qri-io/jsonschema v0.2.1
github.com/urfave/cli/v2 v2.24.4
gitlab.com/wpetit/goweb v0.0.0-20231019192040-4c72331a7648
gitlab.com/wpetit/goweb v0.0.0-20230419082146-a94d9ed7202b
gopkg.in/yaml.v3 v3.0.1
modernc.org/sqlite v1.21.0
)
@ -36,7 +34,6 @@ require (
require (
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.2.0 // indirect
github.com/allegro/bigcache/v3 v3.1.0 // indirect
github.com/barnybug/go-cast v0.0.0-20201201064555-a87ccbc26692 // indirect
github.com/dop251/goja_nodejs v0.0.0-20230320130059-dcf93ba651dd // indirect
github.com/gabriel-vasile/mimetype v1.4.1 // indirect
@ -44,13 +41,10 @@ require (
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/golang-lru/v2 v2.0.7 // indirect
github.com/hashicorp/mdns v1.0.5 // indirect
github.com/huandu/xstrings v1.3.3 // indirect
github.com/igm/sockjs-go/v3 v3.0.2 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/keegancsmith/rpc v1.3.0 // indirect
github.com/klauspost/compress v1.16.6 // indirect
github.com/miekg/dns v1.1.53 // indirect
github.com/mitchellh/copystructure v1.0.0 // indirect
github.com/mitchellh/reflectwalk v1.0.0 // indirect
@ -58,8 +52,7 @@ require (
github.com/orcaman/concurrent-map v1.0.0 // indirect
github.com/shopspring/decimal v1.2.0 // indirect
github.com/spf13/cast v1.3.1 // indirect
github.com/ulikunitz/xz v0.5.11 // indirect
golang.org/x/net v0.11.0 // indirect
golang.org/x/net v0.9.0 // indirect
google.golang.org/genproto v0.0.0-20220728213248-dd149ef739b9 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
@ -82,7 +75,7 @@ require (
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/puddle/v2 v2.2.1 // indirect
github.com/jackc/puddle/v2 v2.2.0 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/leodido/go-urn v1.2.2 // indirect
github.com/lestrrat-go/blackmagic v1.0.1 // indirect
@ -103,14 +96,15 @@ 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.10.0 // indirect
golang.org/x/crypto v0.7.0 // indirect
golang.org/x/mod v0.10.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.9.0 // indirect
golang.org/x/term v0.9.0 // indirect
golang.org/x/text v0.10.0 // indirect
golang.org/x/sys v0.7.0 // indirect
golang.org/x/term v0.7.0 // indirect
golang.org/x/text v0.9.0 // indirect
golang.org/x/tools v0.8.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/go-playground/validator.v9 v9.31.0 // indirect
lukechampine.com/uint128 v1.2.0 // indirect
modernc.org/cc/v3 v3.40.0 // indirect

75
go.sum
View File

@ -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-20231130180951-32f04af138d7 h1:aDiZNT87sSC014GIapyEZ9O98EHOWHBNLtJR6p1ngG0=
forge.cadoles.com/arcad/edge v0.0.0-20231130180951-32f04af138d7/go.mod h1:DXxP+2fbR3hD3Q4ePoJn6jJItpOyBWx9wNsxCZEh4M4=
forge.cadoles.com/arcad/edge v0.0.0-20230426135323-17808d14c978 h1:fekSRSb8gYcVx8C0B9K6B7+KiFHVixIwvPUkxcnRFp4=
forge.cadoles.com/arcad/edge v0.0.0-20230426135323-17808d14c978/go.mod h1:uv3wBa+UbcEUb7IiJCj1T96Xo3cmx1BwNxbBYRZhln8=
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=
@ -128,7 +128,6 @@ github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkK
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 h1:smF2tmSOzy2Mm+0dGI2AIUHY+w0BUc+4tn40djz7+6U=
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/assert/v2 v2.0.3/go.mod h1:b/+1DI2Q6NckYi+3mXyH3wFb8qG37K/DuK80n7WefXA=
github.com/alecthomas/chroma v0.7.0/go.mod h1:1U/PfCsTALWWYHDnsIQkxEBM0+6LLe0v8+RSVMOwxeY=
github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek=
github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s=
@ -140,7 +139,6 @@ github.com/alecthomas/participle/v2 v2.0.0-beta.5 h1:y6dsSYVb1G5eK6mgmy+BgI3Mw35
github.com/alecthomas/participle/v2 v2.0.0-beta.5/go.mod h1:RC764t6n4L8D8ITAJv0qdokritYSNR3wV5cVwmIEaMM=
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
github.com/alecthomas/repr v0.1.0 h1:ENn2e1+J3k09gyj2shc0dHr/yjaWSHRlrJ4DPMevDqE=
github.com/alecthomas/repr v0.1.0/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@ -148,8 +146,6 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk=
github.com/allegro/bigcache/v3 v3.1.0 h1:H2Vp8VOvxcrB91o86fUSVJFqeuz8kpyyB02eH3bSzwk=
github.com/allegro/bigcache/v3 v3.1.0/go.mod h1:aPyh7jEvrog9zAwx5N7+JUQX5dZTSGpxF1LAR4dr35I=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
@ -508,17 +504,15 @@ github.com/gabriel-vasile/mimetype v1.4.1 h1:TRWk7se+TOjCYgRth7+1/OYLNiRNIotknkF
github.com/gabriel-vasile/mimetype v1.4.1/go.mod h1:05Vi0w3Y9c/lNvJOdmIwvrrAhX3rYhfQQCaf9VJcv7M=
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
github.com/getsentry/sentry-go v0.25.0 h1:q6Eo+hS+yoJlTO3uu/azhQadsD8V+jQn2D8VvX1eOyI=
github.com/getsentry/sentry-go v0.25.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec=
github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0=
github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g=
github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks=
github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY=
@ -556,10 +550,10 @@ github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dp
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU=
@ -679,7 +673,6 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0=
github.com/google/go-github/v39 v39.2.0/go.mod h1:C1s8C5aCC9L+JXIYpJM5GYytdX52vC1bLvHEF1IhBrE=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
@ -768,8 +761,6 @@ github.com/hashicorp/go.net v0.0.0-20151006203346-104dcad90073/go.mod h1:hjKkEWc
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v0.0.0-20151206042412-9d85cf22f9f8/go.mod h1:aa76Av3qgPeIQp9Y3qIkTBPieQYNkQ13Kxe7pze9Wb0=
@ -779,7 +770,6 @@ github.com/hashicorp/mdns v1.0.5/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4=
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
@ -847,8 +837,8 @@ github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0f
github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jackc/puddle/v2 v2.2.0 h1:RdcDk92EJBuBS55nQMMYFXTxwstHug4jkhT5pq8VxPk=
github.com/jackc/puddle/v2 v2.2.0/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jedib0t/go-pretty/v6 v6.4.4 h1:N+gz6UngBPF4M288kiMURPHELDMIhF/Em35aYuKrsSc=
github.com/jedib0t/go-pretty/v6 v6.4.4/go.mod h1:MgmISkTWDSFu0xOqiZ0mKNntMQ2mDgOcwOkwBEkMDJI=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
@ -888,8 +878,6 @@ github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaR
github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/keegancsmith/rpc v1.3.0 h1:wGWOpjcNrZaY8GDYZJfvyxmlLljm3YQWF+p918DXtDk=
github.com/keegancsmith/rpc v1.3.0/go.mod h1:6O2xnOGjPyvIPbvp0MdrOe5r6cu1GZ4JoTzpzDhWeo0=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
@ -901,8 +889,6 @@ github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdY
github.com/klauspost/compress v1.13.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.16.6 h1:91SKEy4K37vkp255cJ8QesJhjyRO0hn9i9G0GoUwLsk=
github.com/klauspost/compress v1.16.6/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@ -920,7 +906,7 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/ktrysmt/go-bitbucket v0.6.4/go.mod h1:9u0v3hsd2rqCHRIpbir1oP7F58uo5dq19sBYvuMoyQ4=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
github.com/leodido/go-urn v1.2.2 h1:7z68G0FCGvDk646jz1AelTYNYWrTNm0bEcFAo147wt4=
github.com/leodido/go-urn v1.2.2/go.mod h1:kUaIbLZWttglzwNuG0pgsh5vuV6u2YcGBYz1hIPjtOQ=
github.com/lestrrat-go/blackmagic v1.0.1 h1:lS5Zts+5HIC/8og6cGHb0uCcNCa3OUt1ygh3Qz2Fe80=
@ -990,7 +976,6 @@ github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOq
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY=
@ -1126,11 +1111,8 @@ github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2
github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pierrec/lz4/v4 v4.1.8/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -1192,7 +1174,6 @@ github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
@ -1228,9 +1209,8 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
@ -1291,8 +1271,6 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8=
github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
@ -1334,8 +1312,8 @@ github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPS
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE=
gitlab.com/wpetit/goweb v0.0.0-20231019192040-4c72331a7648 h1:t2UQmCmUoElIBBuVTqxqo8DcTJA/exQ/Q7XycfLqCZo=
gitlab.com/wpetit/goweb v0.0.0-20231019192040-4c72331a7648/go.mod h1:WdxGjM3HJWgBkUa4TwaTXUqY2BnRKlNSyUIv1aF4jxk=
gitlab.com/wpetit/goweb v0.0.0-20230419082146-a94d9ed7202b h1:nkvOl8TCj/mErADnwFFynjxBtC+hHsrESw6rw56JGmg=
gitlab.com/wpetit/goweb v0.0.0-20230419082146-a94d9ed7202b/go.mod h1:3sus4zjoUv1GB7eDLL60QaPkUnXJCWBpjvbe0jWifeY=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
@ -1389,8 +1367,6 @@ 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/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
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=
@ -1425,9 +1401,8 @@ golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm
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.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
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.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
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=
@ -1556,8 +1531,8 @@ 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/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU=
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/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=
@ -1722,8 +1697,8 @@ 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/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.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=
@ -1733,8 +1708,8 @@ 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/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28=
golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
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=
@ -1749,8 +1724,8 @@ 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/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58=
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.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=
@ -2005,7 +1980,6 @@ google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ5
google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
google.golang.org/grpc v1.48.0 h1:rQOsyJ/8+ufEDJd/Gdsz7HG220Mh9HAhFHRGnIjda0w=
google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
@ -2020,8 +1994,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.29.1 h1:7QBf+IK2gx70Ap/hDsOmam3GE0v9HicjfEdAxE62UoM=
google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@ -2132,7 +2106,6 @@ modernc.org/ccgo/v3 v3.9.2/go.mod h1:gnJpy6NIVqkETT+L5zPsQFj7L2kkhfPMzOghRNv/CFo
modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw=
modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY=
modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk=
modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
modernc.org/db v1.0.0/go.mod h1:kYD/cO29L/29RM0hXYl4i3+Q5VojL31kTUVpVJDw0s8=
modernc.org/file v1.0.0/go.mod h1:uqEokAEn1u6e+J45e54dsEA/pw4o7zLrA2GwyntZzjw=
modernc.org/fileutil v1.0.0/go.mod h1:JHsWpkrk/CnVV1H/eGlFf85BEpfkrp56ro8nojIq9Q8=
@ -2166,14 +2139,12 @@ modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY=
modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw=
modernc.org/tcl v1.5.2/go.mod h1:pmJYOLgpiys3oI4AeAafkcUfE+TKKilminxNyU/+Zlo=
modernc.org/tcl v1.15.1 h1:mOQwiEK4p7HruMZcwKTZPw/aqtGM4aY00uzWhlKKYws=
modernc.org/tcl v1.15.1/go.mod h1:aEjeGJX2gz1oWKOLDVZ2tnEWLUrIn8H+GFu+akoDhqs=
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/z v1.0.1-0.20210308123920-1f282aa71362/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA=
modernc.org/z v1.0.1/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA=
modernc.org/z v1.7.0 h1:xkDw/KepgEjeizO2sNco+hqYkU12taxQFqPEmgm1GWE=
modernc.org/z v1.7.0/go.mod h1:hVdgNMh8ggTuRG1rGU8x+xGRFfiQUIAw0ZqlPy8+HyQ=
modernc.org/zappy v1.0.0/go.mod h1:hHe+oGahLVII/aTTyWK/b53VDHMAGCBYYeZ9sn83HC4=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

View File

@ -43,15 +43,13 @@ func (a *Agent) Run(ctx context.Context) error {
logger.Debug(ctx, "registering agent")
if err := a.registerAgent(ctx, client, state); err != nil {
err = errors.WithStack(err)
logger.Error(ctx, "could not register agent", logger.CapturedE(err))
logger.Error(ctx, "could not register agent", logger.E(errors.WithStack(err)))
}
logger.Debug(ctx, "state before reconciliation", logger.F("state", state))
if err := a.Reconcile(ctx, state); err != nil {
err = errors.WithStack(err)
logger.Error(ctx, "could not reconcile node with state", logger.CapturedE(err))
logger.Error(ctx, "could not reconcile node with state", logger.E(errors.WithStack(err)))
return
}
@ -81,8 +79,7 @@ func (a *Agent) Reconcile(ctx context.Context, state *State) error {
)
if err := ctrl.Reconcile(ctrlCtx, state); err != nil {
err = errors.WithStack(err)
logger.Error(ctx, "could not reconcile", logger.CapturedE(err))
logger.Error(ctx, "could not reconcile", logger.E(errors.WithStack(err)))
}
}
@ -113,10 +110,9 @@ func (a *Agent) collectMetadata(ctx context.Context) (map[string]any, error) {
for _, collector := range a.collectors {
name, value, err := collector.Collect(ctx)
if err != nil {
err = errors.WithStack(err)
logger.Error(
ctx, "could not collect metadata",
logger.CapturedE(err), logger.F("name", name),
logger.E(errors.WithStack(err)), logger.F("name", name),
)
continue

View File

@ -4,6 +4,7 @@ import (
"bytes"
"context"
"net"
"path/filepath"
"text/template"
"forge.cadoles.com/Cadoles/emissary/internal/agent/controller/app/spec"
@ -16,60 +17,47 @@ import (
appModule "forge.cadoles.com/arcad/edge/pkg/module/app"
"forge.cadoles.com/arcad/edge/pkg/module/blob"
"forge.cadoles.com/arcad/edge/pkg/module/cast"
"forge.cadoles.com/arcad/edge/pkg/module/fetch"
fetchModule "forge.cadoles.com/arcad/edge/pkg/module/fetch"
netModule "forge.cadoles.com/arcad/edge/pkg/module/net"
"forge.cadoles.com/arcad/edge/pkg/module/rpc"
shareModule "forge.cadoles.com/arcad/edge/pkg/module/share"
shareSqlite "forge.cadoles.com/arcad/edge/pkg/module/share/sqlite"
"forge.cadoles.com/arcad/edge/pkg/storage"
"forge.cadoles.com/arcad/edge/pkg/storage/driver"
"forge.cadoles.com/arcad/edge/pkg/storage/share"
"forge.cadoles.com/arcad/edge/pkg/storage/sqlite"
"github.com/Masterminds/sprig/v3"
"github.com/go-chi/chi/v5"
"github.com/lestrrat-go/jwx/v2/jwa"
"github.com/pkg/errors"
"gitlab.com/wpetit/goweb/logger"
// Register storage drivers
_ "forge.cadoles.com/arcad/edge/pkg/storage/driver/cache"
_ "forge.cadoles.com/arcad/edge/pkg/storage/driver/rpc"
_ "forge.cadoles.com/arcad/edge/pkg/storage/driver/sqlite"
)
type Dependencies struct {
Bus bus.Bus
DocumentStore storage.DocumentStore
BlobStore storage.BlobStore
ShareStore share.Store
KeySet jwk.Set
AppRepository appModule.Repository
AppID app.ID
Bus bus.Bus
DocumentStore storage.DocumentStore
BlobStore storage.BlobStore
KeySet jwk.Set
AppRepository appModule.Repository
AppID app.ID
ShareRepository shareModule.Repository
}
const defaultSQLiteParams = "?_pragma=foreign_keys(1)&_pragma=busy_timeout=60000"
func (c *Controller) getHandlerOptions(ctx context.Context, appKey string, specs *spec.Spec) ([]edgeHTTP.HandlerOptionFunc, error) {
appEntry, exists := specs.Apps[appKey]
if !exists {
return nil, errors.Errorf("could not find app entry '%s'", appKey)
}
storage := appEntry.Storage
if storage == nil {
return nil, errors.Errorf("could not find app entry '%s' storage configuration", appKey)
}
documentStore, err := driver.NewDocumentStore(appEntry.Storage.DocumentStoreDSN)
dataDir, err := c.ensureAppDataDir(ctx, appKey)
if err != nil {
return nil, errors.WithStack(err)
return nil, errors.Wrap(err, "could not retrieve app data dir")
}
blobStore, err := driver.NewBlobStore(appEntry.Storage.BlobStoreDSN)
dbFile := filepath.Join(dataDir, appKey+".sqlite")
db, err := sqlite.Open(dbFile + defaultSQLiteParams)
if err != nil {
return nil, errors.WithStack(err)
return nil, errors.Wrapf(err, "could not open database file '%s'", dbFile)
}
shareStore, err := driver.NewShareStore(appEntry.Storage.ShareStoreDSN)
shareDBFile := filepath.Join(dataDir, "shared.sqlite")
shareDB, err := sqlite.Open(shareDBFile + defaultSQLiteParams)
if err != nil {
return nil, errors.WithStack(err)
return nil, errors.Wrapf(err, "could not open database file '%s'", shareDBFile)
}
keySet, err := getAuthKeySet(specs.Config)
@ -88,37 +76,24 @@ func (c *Controller) getHandlerOptions(ctx context.Context, appKey string, specs
mounts = append(mounts, authMount)
}
mounts = append(
mounts,
appModule.Mount(c.appRepository),
blob.Mount(10<<(10*2)), // 10Mb
fetch.Mount(),
)
mounts = append(mounts, appModule.Mount(c.appRepository))
deps := Dependencies{
Bus: memory.NewBus(),
DocumentStore: documentStore,
BlobStore: blobStore,
ShareStore: shareStore,
KeySet: keySet,
AppRepository: c.appRepository,
AppID: app.ID(appKey),
Bus: memory.NewBus(),
DocumentStore: sqlite.NewDocumentStoreWithDB(db),
BlobStore: sqlite.NewBlobStoreWithDB(db),
KeySet: keySet,
AppRepository: c.appRepository,
AppID: app.ID(appKey),
ShareRepository: shareSqlite.NewRepositoryWithDB(shareDB),
}
modules := c.getAppModules(deps)
anonymousUserMiddleware, err := getAnonymousUserMiddleware(specs.Config.Auth)
if err != nil {
return nil, errors.Wrap(err, "could not get anonymous user middleware")
}
options := []edgeHTTP.HandlerOptionFunc{
edgeHTTP.WithBus(deps.Bus),
edgeHTTP.WithServerModules(modules...),
edgeHTTP.WithHTTPMounts(mounts...),
edgeHTTP.WithHTTPMiddlewares(
anonymousUserMiddleware,
),
}
return options, nil
@ -205,10 +180,9 @@ func createResolveAppURL(specs *spec.Spec) (ResolveAppURLFunc, error) {
for ifaceName, ifaceTmpl := range ifaceMappings {
iface, err := net.InterfaceByName(ifaceName)
if err != nil {
err = errors.WithStack(err)
logger.Warn(
logger.Error(
ctx, "could not find interface",
logger.CapturedE(err), logger.F("iface", ifaceName),
logger.E(errors.WithStack(err)), logger.F("iface", ifaceName),
)
continue
@ -216,10 +190,9 @@ func createResolveAppURL(specs *spec.Spec) (ResolveAppURLFunc, error) {
addresses, err := iface.Addrs()
if err != nil {
err = errors.WithStack(err)
logger.Error(
ctx, "could not list interface addresses",
logger.CapturedE(err),
logger.E(errors.WithStack(err)),
logger.F("iface", iface.Name),
)
@ -229,10 +202,9 @@ func createResolveAppURL(specs *spec.Spec) (ResolveAppURLFunc, error) {
for _, addr := range addresses {
ifaIP, network, err := net.ParseCIDR(addr.String())
if err != nil {
err = errors.WithStack(err)
logger.Error(
ctx, "could not parse interface ip",
logger.CapturedE(err),
logger.E(errors.WithStack(err)),
logger.F("iface", iface.Name),
)
@ -307,12 +279,12 @@ func (c *Controller) getAppModules(deps Dependencies) []app.ServerModuleFactory
cast.CastModuleFactory(),
module.LifecycleModuleFactory(),
netModule.ModuleFactory(deps.Bus),
rpc.ModuleFactory(deps.Bus),
module.RPCModuleFactory(deps.Bus),
module.StoreModuleFactory(deps.DocumentStore),
blob.ModuleFactory(deps.Bus, deps.BlobStore),
authModuleFactory(deps.KeySet),
appModule.ModuleFactory(deps.AppRepository),
fetchModule.ModuleFactory(deps.Bus),
shareModule.ModuleFactory(deps.AppID, deps.ShareStore),
shareModule.ModuleFactory(deps.AppID, deps.ShareRepository),
}
}

View File

@ -63,16 +63,14 @@ func (r *AppRepository) List(ctx context.Context) ([]*app.Manifest, error) {
bundle, err := bundle.FromPath(path)
if err != nil {
err = errors.WithStack(err)
logger.Error(bundleCtx, "could not load bundle", logger.CapturedE(err))
logger.Error(bundleCtx, "could not load bundle", logger.E(errors.WithStack(err)))
continue
}
manifest, err := app.LoadManifest(bundle)
if err != nil {
err = errors.WithStack(err)
logger.Error(bundleCtx, "could not load manifest", logger.CapturedE(err))
logger.Error(bundleCtx, "could not load manifest", logger.E(errors.WithStack(err)))
continue
}
@ -99,16 +97,14 @@ func (r *AppRepository) findManifest(ctx context.Context, id app.ID) (*app.Manif
bundle, err := bundle.FromPath(path)
if err != nil {
err = errors.WithStack(err)
logger.Error(bundleCtx, "could not load bundle", logger.CapturedE(err))
logger.Error(bundleCtx, "could not load bundle", logger.E(errors.WithStack(err)))
continue
}
manifest, err := app.LoadManifest(bundle)
if err != nil {
err = errors.WithStack(err)
logger.Error(bundleCtx, "could not load manifest", logger.CapturedE(err))
logger.Error(bundleCtx, "could not load manifest", logger.E(errors.WithStack(err)))
continue
}

View File

@ -1,18 +1,15 @@
package app
import (
"net/http"
"time"
appSpec "forge.cadoles.com/Cadoles/emissary/internal/agent/controller/app/spec"
"forge.cadoles.com/Cadoles/emissary/internal/agent/controller/app/spec"
"forge.cadoles.com/Cadoles/emissary/internal/jwk"
"forge.cadoles.com/arcad/edge/pkg/app"
"forge.cadoles.com/arcad/edge/pkg/module"
"forge.cadoles.com/arcad/edge/pkg/module/auth"
authModule "forge.cadoles.com/arcad/edge/pkg/module/auth"
authHTTP "forge.cadoles.com/arcad/edge/pkg/module/auth/http"
authModuleMiddleware "forge.cadoles.com/arcad/edge/pkg/module/auth/middleware"
"github.com/dop251/goja"
"github.com/lestrrat-go/jwx/v2/jwa"
"github.com/pkg/errors"
@ -57,7 +54,7 @@ func authModuleFactory(keySet jwk.Set) app.ServerModuleFactory {
)
}
func getAuthMount(auth *appSpec.Auth, keySet jwk.Set) (auth.MountFunc, error) {
func getAuthMount(auth *spec.Auth, keySet jwk.Set) (auth.MountFunc, error) {
switch {
case auth.Local != nil:
var rawKey any = auth.Local.Key
@ -80,8 +77,7 @@ func getAuthMount(auth *appSpec.Auth, keySet jwk.Set) (auth.MountFunc, error) {
return authModule.Mount(
authHTTP.NewLocalHandler(
key,
jwa.HS256,
jwa.HS256, key,
authHTTP.WithRoutePrefix("/auth"),
authHTTP.WithAccounts(auth.Local.Accounts...),
authHTTP.WithCookieOptions(getCookieDomain, cookieDuration),
@ -95,72 +91,3 @@ func getAuthMount(auth *appSpec.Auth, keySet jwk.Set) (auth.MountFunc, error) {
return nil, nil
}
}
func getAnonymousUserMiddleware(auth *appSpec.Auth) (func(http.Handler) http.Handler, error) {
anonymousUserSigningKey, err := getAnonymousUserSigningKey(auth)
if err != nil {
return nil, errors.Wrap(err, "could not get anonymous user signing key")
}
cookieDuration := defaultCookieDuration
if auth.Local.CookieDuration != "" {
cookieDuration, err = time.ParseDuration(auth.Local.CookieDuration)
if err != nil {
return nil, errors.WithStack(err)
}
}
middleware := authModuleMiddleware.AnonymousUser(
anonymousUserSigningKey,
auth.Local.SigningAlgorithm,
authModuleMiddleware.WithCookieOptions(getCookieDomain, cookieDuration),
)
return middleware, nil
}
func getAnonymousUserSigningKey(auth *appSpec.Auth) (jwk.Key, error) {
var (
key jwk.Key
err error
)
generateNewKey := func() (jwk.Key, error) {
key, err := jwk.Generate(2048)
if err != nil {
return nil, errors.WithStack(err)
}
return key, nil
}
switch {
default:
fallthrough
case auth == nil:
key, err = generateNewKey()
if err != nil {
return nil, errors.Wrap(err, "could not generate anonymous user signing key")
}
return key, nil
case auth.Local != nil:
switch typedKey := auth.Local.Key.(type) {
case string:
key, err = jwk.FromRaw([]byte(typedKey))
if err != nil {
return nil, errors.Wrap(err, "could not parse local auth key")
}
if err := key.Set(jwk.AlgorithmKey, jwa.HS256); err != nil {
return nil, errors.WithStack(err)
}
default:
return nil, errors.Errorf("unexpected key type '%T'", auth.Local.Key)
}
}
return key, nil
}

View File

@ -66,11 +66,10 @@ func (c *Controller) stopAllApps(ctx context.Context, spec *spec.Spec) {
logger.Info(ctx, "stopping app", logger.F("appID", appID))
if err := entry.Server.Stop(); err != nil {
err = errors.WithStack(err)
logger.Error(
ctx, "error while stopping app",
logger.F("appID", appID),
logger.CapturedE(err),
logger.E(errors.WithStack(err)),
)
delete(c.servers, appID)
@ -88,11 +87,10 @@ func (c *Controller) updateApps(ctx context.Context, specs *spec.Spec) {
logger.Info(ctx, "stopping app", logger.F("appKey", appKey))
if err := server.Server.Stop(); err != nil {
err = errors.WithStack(err)
logger.Error(
ctx, "error while stopping app",
logger.F("appKey", appKey),
logger.CapturedE(err),
logger.E(errors.WithStack(err)),
)
delete(c.servers, appKey)
@ -100,10 +98,9 @@ func (c *Controller) updateApps(ctx context.Context, specs *spec.Spec) {
}
if err := c.updateAppRepository(ctx, specs); err != nil {
err = errors.WithStack(err)
logger.Error(
ctx, "could not update app repository",
logger.CapturedE(err),
logger.E(errors.WithStack(err)),
)
return
@ -114,8 +111,7 @@ func (c *Controller) updateApps(ctx context.Context, specs *spec.Spec) {
appCtx := logger.With(ctx, logger.F("appKey", appKey))
if err := c.updateApp(ctx, specs, appKey); err != nil {
err = errors.WithStack(err)
logger.Error(appCtx, "could not update app", logger.CapturedE(err))
logger.Error(appCtx, "could not update app", logger.E(errors.WithStack(err)))
continue
}
}
@ -204,13 +200,11 @@ func (c *Controller) updateApp(ctx context.Context, specs *spec.Spec, appKey str
return nil
}
ctx = logger.With(ctx,
logger.F("appKey", appKey),
logger.F("address", appEntry.Address),
)
if defChanged && server.AppDefHash != 0 {
logger.Info(ctx, "restarting app")
logger.Info(
ctx, "restarting app",
logger.F("address", appEntry.Address),
)
if err := server.Server.Stop(); err != nil {
return errors.WithStack(err)
@ -223,7 +217,10 @@ func (c *Controller) updateApp(ctx context.Context, specs *spec.Spec, appKey str
c.servers[appKey] = serverEntry
} else {
logger.Info(ctx, "starting app")
logger.Info(
ctx, "starting app",
logger.F("address", appEntry.Address),
)
}
if err := server.Server.Start(ctx, appEntry.Address); err != nil {

View File

@ -8,14 +8,15 @@ import (
"sync"
"time"
"forge.cadoles.com/Cadoles/emissary/internal/agent/controller/app/spec"
appSpec "forge.cadoles.com/Cadoles/emissary/internal/agent/controller/app/spec"
"forge.cadoles.com/Cadoles/emissary/internal/proxy/wildcard"
edgeHTTP "forge.cadoles.com/arcad/edge/pkg/http"
"gitlab.com/wpetit/goweb/logger"
"forge.cadoles.com/arcad/edge/pkg/bundle"
"github.com/go-chi/chi/middleware"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
"github.com/pkg/errors"
_ "forge.cadoles.com/Cadoles/emissary/internal/imports/passwd"
@ -48,7 +49,7 @@ func (s *Server) Start(ctx context.Context, addr string) (err error) {
router.Use(middleware.Compress(5))
handler := edgeHTTP.NewHandler(s.handlerOptions...)
if err := handler.Load(ctx, s.bundle); err != nil {
if err := handler.Load(s.bundle); err != nil {
return errors.Wrap(err, "could not load app bundle")
}
@ -72,8 +73,7 @@ func (s *Server) Start(ctx context.Context, addr string) (err error) {
defer func() {
if recovered := recover(); recovered != nil {
if err, ok := recovered.(error); ok {
err = errors.WithStack(err)
logger.Error(ctx, err.Error(), logger.CapturedE(err))
logger.Error(ctx, err.Error(), logger.E(errors.WithStack(err)))
return
}
@ -128,7 +128,7 @@ func (s *Server) Stop() error {
return nil
}
func NewServer(bundle bundle.Bundle, config *appSpec.Config, handlerOptions ...edgeHTTP.HandlerOptionFunc) *Server {
func NewServer(bundle bundle.Bundle, config *spec.Config, handlerOptions ...edgeHTTP.HandlerOptionFunc) *Server {
return &Server{
bundle: bundle,
config: config,

View File

@ -24,37 +24,15 @@
"type": "string",
"enum": [
"zip",
"tar.gz",
"zim"
"tar.gz"
]
},
"storage": {
"type": "object",
"properties": {
"blobStoreDsn": {
"type": "string"
},
"documentStoreDsn": {
"type": "string"
},
"shareStoreDsn": {
"type": "string"
}
},
"required": [
"blobStoreDsn",
"documentStoreDsn",
"shareStoreDsn"
],
"additionalProperties": false
}
},
"required": [
"url",
"sha256sum",
"address",
"format",
"storage"
"format"
],
"additionalProperties": false
}
@ -106,9 +84,6 @@
"key": {
"type": ["object", "string"]
},
"signingAlgorithm": {
"type": "string"
},
"accounts": {
"type": "array",
"items": {
@ -142,8 +117,7 @@
}
},
"required": [
"key",
"signingAlgorithm"
"key"
],
"additionalProperties": false
}

View File

@ -3,7 +3,6 @@ package spec
import (
"forge.cadoles.com/Cadoles/emissary/internal/spec"
edgeAuth "forge.cadoles.com/arcad/edge/pkg/module/auth/http"
"github.com/lestrrat-go/jwx/v2/jwa"
)
const Name spec.Name = "app.emissary.cadoles.com"
@ -15,17 +14,10 @@ type Spec struct {
}
type AppEntry struct {
URL string `json:"url"`
SHA256Sum string `json:"sha256sum"`
Address string `json:"address"`
Format string `json:"format"`
Storage *AppStorage `json:"storage"`
}
type AppStorage struct {
ShareStoreDSN string `json:"shareStoreDsn"`
DocumentStoreDSN string `json:"documentStoreDsn"`
BlobStoreDSN string `json:"blobStoreDsn"`
URL string `json:"url"`
SHA256Sum string `json:"sha256sum"`
Address string `json:"address"`
Format string `json:"format"`
}
type Auth struct {
@ -33,11 +25,10 @@ type Auth struct {
}
type LocalAuth struct {
Key any `json:"key"`
SigningAlgorithm jwa.SignatureAlgorithm `json:"signingAlgorithm"`
Accounts []edgeAuth.LocalAccount `json:"accounts"`
CookieDomain string `json:"cookieDomain"`
CookieDuration string `json:"cookieDuration"`
Key any `json:"key"`
Accounts []edgeAuth.LocalAccount `json:"accounts"`
CookieDomain string `json:"cookieDomain"`
CookieDuration string `json:"cookieDuration"`
}
type Config struct {

View File

@ -6,12 +6,7 @@
"url": "http://example.com/edge.sdk.client.test_0.0.0.zip",
"sha256sum": "58019192dacdae17755707719707db007e26dac856102280583fbd18427dd352",
"address": ":8081",
"format": "zip",
"storage": {
"blobStoreDsn": "sqlite://apps/data/edge.sdk.client.test/blobstore.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=60000",
"shareStoreDsn": "sqlite://apps/data/sharestore.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=60000",
"documentStoreDsn": "sqlite://apps/data/edge.sdk.client.test/documentstore.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=60000"
}
"format": "zip"
}
},
"config": {
@ -28,7 +23,6 @@
"q": "yJJLNc9w6O4y2icME8k99FugV9E7ObwUxF3v5JN3y1cmAT0h2njyE3iAGqaDZwcY1_jGCisjwoqX6i5E8xqhxX3Gcy3J7SmUAf8fhY8wU3zv9DK7skg2IdvanDb8Y1OM6GchbYZAOVPEg2IvVio8zI-Ih3DDwDk8Df0ufzoHRb8",
"qi": "zOE-4R3cjPesm3MX-4PdwmsaF9QZLUVRUvvHJ08pKs6kAXP18hzjctAoOjhQDxlTYqNYNePfKzKwost3OJoPgRIc9w9qwUCK1gNOS4Z_xozCIaXgMddNFhkoAfZ4JaKjNCiinzjGfqG99Lf-yzmmREuuhRv7SdS3ST4VQjiJQew"
},
"signingAlgorithm": "RS256",
"accounts": [
{
"username": "foo",

View File

@ -117,8 +117,7 @@ func (c *Controller) updateResponder(ctx context.Context, spec *mdns.Spec) error
service, err := dnssd.NewService(config)
if err != nil {
err = errors.WithStack(err)
logger.Error(ctx, "could not create mdns service", logger.CapturedE(err))
logger.Error(ctx, "could not create mdns service", logger.E(errors.WithStack(err)))
continue
}
@ -133,8 +132,7 @@ func (c *Controller) updateResponder(ctx context.Context, spec *mdns.Spec) error
for _, service := range services {
if _, err := responder.Add(service); err != nil {
err = errors.WithStack(err)
logger.Error(ctx, "could not add mdns service", logger.CapturedE(err))
logger.Error(ctx, "could not add mdns service", logger.E(errors.WithStack(err)))
continue
}
@ -150,8 +148,7 @@ func (c *Controller) updateResponder(ctx context.Context, spec *mdns.Spec) error
defer c.stopResponder(ctx)
if err := responder.Respond(ctx); err != nil && !errors.Is(err, context.Canceled) {
err = errors.WithStack(err)
logger.Error(ctx, "could not respond to mdns queries", logger.CapturedE(err))
logger.Error(ctx, "could not respond to mdns queries", logger.E(errors.WithStack(err)))
}
}()

View File

@ -64,10 +64,9 @@ func (c *SysUpgradeController) Reconcile(ctx context.Context, state *agent.State
defer func() {
if err := os.RemoveAll(downloadDir); err != nil {
err = errors.WithStack(err)
logger.Error(
ctx, "could not remove download direction",
logger.CapturedE(err),
logger.E(errors.WithStack(err)),
logger.F("downloadDir", downloadDir),
)
}

View File

@ -46,8 +46,7 @@ func (c *UCIController) Reconcile(ctx context.Context, state *agent.State) error
}
if err := c.updateConfiguration(ctx, uciSpec); err != nil {
err = errors.WithStack(err)
logger.Error(ctx, "could not update configuration", logger.CapturedE(err))
logger.Error(ctx, "could not update configuration", logger.E(errors.WithStack(err)))
return nil
}

View File

@ -145,8 +145,7 @@ func (c *Controller) writeState(ctx context.Context, state *agent.State) error {
return
}
err = errors.WithStack(err)
logger.Error(ctx, "could not remove temporary file", logger.CapturedE(err))
logger.Error(ctx, "could not remove temporary file", logger.E(errors.WithStack(err)))
}
}()
@ -156,8 +155,7 @@ func (c *Controller) writeState(ctx context.Context, state *agent.State) error {
return
}
err = errors.WithStack(err)
logger.Error(ctx, "could not close temporary file", logger.CapturedE(err))
logger.Error(ctx, "could not close temporary file", logger.E(errors.WithStack(err)))
}
}()

View File

@ -58,11 +58,10 @@ func (c *Controller) stopAllProxies(ctx context.Context) {
logger.Info(ctx, "stopping proxy", logger.F("proxyID", proxyID))
if err := entry.Proxy.Stop(); err != nil {
err = errors.WithStack(err)
logger.Error(
ctx, "error while stopping proxy",
logger.F("proxyID", proxyID),
logger.CapturedE(err),
logger.E(errors.WithStack(err)),
)
delete(c.proxies, proxyID)
@ -80,11 +79,10 @@ func (c *Controller) updateProxies(ctx context.Context, spec *spec.Spec) {
logger.Info(ctx, "stopping proxy", logger.F("proxyID", proxyID))
if err := entry.Proxy.Stop(); err != nil {
err = errors.WithStack(err)
logger.Error(
ctx, "error while stopping proxy",
logger.F("proxyID", proxyID),
logger.CapturedE(err),
logger.E(errors.WithStack(err)),
)
delete(c.proxies, proxyID)
@ -96,8 +94,7 @@ func (c *Controller) updateProxies(ctx context.Context, spec *spec.Spec) {
proxyCtx := logger.With(ctx, logger.F("proxyID", proxyID))
if err := c.updateProxy(ctx, proxyID, proxySpec); err != nil {
err = errors.WithStack(err)
logger.Error(proxyCtx, "could not update proxy", logger.CapturedE(err))
logger.Error(proxyCtx, "could not update proxy", logger.E(errors.WithStack(err)))
continue
}
}

View File

@ -38,14 +38,12 @@ func (p *ReverseProxy) Start(ctx context.Context, addr string, funcs ...proxy.Op
go func() {
defer func() {
if err := p.Stop(); err != nil {
err = errors.WithStack(err)
logger.Error(ctx, "error while stopping gateway", logger.CapturedE(err))
logger.Error(ctx, "error while stopping gateway", logger.E(errors.WithStack(err)))
}
}()
if err := server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
err = errors.WithStack(err)
logger.Error(ctx, "error while listening", logger.CapturedE(err))
logger.Error(ctx, "error while listening", logger.E(errors.WithStack(err)))
}
}()

View File

@ -40,15 +40,14 @@ func (c *Controller) reconcileAgent(ctx context.Context, client *client.Client,
ctx = logger.With(ctx, logger.F("agentID", agent.ID))
if agent.Status != datastore.AgentStatusAccepted {
logger.Warn(ctx, "unexpected agent status", logger.F("status", agent.Status))
logger.Error(ctx, "unexpected agent status", logger.F("status", agent.Status))
return nil
}
specs, err := client.GetAgentSpecs(ctx, agent.ID)
if err != nil {
err = errors.WithStack(err)
logger.Error(ctx, "could not retrieve agent specs", logger.CapturedE(err))
logger.Error(ctx, "could not retrieve agent specs", logger.E(errors.WithStack(err)))
return nil
}

View File

@ -7,11 +7,8 @@ import (
"sort"
"time"
"forge.cadoles.com/Cadoles/emissary/internal/command/common"
"github.com/getsentry/sentry-go"
"github.com/pkg/errors"
"github.com/urfave/cli/v2"
"gitlab.com/wpetit/goweb/logger"
)
func Main(buildDate, projectVersion, gitRef, defaultConfigPath string, commands ...*cli.Command) {
@ -49,27 +46,6 @@ func Main(buildDate, projectVersion, gitRef, defaultConfigPath string, commands
return errors.WithStack(err)
}
conf, err := common.LoadConfig(ctx)
if err != nil {
return errors.Wrap(err, "Could not load configuration")
}
if conf.Sentry.DSN != "" {
err = sentry.Init(sentry.ClientOptions{
Dsn: string(conf.Sentry.DSN),
Debug: ctx.Bool("debug"),
AttachStacktrace: true,
Environment: string(conf.Sentry.Environment),
})
if err != nil {
logger.Error(ctx.Context, "could not initialize sentry", logger.E(errors.WithStack(err)))
}
logger.SetCaptureFunc(func(err error) {
sentry.CaptureException(err)
})
}
return nil
},
Flags: []cli.Flag{
@ -108,15 +84,11 @@ func Main(buildDate, projectVersion, gitRef, defaultConfigPath string, commands
},
}
defer sentry.Flush(2 * time.Second)
app.ExitErrHandler = func(ctx *cli.Context, err error) {
if err == nil {
return
}
sentry.CaptureException(err)
debug := ctx.Bool("debug")
if !debug {

View File

@ -32,8 +32,7 @@ func PingCommand() *cli.Command {
defer func() {
if err := db.Close(); err != nil {
err = errors.WithStack(err)
logger.Error(ctx.Context, "error while closing database connection", logger.CapturedE(err))
logger.Error(ctx.Context, "error while closing database connection", logger.E(errors.WithStack(err)))
}
}()

View File

@ -11,7 +11,6 @@ import (
// Config definition
type Config struct {
Logger LoggerConfig `yaml:"logger"`
Sentry SentryConfig `yaml:"sentry"`
Server ServerConfig `yaml:"server"`
Agent AgentConfig `yaml:"agent"`
}
@ -45,7 +44,6 @@ func NewDefault() *Config {
Logger: NewDefaultLoggerConfig(),
Agent: NewDefaultAgentConfig(),
Server: NewDefaultServerConfig(),
Sentry: NewDefaultSentryConfig(),
}
}

View File

@ -15,6 +15,6 @@ type DatabaseConfig struct {
func NewDefaultDatabaseConfig() DatabaseConfig {
return DatabaseConfig{
Driver: "sqlite",
DSN: "sqlite://emissary.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=150000&_pragma=journal_mode=WAL",
DSN: "sqlite://emissary.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=60000",
}
}

View File

@ -10,41 +10,7 @@ import (
"gopkg.in/yaml.v3"
)
var (
interpolationRegExp = regexp.MustCompile(`^\${((?P<varName>\w+)|((?P<varNameWithDefault>\w+):-(?P<defaultValue>[^}]+)))}$`)
varNameGroupIndex = interpolationRegExp.SubexpIndex("varName")
varNameWithDefaultGroupIndex = interpolationRegExp.SubexpIndex("varNameWithDefault")
defaultValueGroupIndex = interpolationRegExp.SubexpIndex("defaultValue")
)
func interpolate(str string, getValueFunc func(name string) string) string {
for _, match := range interpolationRegExp.FindAllStringSubmatch(str, -1) {
varName := match[varNameWithDefaultGroupIndex]
if varName == "" {
varName = match[varNameGroupIndex]
}
if varName == "" {
continue
}
defaultValue := ""
if defaultValueGroupIndex < len(match) {
defaultValue = match[defaultValueGroupIndex]
}
str = getValueFunc(varName)
if str == "" {
str = defaultValue
}
}
return str
}
func interpolateEnv(str string) string {
return interpolate(str, os.Getenv)
}
var reVar = regexp.MustCompile(`^\${(\w+)}$`)
type InterpolatedString string
@ -55,7 +21,11 @@ func (is *InterpolatedString) UnmarshalYAML(value *yaml.Node) error {
return errors.WithStack(err)
}
*is = InterpolatedString(interpolateEnv(str))
if match := reVar.FindStringSubmatch(str); len(match) > 0 {
*is = InterpolatedString(os.Getenv(match[1]))
} else {
*is = InterpolatedString(str)
}
return nil
}
@ -69,7 +39,9 @@ func (ii *InterpolatedInt) UnmarshalYAML(value *yaml.Node) error {
return errors.Wrapf(err, "could not decode value '%v' (line '%d') into string", value.Value, value.Line)
}
str = interpolateEnv(str)
if match := reVar.FindStringSubmatch(str); len(match) > 0 {
str = os.Getenv(match[1])
}
intVal, err := strconv.ParseInt(str, 10, 32)
if err != nil {
@ -90,7 +62,9 @@ func (ib *InterpolatedBool) UnmarshalYAML(value *yaml.Node) error {
return errors.Wrapf(err, "could not decode value '%v' (line '%d') into string", value.Value, value.Line)
}
str = interpolateEnv(str)
if match := reVar.FindStringSubmatch(str); len(match) > 0 {
str = os.Getenv(match[1])
}
boolVal, err := strconv.ParseBool(str)
if err != nil {
@ -117,7 +91,9 @@ func (im *InterpolatedMap) UnmarshalYAML(value *yaml.Node) error {
continue
}
strVal = interpolateEnv(strVal)
if match := reVar.FindStringSubmatch(strVal); len(match) > 0 {
strVal = os.Getenv(match[1])
}
data[key] = strVal
}
@ -137,7 +113,9 @@ func (iss *InterpolatedStringSlice) UnmarshalYAML(value *yaml.Node) error {
}
for index, value := range data {
value = interpolateEnv(value)
if match := reVar.FindStringSubmatch(value); len(match) > 0 {
value = os.Getenv(match[1])
}
data[index] = value
}
@ -156,7 +134,9 @@ func (id *InterpolatedDuration) UnmarshalYAML(value *yaml.Node) error {
return errors.Wrapf(err, "could not decode value '%v' (line '%d') into string", value.Value, value.Line)
}
str = interpolateEnv(str)
if match := reVar.FindStringSubmatch(str); len(match) > 0 {
str = os.Getenv(match[1])
}
duration, err := time.ParseDuration(str)
if err != nil {

View File

@ -1,63 +0,0 @@
package config
import (
"fmt"
"testing"
)
type interpolateTestCase struct {
String string
Data map[string]string
Expected string
}
var interpolateTestCases = []interpolateTestCase{
{
String: "${foo}",
Data: map[string]string{
"foo": "bar",
},
Expected: "bar",
},
{
String: "${hello:-world}",
Data: map[string]string{},
Expected: "world",
},
{
String: "${hello:-}",
Data: map[string]string{},
Expected: "${hello:-}",
},
{
String: "foo",
Data: map[string]string{},
Expected: "foo",
},
{
String: "",
Data: map[string]string{},
Expected: "",
},
}
func TestInterpolate(t *testing.T) {
for idx, tc := range interpolateTestCases {
func(idx int, tc interpolateTestCase) {
t.Run(fmt.Sprintf("Case_%d", idx), func(t *testing.T) {
result := interpolate(tc.String, func(name string) string {
value, exists := tc.Data[name]
if !exists {
return ""
}
return value
})
if e, g := tc.Expected, result; e != g {
t.Errorf("result: expected '%v', got '%v'", tc.Expected, result)
}
})
}(idx, tc)
}
}

View File

@ -1,18 +0,0 @@
package config
import (
"os"
)
type SentryConfig struct {
DSN InterpolatedString `yaml:"dsn"`
Environment InterpolatedString `yaml:"environment"`
}
func NewDefaultSentryConfig() SentryConfig {
hostname, _ := os.Hostname()
return SentryConfig{
DSN: "",
Environment: InterpolatedString(hostname),
}
}

View File

@ -5,7 +5,6 @@ import (
"database/sql"
"encoding/json"
"fmt"
"strings"
"time"
"forge.cadoles.com/Cadoles/emissary/internal/datastore"
@ -16,13 +15,12 @@ import (
)
type AgentRepository struct {
db *sql.DB
sqliteBusyRetryMaxAttempts int
db *sql.DB
}
// DeleteSpec implements datastore.AgentRepository.
func (r *AgentRepository) DeleteSpec(ctx context.Context, agentID datastore.AgentID, name string) error {
err := r.withTxRetry(ctx, func(tx *sql.Tx) error {
err := r.withTx(ctx, func(tx *sql.Tx) error {
exists, err := r.agentExists(ctx, tx, agentID)
if err != nil {
return errors.WithStack(err)
@ -51,7 +49,7 @@ func (r *AgentRepository) DeleteSpec(ctx context.Context, agentID datastore.Agen
func (r *AgentRepository) GetSpecs(ctx context.Context, agentID datastore.AgentID) ([]*datastore.Spec, error) {
specs := make([]*datastore.Spec, 0)
err := r.withTxRetry(ctx, func(tx *sql.Tx) error {
err := r.withTx(ctx, func(tx *sql.Tx) error {
exists, err := r.agentExists(ctx, tx, agentID)
if err != nil {
return errors.WithStack(err)
@ -74,8 +72,7 @@ func (r *AgentRepository) GetSpecs(ctx context.Context, agentID datastore.AgentI
defer func() {
if err := rows.Close(); err != nil {
err = errors.WithStack(err)
logger.Error(ctx, "could not close rows", logger.CapturedE(err))
logger.Error(ctx, "could not close rows", logger.E(errors.WithStack(err)))
}
}()
@ -110,7 +107,7 @@ func (r *AgentRepository) GetSpecs(ctx context.Context, agentID datastore.AgentI
func (r *AgentRepository) UpdateSpec(ctx context.Context, agentID datastore.AgentID, name string, revision int, data map[string]any) (*datastore.Spec, error) {
spec := &datastore.Spec{}
err := r.withTxRetry(ctx, func(tx *sql.Tx) error {
err := r.withTx(ctx, func(tx *sql.Tx) error {
exists, err := r.agentExists(ctx, tx, agentID)
if err != nil {
return errors.WithStack(err)
@ -169,7 +166,7 @@ func (r *AgentRepository) Query(ctx context.Context, opts ...datastore.AgentQuer
agents := make([]*datastore.Agent, 0)
count := 0
err := r.withTxRetry(ctx, func(tx *sql.Tx) error {
err := r.withTx(ctx, func(tx *sql.Tx) error {
query := `SELECT id, label, thumbprint, status, contacted_at, created_at, updated_at FROM agents`
limit := 10
@ -222,15 +219,14 @@ func (r *AgentRepository) Query(ctx context.Context, opts ...datastore.AgentQuer
logger.Debug(ctx, "executing query", logger.F("query", query), logger.F("args", args))
rows, err := tx.QueryContext(ctx, query, args...)
rows, err := r.db.QueryContext(ctx, query, args...)
if err != nil {
return errors.WithStack(err)
}
defer func() {
if err := rows.Close(); err != nil {
err = errors.WithStack(err)
logger.Error(ctx, "could not close rows", logger.CapturedE(err))
logger.Error(ctx, "could not close rows", logger.E(errors.WithStack(err)))
}
}()
@ -274,7 +270,7 @@ func (r *AgentRepository) Query(ctx context.Context, opts ...datastore.AgentQuer
func (r *AgentRepository) Create(ctx context.Context, thumbprint string, keySet jwk.Set, metadata map[string]any) (*datastore.Agent, error) {
agent := &datastore.Agent{}
err := r.withTxRetry(ctx, func(tx *sql.Tx) error {
err := r.withTx(ctx, func(tx *sql.Tx) error {
query := `SELECT count(id) FROM agents WHERE thumbprint = $1`
row := tx.QueryRowContext(ctx, query, thumbprint)
@ -333,15 +329,15 @@ 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.withTxRetry(ctx, func(tx *sql.Tx) error {
err := r.withTx(ctx, func(tx *sql.Tx) error {
query := `DELETE FROM agents WHERE id = $1`
_, err := tx.ExecContext(ctx, query, id)
_, err := r.db.ExecContext(ctx, query, id)
if err != nil {
return errors.WithStack(err)
}
query = `DELETE FROM specs WHERE agent_id = $1`
_, err = tx.ExecContext(ctx, query, id)
_, err = r.db.ExecContext(ctx, query, id)
if err != nil {
return errors.WithStack(err)
}
@ -361,14 +357,14 @@ func (r *AgentRepository) Get(ctx context.Context, id datastore.AgentID) (*datas
ID: id,
}
err := r.withTxRetry(ctx, func(tx *sql.Tx) error {
err := r.withTx(ctx, func(tx *sql.Tx) error {
query := `
SELECT "id", "label", "thumbprint", "keyset", "metadata", "status", "contacted_at", "created_at", "updated_at"
FROM agents
WHERE id = $1
`
row := tx.QueryRowContext(ctx, query, id)
row := r.db.QueryRowContext(ctx, query, id)
metadata := JSONMap{}
contactedAt := sql.NullTime{}
@ -412,7 +408,7 @@ func (r *AgentRepository) Update(ctx context.Context, id datastore.AgentID, opts
agent := &datastore.Agent{}
err := r.withTxRetry(ctx, func(tx *sql.Tx) error {
err := r.withTx(ctx, func(tx *sql.Tx) error {
query := `
UPDATE agents SET id = $1
`
@ -536,59 +532,6 @@ func (r *AgentRepository) agentExists(ctx context.Context, tx *sql.Tx, agentID d
return true, nil
}
func (r *AgentRepository) withTxRetry(ctx context.Context, fn func(*sql.Tx) error) error {
attempts := 0
max := r.sqliteBusyRetryMaxAttempts
ctx = logger.With(ctx, logger.F("max", max))
var err error
for {
ctx = logger.With(ctx)
if attempts >= max {
logger.Debug(ctx, "transaction retrying failed", logger.F("attempts", attempts))
return errors.Wrapf(err, "transaction failed after %d attempts", max)
}
err = r.withTx(ctx, fn)
if err != nil {
if !strings.Contains(err.Error(), "(5) (SQLITE_BUSY)") {
return errors.WithStack(err)
}
err = errors.WithStack(err)
logger.Warn(ctx, "database is busy", logger.E(err))
wait := time.Duration(8<<(attempts+1)) * time.Millisecond
logger.Debug(
ctx, "database is busy, waiting before retrying transaction",
logger.F("wait", wait.String()),
logger.F("attempts", attempts),
)
timer := time.NewTimer(wait)
select {
case <-timer.C:
attempts++
continue
case <-ctx.Done():
if err := ctx.Err(); err != nil {
return errors.WithStack(err)
}
return nil
}
}
return nil
}
}
func (r *AgentRepository) withTx(ctx context.Context, fn func(*sql.Tx) error) error {
tx, err := r.db.BeginTx(ctx, nil)
if err != nil {
@ -601,8 +544,7 @@ func (r *AgentRepository) withTx(ctx context.Context, fn func(*sql.Tx) error) er
return
}
err = errors.WithStack(err)
logger.Error(ctx, "could not rollback transaction", logger.CapturedE(err))
logger.Error(ctx, "could not rollback transaction", logger.E(errors.WithStack(err)))
}
}()
@ -617,8 +559,8 @@ func (r *AgentRepository) withTx(ctx context.Context, fn func(*sql.Tx) error) er
return nil
}
func NewAgentRepository(db *sql.DB, sqliteBusyRetryMaxAttempts int) *AgentRepository {
return &AgentRepository{db, sqliteBusyRetryMaxAttempts}
func NewAgentRepository(db *sql.DB) *AgentRepository {
return &AgentRepository{db}
}
var _ datastore.AgentRepository = &AgentRepository{}

View File

@ -40,7 +40,7 @@ func TestSQLiteAgentRepository(t *testing.T) {
t.Fatalf("%+v", errors.WithStack(err))
}
repo := NewAgentRepository(db, 5)
repo := NewAgentRepository(db)
testsuite.TestAgentRepository(t, repo)
}

View File

@ -9,7 +9,7 @@ import (
"forge.cadoles.com/Cadoles/emissary/internal/agent/metadata"
"forge.cadoles.com/Cadoles/emissary/internal/datastore"
"forge.cadoles.com/Cadoles/emissary/internal/jwk"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi"
"github.com/pkg/errors"
"gitlab.com/wpetit/goweb/api"
"gitlab.com/wpetit/goweb/logger"
@ -39,8 +39,7 @@ func (s *Server) registerAgent(w http.ResponseWriter, r *http.Request) {
keySet, err := jwk.Parse(registerAgentReq.KeySet)
if err != nil {
err = errors.WithStack(err)
logger.Error(ctx, "could not parse key set", logger.CapturedE(err))
logger.Error(ctx, "could not parse key set", logger.E(errors.WithStack(err)))
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
return
@ -52,15 +51,14 @@ func (s *Server) registerAgent(w http.ResponseWriter, r *http.Request) {
validSignature, err := jwk.Verify(keySet, registerAgentReq.Signature, registerAgentReq.Thumbprint, registerAgentReq.Metadata)
if err != nil {
err = errors.WithStack(err)
logger.Error(ctx, "could not validate signature", logger.CapturedE(err))
logger.Error(ctx, "could not validate signature", logger.E(errors.WithStack(err)))
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
return
}
if !validSignature {
logger.Warn(ctx, "conflicting signature", logger.F("signature", registerAgentReq.Signature))
logger.Error(ctx, "conflicting signature", logger.F("signature", registerAgentReq.Signature))
api.ErrorResponse(w, http.StatusConflict, ErrCodeConflict, nil)
return
@ -76,8 +74,7 @@ func (s *Server) registerAgent(w http.ResponseWriter, r *http.Request) {
)
if err != nil {
if !errors.Is(err, datastore.ErrAlreadyExist) {
err = errors.WithStack(err)
logger.Error(ctx, "could not create agent", logger.CapturedE(err))
logger.Error(ctx, "could not create agent", logger.E(errors.WithStack(err)))
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
return
@ -89,16 +86,15 @@ func (s *Server) registerAgent(w http.ResponseWriter, r *http.Request) {
datastore.WithAgentQueryLimit(1),
)
if err != nil {
err = errors.WithStack(err)
logger.Error(ctx, "could not retrieve agents", logger.CapturedE(err))
logger.Error(ctx, "could not retrieve agents", logger.E(errors.WithStack(err)))
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
return
}
if len(agents) == 0 {
err = errors.WithStack(err)
logger.Error(ctx, "could not retrieve matching agent", logger.CapturedE(err))
logger.Error(ctx, "could not retrieve matching agent", logger.E(errors.WithStack(err)))
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeNotFound, nil)
return
@ -108,12 +104,10 @@ func (s *Server) registerAgent(w http.ResponseWriter, r *http.Request) {
agent, err = s.agentRepo.Get(ctx, agentID)
if err != nil {
err = errors.WithStack(err)
logger.Error(
ctx, "could not retrieve agent",
logger.CapturedE(err), logger.F("agentID", agentID),
logger.E(errors.WithStack(err)), logger.F("agentID", agentID),
)
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
return
@ -121,8 +115,7 @@ func (s *Server) registerAgent(w http.ResponseWriter, r *http.Request) {
validSignature, err = jwk.Verify(agent.KeySet.Set, registerAgentReq.Signature, registerAgentReq.Thumbprint, registerAgentReq.Metadata)
if err != nil {
err = errors.WithStack(err)
logger.Error(ctx, "could not validate signature using previous keyset", logger.CapturedE(err))
logger.Error(ctx, "could not validate signature using previous keyset", logger.E(errors.WithStack(err)))
api.ErrorResponse(w, http.StatusConflict, ErrCodeConflict, nil)
@ -136,9 +129,7 @@ func (s *Server) registerAgent(w http.ResponseWriter, r *http.Request) {
datastore.WithAgentUpdateThumbprint(registerAgentReq.Thumbprint),
)
if err != nil {
err = errors.WithStack(err)
logger.Error(ctx, "could not update agent", logger.CapturedE(err))
logger.Error(ctx, "could not update agent", logger.E(errors.WithStack(err)))
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
return
@ -186,8 +177,7 @@ func (s *Server) updateAgent(w http.ResponseWriter, r *http.Request) {
options...,
)
if err != nil {
err = errors.WithStack(err)
logger.Error(ctx, "could not update agent", logger.CapturedE(err))
logger.Error(ctx, "could not update agent", logger.E(errors.WithStack(err)))
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
return
@ -268,8 +258,7 @@ func (s *Server) queryAgents(w http.ResponseWriter, r *http.Request) {
options...,
)
if err != nil {
err = errors.WithStack(err)
logger.Error(ctx, "could not list agents", logger.CapturedE(err))
logger.Error(ctx, "could not list agents", logger.E(errors.WithStack(err)))
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
return
@ -303,8 +292,7 @@ func (s *Server) deleteAgent(w http.ResponseWriter, r *http.Request) {
return
}
err = errors.WithStack(err)
logger.Error(ctx, "could not delete agent", logger.CapturedE(err))
logger.Error(ctx, "could not delete agent", logger.E(errors.WithStack(err)))
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
return
@ -336,8 +324,7 @@ func (s *Server) getAgent(w http.ResponseWriter, r *http.Request) {
return
}
err = errors.WithStack(err)
logger.Error(ctx, "could not get agent", logger.CapturedE(err))
logger.Error(ctx, "could not get agent", logger.E(errors.WithStack(err)))
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
return
@ -355,7 +342,7 @@ func getAgentID(w http.ResponseWriter, r *http.Request) (datastore.AgentID, bool
agentID, err := strconv.ParseInt(rawAgentID, 10, 64)
if err != nil {
logger.Error(r.Context(), "could not parse agent id", logger.CapturedE(errors.WithStack(err)))
logger.Error(r.Context(), "could not parse agent id", logger.E(errors.WithStack(err)))
api.ErrorResponse(w, http.StatusBadRequest, api.ErrCodeMalformedRequest, nil)
return 0, false
@ -369,8 +356,7 @@ func getIntQueryParam(w http.ResponseWriter, r *http.Request, param string, defa
if rawValue != "" {
value, err := strconv.ParseInt(rawValue, 10, 64)
if err != nil {
err = errors.WithStack(err)
logger.Error(r.Context(), "could not parse int param", logger.F("param", param), logger.CapturedE(err))
logger.Error(r.Context(), "could not parse int param", logger.F("param", param), logger.E(errors.WithStack(err)))
api.ErrorResponse(w, http.StatusBadRequest, api.ErrCodeMalformedRequest, nil)
return 0, false
@ -403,8 +389,7 @@ func getIntSliceValues(w http.ResponseWriter, r *http.Request, param string, def
for _, rv := range rawValues {
value, err := strconv.ParseInt(rv, 10, 64)
if err != nil {
err = errors.WithStack(err)
logger.Error(r.Context(), "could not parse int slice param", logger.F("param", param), logger.CapturedE(err))
logger.Error(r.Context(), "could not parse int slice param", logger.F("param", param), logger.E(errors.WithStack(err)))
api.ErrorResponse(w, http.StatusBadRequest, api.ErrCodeMalformedRequest, nil)
return nil, false

View File

@ -124,8 +124,7 @@ func assertRequestUser(w http.ResponseWriter, r *http.Request) (auth.User, bool)
ctx := r.Context()
user, err := auth.CtxUser(ctx)
if err != nil {
err = errors.WithStack(err)
logger.Error(ctx, "could not retrieve user", logger.CapturedE(err))
logger.Error(ctx, "could not retrieve user", logger.E(errors.WithStack(err)))
forbidden(w, r)
@ -148,7 +147,7 @@ func forbidden(w http.ResponseWriter, r *http.Request) {
}
func logUnexpectedUserType(ctx context.Context, user auth.User) {
logger.Warn(
logger.Error(
ctx, "unexpected user type",
logger.F("subject", user.Subject()),
logger.F("type", fmt.Sprintf("%T", user)),

View File

@ -18,8 +18,8 @@ import (
"forge.cadoles.com/Cadoles/emissary/internal/jwk"
"github.com/antonmedv/expr"
"github.com/antonmedv/expr/vm"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
"github.com/go-chi/chi"
"github.com/go-chi/chi/middleware"
"github.com/go-chi/cors"
"github.com/lestrrat-go/jwx/v2/jwa"
"github.com/lestrrat-go/jwx/v2/jwt"

View File

@ -6,7 +6,7 @@ import (
"forge.cadoles.com/Cadoles/emissary/internal/datastore"
"forge.cadoles.com/Cadoles/emissary/internal/spec"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi"
"github.com/pkg/errors"
"gitlab.com/wpetit/goweb/api"
"gitlab.com/wpetit/goweb/logger"
@ -44,9 +44,7 @@ func (s *Server) updateSpec(w http.ResponseWriter, r *http.Request) {
data.Message = validationErr.Error()
}
err = errors.WithStack(err)
logger.Error(ctx, "could not validate spec", logger.CapturedE(err))
logger.Error(ctx, "could not validate spec", logger.E(errors.WithStack(err)))
api.ErrorResponse(w, http.StatusBadRequest, api.ErrCodeInvalidRequest, data)
return
@ -72,9 +70,7 @@ func (s *Server) updateSpec(w http.ResponseWriter, r *http.Request) {
return
}
err = errors.WithStack(err)
logger.Error(ctx, "could not update spec", logger.CapturedE(err))
logger.Error(ctx, "could not update spec", logger.E(errors.WithStack(err)))
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
return
@ -103,9 +99,7 @@ func (s *Server) getAgentSpecs(w http.ResponseWriter, r *http.Request) {
return
}
err = errors.WithStack(err)
logger.Error(ctx, "could not list specs", logger.CapturedE(err))
logger.Error(ctx, "could not list specs", logger.E(errors.WithStack(err)))
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
return
@ -147,9 +141,7 @@ func (s *Server) deleteSpec(w http.ResponseWriter, r *http.Request) {
return
}
err = errors.WithStack(err)
logger.Error(ctx, "could not delete spec", logger.CapturedE(err))
logger.Error(ctx, "could not delete spec", logger.E(errors.WithStack(err)))
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
return
@ -167,9 +159,7 @@ func getSpecID(w http.ResponseWriter, r *http.Request) (datastore.SpecID, bool)
specID, err := strconv.ParseInt(rawSpecID, 10, 64)
if err != nil {
err = errors.WithStack(err)
logger.Error(r.Context(), "could not parse spec id", logger.CapturedE(err))
logger.Error(r.Context(), "could not parse spec id", logger.E(errors.WithStack(err)))
api.ErrorResponse(w, http.StatusBadRequest, api.ErrCodeMalformedRequest, nil)
return 0, false

View File

@ -59,7 +59,7 @@ func NewAgentRepository(ctx context.Context, conf config.DatabaseConfig) (datast
return nil, errors.WithStack(err)
}
agentRepository = sqlite.NewAgentRepository(db, 5)
agentRepository = sqlite.NewAgentRepository(db)
default:
return nil, errors.Errorf("unsupported database driver '%s'", driver)

View File

@ -1,32 +0,0 @@
logger:
level: ${EMISSARY_AGENT_LOGGER_LEVEL:-1}
format: ${EMISSARY_AGENT_LOGGER_FORMAT:-human}
sentry:
dsn: ${EMISSARY_AGENT_SENTRY_DSN}
agent:
serverUrl: ${EMISSARY_AGENT_SERVER_URL:-http://127.0.0.1:3000}
privateKeyPath: ${EMISSARY_AGENT_PRIVATE_KEY_PATH:-/data/agent-key.json}
reconciliationInterval: ${EMISSARY_AGENT_RECONCILIATION_INTERVAL:-30}
controllers:
persistence:
enabled: true
stateFile: ${EMISSARY_AGENT_CONTROLLERS_PERSISTENCE_STATE_FILE:-/data/state.json}
spec:
enabled: true
proxy:
enabled: true
uci:
enabled: false
app:
enabled: true
dataDir: ${EMISSARY_AGENT_CONTROLLERS_APP_DATA_DIR:-/data/apps/data}
downloadDir: ${EMISSARY_AGENT_CONTROLLERS_APP_DOWNLOAD_DIR:-/data/apps/bundles}
sysupgrade:
enabled: false
mdns:
enabled: true
collectors:
- name: uname
command: uname
args:
- -a

View File

@ -1,10 +0,0 @@
#!/bin/sh
set -e
# Generate machine id if not exists
if [ ! -f /etc/machine-id ]; then
cat /proc/sys/kernel/random/uuid > /etc/machine-id
fi
exec $@

View File

@ -1,35 +0,0 @@
logger:
level: ${EMISSARY_SERVER_LOGGER_LEVEL:-1}
format: ${EMISSARY_SERVER_LOGGER_FORMAT:-human}
sentry:
dsn: ${EMISSARY_SERVER_SENTRY_DSN}
server:
http:
host: ${EMISSARY_SERVER_HTTP_HOST:-0.0.0.0}
port: ${EMISSARY_SERVER_HTTP_HOST:-3000}
database:
driver: ${EMISSARY_SERVER_DATABASE_DRIVER:-sqlite}
dsn: ${EMISSARY_SERVER_DATABASE_DSN:-sqlite:///data/emissary.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=150000&_pragma=journal_mode=WAL}
cors:
allowedOrigins:
- ${EMISSARY_SERVER_CORS_ALLOWED_ORIGINS:-http://localhost:3001}
allowCredentials: ${EMISSARY_SERVER_CORS_ALLOW_CREDENTIALS:-true}
allowMethods:
- POST
- GET
- PUT
- DELETE
allowedHeaders:
- Origin
- Accept
- Content-Type
- Authorization
- Sentry-Trace
debug: ${EMISSARY_SERVER_CORS_DEBUG:-false}
auth:
local:
privateKeyPath: ${EMISSARY_SERVER_AUTH_LOCAL_PRIVATE_KEY_PATH:-/data/server-key.json}
remote:
jwksUrl: "${EMISSARY_SERVER_AUTH_REMOTE_JWKS_URL}"
roleExtractionRules:
- "${EMISSARY_SERVER_AUTH_ROLE_EXTRACTION_RULES_0:-jwt.role != nil ? str(jwt.role) : ''}"

View File

@ -4,7 +4,7 @@ ARG HTTP_PROXY=
ARG HTTPS_PROXY=
ARG http_proxy=
ARG https_proxy=
ARG GO_VERSION=1.21.1
ARG GO_VERSION=1.20.2
# Install dev environment dependencies
RUN export DEBIAN_FRONTEND=noninteractive &&\

View File

@ -1,9 +0,0 @@
/var/log/emissary/agent.log {
missingok
sharedscripts
compress
rotate 7
postrotate
/etc/init.d/emissary-agent restart
endscript
}

View File

@ -1,9 +0,0 @@
/var/log/emissary/server.log {
missingok
sharedscripts
compress
rotate 7
postrotate
/etc/init.d/emissary-server restart
endscript
}

View File

@ -4,40 +4,20 @@
"url": "https://emissary.cadol.es/files/apps/app.arcad.edge.hextris_v2023.4.20-2bbbe94.zip",
"sha256sum": "67942ef4b623c46308c3f640b534bd4cb6b1d6021a422e40b62ab97658ba4586",
"address": ":8083",
"format": "zip",
"storage": {
"blobStoreDsn": "sqlite://apps/data/app.arcad.edge.hextris/blobstore.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=60000",
"shareStoreDsn": "sqlite://apps/data/sharestore.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=60000",
"documentStoreDsn": "sqlite://apps/data/app.arcad.edge.hextris/documentstore.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=60000"
}
"format": "zip"
},
"edge.sdk.client.test": {
"url": "https://emissary.cadol.es/files/apps/edge.sdk.client.test_2023.10.22-stable.847.22a3326.zip",
"sha256sum": "37aa6c4af57b647dc5cae4ec7d36f4289d99c1f090e533997e0d59188a0a04f4",
"url": "https://emissary.cadol.es/files/apps/edge.sdk.client.test_v2023.4.20-20c4189.zip",
"sha256sum": "1edeb4aa75c1675db49cf27367b1537234a04526848ea6657931ca63f26e5dae",
"address": ":8084",
"format": "zip",
"storage": {
"blobStoreDsn": "sqlite://apps/data/edge.sdk.client.test/blobstore.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=60000",
"shareStoreDsn": "sqlite://apps/data/sharestore.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=60000",
"documentStoreDsn": "sqlite://apps/data/edge.sdk.client.test/documentstore.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=60000"
}
},
"arcad.diffusion": {
"url": "https://emissary.cadol.es/files/apps/arcad.diffusion_v2023.10.12-cab0070.zip",
"sha256sum": "db58ec1ed463092fea2ee27cfd33dea5259739f1c6a4c9bf909ffd22392ee449",
"address": ":8085",
"format": "zip",
"storage": {
"blobStoreDsn": "sqlite://apps/data/arcad.diffusion/blobstore.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=60000",
"shareStoreDsn": "sqlite://apps/data/sharestore.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=60000",
"documentStoreDsn": "sqlite://apps/data/arcad.diffusion/documentstore.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=60000"
}
"format": "zip"
}
},
"config": {
"appUrlResolving": {
"ifaceMappings": {
"lo": "http://{{ .DeviceIP }}:{{ .AppPort }}"
"eth0": "http://{{ .DeviceIP }}:{{ .AppPort }}",
"eth1": "http://{{ .DeviceIP }}:{{ .AppPort }}"
},
"defaultUrlTemplate": "http://{{ last ( splitList \".\" ( toString .Manifest.ID ) ) }}.localhost.arcad.lan:8080"
},
@ -48,7 +28,6 @@
"auth": {
"local": {
"key": "absolutlynotsecret",
"signingAlgorithm": "HS256",
"cookieDuration": "1h",
"accounts": [
{

View File

@ -14,11 +14,6 @@
"type": "_http._tcp",
"port": 8080,
"host": "arcad-test"
},
"diffusion": {
"type": "_http._tcp",
"port": 8080,
"host": "arcad-diffusion"
}
}
}

View File

@ -11,10 +11,6 @@
"hostPattern": "test.localhost.arcad.lan:*",
"target": "http://localhost:8084"
},
{
"hostPattern": "diffusion.localhost.arcad.lan:*",
"target": "http://localhost:8085"
},
{
"hostPattern": "arcad-hextris.local:*",
"target": "http://localhost:8083"
@ -23,10 +19,6 @@
"hostPattern": "arcad-test.local:*",
"target": "http://localhost:8084"
},
{
"hostPattern": "arcad-diffusion.local:*",
"target": "http://localhost:8085"
},
{
"hostPattern": "*",
"target": "http://localhost:8084"

View File

@ -1,2067 +0,0 @@
{
"config": {
"packages": [
{
"configs": [
{
"name": "dnsmasq",
"options": [
{
"name": "domainneeded",
"type": "option",
"value": "1"
},
{
"name": "boguspriv",
"type": "option",
"value": "1"
},
{
"name": "filterwin2k",
"type": "option",
"value": "0"
},
{
"name": "localise_queries",
"type": "option",
"value": "1"
},
{
"name": "rebind_localhost",
"type": "option",
"value": "1"
},
{
"name": "local",
"type": "option",
"value": "/lan/"
},
{
"name": "domain",
"type": "option",
"value": "lan"
},
{
"name": "expandhosts",
"type": "option",
"value": "1"
},
{
"name": "nonegcache",
"type": "option",
"value": "0"
},
{
"name": "authoritative",
"type": "option",
"value": "1"
},
{
"name": "readethers",
"type": "option",
"value": "1"
},
{
"name": "leasefile",
"type": "option",
"value": "/tmp/dhcp.leases"
},
{
"name": "resolvfile",
"type": "option",
"value": "/tmp/resolv.conf.d/resolv.conf.auto"
},
{
"name": "nonwildcard",
"type": "option",
"value": "1"
},
{
"name": "localservice",
"type": "option",
"value": "1"
},
{
"name": "ednspacket_max",
"type": "option",
"value": "1232"
},
{
"name": "rebind_protection",
"type": "option",
"value": "0"
},
{
"name": "interface",
"type": "list",
"value": "lan"
},
{
"name": "interface",
"type": "list",
"value": "guest"
},
{
"name": "logqueries",
"type": "option",
"value": "1"
},
{
"name": "address",
"type": "list",
"value": "/arcad.lan/10.10.10.1"
},
{
"name": "address",
"type": "list",
"value": "/#/10.10.10.1"
}
]
},
{
"name": "dhcp",
"options": [
{
"name": "interface",
"type": "option",
"value": "lan"
},
{
"name": "start",
"type": "option",
"value": "100"
},
{
"name": "limit",
"type": "option",
"value": "150"
},
{
"name": "leasetime",
"type": "option",
"value": "12h"
},
{
"name": "dhcpv4",
"type": "option",
"value": "server"
},
{
"name": "dhcpv6",
"type": "option",
"value": "server"
},
{
"name": "ra",
"type": "option",
"value": "server"
},
{
"name": "ra_slaac",
"type": "option",
"value": "1"
},
{
"name": "ra_flags",
"type": "list",
"value": "managed-config"
},
{
"name": "ra_flags",
"type": "list",
"value": "other-config"
}
],
"section": "lan"
},
{
"name": "dhcp",
"options": [
{
"name": "interface",
"type": "option",
"value": "wan"
},
{
"name": "ignore",
"type": "option",
"value": "1"
}
],
"section": "wan"
},
{
"name": "odhcpd",
"options": [
{
"name": "maindhcp",
"type": "option",
"value": "0"
},
{
"name": "leasefile",
"type": "option",
"value": "/tmp/hosts/odhcpd"
},
{
"name": "leasetrigger",
"type": "option",
"value": "/usr/sbin/odhcpd-update"
},
{
"name": "loglevel",
"type": "option",
"value": "4"
}
],
"section": "odhcpd"
},
{
"name": "dhcp",
"options": [
{
"name": "interface",
"type": "option",
"value": "guest"
},
{
"name": "start",
"type": "option",
"value": "100"
},
{
"name": "limit",
"type": "option",
"value": "150"
},
{
"name": "leasetime",
"type": "option",
"value": "12h"
},
{
"name": "dhcp_option",
"type": "list",
"value": "160,http://arcad.lan"
}
],
"section": "guest"
}
],
"name": "dhcp"
},
{
"configs": [
{
"name": "dropbear",
"options": [
{
"name": "PasswordAuth",
"type": "option",
"value": "on"
},
{
"name": "RootPasswordAuth",
"type": "option",
"value": "on"
},
{
"name": "Port",
"type": "option",
"value": "22"
}
]
}
],
"name": "dropbear"
},
{
"configs": [
{
"name": "main",
"options": [
{
"name": "reconciliation_interval",
"type": "option",
"value": "60"
},
{
"name": "server_url",
"type": "option",
"value": "https://emissary.cadol.es"
}
],
"section": "agent"
}
],
"name": "emissary"
},
{
"configs": [
{
"name": "defaults",
"options": [
{
"name": "syn_flood",
"type": "option",
"value": "1"
},
{
"name": "input",
"type": "option",
"value": "ACCEPT"
},
{
"name": "output",
"type": "option",
"value": "ACCEPT"
},
{
"name": "forward",
"type": "option",
"value": "REJECT"
}
]
},
{
"name": "zone",
"options": [
{
"name": "name",
"type": "option",
"value": "lan"
},
{
"name": "network",
"type": "list",
"value": "lan"
},
{
"name": "input",
"type": "option",
"value": "ACCEPT"
},
{
"name": "output",
"type": "option",
"value": "ACCEPT"
},
{
"name": "forward",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "zone",
"options": [
{
"name": "name",
"type": "option",
"value": "wan"
},
{
"name": "network",
"type": "list",
"value": "wan"
},
{
"name": "network",
"type": "list",
"value": "wan6"
},
{
"name": "input",
"type": "option",
"value": "REJECT"
},
{
"name": "output",
"type": "option",
"value": "ACCEPT"
},
{
"name": "forward",
"type": "option",
"value": "REJECT"
},
{
"name": "masq",
"type": "option",
"value": "1"
},
{
"name": "mtu_fix",
"type": "option",
"value": "1"
}
]
},
{
"name": "forwarding",
"options": [
{
"name": "src",
"type": "option",
"value": "lan"
},
{
"name": "dest",
"type": "option",
"value": "wan"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow-DHCP-Renew"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "proto",
"type": "option",
"value": "udp"
},
{
"name": "dest_port",
"type": "option",
"value": "68"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
},
{
"name": "family",
"type": "option",
"value": "ipv4"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow-Ping"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "proto",
"type": "option",
"value": "icmp"
},
{
"name": "icmp_type",
"type": "option",
"value": "echo-request"
},
{
"name": "family",
"type": "option",
"value": "ipv4"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow-IGMP"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "proto",
"type": "option",
"value": "igmp"
},
{
"name": "family",
"type": "option",
"value": "ipv4"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow-DHCPv6"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "proto",
"type": "option",
"value": "udp"
},
{
"name": "dest_port",
"type": "option",
"value": "546"
},
{
"name": "family",
"type": "option",
"value": "ipv6"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow-MLD"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "proto",
"type": "option",
"value": "icmp"
},
{
"name": "src_ip",
"type": "option",
"value": "fe80::/10"
},
{
"name": "icmp_type",
"type": "list",
"value": "130/0"
},
{
"name": "icmp_type",
"type": "list",
"value": "131/0"
},
{
"name": "icmp_type",
"type": "list",
"value": "132/0"
},
{
"name": "icmp_type",
"type": "list",
"value": "143/0"
},
{
"name": "family",
"type": "option",
"value": "ipv6"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow-ICMPv6-Input"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "proto",
"type": "option",
"value": "icmp"
},
{
"name": "icmp_type",
"type": "list",
"value": "echo-request"
},
{
"name": "icmp_type",
"type": "list",
"value": "echo-reply"
},
{
"name": "icmp_type",
"type": "list",
"value": "destination-unreachable"
},
{
"name": "icmp_type",
"type": "list",
"value": "packet-too-big"
},
{
"name": "icmp_type",
"type": "list",
"value": "time-exceeded"
},
{
"name": "icmp_type",
"type": "list",
"value": "bad-header"
},
{
"name": "icmp_type",
"type": "list",
"value": "unknown-header-type"
},
{
"name": "icmp_type",
"type": "list",
"value": "router-solicitation"
},
{
"name": "icmp_type",
"type": "list",
"value": "neighbour-solicitation"
},
{
"name": "icmp_type",
"type": "list",
"value": "router-advertisement"
},
{
"name": "icmp_type",
"type": "list",
"value": "neighbour-advertisement"
},
{
"name": "limit",
"type": "option",
"value": "1000/sec"
},
{
"name": "family",
"type": "option",
"value": "ipv6"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow-ICMPv6-Forward"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "dest",
"type": "option",
"value": "*"
},
{
"name": "proto",
"type": "option",
"value": "icmp"
},
{
"name": "icmp_type",
"type": "list",
"value": "echo-request"
},
{
"name": "icmp_type",
"type": "list",
"value": "echo-reply"
},
{
"name": "icmp_type",
"type": "list",
"value": "destination-unreachable"
},
{
"name": "icmp_type",
"type": "list",
"value": "packet-too-big"
},
{
"name": "icmp_type",
"type": "list",
"value": "time-exceeded"
},
{
"name": "icmp_type",
"type": "list",
"value": "bad-header"
},
{
"name": "icmp_type",
"type": "list",
"value": "unknown-header-type"
},
{
"name": "limit",
"type": "option",
"value": "1000/sec"
},
{
"name": "family",
"type": "option",
"value": "ipv6"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow-IPSec-ESP"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "dest",
"type": "option",
"value": "lan"
},
{
"name": "proto",
"type": "option",
"value": "esp"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow-ISAKMP"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "dest",
"type": "option",
"value": "lan"
},
{
"name": "dest_port",
"type": "option",
"value": "500"
},
{
"name": "proto",
"type": "option",
"value": "udp"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow SSH on WAN"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "proto",
"type": "option",
"value": "tcp"
},
{
"name": "dest_port",
"type": "option",
"value": "22"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow HTTP on WAN"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "proto",
"type": "option",
"value": "tcp"
},
{
"name": "dest_port",
"type": "option",
"value": "80"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow HTTPS on WAN"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "proto",
"type": "option",
"value": "tcp"
},
{
"name": "dest_port",
"type": "option",
"value": "443"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "zone",
"options": [
{
"name": "name",
"type": "option",
"value": "guest"
},
{
"name": "input",
"type": "option",
"value": "ACCEPT"
},
{
"name": "output",
"type": "option",
"value": "ACCEPT"
},
{
"name": "forward",
"type": "option",
"value": "REJECT"
},
{
"name": "network",
"type": "list",
"value": "guest"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow 8080 on WAN"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "proto",
"type": "option",
"value": "tcp"
},
{
"name": "dest_port",
"type": "option",
"value": "8080"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow 8443 on WAN"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "proto",
"type": "option",
"value": "tcp"
},
{
"name": "dest_port",
"type": "option",
"value": "8443"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "proto",
"type": "list",
"value": "udp"
},
{
"name": "dest_port",
"type": "option",
"value": "5353"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
},
{
"name": "name",
"type": "option",
"value": "Allow mDNS from device"
},
{
"name": "src",
"type": "option",
"value": "*"
}
]
},
{
"name": "rule",
"options": [
{
"name": "proto",
"type": "list",
"value": "udp"
},
{
"name": "src_port",
"type": "option",
"value": "5353"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
},
{
"name": "name",
"type": "option",
"value": "Allow mDNS to device"
},
{
"name": "src",
"type": "option",
"value": "*"
}
]
},
{
"name": "redirect",
"options": [
{
"name": "target",
"type": "option",
"value": "DNAT"
},
{
"name": "proto",
"type": "list",
"value": "udp"
},
{
"name": "src",
"type": "option",
"value": "guest"
},
{
"name": "src_dport",
"type": "option",
"value": "53"
},
{
"name": "dest_ip",
"type": "option",
"value": "10.10.10.1"
},
{
"name": "dest_port",
"type": "option",
"value": "53"
},
{
"name": "name",
"type": "option",
"value": "Redirect DNS"
}
]
},
{
"name": "redirect",
"options": [
{
"name": "target",
"type": "option",
"value": "DNAT"
},
{
"name": "name",
"type": "option",
"value": "Redirect HTTP"
},
{
"name": "proto",
"type": "list",
"value": "tcp"
},
{
"name": "src",
"type": "option",
"value": "guest"
},
{
"name": "src_dport",
"type": "option",
"value": "80"
},
{
"name": "dest_ip",
"type": "option",
"value": "10.10.10.1"
},
{
"name": "dest_port",
"type": "option",
"value": "80"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow 8081 for edge.sdk.client.test on WAN"
},
{
"name": "proto",
"type": "list",
"value": "tcp"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "dest_port",
"type": "option",
"value": "8081"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow 8082 for app.arcad.edge.hextris on WAN"
},
{
"name": "proto",
"type": "list",
"value": "tcp"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "dest_port",
"type": "option",
"value": "8082"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow 8083 for arcad.diffusion on WAN"
},
{
"name": "proto",
"type": "list",
"value": "tcp"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "dest_port",
"type": "option",
"value": "8083"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow 8084 for app.arcad.edge.menu on WAN"
},
{
"name": "proto",
"type": "list",
"value": "tcp"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "dest_port",
"type": "option",
"value": "8084"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
}
],
"name": "firewall"
},
{
"configs": [
{
"name": "core",
"options": [
{
"name": "lang",
"type": "option",
"value": "auto"
},
{
"name": "mediaurlbase",
"type": "option",
"value": "/luci-static/bootstrap"
},
{
"name": "resourcebase",
"type": "option",
"value": "/luci-static/resources"
},
{
"name": "ubuspath",
"type": "option",
"value": "/ubus/"
}
],
"section": "main"
},
{
"name": "extern",
"options": [
{
"name": "uci",
"type": "option",
"value": "/etc/config/"
},
{
"name": "dropbear",
"type": "option",
"value": "/etc/dropbear/"
},
{
"name": "openvpn",
"type": "option",
"value": "/etc/openvpn/"
},
{
"name": "passwd",
"type": "option",
"value": "/etc/passwd"
},
{
"name": "opkg",
"type": "option",
"value": "/etc/opkg.conf"
},
{
"name": "firewall",
"type": "option",
"value": "/etc/firewall.user"
},
{
"name": "uploads",
"type": "option",
"value": "/lib/uci/upload/"
}
],
"section": "flash_keep"
},
{
"name": "internal",
"options": null,
"section": "languages"
},
{
"name": "internal",
"options": [
{
"name": "sessionpath",
"type": "option",
"value": "/tmp/luci-sessions"
},
{
"name": "sessiontime",
"type": "option",
"value": "3600"
}
],
"section": "sauth"
},
{
"name": "internal",
"options": [
{
"name": "enable",
"type": "option",
"value": "1"
}
],
"section": "ccache"
},
{
"name": "internal",
"options": [
{
"name": "Bootstrap",
"type": "option",
"value": "/luci-static/bootstrap"
},
{
"name": "BootstrapDark",
"type": "option",
"value": "/luci-static/bootstrap-dark"
},
{
"name": "BootstrapLight",
"type": "option",
"value": "/luci-static/bootstrap-light"
}
],
"section": "themes"
},
{
"name": "internal",
"options": [
{
"name": "rollback",
"type": "option",
"value": "90"
},
{
"name": "holdoff",
"type": "option",
"value": "4"
},
{
"name": "timeout",
"type": "option",
"value": "5"
},
{
"name": "display",
"type": "option",
"value": "1.5"
}
],
"section": "apply"
},
{
"name": "internal",
"options": [
{
"name": "dns",
"type": "option",
"value": "openwrt.org"
},
{
"name": "ping",
"type": "option",
"value": "openwrt.org"
},
{
"name": "route",
"type": "option",
"value": "openwrt.org"
}
],
"section": "diag"
}
],
"name": "luci"
},
{
"configs": [
{
"name": "interface",
"options": [
{
"name": "proto",
"type": "option",
"value": "static"
},
{
"name": "ipaddr",
"type": "option",
"value": "127.0.0.1"
},
{
"name": "netmask",
"type": "option",
"value": "255.0.0.0"
},
{
"name": "device",
"type": "option",
"value": "lo"
}
],
"section": "loopback"
},
{
"name": "interface",
"options": [
{
"name": "proto",
"type": "option",
"value": "dhcp"
},
{
"name": "device",
"type": "option",
"value": "eth0"
}
],
"section": "wan"
},
{
"name": "interface",
"options": [
{
"name": "proto",
"type": "option",
"value": "static"
},
{
"name": "device",
"type": "option",
"value": "wlan0"
},
{
"name": "ipaddr",
"type": "option",
"value": "10.10.10.1"
},
{
"name": "netmask",
"type": "option",
"value": "255.255.255.0"
}
],
"section": "guest"
}
],
"name": "network"
},
{
"configs": [
{
"name": "rpcd",
"options": [
{
"name": "socket",
"type": "option",
"value": "/var/run/ubus/ubus.sock"
},
{
"name": "timeout",
"type": "option",
"value": "30"
}
]
},
{
"name": "login",
"options": [
{
"name": "username",
"type": "option",
"value": "root"
},
{
"name": "password",
"type": "option",
"value": "$p$root"
},
{
"name": "read",
"type": "list",
"value": "*"
},
{
"name": "write",
"type": "list",
"value": "*"
}
]
}
],
"name": "rpcd"
},
{
"configs": [
{
"name": "system",
"options": [
{
"name": "hostname",
"type": "option",
"value": "arcad-will"
},
{
"name": "timezone",
"type": "option",
"value": "UTC"
},
{
"name": "ttylogin",
"type": "option",
"value": "0"
},
{
"name": "log_size",
"type": "option",
"value": "64"
},
{
"name": "urandom_seed",
"type": "option",
"value": "0"
}
]
},
{
"name": "timeserver",
"options": [
{
"name": "enabled",
"type": "option",
"value": "1"
},
{
"name": "enable_server",
"type": "option",
"value": "0"
},
{
"name": "server",
"type": "list",
"value": "0.openwrt.pool.ntp.org"
},
{
"name": "server",
"type": "list",
"value": "1.openwrt.pool.ntp.org"
},
{
"name": "server",
"type": "list",
"value": "2.openwrt.pool.ntp.org"
},
{
"name": "server",
"type": "list",
"value": "3.openwrt.pool.ntp.org"
}
],
"section": "ntp"
}
],
"name": "system"
},
{
"configs": [
{
"name": "network",
"options": [
{
"name": "init",
"type": "option",
"value": "network"
},
{
"name": "affects",
"type": "list",
"value": "dhcp"
}
]
},
{
"name": "wireless",
"options": [
{
"name": "affects",
"type": "list",
"value": "network"
}
]
},
{
"name": "firewall",
"options": [
{
"name": "init",
"type": "option",
"value": "firewall"
},
{
"name": "affects",
"type": "list",
"value": "luci-splash"
},
{
"name": "affects",
"type": "list",
"value": "qos"
},
{
"name": "affects",
"type": "list",
"value": "miniupnpd"
}
]
},
{
"name": "olsr",
"options": [
{
"name": "init",
"type": "option",
"value": "olsrd"
}
]
},
{
"name": "dhcp",
"options": [
{
"name": "init",
"type": "option",
"value": "dnsmasq"
},
{
"name": "affects",
"type": "list",
"value": "odhcpd"
}
]
},
{
"name": "odhcpd",
"options": [
{
"name": "init",
"type": "option",
"value": "odhcpd"
}
]
},
{
"name": "dropbear",
"options": [
{
"name": "init",
"type": "option",
"value": "dropbear"
}
]
},
{
"name": "httpd",
"options": [
{
"name": "init",
"type": "option",
"value": "httpd"
}
]
},
{
"name": "fstab",
"options": [
{
"name": "exec",
"type": "option",
"value": "/sbin/block mount"
}
]
},
{
"name": "qos",
"options": [
{
"name": "init",
"type": "option",
"value": "qos"
}
]
},
{
"name": "system",
"options": [
{
"name": "init",
"type": "option",
"value": "led"
},
{
"name": "exec",
"type": "option",
"value": "/etc/init.d/log reload"
},
{
"name": "affects",
"type": "list",
"value": "luci_statistics"
},
{
"name": "affects",
"type": "list",
"value": "dhcp"
}
]
},
{
"name": "luci_splash",
"options": [
{
"name": "init",
"type": "option",
"value": "luci_splash"
}
]
},
{
"name": "upnpd",
"options": [
{
"name": "init",
"type": "option",
"value": "miniupnpd"
}
]
},
{
"name": "ntpclient",
"options": [
{
"name": "init",
"type": "option",
"value": "ntpclient"
}
]
},
{
"name": "samba",
"options": [
{
"name": "init",
"type": "option",
"value": "samba"
}
]
},
{
"name": "tinyproxy",
"options": [
{
"name": "init",
"type": "option",
"value": "tinyproxy"
}
]
}
],
"name": "ucitrack"
},
{
"configs": [
{
"name": "uhttpd",
"options": [
{
"name": "listen_http",
"type": "list",
"value": "0.0.0.0:8080"
},
{
"name": "listen_http",
"type": "list",
"value": "[::]:8080"
},
{
"name": "listen_https",
"type": "list",
"value": "0.0.0.0:8443"
},
{
"name": "listen_https",
"type": "list",
"value": "[::]:8443"
},
{
"name": "redirect_https",
"type": "option",
"value": "0"
},
{
"name": "home",
"type": "option",
"value": "/www"
},
{
"name": "rfc1918_filter",
"type": "option",
"value": "1"
},
{
"name": "max_requests",
"type": "option",
"value": "3"
},
{
"name": "max_connections",
"type": "option",
"value": "100"
},
{
"name": "cert",
"type": "option",
"value": "/etc/uhttpd.crt"
},
{
"name": "key",
"type": "option",
"value": "/etc/uhttpd.key"
},
{
"name": "cgi_prefix",
"type": "option",
"value": "/cgi-bin"
},
{
"name": "lua_prefix",
"type": "list",
"value": "/cgi-bin/luci=/usr/lib/lua/luci/sgi/uhttpd.lua"
},
{
"name": "script_timeout",
"type": "option",
"value": "60"
},
{
"name": "network_timeout",
"type": "option",
"value": "30"
},
{
"name": "http_keepalive",
"type": "option",
"value": "20"
},
{
"name": "tcp_keepalive",
"type": "option",
"value": "1"
},
{
"name": "ubus_prefix",
"type": "option",
"value": "/ubus"
}
],
"section": "main"
},
{
"name": "cert",
"options": [
{
"name": "days",
"type": "option",
"value": "730"
},
{
"name": "key_type",
"type": "option",
"value": "ec"
},
{
"name": "bits",
"type": "option",
"value": "2048"
},
{
"name": "ec_curve",
"type": "option",
"value": "P-256"
},
{
"name": "country",
"type": "option",
"value": "ZZ"
},
{
"name": "state",
"type": "option",
"value": "Somewhere"
},
{
"name": "location",
"type": "option",
"value": "Unknown"
},
{
"name": "commonname",
"type": "option",
"value": "OpenWrt"
}
],
"section": "defaults"
}
],
"name": "uhttpd"
},
{
"configs": [
{
"name": "wifi-device",
"options": [
{
"name": "type",
"type": "option",
"value": "mac80211"
},
{
"name": "path",
"type": "option",
"value": "platform/soc/3f300000.mmcnr/mmc_host/mmc1/mmc1:0001/mmc1:0001:1"
},
{
"name": "channel",
"type": "option",
"value": "1"
},
{
"name": "band",
"type": "option",
"value": "2g"
},
{
"name": "htmode",
"type": "option",
"value": "HT20"
},
{
"name": "cell_density",
"type": "option",
"value": "0"
}
],
"section": "radio0"
},
{
"name": "wifi-iface",
"options": [
{
"name": "device",
"type": "option",
"value": "radio0"
},
{
"name": "mode",
"type": "option",
"value": "ap"
},
{
"name": "ssid",
"type": "option",
"value": "Arcad - Connect and Play"
},
{
"name": "encryption",
"type": "option",
"value": "none"
},
{
"name": "network",
"type": "option",
"value": "guest"
}
],
"section": "default_radio0"
}
],
"name": "wireless"
}
]
},
"postImportCommands": []
}