Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ldap-auth): use lua-resty-ldap instead of lualdap #7590

Merged
merged 6 commits into from
Aug 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 21 additions & 8 deletions apisix/plugins/ldap-auth.lua
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ local ngx = ngx
local ngx_re = require("ngx.re")
local ipairs = ipairs
local consumer_mod = require("apisix.consumer")
local lualdap = require("lualdap")
local ldap = require("resty.ldap")

local lrucache = core.lrucache.new({
ttl = 300, count = 512
Expand All @@ -31,8 +31,9 @@ local schema = {
properties = {
base_dn = { type = "string" },
ldap_uri = { type = "string" },
tzssangglass marked this conversation as resolved.
Show resolved Hide resolved
use_tls = { type = "boolean" },
uid = { type = "string" }
use_tls = { type = "boolean", default = false },
tls_verify = { type = "boolean", default = false },
uid = { type = "string", default = "cn" }
},
required = {"base_dn","ldap_uri"},
}
Expand Down Expand Up @@ -136,11 +137,23 @@ function _M.rewrite(conf, ctx)
end

-- 2. try authenticate the user against the ldap server
local uid = conf.uid or "cn"

local userdn = uid .. "=" .. user.username .. "," .. conf.base_dn
local ld = lualdap.open_simple (conf.ldap_uri, userdn, user.password, conf.use_tls)
if not ld then
local ldap_host, ldap_port = core.utils.parse_addr(conf.ldap_uri)

local userdn = conf.uid .. "=" .. user.username .. "," .. conf.base_dn
local ldapconf = {
timeout = 10000,
start_tls = false,
ldap_host = ldap_host,
ldap_port = ldap_port or 389,
ldaps = conf.use_tls,
tls_verify = conf.tls_verify,
base_dn = conf.base_dn,
attribute = conf.uid,
keepalive = 60000,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's doc the newly added timeout and keepalive

Copy link
Contributor Author

@kingluo kingluo Aug 2, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@spacewander These items are not exported to admin api, we only use default values. So we need to doc the default values? But it's kind of internal parameters.

}
local res, err = ldap.ldap_authenticate(user.username, user.password, ldapconf)
if not res then
core.log.warn("ldap-auth failed: ", err)
return 401, { message = "Invalid user authorization" }
end

Expand Down
14 changes: 10 additions & 4 deletions ci/pod/docker-compose.plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,19 @@ services:
openldap:
image: bitnami/openldap:2.5.8
environment:
LDAP_ADMIN_USERNAME: amdin
LDAP_ADMIN_PASSWORD: adminpassword
LDAP_USERS: user01,user02
LDAP_PASSWORDS: password1,password2
- LDAP_ADMIN_USERNAME=amdin
- LDAP_ADMIN_PASSWORD=adminpassword
- LDAP_USERS=user01,user02
- LDAP_PASSWORDS=password1,password2
- LDAP_ENABLE_TLS=yes
- LDAP_TLS_CERT_FILE=/certs/localhost_slapd_cert.pem
- LDAP_TLS_KEY_FILE=/certs/localhost_slapd_key.pem
- LDAP_TLS_CA_FILE=/certs/apisix.crt
ports:
- "1389:1389"
- "1636:1636"
volumes:
- ./t/certs:/certs


rocketmq_namesrv:
Expand Down
5 changes: 3 additions & 2 deletions docs/en/latest/plugins/ldap-auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ The `ldap-auth` Plugin can be used to add LDAP authentication to a Route or a Se

This Plugin works with the Consumer object and the consumers of the API can authenticate with an LDAP server using [basic authentication](https://en.wikipedia.org/wiki/Basic_access_authentication).

This Plugin uses [lualdap](https://lualdap.github.io/lualdap/) for connecting with an LDAP server.
This Plugin uses [lua-resty-ldap](https://github.com/api7/lua-resty-ldap) for connecting with an LDAP server.

## Attributes

Expand All @@ -49,7 +49,8 @@ For Route:
|----------|---------|----------|---------|------------------------------------------------------------------------|
| base_dn | string | True | | Base dn of the LDAP server. For example, `ou=users,dc=example,dc=org`. |
| ldap_uri | string | True | | URI of the LDAP server. |
| use_tls | boolean | False | `true` | If set to `true` uses TLS. |
| use_tls | boolean | False | `false` | If set to `true` uses TLS. |
| tls_verify| boolean | False | `false` | Whether to verify the server certificate when `use_tls` is enabled; If set to `true`, you must set `ssl_trusted_certificate` in `config.yaml`, and make sure the host of `ldap_uri` matches the host in server certificate. |
| uid | string | False | `cn` | uid attribute. |

## Enabling the plugin
Expand Down
5 changes: 3 additions & 2 deletions docs/zh/latest/plugins/ldap-auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ description: 本篇文档介绍了 Apache APISIX ldap-auth 插件的相关信息

## 描述

`ldap-auth` 插件可用于给路由或服务添加 LDAP 身份认证,该插件使用 [lualdap](https://lualdap.github.io/lualdap/) 连接 LDAP 服务器。
`ldap-auth` 插件可用于给路由或服务添加 LDAP 身份认证,该插件使用 [lua-resty-ldap](https://github.com/api7/lua-resty-ldap) 连接 LDAP 服务器。

该插件需要与 Consumer 一起配合使用,API 的调用方可以使用 [basic authentication](https://en.wikipedia.org/wiki/Basic_access_authentication) 与 LDAP 服务器进行认证。

Expand All @@ -47,7 +47,8 @@ Route 端:
|----------|---------|----------|---------|------------------------------------------------------------------------|
| base_dn | string | 是 | | LDAP 服务器的 dn,例如:`ou=users,dc=example,dc=org`。|
| ldap_uri | string | 是 | | LDAP 服务器的 URI。 |
| use_tls | boolean | 否 | true | 如果设置为 `true` 则表示启用 TLS。 |
| use_tls | boolean | 否 | false | 如果设置为 `true` 则表示启用 TLS。 |
| tls_verify| boolean | 否 | false | 是否校验 LDAP 服务器的证书。如果设置为 `true`,你必须设置 `config.yaml` 里面的 `ssl_trusted_certificate`,并且确保 `ldap_uri` 里的 host 和服务器证书中的 host 匹配。 |
| uid | string | 否 | cn | UID 属性。 |

## 启用插件
Expand Down
3 changes: 2 additions & 1 deletion rockspec/apisix-master-0.rockspec
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ dependencies = {
"net-url = 0.9-1",
"xml2lua = 1.5-2",
"nanoid = 0.1-1",
"lua-resty-mediador = 0.1.2-1"
"lua-resty-mediador = 0.1.2-1",
"lua-resty-ldap = 0.1.0-0"
}

build = {
Expand Down
24 changes: 24 additions & 0 deletions t/certs/localhost_slapd_cert.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
-----BEGIN CERTIFICATE-----
MIIECDCCAnCgAwIBAgIUc40/PofbLcrqu/2MJMEkYfrxB+4wDQYJKoZIhvcNAQEL
BQAwVjELMAkGA1UEBhMCQ04xEjAQBgNVBAgMCUd1YW5nRG9uZzEPMA0GA1UEBwwG
Wmh1SGFpMQ8wDQYDVQQKDAZpcmVzdHkxETAPBgNVBAMMCHRlc3QuY29tMB4XDTIy
MDgwMjA1NDI1OFoXDTIzMDgwMjA1NDI1OFowLjESMBAGA1UEAxMJbG9jYWxob3N0
MRgwFgYDVQQKEw9FeGFtcGxlIENvbXBhbnkwggEiMA0GCSqGSIb3DQEBAQUAA4IB
DwAwggEKAoIBAQCxE5zfta69uPsQVDiV0OwWHDGxTBYNzmp5zsVwOF3bOH+hyB4M
+qFxPEuH84/Ib4GJdLM67qZth1azHudKy/QGPFkoeFUW1JhB9QGyjh/URwxTy05b
Ce5w7Ee1rMV/GWu6fxMfIE3o5U0XuW1IKQFaZVdNuQlvG4VjL59BfnEF+YXb1QDB
kIpvf59q+UuZgit8CrO1dDYeJ/xO3N9v2CS2u6si9/XWgIwayw67tmb7cbTu/srB
C99w97IMP5/Vkeu6fkg2jTuvCRARzMQJ11krDmtGeYum9SSCdyTLxK1u7w33DuhQ
3HE/PfHJj9QV1MKIeruVjEvawJsRiWQG0Ai7AgMBAAGjdjB0MAwGA1UdEwEB/wQC
MAAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0PAQH/BAUDAwegADAdBgNVHQ4E
FgQUcGOrPCoztq5Z7mjgGtaCkPkmDWowHwYDVR0jBBgwFoAUmbUr1fJgcJdG6ZLx
bYMojlFHG7MwDQYJKoZIhvcNAQELBQADggGBABNOTIiLHNQJfyV20UxcyzZ9xTuc
DuMzEexWJ6S33yJTyp5jni0vFaF9wnT1MOtp+Zizz0hQq0d+GvsmBzjkDdipFqUB
Dt4517l4Z/H4n4FV0jhqQhhzcPRWI5H2MNU0Ezno1iCaKD29Kq61fo2qrU7SNDre
RjnGueTW6u+YLj1ss+UK2rTCRX/Nqqz+MrvIift5Kj4c/8sAD3Zn2aXlH0dXSTcX
DaqNDPQvcdlqNMRSJSthLXYBn40Ro6mH7uA+e4aIVn4jyYvyb8qY5LhQPesTcJZw
IEDmIgFEIh0k1YoGvLD6TkMdKPUG536zH+4iZjKpwGwNQ/dTBgn4+5UOqguiYgXd
MP/eeXSCGLAIjQ4+i1ghv1eAlHuHSQ3Dm75icpAL7VHFdoI7I3wqeE5+IyrUXjX0
s1bCjIuwGxgoBBTzv25OijmTmMcLYDp04PR5qSwckvsrrxHr+2ujeqS+AGxzZ4Sk
N1JSJL69zUwfCVdE3mR+6OmmDcuVlB3u+grLFQ==
-----END CERTIFICATE-----
27 changes: 27 additions & 0 deletions t/certs/localhost_slapd_key.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAsROc37Wuvbj7EFQ4ldDsFhwxsUwWDc5qec7FcDhd2zh/ocge
DPqhcTxLh/OPyG+BiXSzOu6mbYdWsx7nSsv0BjxZKHhVFtSYQfUBso4f1EcMU8tO
WwnucOxHtazFfxlrun8THyBN6OVNF7ltSCkBWmVXTbkJbxuFYy+fQX5xBfmF29UA
wZCKb3+favlLmYIrfAqztXQ2Hif8Ttzfb9gktrurIvf11oCMGssOu7Zm+3G07v7K
wQvfcPeyDD+f1ZHrun5INo07rwkQEczECddZKw5rRnmLpvUkgncky8Stbu8N9w7o
UNxxPz3xyY/UFdTCiHq7lYxL2sCbEYlkBtAIuwIDAQABAoIBAGDANpaEzlUbHRJu
8fvpixUJkp0s1V/1yHeFYptOMPn2hMYAcWrmBg+4wgwmKAl742sXOFaazpRJvjVg
TT+w8EP39T8HgHZY8lgXZjYJMZrqtvGRw946Lu3EK+o33DD10sazZ98551e48cZk
qjEjNnoNpQXydBUhFGB9RKakT1zTb8e+ZQdsrE+ZzgM9/xVFRx4gsfNbed/5TMHZ
QbwaqPzQRiS9ScRwvZ+TE20cGQ66qZqR6+JCatc8BpXA9Q6ZmTj61MSl6MMzCuOS
yIGm5J+siPkLV/ki+MAHk59G9iEsTjS1T1l4aQn0kTtdMx9oVCPODY6Jdi8jIaU/
TwGWuQECgYEAxJEg/YKjZGQFhidP64OGi1ochFZxuJFwcZ17DgmZPkiU+vpC8KYl
QpR0r0zN9vqP+71nMMoVJfektXRMP4cy0ebSAbx47X5IfdYUhID+/OAlxbl1O9ah
lGWk90zknVvQKahImtYZqepQEYyetQiDB4gX2bLT+8IIt16ebGC/TyUCgYEA5p3g
Tcj69nxyy4BuGxYuNfTORTCzd9zhURN7325HVBMlhen/f1e+yjV1zth9yLDl5Wyl
99jkVCvy6p83s+1EDKdgOTYrxgD31Y934De/m53U6P/yHeic3z9dIgIAn+qcJqU6
CL28lXEV8jKLNmlR0crWSjtSBDIpA3BWWN834l8CgYAxgcPnVZHFZROnGBue2391
dXqdMhBuReMmGl21yWEZOLqdA478gTv9KtrAk/2D6NN+udNVjHALIfYP5XyWu3xn
NVVLLqbeWeH0H4kHXl3aXrHkvLL0ITiM4ZTM3EbwAwHInCO9K5NHIkaMRPhr6/rk
WLh5Efsl+1aqqGAKN8u3KQKBgFDjcUh3RSdtkSo12ujfR8gfHLaCFYDmVZWFev5s
hNJFgPTOlZJJ6Z6tT6wEnWHmQkzNZg1f4v5vB94piHUwtJynnIWUrZfewQ8EKmzX
wPpJSuOK2paI/3UCmZ0TDLsKpEidzZRBUMMuDh+MgO3N1Sf7uFwDIIpeOap+HZtA
eC6LAoGAFaN/0hr3kBCGGUQ0MKSEw1A4jJntR+Enz5+vJ1F/yW7E3SNp5gHz8sF1
ppt3OZKtZeIoaCapIEr4hRZzzZr2zNHu3tyizscLAdcqKbt2o7OlPK7Z5mhREN8E
F4obLQI+YsAv2aOY2EFTSPq70N2OL45NLsdq3igpKZEIbpUgnwA=
-----END RSA PRIVATE KEY-----
105 changes: 103 additions & 2 deletions t/plugin/ldap-auth.t
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,8 @@ Authorization: Basic Zm9vOmZvbwo=
--- error_code: 401
--- response_body
{"message":"Invalid user authorization"}
--- error_log
The supplied credential is invalid



Expand Down Expand Up @@ -302,7 +304,7 @@ find consumer user01
ngx.HTTP_GET,
nil,
[[
{"title":"work with route or service object","required":["base_dn","ldap_uri"],"properties":{"base_dn":{"type":"string"},"ldap_uri":{"type":"string"},"use_tls":{"type":"boolean"},"disable":{"type":"boolean"},"uid":{"type":"string"}},"type":"object"}
{"title":"work with route or service object","required":["base_dn","ldap_uri"],"properties":{"base_dn":{"type":"string"},"ldap_uri":{"type":"string"},"use_tls":{"type":"boolean"},"tls_verify":{"type":"boolean"},"disable":{"type":"boolean"},"uid":{"type":"string"}},"type":"object"}
]]
)
ngx.status = code
Expand Down Expand Up @@ -338,8 +340,107 @@ find consumer user01
ngx.HTTP_GET,
nil,
[[
{"title":"work with route or service object","required":["base_dn","ldap_uri"],"properties":{"base_dn":{"type":"string"},"ldap_uri":{"type":"string"},"use_tls":{"type":"boolean"},"disable":{"type":"boolean"},"uid":{"type":"string"}},"type":"object"} ]]
{"title":"work with route or service object","required":["base_dn","ldap_uri"],"properties":{"base_dn":{"type":"string"},"ldap_uri":{"type":"string"},"use_tls":{"type":"boolean"},"tls_verify":{"type":"boolean"},"disable":{"type":"boolean"},"uid":{"type":"string"}},"type":"object"} ]]
)
ngx.status = code
}
}



=== TEST 17: enable ldap-auth with tls
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PUT,
[[{
"plugins": {
"ldap-auth": {
"base_dn": "ou=users,dc=example,dc=org",
"ldap_uri": "localhost:1636",
"uid": "cn",
"use_tls": true
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/hello"
}]]
)

if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- response_body
passed



=== TEST 18: verify
--- request
GET /hello
--- more_headers
Authorization: Basic dXNlcjAxOnBhc3N3b3JkMQ==
--- response_body
hello world
--- error_log
find consumer user01



=== TEST 19: enable ldap-auth with tls, verify CA
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PUT,
[[{
"plugins": {
"ldap-auth": {
"base_dn": "ou=users,dc=example,dc=org",
"ldap_uri": "localhost:1636",
"uid": "cn",
"use_tls": true,
"tls_verify": true
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/hello"
}]]
)

if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- response_body
passed



=== TEST 20: verify
--- request
GET /hello
--- more_headers
Authorization: Basic dXNlcjAxOnBhc3N3b3JkMQ==
--- response_body
hello world
--- error_log
find consumer user01