diff --git a/Makefile b/Makefile index 9fe6519..30a1164 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ -VERSION = $(shell < debian/changelog head -1 | egrep -o "[0-9]+\.[0-9]+\.[0-9]+") +export ROOT_DIR = $(shell git rev-parse --show-toplevel) +VERSION = $(shell head -1 < debian/changelog | egrep -o "[0-9]+\.[0-9]+\.[0-9]+") GITCOMMIT = $(shell git rev-parse --short HEAD 2> /dev/null || true) GENERATED = kel-agent kel-agent_*.pkg win/kel-agent_*.msi win/kel-agent.wixobj autorevision.cache \ @@ -39,14 +40,14 @@ deb-orig-tarball: autorevision.cache cd .. && tar -cvJf kel-agent_$(VERSION).orig.tar.xz --exclude-vcs --exclude=debian --exclude=.github --exclude=.idea kel-agent # TODO: This target can be removed once the package is in Debian stable and Ubuntu stable -../golang-github-k0swe-wsjtx-go-dev_4.0.1-1_all.deb: - wget https://github.com/k0swe/wsjtx-go/releases/download/v4.0.1/golang-github-k0swe-wsjtx-go-dev_4.0.1-1_all.deb \ - -O ../golang-github-k0swe-wsjtx-go-dev_4.0.1-1_all.deb +../golang-github-k0swe-wsjtx-go-dev_4.0.6-1_all.deb: + wget https://github.com/k0swe/wsjtx-go/releases/download/v4.0.1/golang-github-k0swe-wsjtx-go-dev_4.0.6-1_all.deb \ + -O ../golang-github-k0swe-wsjtx-go-dev_4.0.6-1_all.deb # TODO: This target can be removed once the package is in Debian stable and Ubuntu stable -../golang-github-mazznoer-csscolorparser-dev_0.1.2-1_all.deb: - wget https://github.com/k0swe/wsjtx-go/releases/download/v4.0.1/golang-github-mazznoer-csscolorparser-dev_0.1.2-1_all.deb \ - -O ../golang-github-mazznoer-csscolorparser-dev_0.1.2-1_all.deb +../golang-github-mazznoer-csscolorparser-dev_0.1.3-1_all.deb: + wget https://github.com/k0swe/wsjtx-go/releases/download/v4.0.1/golang-github-mazznoer-csscolorparser-dev_0.1.3-1_all.deb \ + -O ../golang-github-mazznoer-csscolorparser-dev_0.1.3-1_all.deb # TODO: This target can be removed once the package is in Debian stable and Ubuntu stable ../golang-github-adrg-xdg-dev_0.4.0-1_all.deb: @@ -54,12 +55,12 @@ deb-orig-tarball: autorevision.cache -O ../golang-github-adrg-xdg-dev_0.4.0-1_all.deb .PHONY: deb-package -deb-package: deb-tarball ../golang-github-k0swe-wsjtx-go-dev_4.0.1-1_all.deb ../golang-github-adrg-xdg-dev_0.4.0-1_all.deb ../golang-github-mazznoer-csscolorparser-dev_0.1.2-1_all.deb +deb-package: deb-tarball ../golang-github-k0swe-wsjtx-go-dev_4.0.6-1_all.deb ../golang-github-adrg-xdg-dev_0.4.0-1_all.deb ../golang-github-mazznoer-csscolorparser-dev_0.1.3-1_all.deb # https://wiki.debian.org/sbuild sbuild -d stable \ - --extra-package=../golang-github-k0swe-wsjtx-go-dev_4.0.1-1_all.deb \ + --extra-package=../golang-github-k0swe-wsjtx-go-dev_4.0.6-1_all.deb \ --extra-package=../golang-github-adrg-xdg-dev_0.4.0-1_all.deb \ - --extra-package=../golang-github-mazznoer-csscolorparser-dev_0.1.2-1_all.deb + --extra-package=../golang-github-mazznoer-csscolorparser-dev_0.1.3-1_all.deb .PHONY: flatpak flatpak: kel-agent diff --git a/README.md b/README.md index 05c25c4..5657baa 100644 --- a/README.md +++ b/README.md @@ -21,5 +21,5 @@ See the [Running documentation](RUNNING.md) for how to configure, execute and se ## Acknowledgements -The wire logo for `kel-agent` was created by [Freepik](https://www.flaticon.com/authors/freepik) -on [Flaticon](https://www.flaticon.com). +The wire logo for `kel-agent` was created by [Freepik](https://www.flaticon.com/authors/freepik) on +[Flaticon](https://www.flaticon.com). diff --git a/RUNNING.md b/RUNNING.md index dc1e7fe..c6d3b85 100644 --- a/RUNNING.md +++ b/RUNNING.md @@ -1,24 +1,45 @@ -# Running `kel-agent` +# Configuring and Running `kel-agent` -## Running on localhost +`kel-agent` configuration is primarily done with a YAML file; the default location is +platform-dependent but can be listed with `kel-agent -h`. Many options can also be set with +command-line arguments. -In the simplest case, `kel-agent` is running on the same computer as your radio programs and -browser. In this case, you can have `kel-agent` bind to `localhost` which will only allow programs -on the same computer to connect. This is straightforward, safe and the default. +## Websocket Server + +Default configuration: +```yaml +websocket: + address: localhost + port: 8081 + allowedOrigins: + - https://forester.radio ``` + +### Running on localhost + +In the simplest case, `kel-agent` is running on the same computer as your radio programs and +browser. In this case, you can have `kel-agent` bind to `address: localhost` which will only allow +programs on the same computer to connect. This is straightforward, safe and the default. + +```shell $ kel-agent -2020/10/10 18:50:32 kel-agent ready to serve at ws://localhost:8081 +7:19PM INF Serving websocket address=ws://localhost:8081/websocket ``` -To use a different port, add the `host` argument. +To use a different port, use `websocket.port` YAML config or the `host` program argument. +```yaml +websocket: + port: 9988 ``` -$ kel-agent -host localhost:9988 -2020/10/10 20:06:39 kel-agent ready to serve at ws://localhost:9988 + +```shell +$ kel-agent +7:19PM INF Serving websocket address=ws://localhost:9988/websocket ``` -## Running on another machine +### Running on another machine If you want to run your radio programs and `kel-agent` on one computer and your browser on another, this is possible. There are a couple of approaches. Neither is super easy, which I hope to fix. @@ -27,7 +48,7 @@ NOTE: I do _not_ recommend serving this in a way that's exposed to the internet _no_ authentication. If exposed to the internet, anyone could potentially initiate transmissions with your radio. -### SSH port forwarding +#### SSH port forwarding This method is relatively simple and quick to execute, but is more brittle than serving secure websockets because there is some setup each time you want to use the agent remotely, and @@ -36,15 +57,15 @@ conceptually a little harder. Your remote machine must be running an SSH server On the remote machine with your radio software, run `kel-agent` normally. It can be bound to `localhost`. -``` +```shell $ kel-agent -2020/10/10 18:50:32 kel-agent ready to serve at ws://localhost:8081 +7:19PM INF Serving websocket address=ws://localhost:8081/websocket ``` On the machine with your browser, start a command line and establish an SSH tunnel with port forwarding: -``` +```shell $ ssh -N -L localhost:8081:localhost:8081 radio-pi ``` @@ -59,14 +80,24 @@ Now your web application can be configured to connect to `localhost`. Traffic bo `localhost:8081` will get securely forwarded to the remote machine. Both the browser and `kel-agent` think they're talking to local processes, and you won't get mixed content warnings. -### Secure Websocket with TLS +#### Secure Websocket with TLS This method needs a little more set up ahead of time, but is easier to use once it's set up. First, you'll need `kel-agent` to bind to `0.0.0.0` to allow connections from other computers. Second, due to the mixed content policy which is standard in web browsers, you'll need to specify a -TLS certificate and private key. Eventually I hope to make this easy, but for now you'll need to -follow https://stackoverflow.com/a/60516812/587091. In short, +TLS certificate and private key for `kel-agent` to use. The easy way to do this is to use the +[Let's Encrypt](https://letsencrypt.org/) free public service to generate the private key and +certificate for you, signed by LE's certificate authority and recognized by almost all browsers. +Using LE usually assumes that there's a +[web server exposed to the internet](https://letsencrypt.org/docs/challenge-types/#http-01-challenge) +(again, I _don't_ recommend this with `kel-agent`). There's also a +[`dns-01` challenge](https://letsencrypt.org/docs/challenge-types/) if you have a domain name that +the remote computer can be addressed by, even if it's not accessible on the internet. + +If Let's Encrypt is not an option for you, you'll need to follow +https://stackoverflow.com/a/60516812/587091 to manually generate your private key and certificate. +In short, 1. generate a CA key and root certificate, then 2. a server key and certificate signing request with the server's hostname, @@ -75,15 +106,24 @@ follow https://stackoverflow.com/a/60516812/587091. In short, Yeah, I really need to make this easier. +```yaml +websocket: + address: 0.0.0.0 + port: 8081 + cert: /home/joe/.config/kel-agent/fullchain.pem + key: /home/joe/.config/kel-agent/privkey.pem ``` -$ kel-agent -host 0.0.0.0:8081 -key server.key -cert server.crt -2020/10/10 19:05:39 kel-agent ready to serve at wss://0.0.0.0:8081 + +```shell +$ kel-agent +7:19PM INF Serving websocket address=wss://radio-pi.myhome.net:8081/websocket ``` +Notice that the log message doesn't just say `ws://` but `wss://` which means "secure websocket." Once running this way, your web application can be configured to connect directly to the remote computer. -## Allowed origins +### Allowed origins As part of the same-origin policy which is standard in web browsers, `kel-agent` will only accept browser connections from certain origins (basically, websites). By default, only the website @@ -91,7 +131,35 @@ browser connections from certain origins (basically, websites). By default, only but this can be customized if others develop web applications that use `kel-agent`. I'm happy to accept pull requests to expand the default list! +```yaml +websocket: + allowedOrigins: + - https://forester.radio + - https://someother.nifty.app ``` -$ kel-agent -origins "https://forester.radio,https://someother.nifty.app" -2020/10/10 19:18:52 Allowed origins are [https://forester.radio https://someother.nifty.app] + +```shell +$ kel-agent +7:19PM INF allowed origins origins=["https://forester.radio","https://someother.nifty.app"] ``` + +## WSJT-X + +`kel-agent` can be used with WSJT-X to automate the process of logging contacts. WSJT-X will attempt +to connect to something listening on UDP port 2237 by default; `kel-agent` listens there and will +pass the contact information to the web application. + +```yaml +wsjtx: + enabled: true + address: 224.0.0.1 + port: 2237 +``` + +```shell +$ kel-agent +7:19PM INF Listening to WSJT-X on UDP address=224.0.0.1:2237 +``` + +Note that 224.0.0.1 is the multicast address that WSJT-X uses by default on Linux and Mac. On +Windows, `kel-agent` listens by default instead on 127.0.0.1. This matches WSJT-X's behavior. diff --git a/assets/config-schema.json b/assets/config-schema.json new file mode 100644 index 0000000..8a89e45 --- /dev/null +++ b/assets/config-schema.json @@ -0,0 +1,61 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://github.com/k0swe/kel-agent/internal/config/config", + "$ref": "#/$defs/Config", + "$defs": { + "Config": { + "properties": { + "websocket": { + "$ref": "#/$defs/WebsocketConfig" + }, + "wsjtx": { + "$ref": "#/$defs/WsjtxConfig" + } + }, + "additionalProperties": false, + "type": "object" + }, + "WebsocketConfig": { + "properties": { + "address": { + "type": "string" + }, + "port": { + "type": "integer" + }, + "key": { + "type": "string" + }, + "cert": { + "type": "string" + }, + "allowedOrigins": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "additionalProperties": false, + "type": "object" + }, + "WsjtxConfig": { + "properties": { + "enabled": { + "type": "boolean" + }, + "address": { + "type": "string" + }, + "port": { + "type": "integer" + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "enabled" + ] + } + } +} diff --git a/assets/modules.txt b/assets/modules.txt index bda92aa..44a4b30 100644 --- a/assets/modules.txt +++ b/assets/modules.txt @@ -1,42 +1,67 @@ +# dario.cat/mergo v1.0.0 +## explicit; go 1.13 +dario.cat/mergo # github.com/adrg/xdg v0.4.0 -## explicit +## explicit; go 1.14 github.com/adrg/xdg github.com/adrg/xdg/internal/pathutil -# github.com/davecgh/go-spew v1.1.0 -github.com/davecgh/go-spew/spew -# github.com/gorilla/websocket v1.5.0 +# github.com/bahlo/generic-list-go v0.2.0 +## explicit; go 1.18 +github.com/bahlo/generic-list-go +# github.com/buger/jsonparser v1.1.1 +## explicit; go 1.13 +github.com/buger/jsonparser +# github.com/davecgh/go-spew v1.1.1 ## explicit +github.com/davecgh/go-spew/spew +# github.com/gorilla/websocket v1.5.1 +## explicit; go 1.20 github.com/gorilla/websocket -# dario.cat/mergo v0.3.13 -## explicit -dario.cat/mergo -# github.com/k0swe/wsjtx-go/v4 v4.0.1 -## explicit +# github.com/invopop/jsonschema v0.12.0 +## explicit; go 1.18 +github.com/invopop/jsonschema +# github.com/k0swe/wsjtx-go/v4 v4.0.6 +## explicit; go 1.19 github.com/k0swe/wsjtx-go/v4 # github.com/leemcloughlin/jdn v0.0.0-20201102080031-6f88db6a6bf2 +## explicit github.com/leemcloughlin/jdn -# github.com/mattn/go-colorable v0.1.12 +# github.com/mailru/easyjson v0.7.7 +## explicit; go 1.12 +github.com/mailru/easyjson/buffer +github.com/mailru/easyjson/jwriter +# github.com/mattn/go-colorable v0.1.13 +## explicit; go 1.15 github.com/mattn/go-colorable -# github.com/mattn/go-isatty v0.0.14 +# github.com/mattn/go-isatty v0.0.20 +## explicit; go 1.15 github.com/mattn/go-isatty -# github.com/mazznoer/csscolorparser v0.1.2 +# github.com/mazznoer/csscolorparser v0.1.3 +## explicit; go 1.15 github.com/mazznoer/csscolorparser # github.com/pmezard/go-difflib v1.0.0 -github.com/pmezard/go-difflib/difflib -# github.com/rs/zerolog v1.27.0 ## explicit +github.com/pmezard/go-difflib/difflib +# github.com/rs/zerolog v1.32.0 +## explicit; go 1.15 github.com/rs/zerolog github.com/rs/zerolog/internal/cbor github.com/rs/zerolog/internal/json github.com/rs/zerolog/log -# github.com/stretchr/testify v1.7.2 -## explicit +# github.com/stretchr/testify v1.9.0 +## explicit; go 1.17 github.com/stretchr/testify/assert github.com/stretchr/testify/require github.com/stretchr/testify/suite -# golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d -## explicit -golang.org/x/sys/internal/unsafeheader +# github.com/wk8/go-ordered-map/v2 v2.1.8 +## explicit; go 1.18 +github.com/wk8/go-ordered-map/v2 +# golang.org/x/net v0.22.0 +## explicit; go 1.18 +golang.org/x/net/internal/socks +golang.org/x/net/proxy +# golang.org/x/sys v0.18.0 +## explicit; go 1.18 golang.org/x/sys/unix golang.org/x/sys/windows # gopkg.in/yaml.v3 v3.0.1 diff --git a/cmd/schema/main.go b/cmd/schema/main.go new file mode 100644 index 0000000..a6deebf --- /dev/null +++ b/cmd/schema/main.go @@ -0,0 +1,13 @@ +package main + +import ( + "fmt" + "github.com/invopop/jsonschema" + "github.com/k0swe/kel-agent/internal/config" +) + +func main() { + sch := jsonschema.Reflect(config.Config{}) + schema, _ := sch.MarshalJSON() + fmt.Println(string(schema)) +} diff --git a/flatpak/radio.k0swe.Kel_Agent.yml b/flatpak/radio.k0swe.Kel_Agent.yml index 29b9306..02d6a26 100644 --- a/flatpak/radio.k0swe.Kel_Agent.yml +++ b/flatpak/radio.k0swe.Kel_Agent.yml @@ -15,25 +15,25 @@ finish-args: modules: - name: kel-agent sources: + - type: git + url: https://dario.cat/mergo.git + tag: v1.0.0 + dest: vendor/dario.cat/mergo/ - type: git url: https://github.com/adrg/xdg.git tag: v0.4.0 dest: vendor/github.com/adrg/xdg/ - type: git url: https://github.com/davecgh/go-spew.git - tag: v1.1.0 + tag: v1.1.1 dest: vendor/github.com/davecgh/go-spew/ - type: git url: https://github.com/gorilla/websocket.git - tag: v1.5.0 + tag: v1.5.1 dest: vendor/github.com/gorilla/websocket/ - - type: git - url: https://dario.cat/mergo.git - tag: v0.3.13 - dest: vendor/dario.cat/mergo/ - type: git url: https://github.com/k0swe/wsjtx-go.git - tag: v4.0.1 + tag: v4.0.6 dest: vendor/github.com/k0swe/wsjtx-go/v4/ - type: git url: https://github.com/leemcloughlin/jdn.git @@ -41,15 +41,15 @@ modules: dest: vendor/github.com/leemcloughlin/jdn/ - type: git url: https://github.com/mattn/go-colorable.git - tag: v0.1.12 + tag: v0.1.13 dest: vendor/github.com/mattn/go-colorable/ - type: git url: https://github.com/mattn/go-isatty.git - tag: v0.0.14 + tag: v0.0.20 dest: vendor/github.com/mattn/go-isatty/ - type: git url: https://github.com/mazznoer/csscolorparser.git - tag: v0.1.2 + tag: v0.1.3 dest: vendor/github.com/mazznoer/csscolorparser/ - type: git url: https://github.com/pmezard/go-difflib.git @@ -57,15 +57,19 @@ modules: dest: vendor/github.com/pmezard/go-difflib/ - type: git url: https://github.com/rs/zerolog.git - tag: v1.27.0 + tag: v1.32.0 dest: vendor/github.com/rs/zerolog/ - type: git url: https://github.com/stretchr/testify.git - tag: v1.7.2 + tag: v1.9.0 dest: vendor/github.com/stretchr/testify/ + - type: git + url: https://github.com/golang/net.git + tag: v0.22.0 + dest: vendor/golang.org/x/net/ - type: git url: https://github.com/golang/sys.git - commit: 9f5ed59c137dcb0852024edd2e71af63c2d67707 + tag: v0.18.0 dest: vendor/golang.org/x/sys/ - type: git url: https://github.com/go-yaml/yaml.git diff --git a/go.mod b/go.mod index 1be267d..437c4ec 100644 --- a/go.mod +++ b/go.mod @@ -1,13 +1,14 @@ module github.com/k0swe/kel-agent -// This version needs to track golang in Debian stable backports (currently bullseye) -// https://packages.debian.org/bullseye-backports/golang -go 1.19 +// This version needs to track golang in Debian stable backports (currently bookworm) +// https://packages.debian.org/bookworm-backports/golang +go 1.21 require ( dario.cat/mergo v1.0.0 github.com/adrg/xdg v0.4.0 github.com/gorilla/websocket v1.5.1 + github.com/invopop/jsonschema v0.12.0 github.com/k0swe/wsjtx-go/v4 v4.0.6 github.com/rs/zerolog v1.32.0 github.com/stretchr/testify v1.9.0 @@ -15,12 +16,16 @@ require ( ) require ( + github.com/bahlo/generic-list-go v0.2.0 // indirect + github.com/buger/jsonparser v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/leemcloughlin/jdn v0.0.0-20201102080031-6f88db6a6bf2 // indirect + github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/mazznoer/csscolorparser v0.1.3 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/sys v0.13.0 // indirect + github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect + golang.org/x/net v0.22.0 // indirect + golang.org/x/sys v0.18.0 // indirect ) diff --git a/go.sum b/go.sum index 9296ee6..4421d43 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,10 @@ dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls= github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E= +github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= +github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= +github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -9,15 +13,21 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/invopop/jsonschema v0.12.0 h1:6ovsNSuvn9wEQVOyc72aycBMVQFKz7cPdMJn10CvzRI= +github.com/invopop/jsonschema v0.12.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/k0swe/wsjtx-go/v4 v4.0.6 h1:t7kj5tmuVVqVUwB4nfe+se3enWXGI/4BMhv6aR++Nbw= github.com/k0swe/wsjtx-go/v4 v4.0.6/go.mod h1:vtPvS4U7JyePPVC4jTSjnG2k+y587OPF6du1f0l9OCI= github.com/leemcloughlin/jdn v0.0.0-20201102080031-6f88db6a6bf2 h1:CdyD5OzAIzNFzpJ9WQRjJWj4pVRxZ9v15xdHnhvUPdw= github.com/leemcloughlin/jdn v0.0.0-20201102080031-6f88db6a6bf2/go.mod h1:LAowglanJPLb6WYSx3D1Ht/XE54OGIr0i4mz9kdbXrs= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mazznoer/csscolorparser v0.1.3 h1:vug4zh6loQxAUxfU1DZEu70gTPufDPspamZlHAkKcxE= github.com/mazznoer/csscolorparser v0.1.3/go.mod h1:Aj22+L/rYN/Y6bj3bYqO3N6g1dtdHtGfQ32xZ5PJQic= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -30,14 +40,16 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= +github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= +golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= +golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/config/parse.go b/internal/config/parse.go index 8018385..2c55246 100644 --- a/internal/config/parse.go +++ b/internal/config/parse.go @@ -9,8 +9,8 @@ import ( "gopkg.in/yaml.v3" - "github.com/adrg/xdg" "dario.cat/mergo" + "github.com/adrg/xdg" "github.com/rs/zerolog" "github.com/rs/zerolog/log" ) @@ -28,13 +28,13 @@ func init() { defaultConfigFile = &c } -func ParseAllConfigs() (Config, error) { +func ParseAllConfigs(schemaUrl string) (Config, error) { // Flags take precedence, and need to be parsed first for logging level conf, err := parseFlags() if err != nil { return Config{}, err } - file, err := parseConfigFile() + file, err := parseConfigFile(schemaUrl) if err != nil { return Config{}, err } @@ -44,7 +44,8 @@ func ParseAllConfigs() (Config, error) { if err := mergo.Merge(&conf, defaultConf); err != nil { return Config{}, err } - log.Debug().Msgf("effective configuration is %v", conf) + log.Debug().Object("config", conf).Msgf("coalesced configuration") + log.Info().Strs("origins", conf.Websocket.AllowedOrigins).Msg("allowed origins") return conf, nil } @@ -90,11 +91,11 @@ func parseFlags() (Config, error) { conf.Websocket.Address = conf.Websocket.Address[:i] } - log.Trace().Msgf("flag config: %v", conf) + log.Trace().Object("flags", conf).Msgf("flag config") return conf, nil } -func parseConfigFile() (Config, error) { +func parseConfigFile(schemaUrl string) (Config, error) { var conf Config dat, err := os.ReadFile(*configFile) if os.IsNotExist(err) { @@ -102,6 +103,8 @@ func parseConfigFile() (Config, error) { if dat, err = yaml.Marshal(defaultConf); err != nil { return Config{}, err } + // add schema to top of file + dat = append([]byte("# yaml-language-server: $schema="+schemaUrl+"\n"), dat...) if err := os.WriteFile(*configFile, dat, 0o755); err != nil { return Config{}, err } @@ -114,7 +117,7 @@ func parseConfigFile() (Config, error) { if err := yaml.Unmarshal(dat, &conf); err != nil { return Config{}, err } - log.Debug().Msgf("using config file at '%s'", *configFile) - log.Trace().Msgf("file config: %v", conf) + log.Debug().Str("path", *configFile).Msg("using config file") + log.Trace().Object("file", conf).Msg("file config") return conf, nil } diff --git a/internal/config/types.go b/internal/config/types.go index dfd2dae..e029c31 100644 --- a/internal/config/types.go +++ b/internal/config/types.go @@ -1,9 +1,19 @@ package config +import ( + "encoding/json" + "github.com/rs/zerolog" +) + type Config struct { Websocket WebsocketConfig `json:"websocket,omitempty" yaml:"websocket,omitempty"` Wsjtx WsjtxConfig `json:"wsjtx,omitempty" yaml:"wsjtx,omitempty"` - VersionInfo string `json:"-"` + VersionInfo string `json:"-" yaml:"-"` +} + +func (c Config) MarshalZerologObject(e *zerolog.Event) { + j, _ := json.Marshal(c) + e.RawJSON("config", j) } type WebsocketConfig struct { @@ -21,7 +31,7 @@ type WebsocketConfig struct { type WsjtxConfig struct { // Enabled is whether to listen to WSJT-X - Enabled bool `json:"enabled" yaml:"enabled,omitempty"` + Enabled bool `json:"enabled" yaml:"enabled"` // Address is the IP or hostname on which to listen to WSJT-X Address string `json:"address,omitempty" yaml:"address,omitempty"` // Port is the UDP port on which to listen to WSJT-X diff --git a/internal/ws/hub.go b/internal/ws/hub.go index 7dced0e..ddd068a 100644 --- a/internal/ws/hub.go +++ b/internal/ws/hub.go @@ -91,8 +91,8 @@ func (h *Hub) run() { } func (h *Hub) broadcast(message WebsocketMessage) { - log.Trace().Msgf("broadcasting: %v", message) jsn, _ := json.Marshal(message) + log.Trace().Msgf("broadcasting: %v", string(jsn)) for client := range h.clients { select { case client.send <- jsn: @@ -105,6 +105,7 @@ func (h *Hub) broadcast(message WebsocketMessage) { func (h *Hub) handleClientCommand(command []byte) { var msg = &WebsocketMessage{} + log.Trace().Msgf("received client command: %v", string(command)) if err := json.Unmarshal(command, msg); err != nil { log.Warn().Err(err).Msg("failed to parse client command; dropping") return diff --git a/main.go b/main.go index 3310c5c..be89c26 100644 --- a/main.go +++ b/main.go @@ -12,6 +12,7 @@ import ( ) var versionInfo string +var schemaUrl = "https://raw.githubusercontent.com/k0swe/kel-agent/" + GitCommit + "/assets/config-schema.json" func main() { versionInfo = fmt.Sprintf("kel-agent %v (%v)", Version, GitCommit) @@ -19,7 +20,7 @@ func main() { versionInfo, runtime.Version(), runtime.GOOS, runtime.GOARCH, BuildTime) log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}) - c, err := config.ParseAllConfigs() + c, err := config.ParseAllConfigs(schemaUrl) if err != nil { log.Fatal().Err(err).Msg("couldn't get configuration") } diff --git a/scripts/build.sh b/scripts/build.sh index 2eca4e5..ebbc982 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -1,16 +1,18 @@ #!/usr/bin/env bash set -eu +echo "$ROOT_DIR" +cd "$ROOT_DIR" || exit 1 VERSION=${VERSION:-v$(< debian/changelog head -1 | egrep -o "[0-9]+\.[0-9]+\.[0-9]+")} BUILDTIME=${BUILDTIME:-$(date -u +"%Y-%m-%dT%H:%M:%SZ")} -export LDFLAGS="\ +LDFLAGS=$(echo "\ -w \ -X \"main.Version=${VERSION}\" \ -X \"main.GitCommit=${GITCOMMIT}\" \ -X \"main.BuildTime=${BUILDTIME}\" \ ${LDFLAGS:-} \ -" +" | xargs echo) mod="" if [ -d vendor ]; then @@ -18,4 +20,6 @@ if [ -d vendor ]; then fi # shellcheck disable=SC2086 +set -x go build $mod --ldflags "$LDFLAGS" +{ set +x; } 2>/dev/null