From c5fd63e099cec30154e2a9c0b5ee7715491263bf Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Wed, 21 Jun 2023 10:56:41 +0000 Subject: DTail: Restrict SSH MAC algorithms allowed - Update of few dependencies --- Makefile | 2 +- doc/installation.md | 18 +- examples/check_dserver.sh.example | 3 + examples/dserver-update-keycache.service.example | 6 + examples/dserver-update-keycache.timer.example | 5 + examples/dserver.service.example | 19 + examples/dtail.json.example | 127 ++++++ examples/dtail.schema.json | 532 +++++++++++++++++++++++ examples/update_key_cache.sh.example | 33 ++ go.mod | 6 +- go.sum | 12 +- internal/clients/stats.go | 2 +- internal/config/server.go | 6 + internal/server/server.go | 16 +- internal/version/version.go | 2 +- samples/check_dserver.sh.sample | 3 - samples/dserver-update-keycache.service.sample | 6 - samples/dserver-update-keycache.timer.sample | 5 - samples/dserver.service.sample | 19 - samples/dtail.json.sample | 127 ------ samples/dtail.schema.json | 514 ---------------------- samples/update_key_cache.sh.sample | 33 -- 22 files changed, 763 insertions(+), 733 deletions(-) create mode 100755 examples/check_dserver.sh.example create mode 100644 examples/dserver-update-keycache.service.example create mode 100644 examples/dserver-update-keycache.timer.example create mode 100644 examples/dserver.service.example create mode 100644 examples/dtail.json.example create mode 100755 examples/dtail.schema.json create mode 100644 examples/update_key_cache.sh.example delete mode 100755 samples/check_dserver.sh.sample delete mode 100644 samples/dserver-update-keycache.service.sample delete mode 100644 samples/dserver-update-keycache.timer.sample delete mode 100644 samples/dserver.service.sample delete mode 100644 samples/dtail.json.sample delete mode 100755 samples/dtail.schema.json delete mode 100644 samples/update_key_cache.sh.sample diff --git a/Makefile b/Makefile index 680cef6..d764051 100644 --- a/Makefile +++ b/Makefile @@ -33,7 +33,7 @@ clean: test -f $$cmd && rm $$cmd; \ done vet: - find . -type d | egrep -v '(./samples|./log|./doc)' | while read dir; do \ + find . -type d | egrep -v '(./examples|./log|./doc)' | while read dir; do \ echo ${GO} vet $$dir; \ ${GO} vet $$dir; \ done diff --git a/doc/installation.md b/doc/installation.md index 0f6143b..a2c271a 100644 --- a/doc/installation.md +++ b/doc/installation.md @@ -53,18 +53,18 @@ uid=1001(dserver) 1001=670(dserver) groups=1001(dserver) % sudo chown -R dserver:dserver /var/run/dserver ``` -4. Install the ``dtail.json`` config to ``/etc/dserver/dtail.json``. An example can be found [here](../samples/dtail.json.sample). +4. Install the ``dtail.json`` config to ``/etc/dserver/dtail.json``. An example can be found [here](../examples/dtail.json.example). ```console % sudo mkdir /etc/dserver -% curl https://raw.githubusercontent.com/mimecast/dtail/master/samples/dtail.json.sample | +% curl https://raw.githubusercontent.com/mimecast/dtail/master/examples/dtail.json.example | sudo tee /etc/dserver/dtail.json ``` -5. It is recommended to configure DTail server as a service to ``systemd``. An example unit file for ``systemd`` can be found [here](../samples/dserver.service.sample). +5. It is recommended to configure DTail server as a service to ``systemd``. An example unit file for ``systemd`` can be found [here](../examples/dserver.service.example). ```console -% curl https://raw.githubusercontent.com/mimecast/dtail/master/samples/dserver.service.sample | +% curl https://raw.githubusercontent.com/mimecast/dtail/master/examples/dserver.service.example | sudo tee /etc/systemd/system/dserver.service % sudo systemctl daemon-reload % sudo systemctl enable dserver @@ -97,15 +97,15 @@ To start the DTail server via ``systemd`` run: The DTail server now runs as a ``systemd`` service under system user ``dserver``. However, the system user ``dserver`` has no permissions to read the SSH public keys from ``/home/USER/.ssh/authorized_keys``. Therefore, no user would be able to establish an SSH session to DTail server. As an alternative path DTail server also checks for public SSH key files in ``/var/run/dserver/cache/USER.authorized_keys``. -It is recommended to execute [update_key_cache.sh](../samples/update_key_cache.sh.sample) periodically to update the key cache. In case you manage your public SSH keys via Puppet you could subscribe the script to corresponding module. Or alternatively just configure a cron job or a systemd timer to run every once in a while, e.g. every 30 minutes: +It is recommended to execute [update_key_cache.sh](../examples/update_key_cache.sh.example) periodically to update the key cache. In case you manage your public SSH keys via Puppet you could subscribe the script to corresponding module. Or alternatively just configure a cron job or a systemd timer to run every once in a while, e.g. every 30 minutes: ```console -% curl https://raw.githubusercontent.com/mimecast/dtail/master/samples/update_key_cache.sh.sample | +% curl https://raw.githubusercontent.com/mimecast/dtail/master/examples/update_key_cache.sh.example | sudo tee /var/run/dserver/update_key_cache.sh % sudo chmod 755 /var/run/dserver/update_key_cache.sh -% curl https://raw.githubusercontent.com/mimecast/dtail/master/samples/dserver-update-keycache.service.sample | +% curl https://raw.githubusercontent.com/mimecast/dtail/master/examples/dserver-update-keycache.service.example | sudo tee /etc/systemd/system/dserver-update-keycache.service -% curl https://raw.githubusercontent.com/mimecast/dtail/master/samples/dserver-update-keycache.timer.sample | +% curl https://raw.githubusercontent.com/mimecast/dtail/master/examples/dserver-update-keycache.timer.example | sudo tee /etc/systemd/system/dserver-update-keycache.timer % sudo systemctl daemon-reload % sudo systemctl start dserver-update-keycache.service @@ -119,7 +119,7 @@ Now you should be able to use DTail client like outlined in the [Quick Starting # Monitor it -To verify that DTail server is up and running and functioning as expected, you should configure the Nagios check [check_dserver.sh](../samples/check_dserver.sh.sample) in your monitoring system. The check has to be executed locally on the server (e.g. via NRPE). How to configure the monitoring system in detail is out of scope of this guide. +To verify that DTail server is up and running and functioning as expected, you should configure the Nagios check [check_dserver.sh](../examples/check_dserver.sh.example) in your monitoring system. The check has to be executed locally on the server (e.g. via NRPE). How to configure the monitoring system in detail is out of scope of this guide. ```console % ./check_dserver.sh diff --git a/examples/check_dserver.sh.example b/examples/check_dserver.sh.example new file mode 100755 index 0000000..77f01f0 --- /dev/null +++ b/examples/check_dserver.sh.example @@ -0,0 +1,3 @@ +#!/bin/sh + +exec /usr/local/bin/dtailhealth --server localhost:2222 diff --git a/examples/dserver-update-keycache.service.example b/examples/dserver-update-keycache.service.example new file mode 100644 index 0000000..7e6144c --- /dev/null +++ b/examples/dserver-update-keycache.service.example @@ -0,0 +1,6 @@ +[Unit] +Description=Refresh DServer SSH Key Cache + +[Service] +Type=oneshot +ExecStart=/var/run/dserver/update_key_cache.sh diff --git a/examples/dserver-update-keycache.timer.example b/examples/dserver-update-keycache.timer.example new file mode 100644 index 0000000..e7158ca --- /dev/null +++ b/examples/dserver-update-keycache.timer.example @@ -0,0 +1,5 @@ +[Unit] +Description=Refresh DServer SSH Key Cache every 30 minutes. + +[Timer] +OnCalendar=*:0/30 diff --git a/examples/dserver.service.example b/examples/dserver.service.example new file mode 100644 index 0000000..c5e5e59 --- /dev/null +++ b/examples/dserver.service.example @@ -0,0 +1,19 @@ +[Unit] +Description=DTail server +After=network.target + +[Service] +Slice=dserver.slice +User=dserver +Group=dserver +ExecStart=/usr/local/bin/dserver -cfg /etc/dserver/dtail.json +WorkingDirectory=/var/run/dserver +NoNewPrivileges=true +PrivateDevices=true +PrivateTmp=true +CPUAccounting=true +MemoryAccounting=true +BlockIOAccounting=true + +[Install] +WantedBy=multi-user.target diff --git a/examples/dtail.json.example b/examples/dtail.json.example new file mode 100644 index 0000000..26eb8a1 --- /dev/null +++ b/examples/dtail.json.example @@ -0,0 +1,127 @@ +{ + "Client": { + "TermColorsEnable": true, + "TermColors": { + "Remote": { + "DelimiterAttr": "Dim", + "DelimiterBg": "Blue", + "DelimiterFg": "Cyan", + "RemoteAttr": "Dim", + "RemoteBg": "Blue", + "RemoteFg": "White", + "CountAttr": "Dim", + "CountBg": "Blue", + "CountFg": "White", + "HostnameAttr": "Bold", + "HostnameBg": "Blue", + "HostnameFg": "White", + "IDAttr": "Dim", + "IDBg": "Blue", + "IDFg": "White", + "StatsOkAttr": "None", + "StatsOkBg": "Green", + "StatsOkFg": "Black", + "StatsWarnAttr": "None", + "StatsWarnBg": "Red", + "StatsWarnFg": "White", + "TextAttr": "None", + "TextBg": "Black", + "TextFg": "White" + }, + "Client": { + "DelimiterAttr": "Dim", + "DelimiterBg": "Yellow", + "DelimiterFg": "Black", + "ClientAttr": "Dim", + "ClientBg": "Yellow", + "ClientFg": "Black", + "HostnameAttr": "Dim", + "HostnameBg": "Yellow", + "HostnameFg": "Black", + "TextAttr": "None", + "TextBg": "Black", + "TextFg": "White" + }, + "Server": { + "DelimiterAttr": "AttrDim", + "DelimiterBg": "BgCyan", + "DelimiterFg": "FgBlack", + "ServerAttr": "AttrDim", + "ServerBg": "BgCyan", + "ServerFg": "FgBlack", + "HostnameAttr": "AttrBold", + "HostnameBg": "BgCyan", + "HostnameFg": "FgBlack", + "TextAttr": "AttrNone", + "TextBg": "BgBlack", + "TextFg": "FgWhite" + }, + "Common": { + "SeverityErrorAttr": "AttrBold", + "SeverityErrorBg": "BgRed", + "SeverityErrorFg": "FgWhite", + "SeverityFatalAttr": "AttrBold", + "SeverityFatalBg": "BgMagenta", + "SeverityFatalFg": "FgWhite", + "SeverityWarnAttr": "AttrBold", + "SeverityWarnBg": "BgBlack", + "SeverityWarnFg": "FgWhite" + }, + "MaprTable": { + "DataAttr": "AttrNone", + "DataBg": "BgBlue", + "DataFg": "FgWhite", + "DelimiterAttr": "AttrDim", + "DelimiterBg": "BgBlue", + "DelimiterFg": "FgWhite", + "HeaderAttr": "AttrBold", + "HeaderBg": "BgBlue", + "HeaderFg": "FgWhite", + "HeaderDelimiterAttr": "AttrDim", + "HeaderDelimiterBg": "BgBlue", + "HeaderDelimiterFg": "FgWhite", + "HeaderSortKeyAttr": "AttrUnderline", + "HeaderGroupKeyAttr": "AttrReverse", + "RawQueryAttr": "AttrDim", + "RawQueryBg": "BgBlack", + "RawQueryFg": "FgCyan" + } + } + }, + "Server": { + "SSHBindAddress": "0.0.0.0", + "HostKeyFile": "cache/ssh_host_key", + "HostKeyBits": 2048, + "MapreduceLogFormat": "default", + "MaxConcurrentCats": 2, + "MaxConcurrentTails": 50, + "MaxConnections": 50, + "MaxLineLength": 1048576, + "Permissions": { + "Default": [ + "readfiles:^/.*$" + ], + "Users": { + "paul": [ + "readfiles:^/.*$" + ], + "pbuetow": [ + "readfiles:^/.*$" + ], + "jamesblake": [ + "readfiles:^/tmp/foo.log$", + "readfiles:^/.*$", + "readfiles:!^/tmp/bar.log$" + ] + } + } + }, + "Common": { + "LogDir": "log", + "Logger": "Fout", + "LogRotation": "Daily", + "CacheDir": "cache", + "SSHPort": 2222, + "LogLevel": "Info" + } +} diff --git a/examples/dtail.schema.json b/examples/dtail.schema.json new file mode 100755 index 0000000..d13b133 --- /dev/null +++ b/examples/dtail.schema.json @@ -0,0 +1,532 @@ +{ + "$schema": "https://json-schema.org/2019-09/schema", + "description": "Schema for dtail.json", + "definitions": { + "userPermission": { + "type": "array", + "items": { + "type": "string" + } + }, + "userPermissions": { + "type": "object", + "patternProperties": { + "^.*$": { + "$ref": "#/definitions/userPermission" + } + } + }, + "loglevel": { + "type": "string", + "enum": [ + "None", + "Fatal", + "Error", + "Warn", + "Info", + "Default", + "Verbose", + "Debug", + "Devel", + "Trace", + "All" + ] + }, + "logger": { + "type": "string", + "enum": [ + "None", + "Stdout", + "File", + "Fout" + ] + }, + "logrotation": { + "type": "string", + "enum": [ + "Daily", + "Signal" + ] + }, + "color": { + "type": "string", + "enum": [ + "Black", + "Red", + "Green", + "Yellow", + "Blue", + "Magenta", + "Cyan", + "White" + ] + }, + "attribute": { + "type": "string", + "enum": [ + "None", + "Bold", + "Dim", + "Italic", + "Underline", + "Blink", + "SlowBlink", + "RapidBlink", + "Reverse", + "Hidden" + ] + } + }, + "type": "object", + "additionalProperties": false, + "properties": { + "Client": { + "additionalProperties": false, + "properties": { + "TermColorsEnable": { + "type": "boolean" + }, + "TermColors": { + "type": "object", + "additionalProperties": false, + "properties": { + "Remote": { + "additionalProperties": false, + "properties": { + "DelimiterAttr": { + "$ref": "#/definitions/attribute" + }, + "DelimiterBg": { + "$ref": "#/definitions/color" + }, + "DelimiterFg": { + "$ref": "#/definitions/color" + }, + "RemoteAttr": { + "$ref": "#/definitions/attribute" + }, + "RemoteBg": { + "$ref": "#/definitions/color" + }, + "RemoteFg": { + "$ref": "#/definitions/color" + }, + "CountAttr": { + "$ref": "#/definitions/attribute" + }, + "CountBg": { + "$ref": "#/definitions/color" + }, + "CountFg": { + "$ref": "#/definitions/color" + }, + "HostnameAttr": { + "$ref": "#/definitions/attribute" + }, + "HostnameBg": { + "$ref": "#/definitions/color" + }, + "HostnameFg": { + "$ref": "#/definitions/color" + }, + "IDAttr": { + "$ref": "#/definitions/attribute" + }, + "IDBg": { + "$ref": "#/definitions/color" + }, + "IDFg": { + "$ref": "#/definitions/color" + }, + "StatsOkAttr": { + "$ref": "#/definitions/attribute" + }, + "StatsOkBg": { + "$ref": "#/definitions/color" + }, + "StatsOkFg": { + "$ref": "#/definitions/color" + }, + "StatsWarnAttr": { + "$ref": "#/definitions/attribute" + }, + "StatsWarnBg": { + "$ref": "#/definitions/color" + }, + "StatsWarnFg": { + "$ref": "#/definitions/color" + }, + "TextAttr": { + "$ref": "#/definitions/attribute" + }, + "TextBg": { + "$ref": "#/definitions/color" + }, + "TextFg": { + "$ref": "#/definitions/color" + } + } + }, + "Client": { + "additionalProperties": false, + "properties": { + "DelimiterAttr": { + "$ref": "#/definitions/attribute" + }, + "DelimiterBg": { + "$ref": "#/definitions/color" + }, + "DelimiterFg": { + "$ref": "#/definitions/color" + }, + "ClientAttr": { + "$ref": "#/definitions/attribute" + }, + "ClientBg": { + "$ref": "#/definitions/color" + }, + "ClientFg": { + "$ref": "#/definitions/color" + }, + "HostnameAttr": { + "$ref": "#/definitions/attribute" + }, + "HostnameBg": { + "$ref": "#/definitions/color" + }, + "HostnameFg": { + "$ref": "#/definitions/color" + }, + "TextAttr": { + "$ref": "#/definitions/attribute" + }, + "TextBg": { + "$ref": "#/definitions/color" + }, + "TextFg": { + "$ref": "#/definitions/color" + } + } + }, + "Server": { + "additionalProperties": false, + "properties": { + "DelimiterAttr": { + "#ref": "#/definitions/attribute" + }, + "DelimiterBg": { + "#ref": "#/definitions/color" + }, + "DelimiterFg": { + "#ref": "#/definitions/color" + }, + "ServerAttr": { + "#ref": "#/definitions/attribute" + }, + "ServerBg": { + "#ref": "#/definitions/color" + }, + "ServerFg": { + "#ref": "#/definitions/color" + }, + "HostnameAttr": { + "#ref": "#/definitions/attribute" + }, + "HostnameBg": { + "#ref": "#/definitions/color" + }, + "HostnameFg": { + "#ref": "#/definitions/color" + }, + "TextAttr": { + "#ref": "#/definitions/attribute" + }, + "TextBg": { + "#ref": "#/definitions/color" + }, + "TextFg": { + "#ref": "#/definitions/color" + } + } + }, + "Common": { + "additionalProperties": false, + "properties": { + "SeverityErrorAttr": { + "#ref": "#/definitions/attribute" + }, + "SeverityErrorBg": { + "#ref": "#/definitions/color" + }, + "SeverityErrorFg": { + "#ref": "#/definitions/color" + }, + "SeverityFatalAttr": { + "#ref": "#/definitions/attribute" + }, + "SeverityFatalBg": { + "#ref": "#/definitions/color" + }, + "SeverityFatalFg": { + "#ref": "#/definitions/color" + }, + "SeverityWarnAttr": { + "#ref": "#/definitions/attribute" + }, + "SeverityWarnBg": { + "#ref": "#/definitions/color" + }, + "SeverityWarnFg": { + "#ref": "#/definitions/color" + } + } + }, + "MaprTable": { + "additionalProperties": false, + "properties": { + "DataAttr": { + "#ref": "#/definitions/attribute" + }, + "DataBg": { + "#ref": "#/definitions/color" + }, + "DataFg": { + "#ref": "#/definitions/color" + }, + "DelimiterAttr": { + "#ref": "#/definitions/attribute" + }, + "DelimiterBg": { + "#ref": "#/definitions/color" + }, + "DelimiterFg": { + "#ref": "#/definitions/color" + }, + "HeaderAttr": { + "#ref": "#/definitions/attribute" + }, + "HeaderBg": { + "#ref": "#/definitions/color" + }, + "HeaderFg": { + "#ref": "#/definitions/color" + }, + "HeaderDelimiterAttr": { + "#ref": "#/definitions/attribute" + }, + "HeaderDelimiterBg": { + "#ref": "#/definitions/color" + }, + "HeaderDelimiterFg": { + "#ref": "#/definitions/color" + }, + "HeaderSortKeyAttr": { + "#ref": "#/definitions/attribute" + }, + "HeaderGroupKeyAttr": { + "#ref": "#/definitions/attribute" + }, + "RawQueryAttr": { + "#ref": "#/definitions/attribute" + }, + "RawQueryBg": { + "#ref": "#/definitions/color" + }, + "RawQueryFg": { + "#ref": "#/definitions/color" + } + } + } + } + } + } + }, + "Server": { + "additionalProperties": false, + "properties": { + "SSHBindAddress": { + "type": "string" + }, + "KeyExchanges": { + "type": "array", + "items": { + "type": "string" + } + }, + "Ciphers": { + "type": "array", + "items": { + "type": "string" + } + }, + "MACs": { + "type": "array", + "items": { + "type": "string" + } + }, + "HostKeyFile": { + "type": "string" + }, + "HostKeyBits": { + "type": "integer", + "minimum": 2048 + }, + "MapreduceLogFormat": { + "type": "string" + }, + "MaxConcurrentCats": { + "type": "integer", + "minimum": 1, + "maximum": 20 + }, + "MaxConcurrentTails": { + "type": "integer", + "minimum": 1, + "maximum": 200 + }, + "MaxConnections": { + "type": "integer", + "minimum": 1, + "maximum": 200 + }, + "MaxLineLength": { + "type": "integer", + "minimum": 1024, + "maximum": 10240000 + }, + "Permissions": { + "type": "object", + "additionalProperties": true, + "patternProperties": { + "^Default$": { + "$ref": "#/definitions/userPermission" + }, + "^Users$": { + "$ref": "#/definitions/userPermissions" + } + } + }, + "Schedule": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "Name": { + "type": "string" + }, + "Enable": { + "type": "boolean" + }, + "AllowFrom": { + "type": "array", + "items": { + "type": "string" + } + }, + "Servers": { + "type": "array", + "items": { + "type": "string" + } + }, + "TimeRange": { + "type": "array", + "items": [ + { + "type": "integer" + }, + { + "type": "integer" + } + ] + }, + "Files": { + "type": "string" + }, + "Outfile": { + "type": "string" + }, + "Query": { + "type": "string" + } + } + } + }, + "Continuous": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "Name": { + "type": "string" + }, + "Enable": { + "type": "boolean" + }, + "AllowFrom": { + "type": "array", + "items": { + "type": "string" + } + }, + "Servers": { + "type": "array", + "items": { + "type": "string" + } + }, + "RestartOnDayChange": { + "type": "boolean" + }, + "Files": { + "type": "string" + }, + "Outfile": { + "type": "string" + }, + "Query": { + "type": "string" + } + } + } + } + } + }, + "Common": { + "additionalProperties": false, + "properties": { + "LogDir": { + "type": "string" + }, + "Logger": { + "#ref": "#/definitions/logger" + }, + "LogLevel": { + "#ref": "#/definitions/loglevel" + }, + "LogRotation": { + "#ref": "#/definitions/logrotation" + }, + "CacheDir": { + "type": "string" + }, + "SSHPort": { + "type": "integer", + "minimum": 2, + "maximum": 16000 + }, + "ExperimentalFeaturesEnable": { + "type": "boolean" + } + } + } + }, + "required": [ + "Client", + "Server", + "Common" + ] +} diff --git a/examples/update_key_cache.sh.example b/examples/update_key_cache.sh.example new file mode 100644 index 0000000..9817f04 --- /dev/null +++ b/examples/update_key_cache.sh.example @@ -0,0 +1,33 @@ +#!/bin/bash + +declare -r CACHEDIR=/var/run/dserver/cache +declare -r DSERVER_USER=dserver + +echo "Updating SSH key cache" + +ls /home/ | while read remoteuser; do + keysfile=/home/$remoteuser/.ssh/authorized_keys + + if [ -f $keysfile ]; then + cachefile=$CACHEDIR/$remoteuser.authorized_keys + echo "Caching $keysfile -> $cachefile" + + cp $keysfile $cachefile + chown $DSERVER_USER $cachefile + chmod 600 $cachefile + fi +done + +# Cleanup obsolete public SSH keys +find $CACHEDIR -name \*.authorized_keys -type f | +while read cachefile; do + remoteuser=$(basename $cachefile | cut -d. -f1) + keysfile=/home/$remoteuser/.ssh/authorized_keys + + if [ ! -f $keysfile ]; then + echo "Deleting obsolete cache file $cachefile" + rm $cachefile + fi +done + +echo "All set..." diff --git a/go.mod b/go.mod index c61f05b..5c9cf64 100644 --- a/go.mod +++ b/go.mod @@ -4,10 +4,10 @@ go 1.20 require ( github.com/DataDog/zstd v1.5.5 - golang.org/x/crypto v0.8.0 + golang.org/x/crypto v0.9.0 ) require ( - golang.org/x/sys v0.7.0 // indirect - golang.org/x/term v0.7.0 // indirect + golang.org/x/sys v0.8.0 // indirect + golang.org/x/term v0.8.0 // indirect ) diff --git a/go.sum b/go.sum index 584b186..5e3fe8c 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,8 @@ github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= -golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ= -golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= -golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= -golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= diff --git a/internal/clients/stats.go b/internal/clients/stats.go index 1315aea..2da3cf7 100644 --- a/internal/clients/stats.go +++ b/internal/clients/stats.go @@ -34,7 +34,7 @@ func newTailStats(servers int) *stats { } } -// Start starts printing client connection stats every time a signal is recieved or +// Start starts printing client connection stats every time a signal is received or // connection count has changed. func (s *stats) Start(ctx context.Context, throttleCh <-chan struct{}, statsCh <-chan string, quiet bool) { diff --git a/internal/config/server.go b/internal/config/server.go index 4c96567..cb9ca2b 100644 --- a/internal/config/server.go +++ b/internal/config/server.go @@ -61,6 +61,12 @@ type ServerConfig struct { Schedule []Scheduled `json:",omitempty"` // Continuous mapreduce jobs Continuous []Continuous `json:",omitempty"` + // The allowed key exchanges algorithms. + KeyExchanges []string `json:",omitempty"` + // The allowed cipher algorithms. + Ciphers []string `json:",omitempty"` + // The allowed MAC algorithms. + MACs []string `json:",omitempty"` } // Create a new default server configuration. diff --git a/internal/server/server.go b/internal/server/server.go index 30602ff..761880d 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -39,11 +39,17 @@ func New() *Server { dlog.Server.Info("Starting server", version.String()) s := Server{ - sshServerConfig: &gossh.ServerConfig{}, - catLimiter: make(chan struct{}, config.Server.MaxConcurrentCats), - tailLimiter: make(chan struct{}, config.Server.MaxConcurrentTails), - sched: newScheduler(), - cont: newContinuous(), + sshServerConfig: &gossh.ServerConfig{ + Config: gossh.Config{ + KeyExchanges: config.Server.KeyExchanges, + Ciphers: config.Server.Ciphers, + MACs: config.Server.MACs, + }, + }, + catLimiter: make(chan struct{}, config.Server.MaxConcurrentCats), + tailLimiter: make(chan struct{}, config.Server.MaxConcurrentTails), + sched: newScheduler(), + cont: newContinuous(), } s.sshServerConfig.PasswordCallback = s.Callback diff --git a/internal/version/version.go b/internal/version/version.go index f381be6..90073b5 100644 --- a/internal/version/version.go +++ b/internal/version/version.go @@ -13,7 +13,7 @@ const ( // Name of DTail. Name string = "DTail" // Version of DTail. - Version string = "4.1.1" + Version string = "4.2.0" // Additional information for DTail Additional string = "Have a lot of fun!" ) diff --git a/samples/check_dserver.sh.sample b/samples/check_dserver.sh.sample deleted file mode 100755 index 77f01f0..0000000 --- a/samples/check_dserver.sh.sample +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -exec /usr/local/bin/dtailhealth --server localhost:2222 diff --git a/samples/dserver-update-keycache.service.sample b/samples/dserver-update-keycache.service.sample deleted file mode 100644 index 7e6144c..0000000 --- a/samples/dserver-update-keycache.service.sample +++ /dev/null @@ -1,6 +0,0 @@ -[Unit] -Description=Refresh DServer SSH Key Cache - -[Service] -Type=oneshot -ExecStart=/var/run/dserver/update_key_cache.sh diff --git a/samples/dserver-update-keycache.timer.sample b/samples/dserver-update-keycache.timer.sample deleted file mode 100644 index e7158ca..0000000 --- a/samples/dserver-update-keycache.timer.sample +++ /dev/null @@ -1,5 +0,0 @@ -[Unit] -Description=Refresh DServer SSH Key Cache every 30 minutes. - -[Timer] -OnCalendar=*:0/30 diff --git a/samples/dserver.service.sample b/samples/dserver.service.sample deleted file mode 100644 index c5e5e59..0000000 --- a/samples/dserver.service.sample +++ /dev/null @@ -1,19 +0,0 @@ -[Unit] -Description=DTail server -After=network.target - -[Service] -Slice=dserver.slice -User=dserver -Group=dserver -ExecStart=/usr/local/bin/dserver -cfg /etc/dserver/dtail.json -WorkingDirectory=/var/run/dserver -NoNewPrivileges=true -PrivateDevices=true -PrivateTmp=true -CPUAccounting=true -MemoryAccounting=true -BlockIOAccounting=true - -[Install] -WantedBy=multi-user.target diff --git a/samples/dtail.json.sample b/samples/dtail.json.sample deleted file mode 100644 index 26eb8a1..0000000 --- a/samples/dtail.json.sample +++ /dev/null @@ -1,127 +0,0 @@ -{ - "Client": { - "TermColorsEnable": true, - "TermColors": { - "Remote": { - "DelimiterAttr": "Dim", - "DelimiterBg": "Blue", - "DelimiterFg": "Cyan", - "RemoteAttr": "Dim", - "RemoteBg": "Blue", - "RemoteFg": "White", - "CountAttr": "Dim", - "CountBg": "Blue", - "CountFg": "White", - "HostnameAttr": "Bold", - "HostnameBg": "Blue", - "HostnameFg": "White", - "IDAttr": "Dim", - "IDBg": "Blue", - "IDFg": "White", - "StatsOkAttr": "None", - "StatsOkBg": "Green", - "StatsOkFg": "Black", - "StatsWarnAttr": "None", - "StatsWarnBg": "Red", - "StatsWarnFg": "White", - "TextAttr": "None", - "TextBg": "Black", - "TextFg": "White" - }, - "Client": { - "DelimiterAttr": "Dim", - "DelimiterBg": "Yellow", - "DelimiterFg": "Black", - "ClientAttr": "Dim", - "ClientBg": "Yellow", - "ClientFg": "Black", - "HostnameAttr": "Dim", - "HostnameBg": "Yellow", - "HostnameFg": "Black", - "TextAttr": "None", - "TextBg": "Black", - "TextFg": "White" - }, - "Server": { - "DelimiterAttr": "AttrDim", - "DelimiterBg": "BgCyan", - "DelimiterFg": "FgBlack", - "ServerAttr": "AttrDim", - "ServerBg": "BgCyan", - "ServerFg": "FgBlack", - "HostnameAttr": "AttrBold", - "HostnameBg": "BgCyan", - "HostnameFg": "FgBlack", - "TextAttr": "AttrNone", - "TextBg": "BgBlack", - "TextFg": "FgWhite" - }, - "Common": { - "SeverityErrorAttr": "AttrBold", - "SeverityErrorBg": "BgRed", - "SeverityErrorFg": "FgWhite", - "SeverityFatalAttr": "AttrBold", - "SeverityFatalBg": "BgMagenta", - "SeverityFatalFg": "FgWhite", - "SeverityWarnAttr": "AttrBold", - "SeverityWarnBg": "BgBlack", - "SeverityWarnFg": "FgWhite" - }, - "MaprTable": { - "DataAttr": "AttrNone", - "DataBg": "BgBlue", - "DataFg": "FgWhite", - "DelimiterAttr": "AttrDim", - "DelimiterBg": "BgBlue", - "DelimiterFg": "FgWhite", - "HeaderAttr": "AttrBold", - "HeaderBg": "BgBlue", - "HeaderFg": "FgWhite", - "HeaderDelimiterAttr": "AttrDim", - "HeaderDelimiterBg": "BgBlue", - "HeaderDelimiterFg": "FgWhite", - "HeaderSortKeyAttr": "AttrUnderline", - "HeaderGroupKeyAttr": "AttrReverse", - "RawQueryAttr": "AttrDim", - "RawQueryBg": "BgBlack", - "RawQueryFg": "FgCyan" - } - } - }, - "Server": { - "SSHBindAddress": "0.0.0.0", - "HostKeyFile": "cache/ssh_host_key", - "HostKeyBits": 2048, - "MapreduceLogFormat": "default", - "MaxConcurrentCats": 2, - "MaxConcurrentTails": 50, - "MaxConnections": 50, - "MaxLineLength": 1048576, - "Permissions": { - "Default": [ - "readfiles:^/.*$" - ], - "Users": { - "paul": [ - "readfiles:^/.*$" - ], - "pbuetow": [ - "readfiles:^/.*$" - ], - "jamesblake": [ - "readfiles:^/tmp/foo.log$", - "readfiles:^/.*$", - "readfiles:!^/tmp/bar.log$" - ] - } - } - }, - "Common": { - "LogDir": "log", - "Logger": "Fout", - "LogRotation": "Daily", - "CacheDir": "cache", - "SSHPort": 2222, - "LogLevel": "Info" - } -} diff --git a/samples/dtail.schema.json b/samples/dtail.schema.json deleted file mode 100755 index 1ee9980..0000000 --- a/samples/dtail.schema.json +++ /dev/null @@ -1,514 +0,0 @@ -{ - "$schema": "https://json-schema.org/2019-09/schema", - "description": "Schema for dtail.json", - "definitions": { - "userPermission": { - "type": "array", - "items": { - "type": "string" - } - }, - "userPermissions": { - "type": "object", - "patternProperties": { - "^.*$": { - "$ref": "#/definitions/userPermission" - } - } - }, - "loglevel": { - "type": "string", - "enum": [ - "None", - "Fatal", - "Error", - "Warn", - "Info", - "Default", - "Verbose", - "Debug", - "Devel", - "Trace", - "All" - ] - }, - "logger": { - "type": "string", - "enum": [ - "None", - "Stdout", - "File", - "Fout" - ] - }, - "logrotation": { - "type": "string", - "enum": [ - "Daily", - "Signal" - ] - }, - "color": { - "type": "string", - "enum": [ - "Black", - "Red", - "Green", - "Yellow", - "Blue", - "Magenta", - "Cyan", - "White" - ] - }, - "attribute": { - "type": "string", - "enum": [ - "None", - "Bold", - "Dim", - "Italic", - "Underline", - "Blink", - "SlowBlink", - "RapidBlink", - "Reverse", - "Hidden" - ] - } - }, - "type": "object", - "additionalProperties": false, - "properties": { - "Client": { - "additionalProperties": false, - "properties": { - "TermColorsEnable": { - "type": "boolean" - }, - "TermColors": { - "type": "object", - "additionalProperties": false, - "properties": { - "Remote": { - "additionalProperties": false, - "properties": { - "DelimiterAttr": { - "$ref": "#/definitions/attribute" - }, - "DelimiterBg": { - "$ref": "#/definitions/color" - }, - "DelimiterFg": { - "$ref": "#/definitions/color" - }, - "RemoteAttr": { - "$ref": "#/definitions/attribute" - }, - "RemoteBg": { - "$ref": "#/definitions/color" - }, - "RemoteFg": { - "$ref": "#/definitions/color" - }, - "CountAttr": { - "$ref": "#/definitions/attribute" - }, - "CountBg": { - "$ref": "#/definitions/color" - }, - "CountFg": { - "$ref": "#/definitions/color" - }, - "HostnameAttr": { - "$ref": "#/definitions/attribute" - }, - "HostnameBg": { - "$ref": "#/definitions/color" - }, - "HostnameFg": { - "$ref": "#/definitions/color" - }, - "IDAttr": { - "$ref": "#/definitions/attribute" - }, - "IDBg": { - "$ref": "#/definitions/color" - }, - "IDFg": { - "$ref": "#/definitions/color" - }, - "StatsOkAttr": { - "$ref": "#/definitions/attribute" - }, - "StatsOkBg": { - "$ref": "#/definitions/color" - }, - "StatsOkFg": { - "$ref": "#/definitions/color" - }, - "StatsWarnAttr": { - "$ref": "#/definitions/attribute" - }, - "StatsWarnBg": { - "$ref": "#/definitions/color" - }, - "StatsWarnFg": { - "$ref": "#/definitions/color" - }, - "TextAttr": { - "$ref": "#/definitions/attribute" - }, - "TextBg": { - "$ref": "#/definitions/color" - }, - "TextFg": { - "$ref": "#/definitions/color" - } - } - }, - "Client": { - "additionalProperties": false, - "properties": { - "DelimiterAttr": { - "$ref": "#/definitions/attribute" - }, - "DelimiterBg": { - "$ref": "#/definitions/color" - }, - "DelimiterFg": { - "$ref": "#/definitions/color" - }, - "ClientAttr": { - "$ref": "#/definitions/attribute" - }, - "ClientBg": { - "$ref": "#/definitions/color" - }, - "ClientFg": { - "$ref": "#/definitions/color" - }, - "HostnameAttr": { - "$ref": "#/definitions/attribute" - }, - "HostnameBg": { - "$ref": "#/definitions/color" - }, - "HostnameFg": { - "$ref": "#/definitions/color" - }, - "TextAttr": { - "$ref": "#/definitions/attribute" - }, - "TextBg": { - "$ref": "#/definitions/color" - }, - "TextFg": { - "$ref": "#/definitions/color" - } - } - }, - "Server": { - "additionalProperties": false, - "properties": { - "DelimiterAttr": { - "#ref": "#/definitions/attribute" - }, - "DelimiterBg": { - "#ref": "#/definitions/color" - }, - "DelimiterFg": { - "#ref": "#/definitions/color" - }, - "ServerAttr": { - "#ref": "#/definitions/attribute" - }, - "ServerBg": { - "#ref": "#/definitions/color" - }, - "ServerFg": { - "#ref": "#/definitions/color" - }, - "HostnameAttr": { - "#ref": "#/definitions/attribute" - }, - "HostnameBg": { - "#ref": "#/definitions/color" - }, - "HostnameFg": { - "#ref": "#/definitions/color" - }, - "TextAttr": { - "#ref": "#/definitions/attribute" - }, - "TextBg": { - "#ref": "#/definitions/color" - }, - "TextFg": { - "#ref": "#/definitions/color" - } - } - }, - "Common": { - "additionalProperties": false, - "properties": { - "SeverityErrorAttr": { - "#ref": "#/definitions/attribute" - }, - "SeverityErrorBg": { - "#ref": "#/definitions/color" - }, - "SeverityErrorFg": { - "#ref": "#/definitions/color" - }, - "SeverityFatalAttr": { - "#ref": "#/definitions/attribute" - }, - "SeverityFatalBg": { - "#ref": "#/definitions/color" - }, - "SeverityFatalFg": { - "#ref": "#/definitions/color" - }, - "SeverityWarnAttr": { - "#ref": "#/definitions/attribute" - }, - "SeverityWarnBg": { - "#ref": "#/definitions/color" - }, - "SeverityWarnFg": { - "#ref": "#/definitions/color" - } - } - }, - "MaprTable": { - "additionalProperties": false, - "properties": { - "DataAttr": { - "#ref": "#/definitions/attribute" - }, - "DataBg": { - "#ref": "#/definitions/color" - }, - "DataFg": { - "#ref": "#/definitions/color" - }, - "DelimiterAttr": { - "#ref": "#/definitions/attribute" - }, - "DelimiterBg": { - "#ref": "#/definitions/color" - }, - "DelimiterFg": { - "#ref": "#/definitions/color" - }, - "HeaderAttr": { - "#ref": "#/definitions/attribute" - }, - "HeaderBg": { - "#ref": "#/definitions/color" - }, - "HeaderFg": { - "#ref": "#/definitions/color" - }, - "HeaderDelimiterAttr": { - "#ref": "#/definitions/attribute" - }, - "HeaderDelimiterBg": { - "#ref": "#/definitions/color" - }, - "HeaderDelimiterFg": { - "#ref": "#/definitions/color" - }, - "HeaderSortKeyAttr": { - "#ref": "#/definitions/attribute" - }, - "HeaderGroupKeyAttr": { - "#ref": "#/definitions/attribute" - }, - "RawQueryAttr": { - "#ref": "#/definitions/attribute" - }, - "RawQueryBg": { - "#ref": "#/definitions/color" - }, - "RawQueryFg": { - "#ref": "#/definitions/color" - } - } - } - } - } - } - }, - "Server": { - "additionalProperties": false, - "properties": { - "SSHBindAddress": { - "type": "string" - }, - "HostKeyFile": { - "type": "string" - }, - "HostKeyBits": { - "type": "integer", - "minimum": 2048 - }, - "MapreduceLogFormat": { - "type": "string" - }, - "MaxConcurrentCats": { - "type": "integer", - "minimum": 1, - "maximum": 20 - }, - "MaxConcurrentTails": { - "type": "integer", - "minimum": 1, - "maximum": 200 - }, - "MaxConnections": { - "type": "integer", - "minimum": 1, - "maximum": 200 - }, - "MaxLineLength": { - "type": "integer", - "minimum": 1024, - "maximum": 10240000 - }, - "Permissions": { - "type": "object", - "additionalProperties": true, - "patternProperties": { - "^Default$": { - "$ref": "#/definitions/userPermission" - }, - "^Users$": { - "$ref": "#/definitions/userPermissions" - } - } - }, - "Schedule": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": false, - "properties": { - "Name": { - "type": "string" - }, - "Enable": { - "type": "boolean" - }, - "AllowFrom": { - "type": "array", - "items": { - "type": "string" - } - }, - "Servers": { - "type": "array", - "items": { - "type": "string" - } - }, - "TimeRange": { - "type": "array", - "items": [ - { - "type": "integer" - }, - { - "type": "integer" - } - ] - }, - "Files": { - "type": "string" - }, - "Outfile": { - "type": "string" - }, - "Query": { - "type": "string" - } - } - } - }, - "Continuous": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": false, - "properties": { - "Name": { - "type": "string" - }, - "Enable": { - "type": "boolean" - }, - "AllowFrom": { - "type": "array", - "items": { - "type": "string" - } - }, - "Servers": { - "type": "array", - "items": { - "type": "string" - } - }, - "RestartOnDayChange": { - "type": "boolean" - }, - "Files": { - "type": "string" - }, - "Outfile": { - "type": "string" - }, - "Query": { - "type": "string" - } - } - } - } - } - }, - "Common": { - "additionalProperties": false, - "properties": { - "LogDir": { - "type": "string" - }, - "Logger": { - "#ref": "#/definitions/logger" - }, - "LogLevel": { - "#ref": "#/definitions/loglevel" - }, - "LogRotation": { - "#ref": "#/definitions/logrotation" - }, - "CacheDir": { - "type": "string" - }, - "SSHPort": { - "type": "integer", - "minimum": 2, - "maximum": 16000 - }, - "ExperimentalFeaturesEnable": { - "type": "boolean" - } - } - } - }, - "required": [ - "Client", - "Server", - "Common" - ] -} diff --git a/samples/update_key_cache.sh.sample b/samples/update_key_cache.sh.sample deleted file mode 100644 index 9817f04..0000000 --- a/samples/update_key_cache.sh.sample +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash - -declare -r CACHEDIR=/var/run/dserver/cache -declare -r DSERVER_USER=dserver - -echo "Updating SSH key cache" - -ls /home/ | while read remoteuser; do - keysfile=/home/$remoteuser/.ssh/authorized_keys - - if [ -f $keysfile ]; then - cachefile=$CACHEDIR/$remoteuser.authorized_keys - echo "Caching $keysfile -> $cachefile" - - cp $keysfile $cachefile - chown $DSERVER_USER $cachefile - chmod 600 $cachefile - fi -done - -# Cleanup obsolete public SSH keys -find $CACHEDIR -name \*.authorized_keys -type f | -while read cachefile; do - remoteuser=$(basename $cachefile | cut -d. -f1) - keysfile=/home/$remoteuser/.ssh/authorized_keys - - if [ ! -f $keysfile ]; then - echo "Deleting obsolete cache file $cachefile" - rm $cachefile - fi -done - -echo "All set..." -- cgit v1.2.3