add debug output to lldap with mitmdump module
This commit is contained in:
parent
d824da617c
commit
b4d6965231
3 changed files with 102 additions and 48 deletions
|
|
@ -342,7 +342,7 @@ in
|
||||||
allow ${cfg.restrictAccessIPRange};
|
allow ${cfg.restrictAccessIPRange};
|
||||||
deny all;
|
deny all;
|
||||||
'');
|
'');
|
||||||
proxyPass = "http://${toString config.services.lldap.settings.http_host}:${toString config.services.lldap.settings.http_port}/";
|
proxyPass = "http://${toString config.services.lldap.settings.http_host}:${toString config.shb.lldap.webUIListenPort}/";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
@ -366,10 +366,10 @@ in
|
||||||
settings = {
|
settings = {
|
||||||
http_url = "https://${fqdn}";
|
http_url = "https://${fqdn}";
|
||||||
http_host = "127.0.0.1";
|
http_host = "127.0.0.1";
|
||||||
http_port = cfg.webUIListenPort;
|
http_port = if !cfg.debug then cfg.webUIListenPort else cfg.webUIListenPort + 1;
|
||||||
|
|
||||||
ldap_host = "127.0.0.1";
|
ldap_host = "127.0.0.1";
|
||||||
ldap_port = cfg.ldapPort;
|
ldap_port = cfg.ldapPort; # Would be great to be able to inspect this but it requires tcpdump instead of mitmproxy.
|
||||||
ldap_base_dn = cfg.dcdomain;
|
ldap_base_dn = cfg.dcdomain;
|
||||||
|
|
||||||
ldap_user_pass_file = toString cfg.ldapUserPassword.result.path;
|
ldap_user_pass_file = toString cfg.ldapUserPassword.result.path;
|
||||||
|
|
@ -384,5 +384,15 @@ in
|
||||||
"password_file" = toString v.password.result.path;
|
"password_file" = toString v.password.result.path;
|
||||||
}) cfg.ensureUsers;
|
}) cfg.ensureUsers;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
shb.mitmdump.instances."lldap-web" = lib.mkIf cfg.debug {
|
||||||
|
listenPort = config.shb.lldap.webUIListenPort;
|
||||||
|
upstreamPort = config.shb.lldap.webUIListenPort + 1;
|
||||||
|
after = [ "lldap.service" ];
|
||||||
|
enabledAddons = [ config.shb.mitmdump.addons.logger ];
|
||||||
|
extraArgs = [
|
||||||
|
"--set" "verbose_pattern=/api"
|
||||||
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -168,6 +168,15 @@ so you will want to revert this at some point.
|
||||||
|
|
||||||
To see the logs, then run `journalctl -u lldap.service`.
|
To see the logs, then run `journalctl -u lldap.service`.
|
||||||
|
|
||||||
|
Setting the `debug` option to `true` will also
|
||||||
|
add an [shb.mitmdump][] instance in front of the LLDAP [web UI port](#blocks-lldap-options-shb.lldap.webUIListenPort)
|
||||||
|
which prints all requests and responses headers and body
|
||||||
|
to the systemd service `mitmdump-lldap.service`. Note the you won't
|
||||||
|
see the query done using something like `ldapsearch` since those
|
||||||
|
go through the [`LDAP` port](#blocks-lldap-options-shb.lldap.ldapPort).
|
||||||
|
|
||||||
|
[shb.mitmdump]: ./blocks-mitmdump.html
|
||||||
|
|
||||||
## Tests {#blocks-lldap-tests}
|
## Tests {#blocks-lldap-tests}
|
||||||
|
|
||||||
Specific integration tests are defined in [`/test/blocks/lldap.nix`](@REPO@/test/blocks/lldap.nix).
|
Specific integration tests are defined in [`/test/blocks/lldap.nix`](@REPO@/test/blocks/lldap.nix).
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ in
|
||||||
}
|
}
|
||||||
../../modules/blocks/hardcodedsecret.nix
|
../../modules/blocks/hardcodedsecret.nix
|
||||||
../../modules/blocks/lldap.nix
|
../../modules/blocks/lldap.nix
|
||||||
|
../../modules/blocks/mitmdump.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
shb.lldap = {
|
shb.lldap = {
|
||||||
|
|
@ -29,7 +30,6 @@ in
|
||||||
domain = "example.com";
|
domain = "example.com";
|
||||||
ldapUserPassword.result = config.shb.hardcodedsecret.ldapUserPassword.result;
|
ldapUserPassword.result = config.shb.hardcodedsecret.ldapUserPassword.result;
|
||||||
jwtSecret.result = config.shb.hardcodedsecret.jwtSecret.result;
|
jwtSecret.result = config.shb.hardcodedsecret.jwtSecret.result;
|
||||||
debug = true;
|
|
||||||
|
|
||||||
ensureUsers = {
|
ensureUsers = {
|
||||||
"charlie" = {
|
"charlie" = {
|
||||||
|
|
@ -56,64 +56,99 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.firewall.allowedTCPPorts = [ 80 ]; # nginx port
|
networking.firewall.allowedTCPPorts = [ 80 ]; # nginx port
|
||||||
|
|
||||||
|
environment.systemPackages = [ pkgs.openldap ];
|
||||||
|
|
||||||
|
specialisation = {
|
||||||
|
withDebug.configuration = {
|
||||||
|
shb.lldap.debug = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
nodes.client = {};
|
nodes.client = {};
|
||||||
|
|
||||||
# Inspired from https://github.com/lldap/lldap/blob/33f50d13a2e2d24a3e6bb05a148246bc98090df0/example_configs/lldap-ha-auth.sh
|
# Inspired from https://github.com/lldap/lldap/blob/33f50d13a2e2d24a3e6bb05a148246bc98090df0/example_configs/lldap-ha-auth.sh
|
||||||
testScript = { nodes, ... }: ''
|
testScript = { nodes, ... }:
|
||||||
|
let
|
||||||
|
specializations = "${nodes.server.system.build.toplevel}/specialisation";
|
||||||
|
in
|
||||||
|
''
|
||||||
import json
|
import json
|
||||||
|
|
||||||
start_all()
|
start_all()
|
||||||
server.wait_for_unit("lldap.service")
|
|
||||||
server.wait_for_open_port(${toString nodes.server.services.lldap.settings.http_port})
|
|
||||||
|
|
||||||
with subtest("fail without authenticating"):
|
def tests():
|
||||||
client.fail(
|
server.wait_for_unit("lldap.service")
|
||||||
"curl -f -s -X GET"
|
server.wait_for_open_port(${toString nodes.server.shb.lldap.webUIListenPort})
|
||||||
+ """ -H "Content-type: application/json" """
|
server.wait_for_open_port(${toString nodes.server.shb.lldap.ldapPort})
|
||||||
+ """ -H "Host: ldap.example.com" """
|
|
||||||
+ " http://server/api/graphql"
|
|
||||||
)
|
|
||||||
|
|
||||||
with subtest("fail authenticating with wrong credentials"):
|
with subtest("fail without authenticating"):
|
||||||
client.fail(
|
client.fail(
|
||||||
"curl -f -s -X POST"
|
"curl -f -s -X GET"
|
||||||
+ """ -H "Content-type: application/json" """
|
+ """ -H "Content-type: application/json" """
|
||||||
+ """ -H "Host: ldap.example.com" """
|
+ """ -H "Host: ldap.example.com" """
|
||||||
+ " http://server/auth/simple/login"
|
+ " http://server/api/graphql"
|
||||||
+ """ -d '{"username": "admin", "password": "wrong"}'"""
|
)
|
||||||
)
|
|
||||||
|
|
||||||
with subtest("succeed with correct authentication"):
|
with subtest("fail authenticating with wrong credentials"):
|
||||||
token = json.loads(client.succeed(
|
resp = client.fail(
|
||||||
"curl -f -s -X POST "
|
"curl -f -s -X POST"
|
||||||
+ """ -H "Content-type: application/json" """
|
+ """ -H "Content-type: application/json" """
|
||||||
+ """ -H "Host: ldap.example.com" """
|
+ """ -H "Host: ldap.example.com" """
|
||||||
+ " http://server/auth/simple/login "
|
+ " http://server/auth/simple/login"
|
||||||
+ """ -d '{"username": "admin", "password": "${password}"}' """
|
+ """ -d '{"username": "admin", "password": "wrong"}'"""
|
||||||
))['token']
|
)
|
||||||
|
|
||||||
data = json.loads(client.succeed(
|
print(resp)
|
||||||
"curl -f -s -X POST "
|
|
||||||
+ """ -H "Content-type: application/json" """
|
|
||||||
+ """ -H "Host: ldap.example.com" """
|
|
||||||
+ """ -H "Authorization: Bearer {token}" """.format(token=token)
|
|
||||||
+ " http://server/api/graphql "
|
|
||||||
+ """ -d '{"variables": {"id": "admin"}, "query":"query($id:String!){user(userId:$id){displayName groups{displayName}}}"}' """
|
|
||||||
))['data']
|
|
||||||
|
|
||||||
assert data['user']['displayName'] == "Administrator"
|
with subtest("succeed with correct authentication"):
|
||||||
assert data['user']['groups'][0]['displayName'] == "lldap_admin"
|
token = json.loads(client.succeed(
|
||||||
|
"curl -f -s -X POST "
|
||||||
|
+ """ -H "Content-type: application/json" """
|
||||||
|
+ """ -H "Host: ldap.example.com" """
|
||||||
|
+ " http://server/auth/simple/login "
|
||||||
|
+ """ -d '{"username": "admin", "password": "${password}"}' """
|
||||||
|
))['token']
|
||||||
|
|
||||||
with subtest("succeed charlie"):
|
data = json.loads(client.succeed(
|
||||||
client.succeed(
|
"curl -f -s -X POST "
|
||||||
"curl -f -s -X POST "
|
+ """ -H "Content-type: application/json" """
|
||||||
+ """ -H "Content-type: application/json" """
|
+ """ -H "Host: ldap.example.com" """
|
||||||
+ """ -H "Host: ldap.example.com" """
|
+ """ -H "Authorization: Bearer {token}" """.format(token=token)
|
||||||
+ " http://server/auth/simple/login "
|
+ " http://server/api/graphql "
|
||||||
+ """ -d '{"username": "charlie", "password": "${charliePassword}"}' """
|
+ """ -d '{"variables": {"id": "admin"}, "query":"query($id:String!){user(userId:$id){displayName groups{displayName}}}"}' """
|
||||||
)
|
))['data']
|
||||||
|
|
||||||
|
assert data['user']['displayName'] == "Administrator"
|
||||||
|
assert data['user']['groups'][0]['displayName'] == "lldap_admin"
|
||||||
|
|
||||||
|
with subtest("succeed charlie"):
|
||||||
|
resp = client.succeed(
|
||||||
|
"curl -f -s -X POST "
|
||||||
|
+ """ -H "Content-type: application/json" """
|
||||||
|
+ """ -H "Host: ldap.example.com" """
|
||||||
|
+ " http://server/auth/simple/login "
|
||||||
|
+ """ -d '{"username": "charlie", "password": "${charliePassword}"}' """
|
||||||
|
)
|
||||||
|
print(resp)
|
||||||
|
|
||||||
|
with subtest("ldap user search"):
|
||||||
|
resp = server.succeed('ldapsearch -H ldap://127.0.0.1:${toString nodes.server.shb.lldap.ldapPort} -D uid=admin,ou=people,dc=example,dc=com -b "ou=people,dc=example,dc=com" -w ${password}')
|
||||||
|
print(resp)
|
||||||
|
|
||||||
|
if "uid=admin" not in resp:
|
||||||
|
raise Exception("Expected to find admin")
|
||||||
|
|
||||||
|
if "uid=charlie" not in resp:
|
||||||
|
raise Exception("Expected to find charlie")
|
||||||
|
|
||||||
|
with subtest("no debug"):
|
||||||
|
tests()
|
||||||
|
|
||||||
|
with subtest("with debug"):
|
||||||
|
server.succeed('${specializations}/withDebug/bin/switch-to-configuration test')
|
||||||
|
tests()
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue