summaryrefslogtreecommitdiff
path: root/lib/gitano/auth.lua
blob: 2fd37408e4d473763a8bfe4f345c83d6761c1455 (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
136
137
138
139
140
141
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 i18n = require 'gitano.i18n'
local gall = require 'gall'
local luxio = require 'luxio'

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(i18n.expand("ERROR_CANNOT_FIND_ADMIN_REPO"))
      return nil
   end

   local admin_head = admin_repo:get(admin_repo.HEAD)

   if not admin_head then
      log.critical(i18n.expand("ERROR_BAD_ADMIN_REPO"))
      return nil
   end

   local admin_conf, msg = config.parse(admin_head)

   if not admin_conf then
      log.critical(i18n.expand("ERROR_CANNOT_PARSE_ADMIN"))
      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,
                             transactionid, start_log_level, keytag)

   local authorized = false

   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(i18n.expand("ERROR_PARSING_COMMAND"))
      return nil
   end

   local admin_conf = load_admin_conf(repo_root)
   if admin_conf == nil then
      log.fatal(i18n.expand("ERROR_COULD_NOT_LOAD_CONFIG"))
   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(
      i18n.expand("CLIENT_CONNECTED",
		  { ip=ip, user=user, key=keytag, cmdline=cmdline}))

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

   if not cmd then
      log.critical(i18n.expand("ERROR_UNKNOWN_COMMAND", {cmd=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 user == "gitano-bypass" then
      log.state(i18n.expand("BYPASS_USER_BANNER_HEADER"))
      log.state(i18n.expand("BYPASS_USER_ALERT_MESSAGE"))
      log.state(i18n.expand("BYPASS_USER_BANNER_FOOTER"))
   end

   if not cmd.validate(admin_conf, repo, parsed_cmdline) then
      log.critical(i18n.expand("ERROR_VALIDATION_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(i18n.expand("ERROR_RULESET_UNCLEAN"))
      return nil
   end

   local env
   if action == "allow" then
      log.info(reason or i18n.expand("RULESET_ALLOWED"))
      authorized = true
      env = set_environment(repo_root, repo, context, transactionid)
   else
      log.critical(reason)
      log.critical(i18n.expand("RULESET_DENIED"))
   end

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

return {
   is_authorized = is_authorized
}