Skip to content

Commit

Permalink
Merge pull request #1133 from Mashape/plugins/ldap
Browse files Browse the repository at this point in the history
LDAP plugin
  • Loading branch information
subnetmarco committed Apr 9, 2016
2 parents 82aee82 + e7c6afa commit 0eb3a7b
Show file tree
Hide file tree
Showing 9 changed files with 792 additions and 3 deletions.
10 changes: 9 additions & 1 deletion kong-0.8.0rc2-0.rockspec
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ description = {
dependencies = {
"luasec ~> 0.5-2",

"penlight ~> 1.3.2",
"lua_uuid ~> 0.2.0-2",
"lua_system_constants ~> 0.1.1-0",
"luatz ~> 0.3-1",
Expand All @@ -33,7 +34,8 @@ dependencies = {
"lrexlib-pcre ~> 2.7.2-1",
"lua-llthreads2 ~> 0.1.3-1",
"luacrypto >= 0.3.2-1",
"luasyslog >= 1.0.0-2"
"luasyslog >= 1.0.0-2",
"lua_pack ~> 1.0.4-0"
}
build = {
type = "builtin",
Expand Down Expand Up @@ -247,6 +249,12 @@ build = {
["kong.plugins.hmac-auth.api"] = "kong/plugins/hmac-auth/api.lua",
["kong.plugins.hmac-auth.daos"] = "kong/plugins/hmac-auth/daos.lua",

["kong.plugins.ldap-auth.handler"] = "kong/plugins/ldap-auth/handler.lua",
["kong.plugins.ldap-auth.access"] = "kong/plugins/ldap-auth/access.lua",
["kong.plugins.ldap-auth.schema"] = "kong/plugins/ldap-auth/schema.lua",
["kong.plugins.ldap-auth.ldap"] = "kong/plugins/ldap-auth/ldap.lua",
["kong.plugins.ldap-auth.asn1"] = "kong/plugins/ldap-auth/asn1.lua",

["kong.plugins.syslog.handler"] = "kong/plugins/syslog/handler.lua",
["kong.plugins.syslog.schema"] = "kong/plugins/syslog/schema.lua",

Expand Down
2 changes: 1 addition & 1 deletion kong/constants.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ return {
"http-log", "key-auth", "hmac-auth", "basic-auth", "ip-restriction",
"mashape-analytics", "request-transformer", "response-transformer",
"request-size-limiting", "rate-limiting", "response-ratelimiting", "syslog",
"loggly", "datadog", "runscope"
"loggly", "datadog", "runscope", "ldap-auth"
},
-- Non standard headers, specific to Kong
HEADERS = {
Expand Down
114 changes: 114 additions & 0 deletions kong/plugins/ldap-auth/access.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
local responses = require "kong.tools.responses"
local constants = require "kong.constants"
local cache = require "kong.tools.database_cache"
local base64 = require "base64"
local ldap = require "kong.plugins.ldap-auth.ldap"

local match = string.match
local ngx_log = ngx.log
local request = ngx.req
local ngx_error = ngx.ERR
local ngx_debug = ngx.DEBUG
local ngx_socket_tcp = ngx.socket.tcp
local tostring = tostring

local AUTHORIZATION = "authorization"
local PROXY_AUTHORIZATION = "proxy-authorization"

local _M = {}

local function retrieve_credentials(authorization_header_value, conf)
local username, password
if authorization_header_value then
local cred = match(authorization_header_value, "%s*[ldap|LDAP]%s+(.*)")

if cred ~= nil then
local decoded_cred = base64.decode(cred)
username, password = match(decoded_cred, "(.+):(.+)")
end
end
return username, password
end

local function ldap_authenticate(given_username, given_password, conf)
local is_authenticated
local error, suppressed_err, ok
local who = conf.attribute.."="..given_username..","..conf.base_dn

local sock = ngx_socket_tcp()
sock:settimeout(conf.timeout)
ok, error = sock:connect(conf.ldap_host, conf.ldap_port)
if not ok then
ngx_log(ngx_error, "[ldap-auth] failed to connect to "..conf.ldap_host..":"..tostring(conf.ldap_port)..": ", error)
return responses.send_HTTP_INTERNAL_SERVER_ERROR(error)
end

if conf.start_tls then
local success, error = ldap.start_tls(sock)
if not success then
return false, error
end
local _, error = sock:sslhandshake(true, conf.ldap_host, conf.verify_ldap_host)
if error ~= nil then
return false, "failed to do SSL handshake with "..conf.ldap_host..":"..tostring(conf.ldap_port)..": ".. error
end
end

is_authenticated, error = ldap.bind_request(sock, who, given_password)

ok, suppressed_err = sock:setkeepalive(conf.keepalive)
if not ok then
ngx_log(ngx_error, "[ldap-auth] failed to keepalive to "..conf.ldap_host..":"..tostring(conf.ldap_port)..": ", suppressed_err)
end
return is_authenticated, error
end

local function authenticate(conf, given_credentials)
local given_username, given_password = retrieve_credentials(given_credentials)
if given_username == nil then
return false
end

local credential = cache.get_or_set(cache.ldap_credential_key(given_username), function()
ngx_log(ngx_debug, "[ldap-auth] authenticating user against LDAP server: "..conf.ldap_host..":"..conf.ldap_port)

local ok, err = ldap_authenticate(given_username, given_password, conf)
if err ~= nil then ngx_log(ngx_error, err) end
if not ok then
return nil
end
return {username = given_username, password = given_password}
end, conf.cache_ttl)

return credential and credential.password == given_password, credential
end

function _M.execute(conf)
local authorization_value = request.get_headers()[AUTHORIZATION]
local proxy_authorization_value = request.get_headers()[PROXY_AUTHORIZATION]

-- If both headers are missing, return 401
if not (authorization_value or proxy_authorization_value) then
ngx.header["WWW-Authenticate"] = 'LDAP realm="kong"'
return responses.send_HTTP_UNAUTHORIZED()
end

local is_authorized, credential = authenticate(conf, proxy_authorization_value)
if not is_authorized then
is_authorized, credential = authenticate(conf, authorization_value)
end

if not is_authorized then
return responses.send_HTTP_FORBIDDEN("Invalid authentication credentials")
end

if conf.hide_credentials then
request.clear_header(AUTHORIZATION)
request.clear_header(PROXY_AUTHORIZATION)
end

request.set_header(constants.HEADERS.CREDENTIAL_USERNAME, credential.username)
ngx.ctx.authenticated_credential = credential
end

return _M
Loading

0 comments on commit 0eb3a7b

Please sign in to comment.