123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- local resty_cookie = require("resty.cookie") -- https://github.com/cloudflare/lua-resty-cookie
- local util = require("util")
- local json = require("json")
- local agent_pub = require("agent_pub")
- local config = require("config")
- local no_permission = "/wolf/rbac/no_permission"
- local no_permission_html = "/wolf/rbac/no_permission.html"
- local basic_auth_access_check_url = "/wolf/rbac/access_check"
- function get_authorization()
- local headers = ngx.req.get_headers()
- local authorization = headers["Authorization"]
- return authorization
- end
- local function get_host_port()
- local host = ngx.var.host
- local port = ""
- if ngx.var.server_port and ngx.var.server_port ~= 80 then
- port = ":" .. tostring(ngx.var.server_port)
- end
- local host_port = (ngx.var.scheme or "http") .. "://" .. host .. port
- return host_port
- end
- local function url_args_as_args(ext_args)
- local args = ngx.req.get_uri_args()
- local host_port = get_host_port()
- local full_url = host_port .. ngx.var.uri
- args["return_to"] = full_url
- if ext_args and type(ext_args) == 'table' then
- for k, v in pairs(ext_args) do
- args[k] = v
- end
- end
- return args
- end
- local function check_url_permission(appID, action, resName, clientIP)
- local retry_max = 3
- local reason = nil;
- local userInfo = nil
- local res = nil
- for i = 1, retry_max do
- local args = { appID = appID, resName = resName, action = action, agentName=config.agentName, clientIP=clientIP}
- local url = basic_auth_access_check_url .. "?" .. ngx.encode_args(args)
- res = ngx.location.capture(url)
- if res then
- ngx.log(ngx.INFO, "check permission request:", url, ", status:", res.status, ",body:", tostring(res.body))
- if res.status < 500 then
- break
- else
- ngx.log(ngx.ERR, string.format("request [curl -v %s] failed! status:%d", url, res.status))
- end
- else
- reason = 'check permission failed, check request failed!'
- ngx.log(ngx.ERR, "fail request: ", url)
- end
- end
- if not res then
- return false, 500, reason
- end
- if res.status ~= 200 then
- local strBody = util.trim(res.body or "")
- local body, err = json.loads(strBody)
- if err then
- userInfo = res.body
- reason = 'check permission failed! parse response json failed!'
- else
- reason = body.reason
- end
- return false, res.status, reason, userInfo, res.headers
- else
- local body, err = json.loads(res.body)
- if err then
- userInfo = res.body
- reason = 'check permission failed! parse response json failed!'
- ngx.log(ngx.ERR, "json.loads(", res.body, ") failed! err:", err)
- else
- userInfo = body.data.userInfo
- reason = body.reason
- end
- return true, res.status, reason, userInfo, res.headers
- end
- end
- local function url_redirect(url, args)
- local appID = ngx.var.appID or "appIDUnset"
- args.appid = appID
- args = ngx.encode_args(args)
- util.redirect(url, args)
- end
- local function access_check()
- local url = ngx.var.uri
- local action = ngx.req.get_method()
- if util.url_in_ignore_list(url) then
- ngx.log(ngx.INFO, "check permission, ignore current request!")
- return
- end
- local appID = ngx.var.appID or "appIDUnset"
- local loginPrompt = ngx.var.loginPrompt or "input you username and password"
- local clientIP = util.clientIP()
- local permItem = "{appID: " .. appID .. ", action: " .. action .. ", url: " .. url .. ", clientIP: " .. clientIP .. "}"
- ngx.log(ngx.INFO, "Cookie: ", ngx.var.http_cookie, ", permItem=", permItem)
- local authorization = get_authorization()
- if authorization == nil then
- ngx.log(ngx.WARN, "no permission to access ", permItem, ", need login!")
- ngx.status = ngx.HTTP_UNAUTHORIZED
- ngx.header["WWW-Authenticate"] = "Basic realm=\"" .. loginPrompt .. "\""
- ngx.send_headers()
- ngx.flush(true)
- end
- local ok, status, reason, userInfo, headers = check_url_permission(appID, action, url, clientIP)
- ngx.log(ngx.INFO, " check_url_permission(", permItem, ",token=", tostring(token), ")=",
- ok, ", status:", tostring(status), ", userInfo:", tostring(json.dumps(userInfo)))
- local userID = -1
- local username = nil
- local nickname = nil
- if type(userInfo) == 'table' then
- ngx.req.set_header("X-UserId", userInfo.id)
- ngx.req.set_header("X-Username", userInfo.username)
- ngx.req.set_header("X-nickname", ngx.escape_uri(userInfo.nickname) or userInfo.username)
- -- local args = ngx.req.get_uri_args()
- ngx.ctx.userInfo = userInfo
- userID = userInfo.id
- username = userInfo.username
- nickname = userInfo.nickname
- end
- if headers and headers["Set-Cookie"] then
- local cookie_value = headers["Set-Cookie"]
- ngx.header['Set-Cookie'] = cookie_value
- ngx.log(ngx.INFO, "******* Re Set-Cookie:", cookie_value, " *******")
- end
- if ok then
- ---
- else
- -- no permission.
- if status == ngx.HTTP_UNAUTHORIZED or status == ngx.HTTP_FORBIDDEN then
- if reason == "ERR_TOKEN_INVALID" then
- ngx.status = ngx.HTTP_UNAUTHORIZED
- ngx.header["WWW-Authenticate"] = "Basic realm=\"" .. loginPrompt .. "\""
- ngx.send_headers()
- ngx.flush(true)
- else
- local redirect_url = no_permission_html
- if url == '/' then
- redirect_url = no_permission_html
- end
- url_redirect(redirect_url, { username = username, reason=reason })
- end
- elseif status == ngx.HTTP_BAD_REQUEST then
- ngx.status = ngx.HTTP_INTERNAL_SERVER_ERROR
- ngx.header["Content-Type"] = "text/plain"
- ngx.send_headers()
- ngx.flush(true)
- ngx.say("rbac check permission failed! status:" .. tostring(status))
- ngx.flush(true)
- else
- ngx.status = status
- ngx.header["Content-Type"] = "text/plain"
- ngx.send_headers()
- ngx.flush(true)
- ngx.say("rbac check permission failed! status:" .. tostring(status))
- ngx.flush(true)
- end
- end
- end
- access_check()
|