-- @@SHEBANG -- -*- Lua -*- -- gitano-auth -- -- Git (with) Augmented network operations -- User authentication wrapper -- -- Copyright 2012 Daniel Silverstone -- -- -- @@GITANO_LUA_PATH local gitano = require "gitano" local gall = require "gall" local luxio = require "luxio" local sio = require "luxio.simple" local sp = require "luxio.subprocess" -- @@GITANO_BIN_PATH -- @@GITANO_SHARE_PATH local repo_root, username, keytag = ... gitano.config.repo_path(repo_root) local cmdline = luxio.getenv "SSH_ORIGINAL_COMMAND" or "" local transactionid = gitano.log.syslog.open() if cmdline:match("^[ \t\n]*$") then gitano.log.fatal("No command provided, cannot continue") end local parsed_cmdline, warnings = gitano.util.parse_cmdline(cmdline) local start_log_level = gitano.log.get_level() -- Clamp level at info until we have checked if the caller -- is an admin or not gitano.log.cap_level(gitano.log.level.INFO) if (#warnings > 0) then gitano.log.error("Warnings encountered parsing commandline."); gitano.log.warn("\t" .. cmdline) gitano.log.warn("") gitano.log.warn("Parsed as:") for i = 1, #parsed_cmdline do gitano.log.warn((" =[%2d]> %s"):format(i, parsed_cmdline[i])) end gitano.log.warn("\nWarnings were:") for i = 1, #warnings do gitano.log.warn(" * " .. warnings[i]) end gitano.log.warn("") gitano.log.fatal("Game over, sorry\n") end -- Now load the administration data local admin_repo = gall.repository.new((repo_root or "") .. "/gitano-admin.git") if not admin_repo then gitano.log.fatal("Unable to locate administration repository. Cannot continue"); end local admin_head = admin_repo:get(admin_repo.HEAD) if not admin_head then gitano.log.fatal("Unable to find the HEAD of the administration repository. Cannot continue"); end local config, msg = gitano.config.parse(admin_head) if not config then gitano.log.critical("Unable to parse administration repository.") gitano.log.critical(" * " .. (msg or "No error?")) gitano.log.fatal("Cannot continue") end -- Now, are we an admin? if config.groups["gitano-admin"].filtered_members[username] then -- Yep, so blithely reset logging level gitano.log.set_level(start_log_level) end if not config.global.silent then -- Not silent, bump to chatty level automatically gitano.log.bump_level(gitano.log.level.CHAT) end local repo -- Find the command ip = string.match(luxio.getenv "SSH_CLIENT", "^[^ ]+") or "" gitano.log.syslog.info("Client connected from", ip, "as", username, "(" .. keytag .. ")", "Executing command:", cmdline) local cmd = gitano.command.get(parsed_cmdline[1]) if not cmd then gitano.log.fatal("Unknown command: " .. parsed_cmdline[1]) end if cmd.takes_repo and #parsed_cmdline > 1 then -- Acquire the repository object for the target repo local msg repo, msg = gitano.repository.find(config, parsed_cmdline[2]) if not repo then gitano.log.critical("Unable to locate repository.") gitano.log.critical(" * " .. (tostring(msg))) gitano.log.fatal("Cannot continue") end if repo.is_nascent then gitano.log.info("Repository " .. repo.name .. " is nascent") end end -- Validate the commandline, massaging it as necessary. if not cmd.validate(config, repo, parsed_cmdline) then gitano.log.fatal("Validation of command line failed") end -- Construct our context ready for prep local context = { source = "ssh", user = username, keytag = keytag, } local action, reason = cmd.prep(config, repo, parsed_cmdline, context) if not action then gitano.log.crit(reason) gitano.log.fatal("Ruleset did not complete cleanly") end if action == "allow" then gitano.log.info(reason or "Ruleset permitted action") else gitano.log.critical(reason) gitano.log.fatal("Ruleset denied action. Sorry.") end gitano.log.debug("Welcome to " .. config.global.site_name) gitano.log.debug("Running:") for i = 1, #parsed_cmdline do gitano.log.debug(" => " .. parsed_cmdline[i]) end gitano.log.debug("") gitano.log.debug("On behalf of " .. username .. " using key " .. keytag) -- Set up some useful environment variables local env = { ["GITANO_ROOT"] = repo_root, ["GITANO_USER"] = username, ["GITANO_KEYTAG"] = keytag, ["GITANO_PROJECT"] = (repo or {}).name, ["GITANO_SOURCE"] = "ssh", ["GITANO_TRANSACTION_ID"] = transactionid, } local how, why = cmd.run(config, repo, parsed_cmdline, env) if how ~= "exit" or why ~= 0 then gitano.log.critical("Error running sub-process:", ("%s (%d)"):format(how, why)) gitano.log.fatal("Unable to continue") else gitano.log.syslog.info(cmdline, "completed successfully") end gitano.log.syslog.close() return 0