summaryrefslogtreecommitdiff
path: root/lib/gitano/auth.lua
blob: fa30da2156095e83fd879140d10ba9b75bbd7f08 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
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'

local function load_admin_conf(repo_root)
   local admin_repo = gall.repository.new((repo_root or "") ..
      "/gitano-admin.git")

   if not admin_repo then
      log.critical("Unable to locate administration repository.")
      return nil
   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.")
      return nil
   end

   local admin_conf, msg = config.parse(admin_head)

   if not admin_conf then
      log.critical("Unable to parse administration repository.")
      log.critical("  * " .. (msg or "No error?"))
      return nil
   end

   return admin_conf
end

local function set_environment(repo_root, repo, context, transactionid)
   local env = {
      ["GITANO_ROOT"] = repo_root,
      ["GITANO_USER"] = context.user,
      ["GITANO_KEYTAG"] = context.keytag,
      ["GITANO_PROJECT"] = (repo or {}).name or "",
      ["GITANO_SOURCE"] = context.source,
      ["GITANO_TRANSACTION_ID"] = transactionid,
      ["GITANO_RUNNING"] = "yes",
   }

   for k, v in pairs(env) do
      luxio.setenv(k, v)
   end

   return env
end

local function is_authorized(user, source, cmdline, repo_root)
   local keytag = ""
   local authorized = false

   local start_log_level = log.get_level()
   log.cap_level(log.level.INFO)
   local transactionid = log.syslog.open()

   config.repo_path(repo_root)

   if not user or not cmdline then
      return nil
   end

   local parsed_cmdline, warnings = util.parse_cmdline(cmdline)

   if (#warnings > 0) then
      log.error("Error parsing command");
      return nil
   end

   local admin_conf = load_admin_conf(repo_root)
   if admin_conf == nil then
      log.fatal("Couldn't load a config from the admin repository")
   end

   if admin_conf.groups["gitano-admin"].filtered_members[user] then
      log.set_level(start_log_level)
   end

   if not admin_conf.global.silent then
      log.bump_level(log.level.CHAT)
   end

   ip = os.getenv("REMOTE_ADDR") or "unknown ip"
   log.syslog.info("Client connected from", ip, "as", user,
      "(" .. keytag .. ")", "Executing command:", cmdline)

   local cmd = command.get(parsed_cmdline[1])

   if not cmd then
      log.critical("Unknown command: " .. parsed_cmdline[1])
      return nil
   end

   local repo
   if cmd.takes_repo and #parsed_cmdline > 1 then
      repo, parsed_cmdline = cmd.detect_repo(admin_conf, parsed_cmdline)
      if not repo and not parsed_cmdline then
	 return nil
      end
   end

   if not cmd.validate(admin_conf, repo, parsed_cmdline) then
      log.critical("Validation of command line failed")
      return nil
   end

   local context = {source = source, user = user, keytag = keytag}
   local action, reason = cmd.prep(admin_conf, repo, parsed_cmdline, context)

   if not action then
      log.critical(reason)
      log.critical("Ruleset did not complete cleanly")
      return nil
   end

   local env
   if action == "allow" then
      log.info(reason or "Ruleset permitted action")
      authorized = true
      env = set_environment(repo_root, repo, context, transactionid)
   else
      log.critical(reason)
      log.critical("Ruleset denied action.  Sorry.")
   end

   return authorized, cmd, parsed_cmdline, admin_conf, env, repo
end

return {
   is_authorized = is_authorized
}