mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-24 04:57:00 +01:00
Improving logging and docs around unixd/PAM/NSS (#577)
This commit is contained in:
parent
0c1ad4e5fe
commit
ea8801f23d
|
@ -241,6 +241,35 @@ edit the content.
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Check POSIX-status of group and config
|
||||||
|
|
||||||
|
If authentication is failing via PAM, make sure that a list of groups is configured in `/etc/kanidm/unixd`:
|
||||||
|
|
||||||
|
```
|
||||||
|
pam_allowed_login_groups = ["example_group"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Check the status of the group with `kanidm group posix show example_group`. If you get something similar to the below:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
> kanidm group posix show example_group
|
||||||
|
Using cached token for name idm_admin
|
||||||
|
Error -> Http(500, Some(InvalidAccountState("Missing class: account && posixaccount OR group && posixgroup")), "b71f137e-39f3-4368-9e58-21d26671ae24")
|
||||||
|
```
|
||||||
|
|
||||||
|
POSIX-enable the group with `kanidm group posix set example_group`. You should get a result similar to this when you search for your group name:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
> kanidm group posix show example_group
|
||||||
|
[ spn: example_group@kanidm.example.com, gidnumber: 3443347205 name: example_group, uuid: b71f137e-39f3-4368-9e58-21d26671ae24 ]
|
||||||
|
```
|
||||||
|
|
||||||
|
Also, ensure the target user is in the group by running:
|
||||||
|
|
||||||
|
```
|
||||||
|
> kanidm group list_members example_group
|
||||||
|
```
|
||||||
|
|
||||||
### Increase logging
|
### Increase logging
|
||||||
|
|
||||||
For the unixd daemon, you can increase the logging with:
|
For the unixd daemon, you can increase the logging with:
|
||||||
|
@ -262,10 +291,10 @@ To debug the pam module interactions add `debug` to the module arguments such as
|
||||||
|
|
||||||
### Check the socket permissions
|
### Check the socket permissions
|
||||||
|
|
||||||
Check that the /var/run/kanidm-unixd/sock is 777, and that non-root readers can see it with
|
Check that the `/var/run/kanidm-unixd/sock` is 777, and that non-root readers can see it with
|
||||||
ls or other tools.
|
ls or other tools.
|
||||||
|
|
||||||
Ensure that /var/run/kanidm-unixd/task_sock is 700, and that it is owned by the kanidm unixd
|
Ensure that `/var/run/kanidm-unixd/task_sock` is 700, and that it is owned by the kanidm unixd
|
||||||
process user.
|
process user.
|
||||||
|
|
||||||
### Check you can access the kanidm server
|
### Check you can access the kanidm server
|
||||||
|
@ -279,6 +308,15 @@ You can check this with the client tools:
|
||||||
You should have:
|
You should have:
|
||||||
|
|
||||||
/usr/lib64/libnss_kanidm.so.2
|
/usr/lib64/libnss_kanidm.so.2
|
||||||
|
/usr/lib64/security/pam_kanidm.so
|
||||||
|
|
||||||
|
The exact path *may* change depending on your distribution, `pam_unixd.so` should be co-located with pam_kanidm.so so looking for it findable with:
|
||||||
|
|
||||||
|
```
|
||||||
|
find /usr/ -name 'pam_unix.so'
|
||||||
|
```
|
||||||
|
|
||||||
|
For example, on a Debian machine, it's located in `/usr/lib/x86_64-linux-gnu/security/`.
|
||||||
|
|
||||||
### Increase connection timeout
|
### Increase connection timeout
|
||||||
|
|
||||||
|
|
|
@ -94,31 +94,42 @@ impl PamHooks for PamKanidm {
|
||||||
match call_daemon_blocking(cfg.sock_path.as_str(), &req) {
|
match call_daemon_blocking(cfg.sock_path.as_str(), &req) {
|
||||||
Ok(r) => match r {
|
Ok(r) => match r {
|
||||||
ClientResponse::PamStatus(Some(true)) => {
|
ClientResponse::PamStatus(Some(true)) => {
|
||||||
// println!("PAM_SUCCESS");
|
if opts.debug {
|
||||||
|
println!("PamResultCode::PAM_SUCCESS");
|
||||||
|
}
|
||||||
PamResultCode::PAM_SUCCESS
|
PamResultCode::PAM_SUCCESS
|
||||||
}
|
}
|
||||||
ClientResponse::PamStatus(Some(false)) => {
|
ClientResponse::PamStatus(Some(false)) => {
|
||||||
// println!("PAM_IGNORE");
|
// println!("PAM_IGNORE");
|
||||||
|
if opts.debug {
|
||||||
|
println!("PamResultCode::PAM_AUTH_ERR");
|
||||||
|
}
|
||||||
PamResultCode::PAM_AUTH_ERR
|
PamResultCode::PAM_AUTH_ERR
|
||||||
}
|
}
|
||||||
ClientResponse::PamStatus(None) => {
|
ClientResponse::PamStatus(None) => {
|
||||||
if opts.ignore_unknown_user {
|
if opts.ignore_unknown_user {
|
||||||
|
if opts.debug {
|
||||||
|
println!("PamResultCode::PAM_IGNORE");
|
||||||
|
}
|
||||||
PamResultCode::PAM_IGNORE
|
PamResultCode::PAM_IGNORE
|
||||||
} else {
|
} else {
|
||||||
|
if opts.debug {
|
||||||
|
println!("PamResultCode::PAM_USER_UNKNOWN");
|
||||||
|
}
|
||||||
PamResultCode::PAM_USER_UNKNOWN
|
PamResultCode::PAM_USER_UNKNOWN
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// unexpected response.
|
// unexpected response.
|
||||||
if opts.debug {
|
if opts.debug {
|
||||||
println!("PAM_IGNORE -> {:?}", r);
|
println!("PamResultCode::PAM_IGNORE -> {:?}", r);
|
||||||
}
|
}
|
||||||
PamResultCode::PAM_IGNORE
|
PamResultCode::PAM_IGNORE
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if opts.debug {
|
if opts.debug {
|
||||||
println!("PAM_IGNORE -> {:?}", e);
|
println!("PamResultCode::PAM_IGNORE -> {:?}", e);
|
||||||
}
|
}
|
||||||
PamResultCode::PAM_IGNORE
|
PamResultCode::PAM_IGNORE
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,6 +80,10 @@ impl CacheLayer {
|
||||||
dbtxn.commit()?;
|
dbtxn.commit()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if pam_allow_groups.len() == 0 {
|
||||||
|
eprintln!("Will not be able to authenticate users, pam_allow_groups config is not configured.");
|
||||||
|
}
|
||||||
|
|
||||||
// We assume we are offline at start up, and we mark the next "online check" as
|
// We assume we are offline at start up, and we mark the next "online check" as
|
||||||
// being valid from "now".
|
// being valid from "now".
|
||||||
Ok(CacheLayer {
|
Ok(CacheLayer {
|
||||||
|
@ -858,21 +862,30 @@ impl CacheLayer {
|
||||||
pub async fn pam_account_allowed(&self, account_id: &str) -> Result<Option<bool>, ()> {
|
pub async fn pam_account_allowed(&self, account_id: &str) -> Result<Option<bool>, ()> {
|
||||||
let token = self.get_usertoken(Id::Name(account_id.to_string())).await?;
|
let token = self.get_usertoken(Id::Name(account_id.to_string())).await?;
|
||||||
|
|
||||||
Ok(token.map(|tok| {
|
if self.pam_allow_groups.len() == 0 {
|
||||||
let user_set: BTreeSet<_> = tok
|
// can't allow anything if the group list is zero...
|
||||||
.groups
|
eprintln!("Cannot authenticate users, no allowed groups in configuration!");
|
||||||
.iter()
|
Ok(Some(false))
|
||||||
.map(|g| vec![g.name.clone(), g.spn.clone(), g.uuid.clone()])
|
} else {
|
||||||
.flatten()
|
Ok(token.map(|tok| {
|
||||||
.collect();
|
let user_set: BTreeSet<_> = tok
|
||||||
|
.groups
|
||||||
|
.iter()
|
||||||
|
.map(|g| vec![g.name.clone(), g.spn.clone(), g.uuid.clone()])
|
||||||
|
.flatten()
|
||||||
|
.collect();
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"Checking if -> {:?} & {:?}",
|
"Checking if user is in allowed groups ({:?}) -> {:?}",
|
||||||
user_set, self.pam_allow_groups
|
self.pam_allow_groups, user_set,
|
||||||
);
|
);
|
||||||
|
let intersection_count = user_set.intersection(&self.pam_allow_groups).count();
|
||||||
|
debug!("Number of intersecting groups: {}", intersection_count);
|
||||||
|
debug!("User has valid token: {}", tok.valid);
|
||||||
|
|
||||||
user_set.intersection(&self.pam_allow_groups).count() > 0 && tok.valid
|
intersection_count > 0 && tok.valid
|
||||||
}))
|
}))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn pam_account_authenticate(
|
pub async fn pam_account_authenticate(
|
||||||
|
|
Loading…
Reference in a new issue