mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-23 12:37:00 +01:00
Add /etc/skel templating and notes adjacent to kanidm-unixd and packaging (#1113)
This commit is contained in:
parent
692c0a3978
commit
55ee2410d7
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -19,6 +19,11 @@ orca/example_profiles/small/orca-edited.toml
|
|||
kanidm_unix_int/pam_tester/Cargo.lock
|
||||
.vscode/
|
||||
|
||||
# kanidm simple packaging
|
||||
deployment-config/
|
||||
kanidm_simple_pkg/
|
||||
kanidm-client-tools.tar.gz
|
||||
|
||||
# python things
|
||||
**/__pycache__/**
|
||||
**/.venv/**
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* Thomas Sanchez (daedric)
|
||||
* Dominik Süß (theSuess)
|
||||
* Florian Klink (flokli)
|
||||
* Kaleb Olson (kalebo)
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
|
|
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2334,6 +2334,7 @@ dependencies = [
|
|||
"toml",
|
||||
"tracing",
|
||||
"users",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -160,6 +160,7 @@ webauthn-rs-proto = "0.4.7"
|
|||
# webauthn-rs-proto = { path = "../webauthn-rs/webauthn-rs-proto" }
|
||||
web-sys = "^0.3.60"
|
||||
whoami = "^1.2.3"
|
||||
walkdir = "2"
|
||||
|
||||
yew = "^0.19.3"
|
||||
yew-agent = "^0.1.0"
|
||||
|
|
|
@ -5,5 +5,6 @@
|
|||
# home_prefix = "/home/"
|
||||
# home_attr = "uuid"
|
||||
# home_alias = "spn"
|
||||
# use_etc_skel = false
|
||||
# uid_attr_map = "spn"
|
||||
# gid_attr_map = "spn"
|
|
@ -30,6 +30,7 @@
|
|||
- [PAM and nsswitch](integrations/pam_and_nsswitch.md)
|
||||
- [RADIUS](integrations/radius.md)
|
||||
- [LDAP](integrations/ldap.md)
|
||||
- [Traefik](integrations/traefik.md)
|
||||
|
||||
# Integration Examples
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ You can also configure some unixd-specific options with the file /etc/kanidm/uni
|
|||
home_prefix = "/home/"
|
||||
home_attr = "uuid"
|
||||
home_alias = "spn"
|
||||
use_etc_skel = false
|
||||
uid_attr_map = "spn"
|
||||
gid_attr_map = "spn"
|
||||
|
||||
|
@ -73,6 +74,9 @@ Valid choices are `none`, `uuid`, `name`, `spn`. Defaults to `spn`.
|
|||
> from the name to the UUID folder. Automatic support is provided for this via the unixd
|
||||
> tasks daemon, as documented here.
|
||||
|
||||
`use_etc_skel` controls if home directories should be prepopulated with the contents of `/etc/skel`
|
||||
when first created. Defaults to false.
|
||||
|
||||
`uid_attr_map` chooses which attribute is used for domain local users in presentation. Defaults
|
||||
to `spn`. Users from a trust will always use spn.
|
||||
|
||||
|
|
56
kanidm_book/src/integrations/traefik.md
Normal file
56
kanidm_book/src/integrations/traefik.md
Normal file
|
@ -0,0 +1,56 @@
|
|||
# Traefik
|
||||
|
||||
Traefik is a flexible HTTP reverse proxy webserver that can be integrated with Docker to allow dynamic configuration
|
||||
and to automatically use LetsEncrypt to provide valid TLS certificates.
|
||||
We can leverage this in the setup of Kanidm by specifying the configuration of Kanidm and Traefik in the same [Docker Compose configuration](https://docs.docker.com/compose/).
|
||||
|
||||
## Example setup
|
||||
Create a new directory and copy the following YAML file into it as `docker-compose.yml`.
|
||||
Edit the YAML to update the LetsEncrypt account email for your domain and the FQDN where Kanidm will be made available.
|
||||
Ensure you adjust this file or Kanidm's configuration to have a matching HTTPS port; the line `traefik.http.services.kanidm.loadbalancer.server.port=8443` sets this on the Traefik side.
|
||||
> **NOTE** You will need to generate self-signed certificates for Kanidm, and copy the configuration into the `kanidm_data` volume. Some instructions are available in the "Installing the Server" section of this book.
|
||||
|
||||
|
||||
`docker-compose.yml`
|
||||
```yaml
|
||||
version: "3.4"
|
||||
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:v2.6
|
||||
container_name: traefik
|
||||
command:
|
||||
- "--certificatesresolvers.http.acme.email=admin@example.com"
|
||||
- "--certificatesresolvers.http.acme.storage=/letsencrypt/acme.json"
|
||||
- "--certificatesresolvers.http.acme.tlschallenge=true"
|
||||
- "--entrypoints.websecure.address=:443"
|
||||
- "--entrypoints.websecure.http.tls=true"
|
||||
- "--entrypoints.websecure.http.tls.certResolver=http"
|
||||
- "--log.level=INFO"
|
||||
- "--providers.docker=true"
|
||||
- "--providers.docker.exposedByDefault=false"
|
||||
- "--serverstransport.insecureskipverify=true"
|
||||
restart: always
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
ports:
|
||||
- "443:443"
|
||||
kanidm:
|
||||
container_name: kanidm
|
||||
image: kanidm/server:devel
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- kanidm_data:/data
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.kanidm.entrypoints=websecure
|
||||
- traefik.http.routers.kanidm.rule=Host(`idm.example.com`)
|
||||
- traefik.http.routers.kanidm.service=kanidm
|
||||
- traefik.http.serversTransports.kanidm.insecureSkipVerify=true
|
||||
- traefik.http.services.kanidm.loadbalancer.server.port=8443
|
||||
- traefik.http.services.kanidm.loadbalancer.server.scheme=https
|
||||
volumes:
|
||||
kanidm_data: {}
|
||||
```
|
||||
|
||||
Finally you may run `docker-compose up` to start up both Kanidm and Traefik.
|
|
@ -70,6 +70,7 @@ tokio-util = { workspace = true, features = ["codec"] }
|
|||
tracing.workspace = true
|
||||
reqwest.workspace = true
|
||||
users.workspace = true
|
||||
walkdir.workspace = true
|
||||
|
||||
[features]
|
||||
# default = [ "libsqlite3-sys/bundled" ]
|
||||
|
|
|
@ -10,5 +10,6 @@ pub const DEFAULT_SHELL: &str = "/bin/sh";
|
|||
pub const DEFAULT_HOME_PREFIX: &str = "/home/";
|
||||
pub const DEFAULT_HOME_ATTR: HomeAttr = HomeAttr::Uuid;
|
||||
pub const DEFAULT_HOME_ALIAS: Option<HomeAttr> = Some(HomeAttr::Spn);
|
||||
pub const DEFAULT_USE_ETC_SKEL: bool = false;
|
||||
pub const DEFAULT_UID_ATTR_MAP: UidAttr = UidAttr::Spn;
|
||||
pub const DEFAULT_GID_ATTR_MAP: UidAttr = UidAttr::Spn;
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
use std::ffi::CString;
|
||||
use std::os::unix::fs::symlink;
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
use std::path::Path;
|
||||
use std::time::Duration;
|
||||
use std::{fs, io};
|
||||
|
@ -29,6 +30,7 @@ use tokio::net::UnixStream;
|
|||
use tokio::time;
|
||||
use tokio_util::codec::{Decoder, Encoder, Framed};
|
||||
use users::{get_effective_gid, get_effective_uid};
|
||||
use walkdir::WalkDir;
|
||||
|
||||
struct TaskCodec;
|
||||
|
||||
|
@ -68,7 +70,18 @@ impl TaskCodec {
|
|||
}
|
||||
}
|
||||
|
||||
fn create_home_directory(info: &HomeDirectoryInfo, home_prefix: &str) -> Result<(), String> {
|
||||
fn chown(path: &Path, gid: u32) -> Result<(), String> {
|
||||
let path_os = CString::new(path.as_os_str().as_bytes())
|
||||
.map_err(|_| "Unable to create c-string".to_string())?;
|
||||
|
||||
// Change the owner to the gid - remember, kanidm ONLY has gid's, the uid is implied.
|
||||
if unsafe { lchown(path_os.as_ptr(), gid, gid) } != 0 {
|
||||
return Err("Unable to set ownership".to_string());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn create_home_directory(info: &HomeDirectoryInfo, home_prefix: &str, use_etc_skel: bool) -> Result<(), String> {
|
||||
// Final sanity check to prevent certain classes of attacks.
|
||||
let name = info
|
||||
.name
|
||||
|
@ -96,14 +109,10 @@ fn create_home_directory(info: &HomeDirectoryInfo, home_prefix: &str) -> Result<
|
|||
return Err("Invalid/Corrupt home directory path - no prefix found".to_string());
|
||||
}
|
||||
|
||||
let hd_path_os =
|
||||
CString::new(hd_path_raw.clone()).map_err(|_| "Unable to create c-string".to_string())?;
|
||||
|
||||
// Does the home directory exist?
|
||||
if !hd_path.exists() {
|
||||
// Set a umask
|
||||
let before = unsafe { umask(0o0027) };
|
||||
// TODO: Should we copy content from /etc/skel?
|
||||
// Create the dir
|
||||
if let Err(e) = fs::create_dir_all(hd_path) {
|
||||
let _ = unsafe { umask(before) };
|
||||
|
@ -111,10 +120,26 @@ fn create_home_directory(info: &HomeDirectoryInfo, home_prefix: &str) -> Result<
|
|||
}
|
||||
let _ = unsafe { umask(before) };
|
||||
|
||||
// Change the owner to the gid - remember, kanidm ONLY has gid's, the uid is implied.
|
||||
chown(hd_path, info.gid)?;
|
||||
|
||||
if unsafe { lchown(hd_path_os.as_ptr(), info.gid, info.gid) } != 0 {
|
||||
return Err("Unable to set ownership".to_string());
|
||||
// Copy in structure from /etc/skel/ if present
|
||||
let skel_dir = Path::new("/etc/skel/");
|
||||
if use_etc_skel && skel_dir.exists() {
|
||||
info!("preparing homedir using /etc/skel");
|
||||
for entry in WalkDir::new(skel_dir).into_iter().filter_map(|e| e.ok()) {
|
||||
let dest = &hd_path.join(
|
||||
entry
|
||||
.path()
|
||||
.strip_prefix(skel_dir)
|
||||
.map_err(|e| e.to_string())?,
|
||||
);
|
||||
if entry.path().is_dir() {
|
||||
fs::create_dir_all(dest).map_err(|e| e.to_string())?;
|
||||
} else {
|
||||
fs::copy(entry.path(), dest).map_err(|e| e.to_string())?;
|
||||
}
|
||||
chown(dest, info.gid)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,7 +191,7 @@ fn create_home_directory(info: &HomeDirectoryInfo, home_prefix: &str) -> Result<
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn handle_tasks(stream: UnixStream, home_prefix: &str) {
|
||||
async fn handle_tasks(stream: UnixStream, cfg: &KanidmUnixdConfig) {
|
||||
let mut reqs = Framed::new(stream, TaskCodec::new());
|
||||
|
||||
loop {
|
||||
|
@ -174,7 +199,7 @@ async fn handle_tasks(stream: UnixStream, home_prefix: &str) {
|
|||
Some(Ok(TaskRequest::HomeDirectory(info))) => {
|
||||
debug!("Received task -> HomeDirectory({:?})", info);
|
||||
|
||||
let resp = match create_home_directory(&info, home_prefix) {
|
||||
let resp = match create_home_directory(&info, &cfg.home_prefix, cfg.use_etc_skel) {
|
||||
Ok(()) => TaskResponse::Success,
|
||||
Err(msg) => TaskResponse::Error(msg),
|
||||
};
|
||||
|
@ -249,7 +274,7 @@ async fn main() {
|
|||
info!("Found kanidm_unixd, waiting for tasks ...");
|
||||
// Yep! Now let the main handler do it's job.
|
||||
// If it returns (dc, etc, then we loop and try again).
|
||||
handle_tasks(stream, &cfg.home_prefix).await;
|
||||
handle_tasks(stream, &cfg).await;
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Unable to find kanidm_unixd, sleeping ...");
|
||||
|
|
|
@ -9,7 +9,7 @@ use serde::Deserialize;
|
|||
use crate::constants::{
|
||||
DEFAULT_CACHE_TIMEOUT, DEFAULT_CONN_TIMEOUT, DEFAULT_DB_PATH, DEFAULT_GID_ATTR_MAP,
|
||||
DEFAULT_HOME_ALIAS, DEFAULT_HOME_ATTR, DEFAULT_HOME_PREFIX, DEFAULT_SHELL, DEFAULT_SOCK_PATH,
|
||||
DEFAULT_TASK_SOCK_PATH, DEFAULT_UID_ATTR_MAP,
|
||||
DEFAULT_TASK_SOCK_PATH, DEFAULT_UID_ATTR_MAP, DEFAULT_USE_ETC_SKEL,
|
||||
};
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
|
@ -24,6 +24,7 @@ struct ConfigInt {
|
|||
home_prefix: Option<String>,
|
||||
home_attr: Option<String>,
|
||||
home_alias: Option<String>,
|
||||
use_etc_skel: Option<bool>,
|
||||
uid_attr_map: Option<String>,
|
||||
gid_attr_map: Option<String>,
|
||||
}
|
||||
|
@ -81,6 +82,7 @@ pub struct KanidmUnixdConfig {
|
|||
pub home_prefix: String,
|
||||
pub home_attr: HomeAttr,
|
||||
pub home_alias: Option<HomeAttr>,
|
||||
pub use_etc_skel: bool,
|
||||
pub uid_attr_map: UidAttr,
|
||||
pub gid_attr_map: UidAttr,
|
||||
}
|
||||
|
@ -135,6 +137,7 @@ impl KanidmUnixdConfig {
|
|||
home_prefix: DEFAULT_HOME_PREFIX.to_string(),
|
||||
home_attr: DEFAULT_HOME_ATTR,
|
||||
home_alias: DEFAULT_HOME_ALIAS,
|
||||
use_etc_skel: DEFAULT_USE_ETC_SKEL,
|
||||
uid_attr_map: DEFAULT_UID_ATTR_MAP,
|
||||
gid_attr_map: DEFAULT_GID_ATTR_MAP,
|
||||
}
|
||||
|
@ -220,6 +223,7 @@ impl KanidmUnixdConfig {
|
|||
}
|
||||
})
|
||||
.unwrap_or(self.home_alias),
|
||||
use_etc_skel: config.use_etc_skel.unwrap_or(self.use_etc_skel),
|
||||
uid_attr_map: config
|
||||
.uid_attr_map
|
||||
.and_then(|v| match v.as_str() {
|
||||
|
|
19
platform/debian/pam-config-kanidm
Normal file
19
platform/debian/pam-config-kanidm
Normal file
|
@ -0,0 +1,19 @@
|
|||
Name: Kanidm Authentication
|
||||
Default: yes
|
||||
Priority: 300
|
||||
|
||||
Auth-Type: Primary
|
||||
Auth:
|
||||
[success=end new_authtok_reqd=done default=ignore] pam_kanidm.so ignore_unknown_user
|
||||
|
||||
Account-Type: Primary
|
||||
Account:
|
||||
[success=end new_authtok_reqd=done default=ignore] pam_kanidm.so ignore_unknown_user
|
||||
|
||||
Session-Type: Additional
|
||||
Session:
|
||||
optional pam_kanidm.so
|
||||
|
||||
Password-Type: Additional
|
||||
Password:
|
||||
optional pam_kanidm.so
|
83
platform/debian/simple_pkg.sh
Executable file
83
platform/debian/simple_pkg.sh
Executable file
|
@ -0,0 +1,83 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -xe
|
||||
|
||||
## NOTE this is based on the Arch Linux PKGBUILD. It combines kanidm_tools, unixd and ssh
|
||||
# as well as the systemd services. This is a simple alternative for building a tarball for
|
||||
# use on debian based systems (tested on ubuntu 22.04).
|
||||
|
||||
pushd "$( dirname -- "$0"; )/../../"
|
||||
|
||||
pkgdir=$(realpath kanidm_simple_pkg)
|
||||
rm -rf "$pkgdir"
|
||||
mkdir -p "$pkgdir"
|
||||
|
||||
# build the project
|
||||
make release/kanidm release/kanidm-unixd
|
||||
|
||||
# enable the following block to include deployment specific configuration files
|
||||
if [ 1 -eq 0 ]; then
|
||||
mkdir -p deployment-config
|
||||
|
||||
# Customize the following heredocs according to the deployment
|
||||
cat << EOF > deployment-config/config
|
||||
uri = "https://idm.example.com"
|
||||
verify_ca = true
|
||||
verify_hostnames = true
|
||||
EOF
|
||||
|
||||
cat << EOF > deployment-config/unixd
|
||||
pam_allowed_login_groups = [""]
|
||||
EOF
|
||||
|
||||
install -Dm644 deployment-config/config "${pkgdir}/etc/kanidm/config"
|
||||
install -Dm644 deployment-config/unixd "${pkgdir}/etc/kanidm/unixd"
|
||||
|
||||
fi
|
||||
|
||||
# This is for allowing login via PAM. It needs to be enabled using `pam-auth-update`
|
||||
install -Dm644 platform/debian/pam-config-kanidm "${pkgdir}/usr/share/pam-configs/kanidm"
|
||||
|
||||
# Install kanidm cli
|
||||
install -Dm755 target/release/kanidm "${pkgdir}/usr/local/sbin/kanidm"
|
||||
install -Dm644 target/release/build/completions/_kanidm "${pkgdir}/usr/share/zsh/site-functions/_kanidm"
|
||||
install -Dm644 target/release/build/completions/kanidm.bash "${pkgdir}/usr/share/bash-completion/completions/kanidm.sh"
|
||||
|
||||
# Install systemd service files
|
||||
install -Dm644 examples/systemd/kanidm-unixd.service "${pkgdir}/usr/lib/systemd/system/kanidm-unixd.service"
|
||||
install -Dm644 examples/systemd/kanidm-unixd-tasks.service "${pkgdir}/usr/lib/systemd/system/kanidm-unixd-tasks.service"
|
||||
|
||||
# NB., the debian style lib dir and security dir
|
||||
install -Dm755 target/release/libnss_kanidm.so "${pkgdir}/usr/lib/x86_64-linux-gnu/libnss_kanidm.so.2"
|
||||
install -Dm755 target/release/libpam_kanidm.so "${pkgdir}/usr/lib/x86_64-linux-gnu/security/pam_kanidm.so"
|
||||
|
||||
# install kanidm unix utilities
|
||||
install -Dm755 target/release/kanidm_cache_clear "${pkgdir}/usr/local/sbin/kanidm_cache_clear"
|
||||
install -Dm755 target/release/kanidm_cache_invalidate "${pkgdir}/usr/local/sbin/kanidm_cache_invalidate"
|
||||
install -Dm755 target/release/kanidm_ssh_authorizedkeys "${pkgdir}/usr/local/sbin/kanidm_ssh_authorizedkeys"
|
||||
install -Dm755 target/release/kanidm_ssh_authorizedkeys_direct "${pkgdir}/usr/local/sbin/kanidm_ssh_authorizedkeys_direct"
|
||||
install -Dm755 target/release/kanidm_unixd "${pkgdir}/usr/local/sbin/kanidm_unixd"
|
||||
install -Dm755 target/release/kanidm_unixd_status "${pkgdir}/usr/local/sbin/kanidm_unixd_status"
|
||||
install -Dm755 target/release/kanidm_unixd_tasks "${pkgdir}/usr/local/sbin/kanidm_unixd_tasks"
|
||||
|
||||
# Install Bash and ZSH completions
|
||||
install -Dm644 target/release/build/completions/_kanidm_ssh_authorizedkeys_direct "${pkgdir}/usr/share/zsh/site-functions/_kanidm_ssh_authorizedkeys_direct"
|
||||
install -Dm644 target/release/build/completions/_kanidm_cache_clear "${pkgdir}/usr/share/zsh/site-functions/_kanidm_cache_clear"
|
||||
install -Dm644 target/release/build/completions/_kanidm_cache_invalidate "${pkgdir}/usr/share/zsh/site-functions/_kanidm_cache_invalidate"
|
||||
install -Dm644 target/release/build/completions/_kanidm_ssh_authorizedkeys "${pkgdir}/usr/share/zsh/site-functions/_kanidm_ssh_authorizedkeys"
|
||||
install -Dm644 target/release/build/completions/_kanidm_unixd_status "${pkgdir}/usr/share/zsh/site-functions/_kanidm_unixd_status"
|
||||
|
||||
install -Dm644 target/release/build/completions/kanidm_ssh_authorizedkeys_direct.bash "${pkgdir}/usr/share/bash-completion/completions/kanidm_ssh_authorizedkeys_direct.sh"
|
||||
install -Dm644 target/release/build/completions/kanidm_cache_clear.bash "${pkgdir}/usr/share/bash-completion/completions/kanidm_cache_clear.sh"
|
||||
install -Dm644 target/release/build/completions/kanidm_cache_invalidate.bash "${pkgdir}/usr/share/bash-completion/completions/kanidm_cache_invalidate.sh"
|
||||
install -Dm644 target/release/build/completions/kanidm_ssh_authorizedkeys.bash "${pkgdir}/usr/share/bash-completion/completions/kanidm_ssh_authorizedkeys.sh"
|
||||
install -Dm644 target/release/build/completions/kanidm_unixd_status.bash "${pkgdir}/usr/share/bash-completion/completions/kanidm_unixd_status.sh"
|
||||
|
||||
tar cvzf "kanidm-client-tools.tar.gz" -C "$pkgdir" .
|
||||
|
||||
# extract the package in root, enable and run the systemd services and then setup nsswitch according to the docs
|
||||
# and run pam-auth-update. You may also want to setup the ssh config. It's wise to leave a root console open until
|
||||
# you've confirmed pam-auth-update worked so you don't lock yourself out.
|
||||
|
||||
popd
|
||||
|
Loading…
Reference in a new issue