diff options
author | Richard Ipsum <richard.ipsum@codethink.co.uk> | 2014-01-28 16:15:15 +0000 |
---|---|---|
committer | Richard Ipsum <richard.ipsum@codethink.co.uk> | 2014-02-12 14:53:06 +0000 |
commit | 67e87f3ce322083d6a7fdd0ba96850a4039d14db (patch) | |
tree | 027c47b6562554f4b04885eb696dfe2409af8f5e | |
parent | 88613939ce2156e5c50fdc63c2c73f08a9047268 (diff) | |
download | gitano-67e87f3ce322083d6a7fdd0ba96850a4039d14db.tar.gz |
Add auth.lua
We now perform auth in 2 cgis as well as gitano-auth,
so auth needs to be in the library
-rw-r--r-- | lib/gitano.lua | 2 | ||||
-rw-r--r-- | lib/gitano/auth.lua | 166 |
2 files changed, 168 insertions, 0 deletions
diff --git a/lib/gitano.lua b/lib/gitano.lua index ad3cd7c..b57bd71 100644 --- a/lib/gitano.lua +++ b/lib/gitano.lua @@ -14,6 +14,7 @@ local actions = require 'gitano.actions' local lace = require 'gitano.lace' local markdown = require 'gitano.markdown' local supple = require 'gitano.supple' +local auth = require 'gitano.auth' return { util = util, @@ -25,4 +26,5 @@ return { lace = lace, markdown = markdown, supple = supple, + auth = auth } diff --git a/lib/gitano/auth.lua b/lib/gitano/auth.lua new file mode 100644 index 0000000..84288f1 --- /dev/null +++ b/lib/gitano/auth.lua @@ -0,0 +1,166 @@ +local config = require 'gitano.config' +local command = require 'gitano.command' +local log = require 'gitano.log' +local repository = require 'gitano.repository' +local util = require 'gitano.util' +local gall = require 'gall' + +-- TODO: this must be split up, it is far too long +function is_authorized(user, cmdline) + + if not user or not cmdline then + return nil + end + + local repo_root = os.getenv("GITANO_ROOT") + local username = user + local keytag = "" + + local authorized = false + + config.repo_path(repo_root) + + local transactionid = log.syslog.open() + + local parsed_cmdline, warnings = util.parse_cmdline(cmdline) + + local start_log_level = log.get_level() + -- Clamp level at info until we have checked if the caller + -- is an admin or not + log.cap_level(log.level.INFO) + + if (#warnings > 0) then + log.error("Warnings encountered parsing commandline."); + log.warn("\t" .. cmdline) + log.warn("") + log.warn("Parsed as:") + for i = 1, #parsed_cmdline do + log.warn((" =[%2d]> %s"):format(i, parsed_cmdline[i])) + end + log.warn("\nWarnings were:") + for i = 1, #warnings do + log.warn(" * " .. warnings[i]) + end + log.warn("") + log.critical("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 + log.critical("Unable to locate administration repository. Cannot continue"); + end + + local admin_head = admin_repo:get(admin_repo.HEAD) + + if not admin_head then + log.critical("Unable to find the HEAD of the administration repository. Cannot continue"); + end + + local config, msg = config.parse(admin_head) + + if not config then + log.critical("Unable to parse administration repository.") + log.critical(" * " .. (msg or "No error?")) + log.critical("Cannot continue") + end + + -- Now, are we an admin? + if config.groups["gitano-admin"].filtered_members[username] then + -- Yep, so blithely reset logging level + log.set_level(start_log_level) + end + + if not config.global.silent then + -- Not silent, bump to chatty level automatically + log.bump_level(log.level.CHAT) + end + + local repo + + -- Find the command + + ip = os.getenv("REMOTE_ADDR") or "unknown ip" + + log.syslog.info("Client connected from", ip, "as", username, + "(" .. keytag .. ")", "Executing command:", + cmdline) + + local cmd = command.get(parsed_cmdline[1]) + + if not cmd then + log.critical("Unknown command: " .. parsed_cmdline[1]) + return authorized + end + + if cmd.takes_repo and #parsed_cmdline > 1 then + -- Acquire the repository object for the target repo + local msg + repo, msg = repository.find(config, parsed_cmdline[2]) + if not repo then + log.critical("Unable to locate repository.") + log.critical(" * " .. (tostring(msg))) + log.critical("Cannot continue") + end + + if repo.is_nascent then + 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 + log.critical("Validation of command line failed") + return authorized + end + + -- Construct our context ready for prep + local context = { + source = "http", + user = username, + keytag = keytag, + } + + local action, reason = cmd.prep(config, repo, parsed_cmdline, context) + + if not action then + log.critical(reason) + log.critical("Ruleset did not complete cleanly") + end + + local env + + if action == "allow" then + log.info(reason or "Ruleset permitted action") + authorized = true + + -- set env vars needed by gitano hooks + luxio.setenv("GITANO_ROOT", repo_root) + luxio.setenv("GITANO_USER", username) + luxio.setenv("GITANO_KEYTAG", keytag) + luxio.setenv("GITANO_PROJECT", (repo or {}).name or "") + luxio.setenv("GITANO_SOURCE", "http") + luxio.setenv("GITANO_TRANSACTION_ID", transactionid) + + env = { + ["GITANO_ROOT"] = repo_root, + ["GITANO_USER"] = username, + ["GITANO_KEYTAG"] = keytag, + ["GITANO_PROJECT"] = (repo or {}).name, + ["GITANO_SOURCE"] = "ssh", + ["GITANO_TRANSACTION_ID"] = transactionid, + } + else + log.critical(reason) + log.critical("Ruleset denied action. Sorry.") + end + + return authorized, cmd, parsed_cmdline, config, env +end + +return { + is_authorized = is_authorized +} |