Compare commits
46 Commits
v2023.8.14
...
2023.12.1-
Author | SHA1 | Date | |
---|---|---|---|
6a7945d05c | |||
86ddb6a4c1 | |||
a6da1be3bf | |||
5c2d128e8c | |||
144fdd8bf3 | |||
8b33bacbd5 | |||
b842dd5263 | |||
0c9d86b850 | |||
b2b839cab4 | |||
7fa3011ab2 | |||
17e06ce19b | |||
0d2aac41a8 | |||
38795a9767 | |||
327226aa74 | |||
fbf818e423 | |||
46a853a3f7 | |||
f31a63efdc | |||
c8a2303ff3 | |||
ced2658eec | |||
ce9b3003fe | |||
b0898eefc3 | |||
4da723e908 | |||
e756a60373 | |||
9068203e71 | |||
a84fa05c27 | |||
6c78bc5c7c | |||
75cab3264f | |||
1a270fa4d8 | |||
6318a8b497 | |||
3d7a094cb8 | |||
077964c7b9 | |||
3af6324121 | |||
b31900ae2f | |||
777648ff44 | |||
d9919c888f | |||
1eb3de4f16 | |||
9326bac792 | |||
3c1f5042c8 | |||
14eecbf01e | |||
c51ac0adc7 | |||
3e168dadf6 | |||
61ac5e8ae0 | |||
929394c479 | |||
a1ec5b87c8 | |||
5c36955c13 | |||
6cf01adb61 |
44
.chglog/CHANGELOG.tpl.md
Normal file
44
.chglog/CHANGELOG.tpl.md
Normal file
@ -0,0 +1,44 @@
|
||||
{{ if .Versions -}}
|
||||
{{ if .Unreleased.CommitGroups -}}
|
||||
<a name="unreleased"></a>
|
||||
## [Unreleased]
|
||||
|
||||
{{ range .Unreleased.CommitGroups -}}
|
||||
### {{ .Title }}
|
||||
{{ range .Commits -}}
|
||||
- {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }}
|
||||
{{ end }}
|
||||
{{ end -}}
|
||||
{{ end -}}
|
||||
{{ end -}}
|
||||
|
||||
{{ range .Versions }}
|
||||
<a name="{{ .Tag.Name }}"></a>
|
||||
## {{ if .Tag.Previous }}[{{ .Tag.Name }}]{{ else }}{{ .Tag.Name }}{{ end }} - {{ datetime "2006-01-02" .Tag.Date }}
|
||||
{{ range .CommitGroups -}}
|
||||
### {{ .Title }}
|
||||
{{ range .Commits -}}
|
||||
- {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }}
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
_Nothing functionally significant._
|
||||
{{ end -}}
|
||||
|
||||
{{- if .NoteGroups -}}
|
||||
{{ range .NoteGroups -}}
|
||||
### {{ .Title }}
|
||||
{{ range .Notes }}
|
||||
{{ .Body }}
|
||||
{{ end }}
|
||||
{{ end -}}
|
||||
{{ end -}}
|
||||
{{ end -}}
|
||||
|
||||
{{- if .Versions }}
|
||||
[Unreleased]: {{ .Info.RepositoryURL }}/compare/{{ $latest := index .Versions 0 }}{{ $latest.Tag.Name }}...HEAD
|
||||
{{ range .Versions -}}
|
||||
{{ if .Tag.Previous -}}
|
||||
[{{ .Tag.Name }}]: {{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }}
|
||||
{{ end -}}
|
||||
{{ end -}}
|
||||
{{ end -}}
|
33
.chglog/config.yml
Normal file
33
.chglog/config.yml
Normal file
@ -0,0 +1,33 @@
|
||||
style: github
|
||||
template: CHANGELOG.tpl.md
|
||||
info:
|
||||
title: CHANGELOG
|
||||
repository_url: https://forge.cadoles.com//
|
||||
options:
|
||||
commits:
|
||||
filters:
|
||||
Type:
|
||||
- feat
|
||||
- fix
|
||||
- perf
|
||||
- refactor
|
||||
- docs
|
||||
commit_groups:
|
||||
title_maps:
|
||||
feat: Features
|
||||
fix: Bug Fixes
|
||||
perf: Performance Improvements
|
||||
refactor: Code Refactoring
|
||||
docs: Documentation
|
||||
header:
|
||||
pattern: "^(\\w*)(?:\\(([\\w\\$\\.\\-\\*\\s]*)\\))?\\:\\s(.*)$"
|
||||
pattern_maps:
|
||||
- Type
|
||||
- Scope
|
||||
- Subject
|
||||
notes:
|
||||
keywords:
|
||||
- BREAKING CHANGE
|
||||
issues:
|
||||
prefix:
|
||||
- '#'
|
14
.dockerignore
Normal file
14
.dockerignore
Normal file
@ -0,0 +1,14 @@
|
||||
/apps
|
||||
/bin
|
||||
/dist
|
||||
/out
|
||||
/tmp
|
||||
/tools
|
||||
/.emissary-token
|
||||
/.env
|
||||
/agent-key.json
|
||||
/server-key.json
|
||||
/CHANGELOG.md
|
||||
/state.json
|
||||
/*.sqlite*
|
||||
/.mktools
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -10,4 +10,6 @@ dist/
|
||||
/apps
|
||||
/server-key.json
|
||||
/.emissary-token
|
||||
/out
|
||||
/out
|
||||
.mktools/
|
||||
/CHANGELOG.md
|
||||
|
@ -105,6 +105,9 @@ 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:
|
||||
@ -147,5 +150,8 @@ 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"
|
||||
|
58
Dockerfile
58
Dockerfile
@ -1,4 +1,12 @@
|
||||
FROM golang:1.19 AS BUILD
|
||||
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
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y make
|
||||
@ -7,9 +15,9 @@ COPY . /src
|
||||
|
||||
WORKDIR /src
|
||||
|
||||
RUN make GORELEASER_ARGS='build --rm-dist --single-target --snapshot' release
|
||||
RUN make mktools && make GORELEASER_ARGS="build --snapshot --clean --single-target --id emissary-server" goreleaser
|
||||
|
||||
FROM busybox:latest AS RUNTIME
|
||||
FROM busybox:latest AS emissary-server
|
||||
|
||||
ARG DUMB_INIT_VERSION=1.2.5
|
||||
|
||||
@ -19,11 +27,47 @@ RUN mkdir -p /usr/local/bin \
|
||||
|
||||
ENTRYPOINT ["/usr/local/bin/dumb-init", "--"]
|
||||
|
||||
COPY --from=BUILD /src/dist/emissary_linux_amd64_v1 /app
|
||||
COPY --from=BUILD /src/tmp/config.yml /etc/emissary/config.yml
|
||||
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
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
ENTRYPOINT ["/app/emissary"]
|
||||
RUN mkdir -p /data
|
||||
|
||||
CMD ["server", "run", "-c", "/etc/emissary/config.yml"]
|
||||
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" ]
|
30
Jenkinsfile
vendored
30
Jenkinsfile
vendored
@ -19,7 +19,7 @@ pipeline {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
stage('Run unit tests') {
|
||||
steps {
|
||||
script {
|
||||
@ -58,20 +58,22 @@ pipeline {
|
||||
passwordVariable: 'GITEA_RELEASE_PASSWORD'
|
||||
])
|
||||
]) {
|
||||
sh 'make gitea-release'
|
||||
}
|
||||
def currentVersion = sh(returnStdout: true, script: 'make full-version').trim()
|
||||
if (currentVersion.endsWith('-dirty')) {
|
||||
unstable('Could not trigger emissary-firmware build, dirty version !')
|
||||
} else {
|
||||
build(
|
||||
job: "../emissary-firmware/${env.GIT_BRANCH}",
|
||||
parameters: [
|
||||
[$class: 'StringParameterValue', name: 'emissaryRelease', value: currentVersion]
|
||||
],
|
||||
wait: false
|
||||
)
|
||||
sh """
|
||||
export MKT_PROJECT_VERSION_BRANCH_NAME=${env.BRANCH_NAME}
|
||||
make mktools
|
||||
make gitea-release
|
||||
"""
|
||||
}
|
||||
|
||||
String currentVersion = sh(script: "MKT_PROJECT_VERSION_BRANCH_NAME=${env.BRANCH_NAME} make version", returnStdout: true).trim()
|
||||
|
||||
build(
|
||||
job: "../emissary-firmware/${env.GIT_BRANCH}",
|
||||
parameters: [
|
||||
[$class: 'StringParameterValue', name: 'emissaryRelease', value: currentVersion]
|
||||
],
|
||||
wait: false
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
89
Makefile
89
Makefile
@ -1,16 +1,12 @@
|
||||
LINT_ARGS ?= --timeout 5m
|
||||
GORELEASER_VERSION ?= v1.13.1
|
||||
GORELEASER_ARGS ?= release --snapshot --rm-dist
|
||||
GORELEASER_ARGS ?= release --snapshot --clean
|
||||
GITCHLOG_ARGS ?=
|
||||
SHELL := /bin/bash
|
||||
|
||||
EMISSARY_VERSION ?=
|
||||
GIT_VERSION := $(shell git describe --always)
|
||||
DATE_VERSION := $(shell date +%Y.%-m.%-d)
|
||||
FULL_VERSION := v$(DATE_VERSION)-$(GIT_VERSION)$(if $(shell git diff --stat),-dirty,)
|
||||
|
||||
DOCKER_IMAGE_NAME ?= bornholm/emissary
|
||||
DOCKER_IMAGE_TAG ?= $(FULL_VERSION)
|
||||
DOCKER_IMAGE_NAME ?= reg.cadoles.com/cadoles/emissary
|
||||
DOCKER_IMAGE_TAG ?= $(MKT_PROJECT_VERSION)
|
||||
|
||||
GOTEST_ARGS ?= -short
|
||||
|
||||
@ -45,7 +41,7 @@ build-emissary-%: deps ## Build executable
|
||||
-v \
|
||||
-ldflags "\
|
||||
-X 'main.GitRef=$(shell git rev-parse --short HEAD)' \
|
||||
-X 'main.ProjectVersion=$(FULL_VERSION)' \
|
||||
-X 'main.ProjectVersion=$(MKT_PROJECT_VERSION)' \
|
||||
-X 'main.BuildDate=$(shell date --utc --rfc-3339=seconds)' \
|
||||
" \
|
||||
-o ./bin/$* \
|
||||
@ -66,7 +62,7 @@ run-emissary-%: .env
|
||||
( set -o allexport && source .env && set +o allexport && bin/$* $(EMISSARY_CMD))
|
||||
|
||||
.PHONY: deps
|
||||
deps: .env
|
||||
deps: .env .mktools
|
||||
|
||||
.PHONY: dump-config
|
||||
dump-config: build-emissary
|
||||
@ -74,36 +70,23 @@ dump-config: build-emissary
|
||||
./bin/emissary config dump > tmp/config.yml
|
||||
|
||||
.PHONY: goreleaser
|
||||
goreleaser: deps
|
||||
( set -o allexport && source .env && set +o allexport && VERSION=$(GORELEASER_VERSION) curl -sfL https://goreleaser.com/static/run | GORELEASER_CURRENT_TAG="$(FULL_VERSION)" bash /dev/stdin $(GORELEASER_ARGS) )
|
||||
|
||||
.PHONY: start-release
|
||||
start-release:
|
||||
if [ -z "$(EMISSARY_VERSION)" ]; then echo "You must define environment variable FAQD_VERSION"; exit 1; fi
|
||||
|
||||
git flow release start $(EMISSARY_VERSION)
|
||||
|
||||
# Update package.json version
|
||||
jq '.version = "$(EMISSARY_VERSION)"' package.json | sponge package.json
|
||||
git add package.json
|
||||
git commit -m "chore: bump to version $(EMISSARY_VERSION)" --allow-empty
|
||||
|
||||
echo "Commit you additional modifications then execute 'make finish-release'"
|
||||
|
||||
.PHONY: finish-release
|
||||
finish-release:
|
||||
git flow release finish -m "v$(EMISSARY_VERSION)"
|
||||
git push --all
|
||||
git push --tags
|
||||
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) )
|
||||
|
||||
install-git-hooks:
|
||||
git config core.hooksPath .githooks
|
||||
|
||||
docker-build:
|
||||
docker build -t $(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG) .
|
||||
docker-build: docker-build-agent docker-build-server
|
||||
|
||||
docker-release:
|
||||
docker push $(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)
|
||||
|
||||
deploy-openwrt-agent:
|
||||
$(MAKE) GOARCH="arm" GORELEASER_ARGS='build --single-target --snapshot --clean' goreleaser
|
||||
@ -119,32 +102,28 @@ deploy-openwrt-agent:
|
||||
scp dist/emissary-agent_linux_arm_6/emissary root@$(OPENWRT_DEVICE):/usr/bin/emissary
|
||||
ssh root@$(OPENWRT_DEVICE) /etc/init.d/emissary-agent start
|
||||
|
||||
gitea-release: tools/gitea-release/bin/gitea-release.sh goreleaser
|
||||
gitea-release: .mktools tools/gitea-release/bin/gitea-release.sh goreleaser changelog
|
||||
mkdir -p .gitea-release
|
||||
rm -rf .gitea-release/*
|
||||
|
||||
cp dist/*.tar.gz .gitea-release/
|
||||
cp dist/*.apk .gitea-release/
|
||||
cp dist/*.deb .gitea-release/
|
||||
cp CHANGELOG.md .gitea-release/
|
||||
|
||||
GITEA_RELEASE_PROJECT="emissary" \
|
||||
GITEA_RELEASE_ORG="arcad" \
|
||||
GITEA_RELEASE_BASE_URL="https://forge.cadoles.com" \
|
||||
GITEA_RELEASE_VERSION="$(FULL_VERSION)" \
|
||||
GITEA_RELEASE_NAME="$(FULL_VERSION)" \
|
||||
GITEA_RELEASE_VERSION="$(MKT_PROJECT_VERSION)" \
|
||||
GITEA_RELEASE_NAME="$(MKT_PROJECT_VERSION)" \
|
||||
GITEA_RELEASE_COMMITISH_TARGET="$(GIT_VERSION)" \
|
||||
GITEA_RELEASE_IS_DRAFT="false" \
|
||||
GITEA_RELEASE_BODY="" \
|
||||
GITEA_RELEASE_ATTACHMENTS="$$(find .gitea-release/* -type f)" \
|
||||
tools/gitea-release/bin/gitea-release.sh
|
||||
|
||||
tools/gitea-release/bin/gitea-release.sh:
|
||||
mkdir -p tools/gitea-release/bin
|
||||
curl --output tools/gitea-release/bin/gitea-release.sh https://forge.cadoles.com/Cadoles/Jenkins/raw/branch/master/resources/com/cadoles/gitea/gitea-release.sh
|
||||
chmod +x tools/gitea-release/bin/gitea-release.sh
|
||||
|
||||
.emissary-token:
|
||||
$(MAKE) run-emissary-server EMISSARY_CMD="--debug --config tmp/server.yml server auth create-token --role writer > .emissary-token"
|
||||
$(MAKE) run-emissary-server EMISSARY_CMD="--debug --config tmp/server.yml server auth create-token --role writer --output .emissary-token"
|
||||
|
||||
AGENT_ID ?= 1
|
||||
|
||||
@ -152,15 +131,31 @@ 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
|
||||
|
||||
full-version:
|
||||
@echo $(FULL_VERSION)
|
||||
version: .mktools
|
||||
@echo $(MKT_PROJECT_VERSION)
|
||||
|
||||
update-edge-lib:
|
||||
git pull --rebase
|
||||
GOPROXY=direct GOPRIVATE=forge.cadoles.com/arcad/edge go get -u forge.cadoles.com/arcad/edge
|
||||
go clean -modcache
|
||||
GONOPROXY=forge.cadoles.com/arcad/edge GOPRIVATE=forge.cadoles.com/arcad/edge go get -v -u forge.cadoles.com/arcad/edge
|
||||
go mod tidy
|
||||
$(MAKE) test
|
||||
git add go.mod go.sum
|
||||
git commit -m "feat: update arcad/edge dependency"
|
||||
git push
|
||||
git push
|
||||
|
||||
.PHONY: changelog
|
||||
changelog: .mktools
|
||||
$(MAKE) MKT_GIT_CHGLOG_ARGS='--next-tag $(MKT_PROJECT_VERSION) --tag-filter-pattern $(MKT_PROJECT_VERSION_CHANNEL) --output CHANGELOG.md' mkt-changelog
|
||||
|
||||
.PHONY: mktools
|
||||
mktools:
|
||||
rm -rf .mktools
|
||||
curl -q https://forge.cadoles.com/Cadoles/mktools/raw/branch/master/install.sh | $(SHELL)
|
||||
|
||||
.mktools:
|
||||
$(MAKE) mktools
|
||||
|
||||
-include .mktools/*.mk
|
@ -7,6 +7,7 @@
|
||||
- (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
|
||||
|
||||
@ -24,3 +25,7 @@ See:
|
||||
|
||||
- [`misc/packaging/common/config-agent.yml`](../misc/packaging/common/config-agent.yml)
|
||||
- [`misc/packaging/common/config-server.yml`](../misc/packaging/common/config-server.yml)
|
||||
|
||||
### Other projects
|
||||
|
||||
- [`emissary-firmware`](https://forge.cadoles.com/arcad/emissary-firmware) - Preconfigured OpenWRT firmwares with an agent
|
10
doc/tutorials/fr/docker-agent.md
Normal file
10
doc/tutorials/fr/docker-agent.md
Normal file
@ -0,0 +1,10 @@
|
||||
# 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
|
||||
```
|
@ -80,9 +80,11 @@
|
||||
5. Créer un jeton d'administration:
|
||||
|
||||
```shell
|
||||
sudo emissary --workdir /usr/share/emissary --config /etc/emissary/server.yml server auth create-token --role writer --subject $(whoami) > .emissary-token
|
||||
sudo emissary --workdir /usr/share/emissary --config /etc/emissary/server.yml server auth create-token --role writer --subject $(whoami)
|
||||
```
|
||||
|
||||
> **Note** Le jeton sera stocké dans le répertoire `$HOME/.config/emissary`.
|
||||
|
||||
6. Vérifier l'authentification sur l'API:
|
||||
|
||||
```shell
|
||||
|
30
go.mod
30
go.mod
@ -1,19 +1,22 @@
|
||||
module forge.cadoles.com/Cadoles/emissary
|
||||
|
||||
go 1.19
|
||||
go 1.21
|
||||
|
||||
toolchain go1.21.2
|
||||
|
||||
require (
|
||||
forge.cadoles.com/arcad/edge v0.0.0-20230426135323-17808d14c978
|
||||
forge.cadoles.com/arcad/edge v0.0.0-20231201112253-83a1e8966559
|
||||
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
|
||||
github.com/antonmedv/expr v1.12.7
|
||||
github.com/brutella/dnssd v1.2.6
|
||||
github.com/btcsuite/btcd/btcutil v1.1.3
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/denisbrodbeck/machineid v1.0.1
|
||||
github.com/dop251/goja v0.0.0-20230304130813-e2f543bf4b4c
|
||||
github.com/evanphx/json-patch/v5 v5.6.0
|
||||
github.com/go-chi/chi v4.1.2+incompatible
|
||||
github.com/getsentry/sentry-go v0.25.0
|
||||
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
|
||||
@ -25,7 +28,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-20230419082146-a94d9ed7202b
|
||||
gitlab.com/wpetit/goweb v0.0.0-20231019192040-4c72331a7648
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
modernc.org/sqlite v1.21.0
|
||||
)
|
||||
@ -33,7 +36,7 @@ require (
|
||||
require (
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.0 // indirect
|
||||
github.com/antonmedv/expr v1.12.7 // 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
|
||||
@ -41,10 +44,13 @@ 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
|
||||
@ -52,7 +58,8 @@ 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
|
||||
golang.org/x/net v0.9.0 // indirect
|
||||
github.com/ulikunitz/xz v0.5.11 // indirect
|
||||
golang.org/x/net v0.11.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20220728213248-dd149ef739b9 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
)
|
||||
@ -75,7 +82,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.0 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.1 // 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
|
||||
@ -96,15 +103,14 @@ require (
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.uber.org/atomic v1.10.0 // indirect
|
||||
golang.org/x/crypto v0.7.0 // indirect
|
||||
golang.org/x/crypto v0.10.0 // indirect
|
||||
golang.org/x/mod v0.10.0 // indirect
|
||||
golang.org/x/sync v0.1.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/sys v0.9.0 // indirect
|
||||
golang.org/x/term v0.9.0 // indirect
|
||||
golang.org/x/text v0.10.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
75
go.sum
@ -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-20230426135323-17808d14c978 h1:fekSRSb8gYcVx8C0B9K6B7+KiFHVixIwvPUkxcnRFp4=
|
||||
forge.cadoles.com/arcad/edge v0.0.0-20230426135323-17808d14c978/go.mod h1:uv3wBa+UbcEUb7IiJCj1T96Xo3cmx1BwNxbBYRZhln8=
|
||||
forge.cadoles.com/arcad/edge v0.0.0-20231201112253-83a1e8966559 h1:w44upL8eAJdCzS2+Sx0WIRT2QaAq8gotRwwL9j9z3yQ=
|
||||
forge.cadoles.com/arcad/edge v0.0.0-20231201112253-83a1e8966559/go.mod h1:tMysrBPkzPFZAi89qD4TioDjcP3L2hadBJ5Eoij8GcA=
|
||||
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,6 +128,7 @@ 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=
|
||||
@ -139,6 +140,7 @@ 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=
|
||||
@ -146,6 +148,8 @@ 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=
|
||||
@ -504,15 +508,17 @@ 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=
|
||||
@ -550,10 +556,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.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
|
||||
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
|
||||
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.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
|
||||
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
||||
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=
|
||||
@ -673,6 +679,7 @@ 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=
|
||||
@ -761,6 +768,8 @@ 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=
|
||||
@ -770,6 +779,7 @@ 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=
|
||||
@ -837,8 +847,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.0 h1:RdcDk92EJBuBS55nQMMYFXTxwstHug4jkhT5pq8VxPk=
|
||||
github.com/jackc/puddle/v2 v2.2.0/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
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/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=
|
||||
@ -878,6 +888,8 @@ 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=
|
||||
@ -889,6 +901,8 @@ 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=
|
||||
@ -906,7 +920,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.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
|
||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||
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=
|
||||
@ -976,6 +990,7 @@ 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=
|
||||
@ -1111,8 +1126,11 @@ 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=
|
||||
@ -1174,6 +1192,7 @@ 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=
|
||||
@ -1209,8 +1228,9 @@ 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=
|
||||
@ -1271,6 +1291,8 @@ 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=
|
||||
@ -1312,8 +1334,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-20230419082146-a94d9ed7202b h1:nkvOl8TCj/mErADnwFFynjxBtC+hHsrESw6rw56JGmg=
|
||||
gitlab.com/wpetit/goweb v0.0.0-20230419082146-a94d9ed7202b/go.mod h1:3sus4zjoUv1GB7eDLL60QaPkUnXJCWBpjvbe0jWifeY=
|
||||
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=
|
||||
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=
|
||||
@ -1367,6 +1389,8 @@ 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=
|
||||
@ -1401,8 +1425,9 @@ 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=
|
||||
@ -1531,8 +1556,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.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
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/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=
|
||||
@ -1697,8 +1722,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.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
||||
golang.org/x/sys v0.7.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/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=
|
||||
@ -1708,8 +1733,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.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ=
|
||||
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||
golang.org/x/term v0.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28=
|
||||
golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
|
||||
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=
|
||||
@ -1724,8 +1749,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.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||
golang.org/x/text v0.9.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/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=
|
||||
@ -1980,6 +2005,7 @@ 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=
|
||||
@ -1994,8 +2020,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.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
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=
|
||||
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=
|
||||
@ -2106,6 +2132,7 @@ 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=
|
||||
@ -2139,12 +2166,14 @@ 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=
|
||||
|
@ -43,13 +43,15 @@ func (a *Agent) Run(ctx context.Context) error {
|
||||
logger.Debug(ctx, "registering agent")
|
||||
|
||||
if err := a.registerAgent(ctx, client, state); err != nil {
|
||||
logger.Error(ctx, "could not register agent", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not register agent", logger.CapturedE(err))
|
||||
}
|
||||
|
||||
logger.Debug(ctx, "state before reconciliation", logger.F("state", state))
|
||||
|
||||
if err := a.Reconcile(ctx, state); err != nil {
|
||||
logger.Error(ctx, "could not reconcile node with state", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not reconcile node with state", logger.CapturedE(err))
|
||||
|
||||
return
|
||||
}
|
||||
@ -79,7 +81,8 @@ func (a *Agent) Reconcile(ctx context.Context, state *State) error {
|
||||
)
|
||||
|
||||
if err := ctrl.Reconcile(ctrlCtx, state); err != nil {
|
||||
logger.Error(ctx, "could not reconcile", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not reconcile", logger.CapturedE(err))
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,9 +113,10 @@ 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.E(errors.WithStack(err)), logger.F("name", name),
|
||||
logger.CapturedE(err), logger.F("name", name),
|
||||
)
|
||||
|
||||
continue
|
||||
|
@ -4,7 +4,6 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"net"
|
||||
"path/filepath"
|
||||
"text/template"
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/agent/controller/app/spec"
|
||||
@ -17,47 +16,60 @@ 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/sqlite"
|
||||
"forge.cadoles.com/arcad/edge/pkg/storage/driver"
|
||||
"forge.cadoles.com/arcad/edge/pkg/storage/share"
|
||||
"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
|
||||
KeySet jwk.Set
|
||||
AppRepository appModule.Repository
|
||||
AppID app.ID
|
||||
ShareRepository shareModule.Repository
|
||||
Bus bus.Bus
|
||||
DocumentStore storage.DocumentStore
|
||||
BlobStore storage.BlobStore
|
||||
ShareStore share.Store
|
||||
KeySet jwk.Set
|
||||
AppRepository appModule.Repository
|
||||
AppID app.ID
|
||||
}
|
||||
|
||||
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) {
|
||||
dataDir, err := c.ensureAppDataDir(ctx, appKey)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not retrieve app data dir")
|
||||
appEntry, exists := specs.Apps[appKey]
|
||||
if !exists {
|
||||
return nil, errors.Errorf("could not find app entry '%s'", appKey)
|
||||
}
|
||||
|
||||
dbFile := filepath.Join(dataDir, appKey+".sqlite")
|
||||
db, err := sqlite.Open(dbFile + defaultSQLiteParams)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not open database file '%s'", dbFile)
|
||||
storage := appEntry.Storage
|
||||
if storage == nil {
|
||||
return nil, errors.Errorf("could not find app entry '%s' storage configuration", appKey)
|
||||
}
|
||||
|
||||
shareDBFile := filepath.Join(dataDir, "shared.sqlite")
|
||||
shareDB, err := sqlite.Open(shareDBFile + defaultSQLiteParams)
|
||||
documentStore, err := driver.NewDocumentStore(appEntry.Storage.DocumentStoreDSN)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not open database file '%s'", shareDBFile)
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
blobStore, err := driver.NewBlobStore(appEntry.Storage.BlobStoreDSN)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
shareStore, err := driver.NewShareStore(appEntry.Storage.ShareStoreDSN)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
keySet, err := getAuthKeySet(specs.Config)
|
||||
@ -76,24 +88,37 @@ func (c *Controller) getHandlerOptions(ctx context.Context, appKey string, specs
|
||||
mounts = append(mounts, authMount)
|
||||
}
|
||||
|
||||
mounts = append(mounts, appModule.Mount(c.appRepository))
|
||||
mounts = append(
|
||||
mounts,
|
||||
appModule.Mount(c.appRepository),
|
||||
blob.Mount(10<<(10*2)), // 10Mb
|
||||
fetch.Mount(),
|
||||
)
|
||||
|
||||
deps := Dependencies{
|
||||
Bus: memory.NewBus(),
|
||||
DocumentStore: sqlite.NewDocumentStoreWithDB(db),
|
||||
BlobStore: sqlite.NewBlobStoreWithDB(db),
|
||||
KeySet: keySet,
|
||||
AppRepository: c.appRepository,
|
||||
AppID: app.ID(appKey),
|
||||
ShareRepository: shareSqlite.NewRepositoryWithDB(shareDB),
|
||||
Bus: memory.NewBus(),
|
||||
DocumentStore: documentStore,
|
||||
BlobStore: blobStore,
|
||||
ShareStore: shareStore,
|
||||
KeySet: keySet,
|
||||
AppRepository: c.appRepository,
|
||||
AppID: app.ID(appKey),
|
||||
}
|
||||
|
||||
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
|
||||
@ -180,9 +205,10 @@ func createResolveAppURL(specs *spec.Spec) (ResolveAppURLFunc, error) {
|
||||
for ifaceName, ifaceTmpl := range ifaceMappings {
|
||||
iface, err := net.InterfaceByName(ifaceName)
|
||||
if err != nil {
|
||||
logger.Error(
|
||||
err = errors.WithStack(err)
|
||||
logger.Warn(
|
||||
ctx, "could not find interface",
|
||||
logger.E(errors.WithStack(err)), logger.F("iface", ifaceName),
|
||||
logger.CapturedE(err), logger.F("iface", ifaceName),
|
||||
)
|
||||
|
||||
continue
|
||||
@ -190,9 +216,10 @@ 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.E(errors.WithStack(err)),
|
||||
logger.CapturedE(err),
|
||||
logger.F("iface", iface.Name),
|
||||
)
|
||||
|
||||
@ -202,9 +229,10 @@ 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.E(errors.WithStack(err)),
|
||||
logger.CapturedE(err),
|
||||
logger.F("iface", iface.Name),
|
||||
)
|
||||
|
||||
@ -279,12 +307,12 @@ func (c *Controller) getAppModules(deps Dependencies) []app.ServerModuleFactory
|
||||
cast.CastModuleFactory(),
|
||||
module.LifecycleModuleFactory(),
|
||||
netModule.ModuleFactory(deps.Bus),
|
||||
module.RPCModuleFactory(deps.Bus),
|
||||
rpc.ModuleFactory(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.ShareRepository),
|
||||
shareModule.ModuleFactory(deps.AppID, deps.ShareStore),
|
||||
}
|
||||
}
|
||||
|
@ -63,14 +63,16 @@ func (r *AppRepository) List(ctx context.Context) ([]*app.Manifest, error) {
|
||||
|
||||
bundle, err := bundle.FromPath(path)
|
||||
if err != nil {
|
||||
logger.Error(bundleCtx, "could not load bundle", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(bundleCtx, "could not load bundle", logger.CapturedE(err))
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
manifest, err := app.LoadManifest(bundle)
|
||||
if err != nil {
|
||||
logger.Error(bundleCtx, "could not load manifest", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(bundleCtx, "could not load manifest", logger.CapturedE(err))
|
||||
|
||||
continue
|
||||
}
|
||||
@ -97,14 +99,16 @@ func (r *AppRepository) findManifest(ctx context.Context, id app.ID) (*app.Manif
|
||||
|
||||
bundle, err := bundle.FromPath(path)
|
||||
if err != nil {
|
||||
logger.Error(bundleCtx, "could not load bundle", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(bundleCtx, "could not load bundle", logger.CapturedE(err))
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
manifest, err := app.LoadManifest(bundle)
|
||||
if err != nil {
|
||||
logger.Error(bundleCtx, "could not load manifest", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(bundleCtx, "could not load manifest", logger.CapturedE(err))
|
||||
|
||||
continue
|
||||
}
|
||||
|
@ -1,15 +1,18 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"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/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"
|
||||
@ -54,7 +57,7 @@ func authModuleFactory(keySet jwk.Set) app.ServerModuleFactory {
|
||||
)
|
||||
}
|
||||
|
||||
func getAuthMount(auth *spec.Auth, keySet jwk.Set) (auth.MountFunc, error) {
|
||||
func getAuthMount(auth *appSpec.Auth, keySet jwk.Set) (auth.MountFunc, error) {
|
||||
switch {
|
||||
case auth.Local != nil:
|
||||
var rawKey any = auth.Local.Key
|
||||
@ -77,7 +80,8 @@ func getAuthMount(auth *spec.Auth, keySet jwk.Set) (auth.MountFunc, error) {
|
||||
|
||||
return authModule.Mount(
|
||||
authHTTP.NewLocalHandler(
|
||||
jwa.HS256, key,
|
||||
key,
|
||||
jwa.HS256,
|
||||
authHTTP.WithRoutePrefix("/auth"),
|
||||
authHTTP.WithAccounts(auth.Local.Accounts...),
|
||||
authHTTP.WithCookieOptions(getCookieDomain, cookieDuration),
|
||||
@ -91,3 +95,72 @@ func getAuthMount(auth *spec.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
|
||||
}
|
||||
|
@ -66,10 +66,11 @@ 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.E(errors.WithStack(err)),
|
||||
logger.CapturedE(err),
|
||||
)
|
||||
|
||||
delete(c.servers, appID)
|
||||
@ -87,10 +88,11 @@ 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.E(errors.WithStack(err)),
|
||||
logger.CapturedE(err),
|
||||
)
|
||||
|
||||
delete(c.servers, appKey)
|
||||
@ -98,9 +100,10 @@ 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.E(errors.WithStack(err)),
|
||||
logger.CapturedE(err),
|
||||
)
|
||||
|
||||
return
|
||||
@ -111,7 +114,8 @@ 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 {
|
||||
logger.Error(appCtx, "could not update app", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(appCtx, "could not update app", logger.CapturedE(err))
|
||||
continue
|
||||
}
|
||||
}
|
||||
@ -200,11 +204,13 @@ 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.F("address", appEntry.Address),
|
||||
)
|
||||
logger.Info(ctx, "restarting app")
|
||||
|
||||
if err := server.Server.Stop(); err != nil {
|
||||
return errors.WithStack(err)
|
||||
@ -217,10 +223,7 @@ func (c *Controller) updateApp(ctx context.Context, specs *spec.Spec, appKey str
|
||||
|
||||
c.servers[appKey] = serverEntry
|
||||
} else {
|
||||
logger.Info(
|
||||
ctx, "starting app",
|
||||
logger.F("address", appEntry.Address),
|
||||
)
|
||||
logger.Info(ctx, "starting app")
|
||||
}
|
||||
|
||||
if err := server.Server.Start(ctx, appEntry.Address); err != nil {
|
||||
|
@ -8,15 +8,14 @@ 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"
|
||||
@ -49,7 +48,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(s.bundle); err != nil {
|
||||
if err := handler.Load(ctx, s.bundle); err != nil {
|
||||
return errors.Wrap(err, "could not load app bundle")
|
||||
}
|
||||
|
||||
@ -73,7 +72,8 @@ func (s *Server) Start(ctx context.Context, addr string) (err error) {
|
||||
defer func() {
|
||||
if recovered := recover(); recovered != nil {
|
||||
if err, ok := recovered.(error); ok {
|
||||
logger.Error(ctx, err.Error(), logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, err.Error(), logger.CapturedE(err))
|
||||
|
||||
return
|
||||
}
|
||||
@ -128,7 +128,7 @@ func (s *Server) Stop() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewServer(bundle bundle.Bundle, config *spec.Config, handlerOptions ...edgeHTTP.HandlerOptionFunc) *Server {
|
||||
func NewServer(bundle bundle.Bundle, config *appSpec.Config, handlerOptions ...edgeHTTP.HandlerOptionFunc) *Server {
|
||||
return &Server{
|
||||
bundle: bundle,
|
||||
config: config,
|
||||
|
@ -24,15 +24,37 @@
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"zip",
|
||||
"tar.gz"
|
||||
"tar.gz",
|
||||
"zim"
|
||||
]
|
||||
},
|
||||
"storage": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"blobStoreDsn": {
|
||||
"type": "string"
|
||||
},
|
||||
"documentStoreDsn": {
|
||||
"type": "string"
|
||||
},
|
||||
"shareStoreDsn": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"blobStoreDsn",
|
||||
"documentStoreDsn",
|
||||
"shareStoreDsn"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"url",
|
||||
"sha256sum",
|
||||
"address",
|
||||
"format"
|
||||
"format",
|
||||
"storage"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
@ -84,6 +106,9 @@
|
||||
"key": {
|
||||
"type": ["object", "string"]
|
||||
},
|
||||
"signingAlgorithm": {
|
||||
"type": "string"
|
||||
},
|
||||
"accounts": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
@ -117,7 +142,8 @@
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"key"
|
||||
"key",
|
||||
"signingAlgorithm"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ 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"
|
||||
@ -14,10 +15,17 @@ type Spec struct {
|
||||
}
|
||||
|
||||
type AppEntry struct {
|
||||
URL string `json:"url"`
|
||||
SHA256Sum string `json:"sha256sum"`
|
||||
Address string `json:"address"`
|
||||
Format string `json:"format"`
|
||||
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"`
|
||||
}
|
||||
|
||||
type Auth struct {
|
||||
@ -25,10 +33,11 @@ type Auth struct {
|
||||
}
|
||||
|
||||
type LocalAuth struct {
|
||||
Key any `json:"key"`
|
||||
Accounts []edgeAuth.LocalAccount `json:"accounts"`
|
||||
CookieDomain string `json:"cookieDomain"`
|
||||
CookieDuration string `json:"cookieDuration"`
|
||||
Key any `json:"key"`
|
||||
SigningAlgorithm jwa.SignatureAlgorithm `json:"signingAlgorithm"`
|
||||
Accounts []edgeAuth.LocalAccount `json:"accounts"`
|
||||
CookieDomain string `json:"cookieDomain"`
|
||||
CookieDuration string `json:"cookieDuration"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
|
@ -6,7 +6,12 @@
|
||||
"url": "http://example.com/edge.sdk.client.test_0.0.0.zip",
|
||||
"sha256sum": "58019192dacdae17755707719707db007e26dac856102280583fbd18427dd352",
|
||||
"address": ":8081",
|
||||
"format": "zip"
|
||||
"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"
|
||||
}
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
@ -23,6 +28,7 @@
|
||||
"q": "yJJLNc9w6O4y2icME8k99FugV9E7ObwUxF3v5JN3y1cmAT0h2njyE3iAGqaDZwcY1_jGCisjwoqX6i5E8xqhxX3Gcy3J7SmUAf8fhY8wU3zv9DK7skg2IdvanDb8Y1OM6GchbYZAOVPEg2IvVio8zI-Ih3DDwDk8Df0ufzoHRb8",
|
||||
"qi": "zOE-4R3cjPesm3MX-4PdwmsaF9QZLUVRUvvHJ08pKs6kAXP18hzjctAoOjhQDxlTYqNYNePfKzKwost3OJoPgRIc9w9qwUCK1gNOS4Z_xozCIaXgMddNFhkoAfZ4JaKjNCiinzjGfqG99Lf-yzmmREuuhRv7SdS3ST4VQjiJQew"
|
||||
},
|
||||
"signingAlgorithm": "RS256",
|
||||
"accounts": [
|
||||
{
|
||||
"username": "foo",
|
||||
|
@ -117,7 +117,8 @@ func (c *Controller) updateResponder(ctx context.Context, spec *mdns.Spec) error
|
||||
|
||||
service, err := dnssd.NewService(config)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "could not create mdns service", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not create mdns service", logger.CapturedE(err))
|
||||
|
||||
continue
|
||||
}
|
||||
@ -132,7 +133,8 @@ func (c *Controller) updateResponder(ctx context.Context, spec *mdns.Spec) error
|
||||
|
||||
for _, service := range services {
|
||||
if _, err := responder.Add(service); err != nil {
|
||||
logger.Error(ctx, "could not add mdns service", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not add mdns service", logger.CapturedE(err))
|
||||
|
||||
continue
|
||||
}
|
||||
@ -148,7 +150,8 @@ 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) {
|
||||
logger.Error(ctx, "could not respond to mdns queries", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not respond to mdns queries", logger.CapturedE(err))
|
||||
}
|
||||
}()
|
||||
|
||||
|
@ -64,9 +64,10 @@ 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.E(errors.WithStack(err)),
|
||||
logger.CapturedE(err),
|
||||
logger.F("downloadDir", downloadDir),
|
||||
)
|
||||
}
|
||||
|
@ -46,7 +46,8 @@ func (c *UCIController) Reconcile(ctx context.Context, state *agent.State) error
|
||||
}
|
||||
|
||||
if err := c.updateConfiguration(ctx, uciSpec); err != nil {
|
||||
logger.Error(ctx, "could not update configuration", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not update configuration", logger.CapturedE(err))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -145,7 +145,8 @@ func (c *Controller) writeState(ctx context.Context, state *agent.State) error {
|
||||
return
|
||||
}
|
||||
|
||||
logger.Error(ctx, "could not remove temporary file", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not remove temporary file", logger.CapturedE(err))
|
||||
}
|
||||
}()
|
||||
|
||||
@ -155,7 +156,8 @@ func (c *Controller) writeState(ctx context.Context, state *agent.State) error {
|
||||
return
|
||||
}
|
||||
|
||||
logger.Error(ctx, "could not close temporary file", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not close temporary file", logger.CapturedE(err))
|
||||
}
|
||||
}()
|
||||
|
||||
|
@ -58,10 +58,11 @@ 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.E(errors.WithStack(err)),
|
||||
logger.CapturedE(err),
|
||||
)
|
||||
|
||||
delete(c.proxies, proxyID)
|
||||
@ -79,10 +80,11 @@ 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.E(errors.WithStack(err)),
|
||||
logger.CapturedE(err),
|
||||
)
|
||||
|
||||
delete(c.proxies, proxyID)
|
||||
@ -94,7 +96,8 @@ 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 {
|
||||
logger.Error(proxyCtx, "could not update proxy", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(proxyCtx, "could not update proxy", logger.CapturedE(err))
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
@ -38,12 +38,14 @@ func (p *ReverseProxy) Start(ctx context.Context, addr string, funcs ...proxy.Op
|
||||
go func() {
|
||||
defer func() {
|
||||
if err := p.Stop(); err != nil {
|
||||
logger.Error(ctx, "error while stopping gateway", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "error while stopping gateway", logger.CapturedE(err))
|
||||
}
|
||||
}()
|
||||
|
||||
if err := server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||
logger.Error(ctx, "error while listening", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "error while listening", logger.CapturedE(err))
|
||||
}
|
||||
}()
|
||||
|
||||
|
@ -40,14 +40,15 @@ 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.Error(ctx, "unexpected agent status", logger.F("status", agent.Status))
|
||||
logger.Warn(ctx, "unexpected agent status", logger.F("status", agent.Status))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
specs, err := client.GetAgentSpecs(ctx, agent.ID)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "could not retrieve agent specs", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not retrieve agent specs", logger.CapturedE(err))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package flag
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
@ -12,6 +11,11 @@ import (
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
AuthTokenDefaultHomePath = "$HOME/.config/emissary/auth-token"
|
||||
AuthTokenDefaultLocalPath = ".emissary-token"
|
||||
)
|
||||
|
||||
func ComposeFlags(flags ...cli.Flag) []cli.Flag {
|
||||
baseFlags := []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
@ -37,10 +41,10 @@ func ComposeFlags(flags ...cli.Flag) []cli.Flag {
|
||||
Aliases: []string{"t"},
|
||||
Usage: "use `TOKEN` as authentication token",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
&cli.StringSliceFlag{
|
||||
Name: "token-file",
|
||||
Usage: "use `TOKEN_FILE` as file containing the authentication token",
|
||||
Value: ".emissary-token",
|
||||
Value: cli.NewStringSlice(AuthTokenDefaultLocalPath, AuthTokenDefaultHomePath),
|
||||
TakesFile: true,
|
||||
},
|
||||
}
|
||||
@ -55,14 +59,14 @@ type BaseFlags struct {
|
||||
Format format.Format
|
||||
OutputMode format.OutputMode
|
||||
Token string
|
||||
TokenFile string
|
||||
TokenFiles []string
|
||||
}
|
||||
|
||||
func GetBaseFlags(ctx *cli.Context) *BaseFlags {
|
||||
serverURL := ctx.String("server")
|
||||
rawFormat := ctx.String("format")
|
||||
rawOutputMode := ctx.String("output-mode")
|
||||
tokenFile := ctx.String("token-file")
|
||||
tokenFiles := ctx.StringSlice("token-file")
|
||||
token := ctx.String("token")
|
||||
|
||||
return &BaseFlags{
|
||||
@ -70,7 +74,7 @@ func GetBaseFlags(ctx *cli.Context) *BaseFlags {
|
||||
Format: format.Format(rawFormat),
|
||||
OutputMode: format.OutputMode(rawOutputMode),
|
||||
Token: token,
|
||||
TokenFile: tokenFile,
|
||||
TokenFiles: tokenFiles,
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,18 +83,20 @@ func GetToken(flags *BaseFlags) (string, error) {
|
||||
return flags.Token, nil
|
||||
}
|
||||
|
||||
if flags.TokenFile == "" {
|
||||
return "", nil
|
||||
for _, tokenFile := range flags.TokenFiles {
|
||||
tokenFile = os.ExpandEnv(tokenFile)
|
||||
|
||||
rawToken, err := os.ReadFile(tokenFile)
|
||||
if err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||
return "", errors.WithStack(err)
|
||||
}
|
||||
|
||||
if rawToken == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
return strings.TrimSpace(string(rawToken)), nil
|
||||
}
|
||||
|
||||
rawToken, err := ioutil.ReadFile(flags.TokenFile)
|
||||
if err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||
return "", errors.WithStack(err)
|
||||
}
|
||||
|
||||
if rawToken == nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
return strings.TrimSpace(string(rawToken)), nil
|
||||
return "", nil
|
||||
}
|
||||
|
@ -7,8 +7,11 @@ 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) {
|
||||
@ -46,6 +49,27 @@ 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{
|
||||
@ -84,11 +108,15 @@ 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 {
|
||||
|
@ -2,8 +2,11 @@ package auth
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/auth/thirdparty"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/api/flag"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/command/common"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/jwk"
|
||||
"github.com/lithammer/shortuuid/v4"
|
||||
@ -26,6 +29,13 @@ func CreateTokenCommand() *cli.Command {
|
||||
Usage: "associate `SUBJECT` to the token",
|
||||
Value: fmt.Sprintf("user-%s", shortuuid.New()),
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "output",
|
||||
Aliases: []string{"o"},
|
||||
TakesFile: true,
|
||||
Usage: "output token to `OUTPUT` (or '-' to print to stdout)",
|
||||
Value: flag.AuthTokenDefaultHomePath,
|
||||
},
|
||||
},
|
||||
Action: func(ctx *cli.Context) error {
|
||||
conf, err := common.LoadConfig(ctx)
|
||||
@ -35,6 +45,7 @@ func CreateTokenCommand() *cli.Command {
|
||||
|
||||
subject := ctx.String("subject")
|
||||
role := ctx.String("role")
|
||||
output := ctx.String("output")
|
||||
|
||||
localAuth := conf.Server.Auth.Local
|
||||
if localAuth == nil {
|
||||
@ -51,7 +62,23 @@ func CreateTokenCommand() *cli.Command {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
fmt.Println(token)
|
||||
output = os.ExpandEnv(output)
|
||||
|
||||
if output == "-" {
|
||||
fmt.Println(token)
|
||||
} else {
|
||||
outputDirectory := filepath.Dir(output)
|
||||
|
||||
if err := os.MkdirAll(outputDirectory, os.FileMode(0o700)); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
if err := os.WriteFile(output, []byte(token), os.FileMode(0o600)); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
fmt.Printf("Token written to '%s'.\n", output)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
|
@ -32,7 +32,8 @@ func PingCommand() *cli.Command {
|
||||
|
||||
defer func() {
|
||||
if err := db.Close(); err != nil {
|
||||
logger.Error(ctx.Context, "error while closing database connection", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx.Context, "error while closing database connection", logger.CapturedE(err))
|
||||
}
|
||||
}()
|
||||
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
// Config definition
|
||||
type Config struct {
|
||||
Logger LoggerConfig `yaml:"logger"`
|
||||
Sentry SentryConfig `yaml:"sentry"`
|
||||
Server ServerConfig `yaml:"server"`
|
||||
Agent AgentConfig `yaml:"agent"`
|
||||
}
|
||||
@ -44,6 +45,7 @@ func NewDefault() *Config {
|
||||
Logger: NewDefaultLoggerConfig(),
|
||||
Agent: NewDefaultAgentConfig(),
|
||||
Server: NewDefaultServerConfig(),
|
||||
Sentry: NewDefaultSentryConfig(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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=60000",
|
||||
DSN: "sqlite://emissary.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=150000&_pragma=journal_mode=WAL",
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,41 @@ import (
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
var reVar = regexp.MustCompile(`^\${(\w+)}$`)
|
||||
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)
|
||||
}
|
||||
|
||||
type InterpolatedString string
|
||||
|
||||
@ -21,11 +55,7 @@ func (is *InterpolatedString) UnmarshalYAML(value *yaml.Node) error {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
if match := reVar.FindStringSubmatch(str); len(match) > 0 {
|
||||
*is = InterpolatedString(os.Getenv(match[1]))
|
||||
} else {
|
||||
*is = InterpolatedString(str)
|
||||
}
|
||||
*is = InterpolatedString(interpolateEnv(str))
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -39,9 +69,7 @@ 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)
|
||||
}
|
||||
|
||||
if match := reVar.FindStringSubmatch(str); len(match) > 0 {
|
||||
str = os.Getenv(match[1])
|
||||
}
|
||||
str = interpolateEnv(str)
|
||||
|
||||
intVal, err := strconv.ParseInt(str, 10, 32)
|
||||
if err != nil {
|
||||
@ -62,9 +90,7 @@ 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)
|
||||
}
|
||||
|
||||
if match := reVar.FindStringSubmatch(str); len(match) > 0 {
|
||||
str = os.Getenv(match[1])
|
||||
}
|
||||
str = interpolateEnv(str)
|
||||
|
||||
boolVal, err := strconv.ParseBool(str)
|
||||
if err != nil {
|
||||
@ -91,9 +117,7 @@ func (im *InterpolatedMap) UnmarshalYAML(value *yaml.Node) error {
|
||||
continue
|
||||
}
|
||||
|
||||
if match := reVar.FindStringSubmatch(strVal); len(match) > 0 {
|
||||
strVal = os.Getenv(match[1])
|
||||
}
|
||||
strVal = interpolateEnv(strVal)
|
||||
|
||||
data[key] = strVal
|
||||
}
|
||||
@ -113,9 +137,7 @@ func (iss *InterpolatedStringSlice) UnmarshalYAML(value *yaml.Node) error {
|
||||
}
|
||||
|
||||
for index, value := range data {
|
||||
if match := reVar.FindStringSubmatch(value); len(match) > 0 {
|
||||
value = os.Getenv(match[1])
|
||||
}
|
||||
value = interpolateEnv(value)
|
||||
|
||||
data[index] = value
|
||||
}
|
||||
@ -134,9 +156,7 @@ 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)
|
||||
}
|
||||
|
||||
if match := reVar.FindStringSubmatch(str); len(match) > 0 {
|
||||
str = os.Getenv(match[1])
|
||||
}
|
||||
str = interpolateEnv(str)
|
||||
|
||||
duration, err := time.ParseDuration(str)
|
||||
if err != nil {
|
||||
|
63
internal/config/environment_test.go
Normal file
63
internal/config/environment_test.go
Normal file
@ -0,0 +1,63 @@
|
||||
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)
|
||||
}
|
||||
}
|
18
internal/config/sentry.go
Normal file
18
internal/config/sentry.go
Normal file
@ -0,0 +1,18 @@
|
||||
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),
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/datastore"
|
||||
@ -15,12 +16,13 @@ import (
|
||||
)
|
||||
|
||||
type AgentRepository struct {
|
||||
db *sql.DB
|
||||
db *sql.DB
|
||||
sqliteBusyRetryMaxAttempts int
|
||||
}
|
||||
|
||||
// DeleteSpec implements datastore.AgentRepository.
|
||||
func (r *AgentRepository) DeleteSpec(ctx context.Context, agentID datastore.AgentID, name string) error {
|
||||
err := r.withTx(ctx, func(tx *sql.Tx) error {
|
||||
err := r.withTxRetry(ctx, func(tx *sql.Tx) error {
|
||||
exists, err := r.agentExists(ctx, tx, agentID)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
@ -49,7 +51,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.withTx(ctx, func(tx *sql.Tx) error {
|
||||
err := r.withTxRetry(ctx, func(tx *sql.Tx) error {
|
||||
exists, err := r.agentExists(ctx, tx, agentID)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
@ -72,7 +74,8 @@ func (r *AgentRepository) GetSpecs(ctx context.Context, agentID datastore.AgentI
|
||||
|
||||
defer func() {
|
||||
if err := rows.Close(); err != nil {
|
||||
logger.Error(ctx, "could not close rows", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not close rows", logger.CapturedE(err))
|
||||
}
|
||||
}()
|
||||
|
||||
@ -107,7 +110,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.withTx(ctx, func(tx *sql.Tx) error {
|
||||
err := r.withTxRetry(ctx, func(tx *sql.Tx) error {
|
||||
exists, err := r.agentExists(ctx, tx, agentID)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
@ -166,7 +169,7 @@ func (r *AgentRepository) Query(ctx context.Context, opts ...datastore.AgentQuer
|
||||
agents := make([]*datastore.Agent, 0)
|
||||
count := 0
|
||||
|
||||
err := r.withTx(ctx, func(tx *sql.Tx) error {
|
||||
err := r.withTxRetry(ctx, func(tx *sql.Tx) error {
|
||||
query := `SELECT id, label, thumbprint, status, contacted_at, created_at, updated_at FROM agents`
|
||||
|
||||
limit := 10
|
||||
@ -219,14 +222,15 @@ 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 := r.db.QueryContext(ctx, query, args...)
|
||||
rows, err := tx.QueryContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := rows.Close(); err != nil {
|
||||
logger.Error(ctx, "could not close rows", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not close rows", logger.CapturedE(err))
|
||||
}
|
||||
}()
|
||||
|
||||
@ -270,7 +274,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.withTx(ctx, func(tx *sql.Tx) error {
|
||||
err := r.withTxRetry(ctx, func(tx *sql.Tx) error {
|
||||
query := `SELECT count(id) FROM agents WHERE thumbprint = $1`
|
||||
row := tx.QueryRowContext(ctx, query, thumbprint)
|
||||
|
||||
@ -329,15 +333,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.withTx(ctx, func(tx *sql.Tx) error {
|
||||
err := r.withTxRetry(ctx, func(tx *sql.Tx) error {
|
||||
query := `DELETE FROM agents WHERE id = $1`
|
||||
_, err := r.db.ExecContext(ctx, query, id)
|
||||
_, err := tx.ExecContext(ctx, query, id)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
query = `DELETE FROM specs WHERE agent_id = $1`
|
||||
_, err = r.db.ExecContext(ctx, query, id)
|
||||
_, err = tx.ExecContext(ctx, query, id)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
@ -357,14 +361,14 @@ func (r *AgentRepository) Get(ctx context.Context, id datastore.AgentID) (*datas
|
||||
ID: id,
|
||||
}
|
||||
|
||||
err := r.withTx(ctx, func(tx *sql.Tx) error {
|
||||
err := r.withTxRetry(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 := r.db.QueryRowContext(ctx, query, id)
|
||||
row := tx.QueryRowContext(ctx, query, id)
|
||||
|
||||
metadata := JSONMap{}
|
||||
contactedAt := sql.NullTime{}
|
||||
@ -408,7 +412,7 @@ func (r *AgentRepository) Update(ctx context.Context, id datastore.AgentID, opts
|
||||
|
||||
agent := &datastore.Agent{}
|
||||
|
||||
err := r.withTx(ctx, func(tx *sql.Tx) error {
|
||||
err := r.withTxRetry(ctx, func(tx *sql.Tx) error {
|
||||
query := `
|
||||
UPDATE agents SET id = $1
|
||||
`
|
||||
@ -532,6 +536,59 @@ 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 {
|
||||
@ -544,7 +601,8 @@ func (r *AgentRepository) withTx(ctx context.Context, fn func(*sql.Tx) error) er
|
||||
return
|
||||
}
|
||||
|
||||
logger.Error(ctx, "could not rollback transaction", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not rollback transaction", logger.CapturedE(err))
|
||||
}
|
||||
}()
|
||||
|
||||
@ -559,8 +617,8 @@ func (r *AgentRepository) withTx(ctx context.Context, fn func(*sql.Tx) error) er
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewAgentRepository(db *sql.DB) *AgentRepository {
|
||||
return &AgentRepository{db}
|
||||
func NewAgentRepository(db *sql.DB, sqliteBusyRetryMaxAttempts int) *AgentRepository {
|
||||
return &AgentRepository{db, sqliteBusyRetryMaxAttempts}
|
||||
}
|
||||
|
||||
var _ datastore.AgentRepository = &AgentRepository{}
|
||||
|
@ -40,7 +40,7 @@ func TestSQLiteAgentRepository(t *testing.T) {
|
||||
t.Fatalf("%+v", errors.WithStack(err))
|
||||
}
|
||||
|
||||
repo := NewAgentRepository(db)
|
||||
repo := NewAgentRepository(db, 5)
|
||||
|
||||
testsuite.TestAgentRepository(t, repo)
|
||||
}
|
||||
|
@ -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"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/pkg/errors"
|
||||
"gitlab.com/wpetit/goweb/api"
|
||||
"gitlab.com/wpetit/goweb/logger"
|
||||
@ -39,7 +39,8 @@ func (s *Server) registerAgent(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
keySet, err := jwk.Parse(registerAgentReq.KeySet)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "could not parse key set", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not parse key set", logger.CapturedE(err))
|
||||
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
|
||||
|
||||
return
|
||||
@ -51,14 +52,15 @@ func (s *Server) registerAgent(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
validSignature, err := jwk.Verify(keySet, registerAgentReq.Signature, registerAgentReq.Thumbprint, registerAgentReq.Metadata)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "could not validate signature", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not validate signature", logger.CapturedE(err))
|
||||
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if !validSignature {
|
||||
logger.Error(ctx, "conflicting signature", logger.F("signature", registerAgentReq.Signature))
|
||||
logger.Warn(ctx, "conflicting signature", logger.F("signature", registerAgentReq.Signature))
|
||||
api.ErrorResponse(w, http.StatusConflict, ErrCodeConflict, nil)
|
||||
|
||||
return
|
||||
@ -74,7 +76,8 @@ func (s *Server) registerAgent(w http.ResponseWriter, r *http.Request) {
|
||||
)
|
||||
if err != nil {
|
||||
if !errors.Is(err, datastore.ErrAlreadyExist) {
|
||||
logger.Error(ctx, "could not create agent", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not create agent", logger.CapturedE(err))
|
||||
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
|
||||
|
||||
return
|
||||
@ -86,15 +89,16 @@ func (s *Server) registerAgent(w http.ResponseWriter, r *http.Request) {
|
||||
datastore.WithAgentQueryLimit(1),
|
||||
)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "could not retrieve agents", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not retrieve agents", logger.CapturedE(err))
|
||||
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if len(agents) == 0 {
|
||||
logger.Error(ctx, "could not retrieve matching agent", logger.E(errors.WithStack(err)))
|
||||
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not retrieve matching agent", logger.CapturedE(err))
|
||||
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeNotFound, nil)
|
||||
|
||||
return
|
||||
@ -104,10 +108,12 @@ 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.E(errors.WithStack(err)), logger.F("agentID", agentID),
|
||||
logger.CapturedE(err), logger.F("agentID", agentID),
|
||||
)
|
||||
|
||||
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
|
||||
|
||||
return
|
||||
@ -115,7 +121,8 @@ 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 {
|
||||
logger.Error(ctx, "could not validate signature using previous keyset", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not validate signature using previous keyset", logger.CapturedE(err))
|
||||
|
||||
api.ErrorResponse(w, http.StatusConflict, ErrCodeConflict, nil)
|
||||
|
||||
@ -129,7 +136,9 @@ func (s *Server) registerAgent(w http.ResponseWriter, r *http.Request) {
|
||||
datastore.WithAgentUpdateThumbprint(registerAgentReq.Thumbprint),
|
||||
)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "could not update agent", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not update agent", logger.CapturedE(err))
|
||||
|
||||
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
|
||||
|
||||
return
|
||||
@ -177,7 +186,8 @@ func (s *Server) updateAgent(w http.ResponseWriter, r *http.Request) {
|
||||
options...,
|
||||
)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "could not update agent", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not update agent", logger.CapturedE(err))
|
||||
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
|
||||
|
||||
return
|
||||
@ -258,7 +268,8 @@ func (s *Server) queryAgents(w http.ResponseWriter, r *http.Request) {
|
||||
options...,
|
||||
)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "could not list agents", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not list agents", logger.CapturedE(err))
|
||||
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
|
||||
|
||||
return
|
||||
@ -292,7 +303,8 @@ func (s *Server) deleteAgent(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
logger.Error(ctx, "could not delete agent", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not delete agent", logger.CapturedE(err))
|
||||
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
|
||||
|
||||
return
|
||||
@ -324,7 +336,8 @@ func (s *Server) getAgent(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
logger.Error(ctx, "could not get agent", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not get agent", logger.CapturedE(err))
|
||||
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
|
||||
|
||||
return
|
||||
@ -342,7 +355,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.E(errors.WithStack(err)))
|
||||
logger.Error(r.Context(), "could not parse agent id", logger.CapturedE(errors.WithStack(err)))
|
||||
api.ErrorResponse(w, http.StatusBadRequest, api.ErrCodeMalformedRequest, nil)
|
||||
|
||||
return 0, false
|
||||
@ -356,7 +369,8 @@ func getIntQueryParam(w http.ResponseWriter, r *http.Request, param string, defa
|
||||
if rawValue != "" {
|
||||
value, err := strconv.ParseInt(rawValue, 10, 64)
|
||||
if err != nil {
|
||||
logger.Error(r.Context(), "could not parse int param", logger.F("param", param), logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(r.Context(), "could not parse int param", logger.F("param", param), logger.CapturedE(err))
|
||||
api.ErrorResponse(w, http.StatusBadRequest, api.ErrCodeMalformedRequest, nil)
|
||||
|
||||
return 0, false
|
||||
@ -389,7 +403,8 @@ 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 {
|
||||
logger.Error(r.Context(), "could not parse int slice param", logger.F("param", param), logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(r.Context(), "could not parse int slice param", logger.F("param", param), logger.CapturedE(err))
|
||||
api.ErrorResponse(w, http.StatusBadRequest, api.ErrCodeMalformedRequest, nil)
|
||||
|
||||
return nil, false
|
||||
|
@ -124,7 +124,8 @@ func assertRequestUser(w http.ResponseWriter, r *http.Request) (auth.User, bool)
|
||||
ctx := r.Context()
|
||||
user, err := auth.CtxUser(ctx)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "could not retrieve user", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not retrieve user", logger.CapturedE(err))
|
||||
|
||||
forbidden(w, r)
|
||||
|
||||
@ -147,7 +148,7 @@ func forbidden(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func logUnexpectedUserType(ctx context.Context, user auth.User) {
|
||||
logger.Error(
|
||||
logger.Warn(
|
||||
ctx, "unexpected user type",
|
||||
logger.F("subject", user.Subject()),
|
||||
logger.F("type", fmt.Sprintf("%T", user)),
|
||||
|
@ -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"
|
||||
"github.com/go-chi/chi/middleware"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/chi/v5/middleware"
|
||||
"github.com/go-chi/cors"
|
||||
"github.com/lestrrat-go/jwx/v2/jwa"
|
||||
"github.com/lestrrat-go/jwx/v2/jwt"
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/datastore"
|
||||
"forge.cadoles.com/Cadoles/emissary/internal/spec"
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/pkg/errors"
|
||||
"gitlab.com/wpetit/goweb/api"
|
||||
"gitlab.com/wpetit/goweb/logger"
|
||||
@ -44,7 +44,9 @@ func (s *Server) updateSpec(w http.ResponseWriter, r *http.Request) {
|
||||
data.Message = validationErr.Error()
|
||||
}
|
||||
|
||||
logger.Error(ctx, "could not validate spec", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not validate spec", logger.CapturedE(err))
|
||||
|
||||
api.ErrorResponse(w, http.StatusBadRequest, api.ErrCodeInvalidRequest, data)
|
||||
|
||||
return
|
||||
@ -70,7 +72,9 @@ func (s *Server) updateSpec(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
logger.Error(ctx, "could not update spec", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not update spec", logger.CapturedE(err))
|
||||
|
||||
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
|
||||
|
||||
return
|
||||
@ -99,7 +103,9 @@ func (s *Server) getAgentSpecs(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
logger.Error(ctx, "could not list specs", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not list specs", logger.CapturedE(err))
|
||||
|
||||
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
|
||||
|
||||
return
|
||||
@ -141,7 +147,9 @@ func (s *Server) deleteSpec(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
logger.Error(ctx, "could not delete spec", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not delete spec", logger.CapturedE(err))
|
||||
|
||||
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
|
||||
|
||||
return
|
||||
@ -159,7 +167,9 @@ func getSpecID(w http.ResponseWriter, r *http.Request) (datastore.SpecID, bool)
|
||||
|
||||
specID, err := strconv.ParseInt(rawSpecID, 10, 64)
|
||||
if err != nil {
|
||||
logger.Error(r.Context(), "could not parse spec id", logger.E(errors.WithStack(err)))
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(r.Context(), "could not parse spec id", logger.CapturedE(err))
|
||||
|
||||
api.ErrorResponse(w, http.StatusBadRequest, api.ErrCodeMalformedRequest, nil)
|
||||
|
||||
return 0, false
|
||||
|
@ -59,7 +59,7 @@ func NewAgentRepository(ctx context.Context, conf config.DatabaseConfig) (datast
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
agentRepository = sqlite.NewAgentRepository(db)
|
||||
agentRepository = sqlite.NewAgentRepository(db, 5)
|
||||
|
||||
default:
|
||||
return nil, errors.Errorf("unsupported database driver '%s'", driver)
|
||||
|
32
misc/docker/agent.yml
Normal file
32
misc/docker/agent.yml
Normal file
@ -0,0 +1,32 @@
|
||||
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
|
10
misc/docker/docker-agent-wrapper.sh
Normal file
10
misc/docker/docker-agent-wrapper.sh
Normal file
@ -0,0 +1,10 @@
|
||||
#!/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 $@
|
35
misc/docker/server.yml
Normal file
35
misc/docker/server.yml
Normal file
@ -0,0 +1,35 @@
|
||||
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) : ''}"
|
@ -4,7 +4,7 @@ ARG HTTP_PROXY=
|
||||
ARG HTTPS_PROXY=
|
||||
ARG http_proxy=
|
||||
ARG https_proxy=
|
||||
ARG GO_VERSION=1.20.2
|
||||
ARG GO_VERSION=1.21.1
|
||||
|
||||
# Install dev environment dependencies
|
||||
RUN export DEBIAN_FRONTEND=noninteractive &&\
|
||||
|
@ -1,26 +1,55 @@
|
||||
# Emissary agent configuration
|
||||
|
||||
# Logger configuration
|
||||
logger:
|
||||
# Logging verbosity
|
||||
# DEBUG: 0
|
||||
# INFO: 1
|
||||
# WARN: 2
|
||||
# ERROR: 3
|
||||
# CRITICAL: 4
|
||||
level: 1
|
||||
# Logging format
|
||||
# Possible values: human, json
|
||||
format: human
|
||||
|
||||
# Agent configuration
|
||||
agent:
|
||||
# Emissary server URL
|
||||
serverUrl: http://127.0.0.1:3000
|
||||
# Agent private key path
|
||||
privateKeyPath: /var/lib/emissary/agent-key.json
|
||||
reconciliationInterval: 5
|
||||
# Agent reconciliation interval (in seconds)
|
||||
reconciliationInterval: 30
|
||||
|
||||
# Controllers configuration
|
||||
controllers:
|
||||
# Persistence controller configuration
|
||||
persistence:
|
||||
enabled: true
|
||||
stateFile: /var/lib/emissary/state.json
|
||||
|
||||
# Spec controller configuration
|
||||
spec:
|
||||
enabled: true
|
||||
|
||||
# Proxy controller configuration
|
||||
proxy:
|
||||
enabled: true
|
||||
|
||||
# UCI controller configuration
|
||||
uci:
|
||||
enabled: true
|
||||
binPath: uci
|
||||
configBackupFile: /var/lib/emissary/uci-backup.conf
|
||||
|
||||
# App controller configuration
|
||||
app:
|
||||
enabled: true
|
||||
dataDir: /var/lib/emissary/apps/data
|
||||
downloadDir: /var/lib/emissary/apps/bundles
|
||||
|
||||
# Sysupgrade controller configuration
|
||||
sysupgrade:
|
||||
enabled: true
|
||||
sysupgradeCommand:
|
||||
@ -33,6 +62,8 @@ agent:
|
||||
- sh
|
||||
- -c
|
||||
- source /etc/openwrt_release && echo "$DISTRIB_ID-$DISTRIB_RELEASE-$DISTRIB_REVISION"
|
||||
|
||||
# Collectors configuration
|
||||
collectors:
|
||||
- name: uname
|
||||
command: uname
|
||||
|
@ -1,13 +1,38 @@
|
||||
# Emissary server configuration
|
||||
|
||||
# Logger configuration
|
||||
logger:
|
||||
# Logging verbosity
|
||||
# DEBUG: 0
|
||||
# INFO: 1
|
||||
# WARN: 2
|
||||
# ERROR: 3
|
||||
# CRITICAL: 4
|
||||
level: 1
|
||||
# Logging format
|
||||
# Possible values: human, json
|
||||
format: human
|
||||
|
||||
# Server configuration
|
||||
server:
|
||||
# HTTP server configuration
|
||||
http:
|
||||
# Listening address (0.0.0.0 to listen on all interfaces)
|
||||
host: 0.0.0.0
|
||||
# Listening port
|
||||
port: 3000
|
||||
|
||||
# Database configuration
|
||||
database:
|
||||
# Database driver
|
||||
# Possible values: sqlite
|
||||
driver: sqlite
|
||||
# Database DSN
|
||||
# sqlite: see https://github.com/mattn/go-sqlite3#connection-string
|
||||
dsn: sqlite:///var/lib/emissary/data.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=60000
|
||||
|
||||
# CORS configuration
|
||||
# See https://developer.mozilla.org/en/docs/Glossary/CORS
|
||||
cors:
|
||||
allowedOrigins: []
|
||||
allowCredentials: true
|
||||
@ -22,12 +47,25 @@ server:
|
||||
- Content-Type
|
||||
- Authorization
|
||||
- Sentry-Trace
|
||||
debug: false
|
||||
|
||||
# Auth configuration
|
||||
auth:
|
||||
# Local authentication configuration
|
||||
local:
|
||||
privateKeyPath: /var/lib/emissary/server-key.json
|
||||
roleExtractionRules:
|
||||
- "jwt.role != nil ? str(jwt.role) : ''"
|
||||
|
||||
# Remote authentication configuration
|
||||
# Disabled by default
|
||||
remote: ~
|
||||
# jwksUrl: https://my-server/.well-known/jwks.json
|
||||
|
||||
|
||||
# Role extraction rules
|
||||
# Permit to derivate user's role
|
||||
# from the received JWT.
|
||||
#
|
||||
# The first rule returning a non empty
|
||||
# string will define the role of the user.
|
||||
#
|
||||
# The role should be 'reader' or 'writer'.
|
||||
roleExtractionRules:
|
||||
- "jwt.role != nil ? str(jwt.role) : ''"
|
||||
|
9
misc/packaging/openrc/emissary-agent.logrotate.conf
Normal file
9
misc/packaging/openrc/emissary-agent.logrotate.conf
Normal file
@ -0,0 +1,9 @@
|
||||
/var/log/emissary/agent.log {
|
||||
missingok
|
||||
sharedscripts
|
||||
compress
|
||||
rotate 7
|
||||
postrotate
|
||||
/etc/init.d/emissary-agent restart
|
||||
endscript
|
||||
}
|
9
misc/packaging/openrc/emissary-server.logrotate.conf
Normal file
9
misc/packaging/openrc/emissary-server.logrotate.conf
Normal file
@ -0,0 +1,9 @@
|
||||
/var/log/emissary/server.log {
|
||||
missingok
|
||||
sharedscripts
|
||||
compress
|
||||
rotate 7
|
||||
postrotate
|
||||
/etc/init.d/emissary-server restart
|
||||
endscript
|
||||
}
|
@ -4,20 +4,40 @@
|
||||
"url": "https://emissary.cadol.es/files/apps/app.arcad.edge.hextris_v2023.4.20-2bbbe94.zip",
|
||||
"sha256sum": "67942ef4b623c46308c3f640b534bd4cb6b1d6021a422e40b62ab97658ba4586",
|
||||
"address": ":8083",
|
||||
"format": "zip"
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"edge.sdk.client.test": {
|
||||
"url": "https://emissary.cadol.es/files/apps/edge.sdk.client.test_v2023.4.20-20c4189.zip",
|
||||
"sha256sum": "1edeb4aa75c1675db49cf27367b1537234a04526848ea6657931ca63f26e5dae",
|
||||
"url": "https://emissary.cadol.es/files/apps/edge.sdk.client.test_2023.10.22-stable.847.22a3326.zip",
|
||||
"sha256sum": "37aa6c4af57b647dc5cae4ec7d36f4289d99c1f090e533997e0d59188a0a04f4",
|
||||
"address": ":8084",
|
||||
"format": "zip"
|
||||
"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"
|
||||
}
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"appUrlResolving": {
|
||||
"ifaceMappings": {
|
||||
"eth0": "http://{{ .DeviceIP }}:{{ .AppPort }}",
|
||||
"eth1": "http://{{ .DeviceIP }}:{{ .AppPort }}"
|
||||
"lo": "http://{{ .DeviceIP }}:{{ .AppPort }}"
|
||||
},
|
||||
"defaultUrlTemplate": "http://{{ last ( splitList \".\" ( toString .Manifest.ID ) ) }}.localhost.arcad.lan:8080"
|
||||
},
|
||||
@ -28,6 +48,7 @@
|
||||
"auth": {
|
||||
"local": {
|
||||
"key": "absolutlynotsecret",
|
||||
"signingAlgorithm": "HS256",
|
||||
"cookieDuration": "1h",
|
||||
"accounts": [
|
||||
{
|
||||
|
@ -14,6 +14,11 @@
|
||||
"type": "_http._tcp",
|
||||
"port": 8080,
|
||||
"host": "arcad-test"
|
||||
},
|
||||
"diffusion": {
|
||||
"type": "_http._tcp",
|
||||
"port": 8080,
|
||||
"host": "arcad-diffusion"
|
||||
}
|
||||
}
|
||||
}
|
@ -11,6 +11,10 @@
|
||||
"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"
|
||||
@ -19,6 +23,10 @@
|
||||
"hostPattern": "arcad-test.local:*",
|
||||
"target": "http://localhost:8084"
|
||||
},
|
||||
{
|
||||
"hostPattern": "arcad-diffusion.local:*",
|
||||
"target": "http://localhost:8085"
|
||||
},
|
||||
{
|
||||
"hostPattern": "*",
|
||||
"target": "http://localhost:8084"
|
||||
|
2067
misc/spec-samples/uci.emissary.cadoles.com.json
Normal file
2067
misc/spec-samples/uci.emissary.cadoles.com.json
Normal file
@ -0,0 +1,2067 @@
|
||||
{
|
||||
"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": []
|
||||
}
|
Reference in New Issue
Block a user