diff options
-rw-r--r-- | main/aaudit/APKBUILD | 75 | ||||
-rwxr-xr-x | main/aaudit/aaudit | 106 | ||||
-rw-r--r-- | main/aaudit/aaudit-common.lua | 31 | ||||
-rwxr-xr-x | main/aaudit/aaudit-repo | 47 | ||||
-rw-r--r-- | main/aaudit/aaudit-server.json | 21 | ||||
-rw-r--r-- | main/aaudit/aaudit-server.lua | 399 | ||||
-rwxr-xr-x | main/aaudit/aaudit-shell | 15 | ||||
-rwxr-xr-x | main/aaudit/aaudit-update-keys | 18 | ||||
-rw-r--r-- | main/aaudit/aaudit.json | 1 |
9 files changed, 713 insertions, 0 deletions
diff --git a/main/aaudit/APKBUILD b/main/aaudit/APKBUILD new file mode 100644 index 0000000000..b88f7cb1c9 --- /dev/null +++ b/main/aaudit/APKBUILD @@ -0,0 +1,75 @@ +# Contributor: Timo Teräs <timo.teras@iki.fi> +# Maintainer: Timo Teräs <timo.teras@iki.fi> +pkgname=aaudit +pkgver=0.6 +pkgrel=0 +pkgdesc="Alpine Auditor" +url="http://alpinelinux.org" +arch="noarch" +license="GPL" +depends="lua5.2 lua5.2-posix lua5.2-cjson lua5.2-pc lua5.2-socket" +makedepends="" +install="" +subpackages="$pkgname-server" +replaces="" +source="aaudit-common.lua + aaudit-server.lua + aaudit + aaudit-shell + aaudit-update-keys + aaudit-repo + aaudit.json + aaudit-server.json + " +_luaver="5.2" + +build() { + return 0 +} + +package() { + mkdir -p "$pkgdir"/etc/aaudit \ + "$pkgdir"/usr/bin \ + "$pkgdir"/usr/share/lua/$_luaver/aaudit + cp aaudit.json "$pkgdir"/etc/aaudit + cp aaudit-common.lua "$pkgdir"/usr/share/lua/$_luaver/aaudit/common.lua + cp aaudit "$pkgdir"/usr/bin +} + +server() { + depends="aaudit git lua5.2 lua5.2-posix lua5.2-cjson lua5.2-zlib" + + mkdir -p "$subpkgdir"/etc/aaudit \ + "$subpkgdir"/usr/libexec/aaudit \ + "$subpkgdir"/usr/bin \ + "$subpkgdir"/usr/share/lua/$_luaver/aaudit + cp aaudit-server.json "$subpkgdir"/etc/aaudit + cp aaudit-server.lua "$subpkgdir"/usr/share/lua/$_luaver/aaudit/server.lua + cp aaudit-update-keys aaudit-repo "$subpkgdir"/usr/bin + cp aaudit-shell "$subpkgdir"/usr/libexec/aaudit +} + +md5sums="b81b0707b297a69dacbc1606324de029 aaudit-common.lua +40131250bb7fd3c92e2b302682d5c5f7 aaudit-server.lua +028ecf2a733387560b15563de1777c68 aaudit +f5de73f12b6df1a751c89f19c92871be aaudit-shell +feef077f56f40002ca11846512d347af aaudit-update-keys +9c88f34f561a2d0955b07de467b18a70 aaudit-repo +8a80554c91d9fca8acb82f023de02f11 aaudit.json +f0e97a7a07a472278298b5999a397f58 aaudit-server.json" +sha256sums="ee1998e730356c2de0ff9d5e27d9e0277e3c1f051777146b7c5b820437edfd7f aaudit-common.lua +6bb3968e0753e8ca6283f0ba838ce3cb18ea18ba7014bfa4c25e150093d48ba0 aaudit-server.lua +91b5247e856b6531796a0ac61c3c82a37880fbabc1afc9bf4793667f03fb3ea0 aaudit +659c755cfca95a76da78f4d28d0ab9a32d55bea0077be7420ceaf9d45c518354 aaudit-shell +660dcf86f02a9d0e3ff47cb359e0291a0921d03215e368552a2878d2d691a9cc aaudit-update-keys +83868f17e1162e2b621eb2115a36f989c300aeda7cadf82ec1c991ee19d25664 aaudit-repo +ca3d163bab055381827226140568f3bef7eaac187cebd76878e0b63e9e442356 aaudit.json +ab276c9caeaa238c8999c79cd3b016f4ba149e6793475c5cde088597cedd849c aaudit-server.json" +sha512sums="aaa378fd710d17cb3663954648e97dd5128406cc6f37e9834075046aed1912dcc9e448b6c96502350b8d3496e00b7803cae671a4be2c12c584a84dc0b6e843e9 aaudit-common.lua +550385e27c7492e2234ddcf7c3c4a43dda2f3b598e52422af789febe68dfe0f88598c93f525f29f47173c878f4da4bef73c59eb8ca4605a8967634190a62605e aaudit-server.lua +e12b1623506382e04307f1c7fc361b544b4fbe992d41fcbaa7efd4c8568060fa7fad17e4db7a4ae96ebadc2b95f3c545809b948460a5446608bac6a35d3c35f3 aaudit +18499771d7d425f9305209c562eb8e62ef41910e88b08219baf010cdb472d49087080feb67384c4826c53bddcc0ce92c0c23c78df22dc40c64f1b17bf0ad05ec aaudit-shell +aec728a9a1e4c92baeb94a9d95e1785ea166652a157571fe2e848e71c1246635ecb99512e92435e1314c620b1fa8e4f37400350bed78bd375db4a63828c500f0 aaudit-update-keys +7507dea2b8ec4054e507aa3b42818863b9737402f3a9f967e16a63dd3ea12385463c2bce178a819a5f1fef76e74887a136de665e0b54172f1c1ce5f61b73403f aaudit-repo +ca4b6defb8adcc010050bc8b1bb8f8092c4928b8a0fba32146abcfb256e4d91672f88ca2cdf6210e754e5b8ac5e23fb023806ccd749ac8b701f79a691f03c87a aaudit.json +52da35598b8638a34d5a6352b2ccfd046dc529e0e5e6b541d3111016cbe6b091ff3fb4175e98b4f39e226ca1e6c973b9aa9a7a74fcb49b41862bbe64979d9186 aaudit-server.json" diff --git a/main/aaudit/aaudit b/main/aaudit/aaudit new file mode 100755 index 0000000000..44652a1deb --- /dev/null +++ b/main/aaudit/aaudit @@ -0,0 +1,106 @@ +#!/usr/bin/lua5.2 + +local posix = require 'posix' +local json = require 'cjson' +local lpc = require 'lpc' +local aac = require 'aaudit.common' + +local function usage() + print([[ +Usage: aaudit [create|commit] [OPTIONS...] + +Options for create: + -s SERV Use server SERV + -d DESC Description for repository (default: hostname) + -t ADDR Specify ADDR as target device (default: local source IP) + -g GRP Add in group GRP (can be specified multiple times) + +Options for create and commit: + -m MSG Specify message for the commit + -L Local change (use local 'contact' as change author) +]]) + os.exit(1) +end + +local verbose = false +local conf = aac.readconfig() or {} +local req = {} + +for ret, optval in posix.getopt(arg, 'vs:d:t:m:Lg:') do + if ret == 'v' then + verbose = true + elseif ret == 's' then + conf.server = optval + elseif ret == 'd' then + conf.description = optval + elseif ret == 't' then + conf.target_address = optval + elseif ret == 'm' then + req.message = optval + elseif ret == 'L' then + req.local_change = true + elseif ret == 'g' then + req.groups = req.groups or {} + table.insert(req.groups, optval) + else + usage() + end +end + +if conf.server == nil then + print("Error: No server configured.") + usage() +end + +req.command = arg[1] +if arg[1] == "create" then + req.description = conf.description or aac.readfile("/etc/hostname"):gsub("\n","") + req.ssh_host_key = aac.readfile("/etc/ssh/ssh_host_ecdsa_key.pub") + or aac.readfile("/etc/ssh/ssh_host_dsa_key.pub") + or aac.readfile("/etc/ssh/ssh_host_rsa_key.pub") + aac.writeconfig(conf) + arg[1] = "commit" +end + +req.apkovl_follows = true + +if arg[1] ~= "commit" then usage() end + +local pid, SW, SR = lpc.run('ssh', '-T', ('%s@%s'):format(conf.user or "aaudit", conf.server)) + +SW:write(json.encode(req),'\n') +if req.apkovl_follows then + local APKOVL = io.popen("lbu package -", "rb") + while true do + local block = APKOVL:read(2^13) + if not block then break end + SW:write(block) + end + APKOVL:close() +end +SW:close() + +local reply +for line in SR:lines() do + if line:match("^{") and line:match("}$") then + reply = json.decode(line) + elseif verbose then + print(line) + end +end +SR:close() + +lpc.wait(pid) + +if reply then + if reply.ok then + io.write("OK: ",reply.msg,"\n") + else + io.write("ERROR: ",reply.msg,"\n") + end + if reply.notified then + io.write("Notified: ",reply.notified,"\n") + end +else + io.write("ERROR: No reply received from server\n") +end diff --git a/main/aaudit/aaudit-common.lua b/main/aaudit/aaudit-common.lua new file mode 100644 index 0000000000..d7b1bc4837 --- /dev/null +++ b/main/aaudit/aaudit-common.lua @@ -0,0 +1,31 @@ +local M = {} + +local posix = require 'posix' +local json = require 'cjson' + +M.config = "/etc/aaudit/aaudit.json" + +function M.readfile(fn) + local F = io.open(fn, "r") + if F == nil then return nil end + local ret = F:read("*all") + F:close() + return ret +end + +function M.readconfig(fn) + fn = fn or M.config + local success, res = pcall(json.decode, M.readfile(fn)) + if not success then io.stderr:write(("Error reading %s: %s\n"):format(fn, res)) end + return res +end + +function M.writefile(content, fn) + assert(io.open(fn, "w")):write(content):close() +end + +function M.writeconfig(config, fn) + M.writefile(json.encode(config), fn or M.config) +end + +return M diff --git a/main/aaudit/aaudit-repo b/main/aaudit/aaudit-repo new file mode 100755 index 0000000000..dbacd976bf --- /dev/null +++ b/main/aaudit/aaudit-repo @@ -0,0 +1,47 @@ +#!/usr/bin/lua5.2 + +local posix = require 'posix' +local aac = require 'aaudit.common' +local aas = require 'aaudit.server' + +local pullafter = aas.serverconfig["pull-after"] or 24*60*60 +local warnafter = aas.serverconfig["warn-after"] or 4*24*60*60 + +local function dorepo(repodir) + -- Check if it's time to update + local repoconf = aas.loadrepoconfig(repodir) + local stampfile = ("%s/lastcheck"):format(repodir) + local mtime = posix.stat(stampfile, "mtime") or 0 + + if os.time() > mtime + pullafter then + -- Pull for changes + local req = { + command = "commit", + target_address = repoconf.address, + message = "Unexpected configuration change", + local_change = true, + } + local ret, msg = aas.handle(req) + print(("Updating repository %s -> %s: %s"):format(repodir, repoconf.address, msg)) + mtime = posix.stat(stampfile, "mtime") or 0 + end + + return mtime, repoconf.address +end + +local home = os.getenv("HOME") +local outdated = {"List of unreachable monitored hosts:"} +for _, repodir in ipairs(posix.glob(("%s/*.git"):format(home))) do + local mtime, address = dorepo(repodir) + if os.time() > mtime + warnafter then + table.insert(outdated, address) + end +end + +if #outdated > 1 and aas.serverconfig["notify-unreachables"] then + aas.sendemail { + to = aas.serverconfig["notify-unreachables"], + subject = "aaudit report of unreachable hosts", + message = table.concat(outdated, "\n"), + } +end diff --git a/main/aaudit/aaudit-server.json b/main/aaudit/aaudit-server.json new file mode 100644 index 0000000000..d00c0be812 --- /dev/null +++ b/main/aaudit/aaudit-server.json @@ -0,0 +1,21 @@ +{ + "smtp_server": "localhost", + "rtqueue": "rtqueue", + "identities": { + "_default": "Alpine Auditor <auditor@alpine.local>" + }, + "groups": { + "all": { + "notify_email": [ "Notify Group <config-changes@alpine.local>" ], + "track_filemode": true, + "no_track": [ + "*/.git/*", "*.apk-new", "*~", + "etc/unbound/root.hints", + "etc/chrony/chrony.drift", + "etc/ld.so.cache" + ], + "no_notify": [ "etc/acf/password", "*/.ssh/known_hosts" ], + "no_diff": [ "etc/shadow*", "etc/ssh/ssh_host_*_key", "*/.ssh/*", "*.crt","*.pem", "*.pfx" ] + } + } +} diff --git a/main/aaudit/aaudit-server.lua b/main/aaudit/aaudit-server.lua new file mode 100644 index 0000000000..89f2fc0219 --- /dev/null +++ b/main/aaudit/aaudit-server.lua @@ -0,0 +1,399 @@ +local M = {} + +local posix = require 'posix' +local json = require 'cjson' +local zlib = require 'zlib' +local aac = require 'aaudit.common' +local smtp = require 'socket.smtp' + +local HOME = os.getenv("HOME") + +M.serverconfig = aac.readconfig(("%s/aaudit-server.json"):format(HOME)) or {} + +local function merge_bool(a, b) return a or b end +local function merge_array(a, b) if b then for i=1,#b do a[#a+1] = b[i] end end return a end + +local function match_file(fn, match_list) + if not match_list then return false end + local i, m + for i, pattern in ipairs(match_list) do + if posix.fnmatch(pattern, fn) then return true end + end + return false +end + +local function sortedpairs(t) + local i, keys, k = 0, {} + for k in pairs(t) do keys[#keys+1] = k end + table.sort(keys) + return function() + i = i + 1 + if keys[i] then return keys[i], t[keys[i]] end + end +end + +local function checksum_header(block) + local sum = 256 + for i = 1,148 do sum = sum + block:byte(i) end + for i = 157,500 do sum = sum + block:byte(i) end + return sum +end + +local function nullterm(s) return s:match("^[^%z]*") end +local function octal_to_number(str) return tonumber(nullterm(str), 8) end + +local function read_header_block(block) + local header = { + name = nullterm(block:sub(1,100)), + mode = octal_to_number(block:sub(101,108)), + uid = octal_to_number(block:sub(109,116)), + gid = octal_to_number(block:sub(117,124)), + size = octal_to_number(block:sub(125,136)), + mtime = octal_to_number(block:sub(137,148)), + chksum = octal_to_number(block:sub(149,156)), + typeflag = block:sub(157,157), + linkname = nullterm(block:sub(158,257)), + magic = block:sub(258,263), + version = block:sub(264,265), + uname = nullterm(block:sub(266,297)), + gname = nullterm(block:sub(298,329)), + devmajor = octal_to_number(block:sub(330,337)), + devminor = octal_to_number(block:sub(338,345)), + prefix = nullterm(block:sub(346,500)), + } + if header.magic ~= "ustar " and header.magic ~= "ustar\0" then + return false, "Invalid header magic "..header.magic + end + if header.version ~= "00" and header.version ~= " \0" then + return false, "Unknown version "..header.version + end + if not checksum_header(block) == header.chksum then + return false, "Failed header checksum" + end + return header +end + +local function rfc822_address(id) + local identities = M.serverconfig.identities + if id == nil then id = "_default" end + if identities and identities[id] then id = identities[id] end + local name, email = id:match("^(.-) *(<.*>)$") + if not email then return ("<%s>"):format(id) end + return ("%s %s"):format(name, email) +end + +local function rfc822_email(rfc822) + return rfc822:match("(<.*>)$") + +end + +function M.sendemail(mail) + local to = {} + local m = { + headers = { + ["Content-Type"] = 'text/plain; charset=utf8', + ["X-RT-Command"] = mail.rtheader, + from = rfc822_address(mail.from), + subject = mail.subject, + }, + body = mail.message, + } + local rcpt = {} + for _, addr in ipairs(mail.to) do + local rfc822 = rfc822_address(addr) + table.insert(to, rfc822) + table.insert(rcpt, rfc822_email(rfc822)) + end + m.headers.to = table.concat(to, ", ") + return smtp.send{ + from = rfc822_email(m.headers.from), + rcpt = rcpt, + source = smtp.message(m) + } +end + +local rt_keywords = { + fix = true, + fixes = true, + close = true, + closes = true, + ref = false, + refs = false, + rt = false, +} + +local function sendcommitdiff(body, req, R, G) + if not body then return end + if not G.notify_emails then return end + + local mail = { + from = req.committer, + to = G.notify_emails, + subject = ("config change - %s (%s)"):format(R.description, R.address), + message = table.concat(body, '\n') + } + + -- Set Request Tracker headers if relevant + local rtqueue = M.serverconfig.rtqueue + if rtqueue then + for k,no in req.message:gmatch("(%a+) #(%d+)") do + local action = rt_keywords[k] + if action ~= nil then + mail.subject = ("[%s #%s] %s"):format(rtqueue, no, mail.subject) + if action == true then + mail.rtheader = "Status: resolved" + end + break + end + end + end + + -- Send email + return M.sendemail(mail) +end + +local function import_tar(TAR, GIT, req, G) + local branch_ref = "refs/heads/import" + local from_ref = "refs/heads/master" + local blocksize = 512 + local nextmark = 1 + local author_time = 0 + local all_files = {} + local long_name, long_link_name + local symlinkmode = tonumber('0120000', 8) + local rwmode = tonumber('0755', 8) + local romode = tonumber('0644', 8) + local wandmode = tonumber('0111', 8) + + while true do + local block = TAR:read(blocksize) + if not block then return false, "Premature end of archive" end + if not block:match("[^%z]") then break end + + local header, err = read_header_block(block) + if not header then return false, err end + + local file_data = TAR:read(math.ceil(header.size / blocksize) * blocksize):sub(1,header.size) + if header.typeflag == "L" then + long_name = nullterm(file_data) + elseif header.typeflag == "K" then + long_link_name = nullterm(file_data) + else + if long_name then + header.name = long_name + long_name = nil + end + if long_link_name then + header.linkname = long_link_name + long_link_name = nil + end + end + + if header.name == "etc/aaudit/aaudit.json" then + local success, res = pcall(json.decode, file_data) + if success and res.contact then + local contact = res.contact + G.notify_emails = merge_array(G.notify_emails, {contact}) + if req.local_change then + req.author = rfc822_address(res.contact) + end + end + end + + if header.typeflag:match("^[0-46]$") and + not match_file(header.name, G.no_track) then + GIT:write('blob\n', 'mark :', nextmark, '\n') + if header.typeflag == "2" then + GIT:write('data ', tostring(#header.linkname), '\n', header.linkname, '\n') + header.mode = symlinkmode + else + GIT:write('data ', tostring(header.size), '\n', file_data, '\n') + end + local fn = header.prefix..header.name + all_files[fn] = { mark=nextmark, mode=header.mode, uname=header.uname, gname=header.gname } + nextmark = nextmark + 1 + if header.mtime > author_time then author_time = header.mtime end + end + end + if G.track_filemode then + GIT:write('blob\n', 'mark :', nextmark, '\n', + 'data <<END_OF_PERMISSONS\n') + for path, v in sortedpairs(all_files) do + GIT:write(("%o %s:%s %s\n"):format(v.mode, v.uname, v.gname, path)) + end + GIT:write('END_OF_PERMISSONS\n') + end + + GIT:write(([[ +commit %s +author %s %d +0000 +committer %s %d +0000 +data <<END_OF_COMMIT_MESSAGE +%s +END_OF_COMMIT_MESSAGE + +]]):format(branch_ref, + req.author, author_time, + req.committer, os.time(), + req.message)) + + if not req.initial then GIT:write(("from %s^0\n"):format(from_ref)) end + GIT:write("deleteall\n") + if G.track_filemode then + GIT:write(("M %o :%i %s\n"):format(romode, nextmark, '.permissions.txt')) + end + local path, v + for path, v in pairs(all_files) do + local mode = v.mode + if mode ~= symlinkmode then + if bit32.band(mode, wandmode) then + mode = rwmode + else + mode = romode + end + end + GIT:write(("M %o :%i %s\n"):format(mode, v.mark, path)) + end + GIT:write("\n") + + return true +end + +local function generate_diff(repodir, commit, G) + local DIFF = io.popen(("git --git-dir='%s' show --patch-with-stat '%s' --"):format(repodir, commit), "r") + local visible = true + local has_changes, has_visible_changes = false, false + local text = {} + for l in DIFF:lines() do + local fn = l:match("^diff [^ \t]* a/([^ \t]*)") + if fn then + has_changes = true + visible = not match_file(fn, G.no_notify) + if visible then + has_visible_changes = true + visible = not match_file(fn, G.no_diff) + if not visible then + table.insert(text, "Private file "..fn.." changed") + end + end + end + if visible then table.insert(text, l) end + end + DIFF:close() + if not has_visible_changes then text = nil end + return has_changes, text +end + +function M.loadrepoconfig(repohome) + return aac.readconfig(("%s/aaudit-repo.json"):format(repohome)) +end + +local function load_repo_configs(repohome) + local R = M.loadrepoconfig(repohome) + -- merge global and per-repository group configs + local G = (M.serverconfig.groups or {}).all or {} + for _, name in pairs(R.groups or {}) do + local g = M.serverconfig.groups[name] or {} + G.notify_emails = merge_array(G.notify_emails, g.notify_emails) + G.track_filemode = merge_bool(G.track_filemode, g.track_filemode) + G.no_track = merge_array(G.no_track, g.no_track) + G.no_notify = merge_array(G.no_notify, g.no_notify) + G.no_diff = merge_array(G.no_diff, g.no_diff) + end + return R, G +end + +function M.repo_update(req,clientstream) + local repodir = req.repositorydir + local R, G = load_repo_configs(repodir) + + req.committer = rfc822_address(req.identity) + req.author = req.committer + + local TAR + if req.apkovl_follows then + TAR = zlib.inflate(clientstream) + else + TAR = io.popen(("ssh -T root@%s 'lbu package -' | gunzip"):format(R.address), "r") + end + + local GIT = io.popen(("git --git-dir='%s' fast-import --quiet"):format(repodir), "w") + local rc, err = import_tar(TAR, GIT, req, G) + GIT:close() + TAR:close() + if not rc then return rc, err end + + local stampfile = ("%s/lastcheck"):format(repodir) + if posix.utime(stampfile) ~= 0 then + posix.close(posix.open(stampfile, posix.O_CREAT, "0644")) + end + + local has_changes, email_body = generate_diff(repodir, "import", G) + if has_changes then + if not req.initial then + local res, err = sendcommitdiff(email_body, req, R, G) + if not res then + os.execute(("git --git-dir='%s' branch --quiet -D import;".. + "git --git-dir='%s' gc --quiet --prune=now") + :format(repodir, repodir)) + return false, err + end + end + os.execute(("git --git-dir='%s' branch --quiet --force master import;".. + "git --git-dir='%s' branch --quiet -D import") + :format(repodir, repodir)) + return true, "Committed" + end + + os.execute(("git --git-dir='%s' branch --quiet -D import;".. + "git --git-dir='%s' gc --quiet --prune=now") + :format(repodir, repodir)) + return true, "No changes detected" +end + +function M.repo_create(req) + -- Create repository + write config + local repodir = req.repositorydir + os.execute(("mkdir -p '%s'; git init --quiet --bare '%s'") + :format(repodir, repodir)) + aac.writefile( + ("%s (%s)"):format(req.description, req.target_address), + ("%s/description"):format(repodir)) + aac.writeconfig( + { address=req.target_address, + description=req.description, + groups=req.groups }, + ("%s/aaudit-repo.json"):format(repodir)) + + -- Inject ssh identity to known_hosts + if req.ssh_host_key then + local f = io.open(("%s/.ssh/known_hosts"):format(HOME), "a") + f:write(("%s %s\n"):format(req.target_address, req.ssh_host_key)) + f:close() + end +end + +function M.handle(req,clientstream) + req.target_address = req.target_address or req.remote_ip + req.repositorydir = ("%s/%s.git"):format(HOME, req.target_address) + req.initial = false + if req.command == "create" then + if posix.access(req.repositorydir, "rwx") then + return false, "Repository exists already" + end + M.repo_create(req) + req.initial = true + req.command = "commit" + end + if req.command == "commit" then + req.message = req.message or "Configuration change" + if not posix.access(req.repositorydir, "rwx") then + return false, "No such repository" + end + return M.repo_update(req,clientstream) + else + return false,"Invalid request command" + end +end + +return M diff --git a/main/aaudit/aaudit-shell b/main/aaudit/aaudit-shell new file mode 100755 index 0000000000..733341bae9 --- /dev/null +++ b/main/aaudit/aaudit-shell @@ -0,0 +1,15 @@ +#!/usr/bin/lua5.2 + +local json = require 'cjson' +local aas = require 'aaudit.server' + +local req = json.decode(io.read()) +req.remote_ip = (os.getenv("SSH_CLIENT") or ""):match("[^ ]+") +req.identity = arg[1] + +local ok, msg, extra = aas.handle(req, io.stdin) + +local object = extra or {} +object.ok = ok +object.msg = msg +print(json.encode(object)) diff --git a/main/aaudit/aaudit-update-keys b/main/aaudit/aaudit-update-keys new file mode 100755 index 0000000000..3521808cba --- /dev/null +++ b/main/aaudit/aaudit-update-keys @@ -0,0 +1,18 @@ +#!/usr/bin/lua5.2 + +local posix = require 'posix' +local aac = require 'aaudit.common' + +local home = os.getenv("HOME") +local allkeys = {} +for _, keyfile in ipairs(posix.glob(("%s/keydir/*.pub"):format(home))) do + local identity = keyfile:match("keydir/(.*).pub$") + for sshkey in io.lines(keyfile) do + table.insert(allkeys, + ('command="/usr/libexec/aaudit/aaudit-shell %s"'.. + ',no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty %s\n') + :format(identity, sshkey)) + end +end + +aac.writefile(table.concat(allkeys), ("%s/.ssh/authorized_keys"):format(home)) diff --git a/main/aaudit/aaudit.json b/main/aaudit/aaudit.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/main/aaudit/aaudit.json @@ -0,0 +1 @@ +{} |