diff --git a/src/Lhp/Remote.hs b/src/Lhp/Remote.hs index 501dde6..3592530 100644 --- a/src/Lhp/Remote.hs +++ b/src/Lhp/Remote.hs @@ -41,6 +41,7 @@ compileReport h@Types.Host {..} = do _reportKernel <- _mkKernel _hostName kvs _reportDistribution <- _mkDistribution _hostName kvs _reportDockerContainers <- _fetchHostDockerContainers _hostName + _reportSshAuthorizedKeys <- _fetchHostSshAuthorizedKeys _hostName pure Types.Report {..} @@ -104,6 +105,19 @@ _fetchHostDockerContainers h = Right sv -> pure sv +-- | Attempts to find and return all SSH authorized keys on the remote +-- host. +_fetchHostSshAuthorizedKeys + :: MonadIO m + => MonadError LhpError m + => Z.Ssh.Destination + -> m [T.Text] +_fetchHostSshAuthorizedKeys h = + filter (not . T.null . T.strip) . T.lines . Z.Text.unsafeTextFromBL <$> prog + where + prog = _toSshError h (Z.Ssh.runScript h $(embedStringFile "src/scripts/ssh-keys.sh") ["bash"]) + + -- | Smart constructor for remote host cloud information. _mkCloud :: MonadError LhpError m diff --git a/src/Lhp/Types.hs b/src/Lhp/Types.hs index b3a3b1f..fdbf35b 100644 --- a/src/Lhp/Types.hs +++ b/src/Lhp/Types.hs @@ -50,6 +50,7 @@ data Report = Report , _reportKernel :: !Kernel , _reportDistribution :: !Distribution , _reportDockerContainers :: !(Maybe [DockerContainer]) + , _reportSshAuthorizedKeys :: ![T.Text] } deriving (Eq, Generic, Show) deriving (Aeson.FromJSON, Aeson.ToJSON) via (ADC.Autodocodec Report) @@ -68,6 +69,7 @@ instance ADC.HasCodec Report where <*> ADC.requiredField "kernel" "Kernel information." ADC..= _reportKernel <*> ADC.requiredField "distribution" "Distribution information." ADC..= _reportDistribution <*> ADC.requiredField "dockerContainers" "List of Docker containers if the host is a Docker host." ADC..= _reportDockerContainers + <*> ADC.requiredField "sshAuthorizedKeys" "List of SSH authorized keys found on host." ADC..= _reportSshAuthorizedKeys -- * Cloud Information diff --git a/src/scripts/ssh-keys.sh b/src/scripts/ssh-keys.sh new file mode 100644 index 0000000..9036aca --- /dev/null +++ b/src/scripts/ssh-keys.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env sh + +################### +# SHELL BEHAVIOUR # +################### + +# Stop on errors: +set -e + +############# +# PROCEDURE # +############# + +find \ + /etc/ssh/authorized_keys.d/* \ + $(cut -f6 -d ':' /etc/passwd | sort | uniq | xargs -I{} echo "{}/.ssh/authorized_keys") \ + $(cut -f6 -d ':' /etc/passwd | sort | uniq | xargs -I{} echo "{}/.ssh/authorized_keys2") \ + 2>/dev/null | + sort -u | + xargs -I{} cat {} | + xargs -L1 echo | + grep -vE "^#" | + sort -u | + tr -s ' ' diff --git a/website/package-lock.json b/website/package-lock.json index 87c6b4e..e8cabf0 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -15,7 +15,8 @@ "next": "14.1.3", "purify-ts": "^2.0.3", "react": "^18", - "react-dom": "^18" + "react-dom": "^18", + "react-toastify": "^10.0.5" }, "devDependencies": { "@types/node": "^20", @@ -6486,6 +6487,26 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-toastify": { + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-10.0.5.tgz", + "integrity": "sha512-mNKt2jBXJg4O7pSdbNUfDdTsK9FIdikfsIE/yUCxbAEXl4HMyJaivrVFcn3Elvt5xvCQYhUZm+hqTIu1UXM3Pw==", + "dependencies": { + "clsx": "^2.1.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/react-toastify/node_modules/clsx": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz", + "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==", + "engines": { + "node": ">=6" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", diff --git a/website/package.json b/website/package.json index 4c46145..1c21ca3 100644 --- a/website/package.json +++ b/website/package.json @@ -17,7 +17,8 @@ "next": "14.1.3", "purify-ts": "^2.0.3", "react": "^18", - "react-dom": "^18" + "react-dom": "^18", + "react-toastify": "^10.0.5" }, "devDependencies": { "@types/node": "^20", diff --git a/website/src/app/page.tsx b/website/src/app/page.tsx index 5f1b885..efcae9d 100644 --- a/website/src/app/page.tsx +++ b/website/src/app/page.tsx @@ -1,5 +1,8 @@ import { AppMain } from '@/components/app'; import Header from '@/components/header'; +import { ToastContainer } from 'react-toastify'; + +import 'react-toastify/dist/ReactToastify.css'; export default function Home() { return ( @@ -9,6 +12,8 @@ export default function Home() {