From 1b9150a54b5cb0b512265cdcf88ad10c9a4a55b1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Isma=C3=ABl=20Bouya?= Date: Sat, 19 Oct 2019 10:26:54 +0200 Subject: [PATCH] Make ssh ldap connection by modules --- modules/private/gitolite/default.nix | 4 + modules/private/gitolite/ldap_gitolite.sh | 33 +++++++ modules/private/pub/default.nix | 4 + modules/private/pub/ldap_pub.sh | 56 +++++++++++ modules/private/ssh/default.nix | 59 ++++++++++- modules/private/ssh/ldap_authorized_keys.sh | 102 +------------------- modules/private/ssh/ldap_regular.sh | 19 ++++ 7 files changed, 173 insertions(+), 104 deletions(-) create mode 100644 modules/private/gitolite/ldap_gitolite.sh create mode 100644 modules/private/pub/ldap_pub.sh create mode 100644 modules/private/ssh/ldap_regular.sh diff --git a/modules/private/gitolite/default.nix b/modules/private/gitolite/default.nix index dc068b7..94ab134 100644 --- a/modules/private/gitolite/default.nix +++ b/modules/private/gitolite/default.nix @@ -11,6 +11,10 @@ in { }; config = lib.mkIf cfg.enable { + myServices.ssh.modules = [{ + snippet = builtins.readFile ./ldap_gitolite.sh; + dependencies = [ pkgs.gitolite ]; + }]; services.backup.profiles.gitolite = { rootDir = cfg.gitoliteDir; }; diff --git a/modules/private/gitolite/ldap_gitolite.sh b/modules/private/gitolite/ldap_gitolite.sh new file mode 100644 index 0000000..23cb2bf --- /dev/null +++ b/modules/private/gitolite/ldap_gitolite.sh @@ -0,0 +1,33 @@ +### This snippet is not standalone and must be integrated in the global ldap_authorized_keys.sh +LDAP_GITOLITE_MEMBER="cn=users,cn=gitolite,ou=services,dc=immae,dc=eu" +GITOLITE_SHELL=$(which gitolite-shell) + +if [[ $user == gitolite ]]; then + ldap_search '(&(memberOf='$LDAP_GITOLITE_MEMBER')('$KEY'=*))' $KEY | \ + while read line ; + do + if [ ! -z "$line" ]; then + if [[ $line == dn* ]]; then + user=$(sed -n 's/.*uid=\([^,]*\).*/\1/p' <<< "$line") + if [ -n "$user" ]; then + if [[ $user == "immae" ]] || [[ $user == "denise" ]]; then + # Capitalize first letter (backward compatibility) + user=$(sed -r 's/^([a-z])/\U\1/' <<< "$user") + fi + else + # Service fake user + user=$(sed -n 's/.*cn=\([^,]*\).*/\1/p' <<< "$line") + fi + elif [[ $line == $KEY* ]]; then + key=$(clean_key_line git "$line") + if [ ! -z "$key" ]; then + if [[ $key != *$'\n'* ]] && [[ $key == ssh-* ]]; then + echo -n 'command="'$GITOLITE_SHELL' '$user'",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ' + echo $key + fi + fi + fi + fi + done + exit 0 +fi diff --git a/modules/private/pub/default.nix b/modules/private/pub/default.nix index a193d17..7eaabc9 100644 --- a/modules/private/pub/default.nix +++ b/modules/private/pub/default.nix @@ -11,6 +11,10 @@ }; config = lib.mkIf config.myServices.pub.enable { + myServices.ssh.modules = [{ + snippet = builtins.readFile ./ldap_pub.sh; + dependencies = [ pkgs.coreutils ]; + }]; services.backup.profiles.pub = { rootDir = "/var/lib/pub"; }; diff --git a/modules/private/pub/ldap_pub.sh b/modules/private/pub/ldap_pub.sh new file mode 100644 index 0000000..bbbefdc --- /dev/null +++ b/modules/private/pub/ldap_pub.sh @@ -0,0 +1,56 @@ +### This snippet is not standalone and must be integrated in the global ldap_authorized_keys.sh +LDAP_PUB_RESTRICT_MEMBER="cn=restrict,cn=pub,ou=services,dc=immae,dc=eu" +LDAP_PUB_FORWARD_MEMBER="cn=forward,cn=pub,ou=services,dc=immae,dc=eu" +ECHO=$(which echo) + +if [[ $user == pub ]]; then + ldap_search '(&(memberOf='$LDAP_PUB_RESTRICT_MEMBER')('$KEY'=*))' $KEY | \ + while read line ; + do + if [ ! -z "$line" ]; then + if [[ $line == dn* ]]; then + echo "" + user=$(sed -n 's/.*uid=\([^,]*\).*/\1/p' <<< "$line") + echo "# $user" + elif [[ $line == $KEY* ]]; then + key=$(clean_key_line pub "$line") + key_forward=$(clean_key_line forward "$line") + if [ ! -z "$key" ]; then + if [[ $key != *$'\n'* ]] && [[ $key == ssh-* ]]; then + echo -n 'command="/etc/profiles/per-user/pub/bin/restrict '$user'" ' + echo $key + fi + elif [ ! -z "$key_forward" ]; then + if [[ $key_forward != *$'\n'* ]] && [[ $key_forward == ssh-* ]]; then + echo "# forward only" + echo -n 'no-pty,no-X11-forwarding,command="'$ECHO' forward only" ' + echo $key_forward + fi + fi + fi + fi + done + + echo "" + ldap_search '(&(memberOf='$LDAP_PUB_FORWARD_MEMBER')('$KEY'=*))' $KEY | \ + while read line ; + do + if [ ! -z "$line" ]; then + if [[ $line == dn* ]]; then + echo "" + user=$(sed -n 's/.*uid=\([^,]*\).*/\1/p' <<< "$line") + echo "# $user" + elif [[ $line == $KEY* ]]; then + key=$(clean_key_line forward "$line") + if [ ! -z "$key" ]; then + if [[ $key != *$'\n'* ]] && [[ $key == ssh-* ]]; then + echo -n 'no-pty,no-X11-forwarding,command="'$ECHO' forward only" ' + echo $key + fi + fi + fi + fi + done + exit 0 +fi + diff --git a/modules/private/ssh/default.nix b/modules/private/ssh/default.nix index beedaff..d4c1ab3 100644 --- a/modules/private/ssh/default.nix +++ b/modules/private/ssh/default.nix @@ -1,7 +1,50 @@ { lib, pkgs, config, myconfig, ... }: +let + cfg = config.myServices.ssh; +in { + options.myServices.ssh = let + module = lib.types.submodule { + options = { + snippet = lib.mkOption { + type = lib.types.lines; + description = '' + Snippet to use + ''; + }; + dependencies = lib.mkOption { + type = lib.types.listOf lib.types.package; + default = []; + description = '' + Dependencies of the package + ''; + }; + }; + }; + in { + predefinedModules = lib.mkOption { + type = lib.types.attrsOf module; + default = { + regular = { + snippet = builtins.readFile ./ldap_regular.sh; + }; + }; + readOnly = true; + description = '' + Predefined modules + ''; + }; + modules = lib.mkOption { + type = lib.types.listOf module; + default = []; + description = '' + List of modules to enable + ''; + }; + }; config = { networking.firewall.allowedTCPPorts = [ 22 ]; + } // (lib.mkIf (builtins.length cfg.modules > 0) { services.openssh.extraConfig = '' AuthorizedKeysCommand /etc/ssh/ldap_authorized_keys @@ -24,11 +67,21 @@ # ssh is strict about parent directory having correct rights, don't # move it in the nix store. environment.etc."ssh/ldap_authorized_keys" = let + deps = lib.lists.unique ( + [ pkgs.which pkgs.openldap pkgs.stdenv.shellPackage pkgs.gnugrep pkgs.gnused pkgs.coreutils ] + ++ lib.flatten (map (v: v.dependencies) cfg.modules) + ); + fullScript = pkgs.runCommand "ldap_authorized_keys" { + snippets = builtins.concatStringsSep "\n" (map (v: v.snippet) cfg.modules); + } '' + substituteAll ${./ldap_authorized_keys.sh} $out + chmod a+x $out + ''; ldap_authorized_keys = pkgs.mylibs.wrap { name = "ldap_authorized_keys"; - file = ./ldap_authorized_keys.sh; - paths = [ pkgs.which pkgs.gitolite pkgs.openldap pkgs.stdenv.shellPackage pkgs.gnugrep pkgs.gnused pkgs.coreutils ]; + file = fullScript; + paths = deps; }; in { enable = true; @@ -36,5 +89,5 @@ user = "root"; source = ldap_authorized_keys; }; - }; + }); } diff --git a/modules/private/ssh/ldap_authorized_keys.sh b/modules/private/ssh/ldap_authorized_keys.sh index d556452..402f283 100755 --- a/modules/private/ssh/ldap_authorized_keys.sh +++ b/modules/private/ssh/ldap_authorized_keys.sh @@ -5,13 +5,7 @@ KEY="immaeSshKey" LDAP_BIND="cn=ssh,ou=services,dc=immae,dc=eu" LDAP_PASS=$(cat /etc/ssh/ldap_password) LDAP_HOST="ldap.immae.eu" -LDAP_MEMBER="cn=users,cn=ssh,ou=services,dc=immae,dc=eu" -LDAP_GITOLITE_MEMBER="cn=users,cn=gitolite,ou=services,dc=immae,dc=eu" -LDAP_PUB_RESTRICT_MEMBER="cn=restrict,cn=pub,ou=services,dc=immae,dc=eu" -LDAP_PUB_FORWARD_MEMBER="cn=forward,cn=pub,ou=services,dc=immae,dc=eu" LDAP_BASE="dc=immae,dc=eu" -GITOLITE_SHELL=$(which gitolite-shell) -ECHO=$(which echo) suitable_for() { type_for="$1" @@ -52,101 +46,7 @@ ldap_search() { ldap_keys() { user=$1; - if [[ $user == gitolite ]]; then - ldap_search '(&(memberOf='$LDAP_GITOLITE_MEMBER')('$KEY'=*))' $KEY | \ - while read line ; - do - if [ ! -z "$line" ]; then - if [[ $line == dn* ]]; then - user=$(sed -n 's/.*uid=\([^,]*\).*/\1/p' <<< "$line") - if [ -n "$user" ]; then - if [[ $user == "immae" ]] || [[ $user == "denise" ]]; then - # Capitalize first letter (backward compatibility) - user=$(sed -r 's/^([a-z])/\U\1/' <<< "$user") - fi - else - # Service fake user - user=$(sed -n 's/.*cn=\([^,]*\).*/\1/p' <<< "$line") - fi - elif [[ $line == $KEY* ]]; then - key=$(clean_key_line git "$line") - if [ ! -z "$key" ]; then - if [[ $key != *$'\n'* ]] && [[ $key == ssh-* ]]; then - echo -n 'command="'$GITOLITE_SHELL' '$user'",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ' - echo $key - fi - fi - fi - fi - done - exit 0 - elif [[ $user == pub ]]; then - ldap_search '(&(memberOf='$LDAP_PUB_RESTRICT_MEMBER')('$KEY'=*))' $KEY | \ - while read line ; - do - if [ ! -z "$line" ]; then - if [[ $line == dn* ]]; then - echo "" - user=$(sed -n 's/.*uid=\([^,]*\).*/\1/p' <<< "$line") - echo "# $user" - elif [[ $line == $KEY* ]]; then - key=$(clean_key_line pub "$line") - key_forward=$(clean_key_line forward "$line") - if [ ! -z "$key" ]; then - if [[ $key != *$'\n'* ]] && [[ $key == ssh-* ]]; then - echo -n 'command="/etc/profiles/per-user/pub/bin/restrict '$user'" ' - echo $key - fi - elif [ ! -z "$key_forward" ]; then - if [[ $key_forward != *$'\n'* ]] && [[ $key_forward == ssh-* ]]; then - echo "# forward only" - echo -n 'no-pty,no-X11-forwarding,command="'$ECHO' forward only" ' - echo $key_forward - fi - fi - fi - fi - done - - echo "" - ldap_search '(&(memberOf='$LDAP_PUB_FORWARD_MEMBER')('$KEY'=*))' $KEY | \ - while read line ; - do - if [ ! -z "$line" ]; then - if [[ $line == dn* ]]; then - echo "" - user=$(sed -n 's/.*uid=\([^,]*\).*/\1/p' <<< "$line") - echo "# $user" - elif [[ $line == $KEY* ]]; then - key=$(clean_key_line forward "$line") - if [ ! -z "$key" ]; then - if [[ $key != *$'\n'* ]] && [[ $key == ssh-* ]]; then - echo -n 'no-pty,no-X11-forwarding,command="'$ECHO' forward only" ' - echo $key - fi - fi - fi - fi - done - exit 0 - else - ldap_search '(&(memberOf='$LDAP_MEMBER')('$KEY'=*)(uid='$user'))' $KEY | \ - while read line ; - do - if [ ! -z "$line" ]; then - if [[ $line == dn* ]]; then - user=$(sed -n 's/.*uid=\([^,]*\).*/\1/p' <<< "$line") - elif [[ $line == $KEY* ]]; then - key=$(clean_key_line ssh "$line") - if [ ! -z "$key" ]; then - if [[ $key != *$'\n'* ]] && [[ $key == ssh-* ]]; then - echo $key - fi - fi - fi - fi - done - fi + @snippets@ } ldap_keys $@ diff --git a/modules/private/ssh/ldap_regular.sh b/modules/private/ssh/ldap_regular.sh new file mode 100644 index 0000000..4c2f47e --- /dev/null +++ b/modules/private/ssh/ldap_regular.sh @@ -0,0 +1,19 @@ +### This snippet is not standalone and must be integrated in the global ldap_authorized_keys.sh +LDAP_MEMBER="cn=users,cn=ssh,ou=services,dc=immae,dc=eu" + +ldap_search '(&(memberOf='$LDAP_MEMBER')('$KEY'=*)(uid='$user'))' $KEY | \ + while read line ; + do + if [ ! -z "$line" ]; then + if [[ $line == dn* ]]; then + user=$(sed -n 's/.*uid=\([^,]*\).*/\1/p' <<< "$line") + elif [[ $line == $KEY* ]]; then + key=$(clean_key_line ssh "$line") + if [ ! -z "$key" ]; then + if [[ $key != *$'\n'* ]] && [[ $key == ssh-* ]]; then + echo $key + fi + fi + fi + fi + done -- 2.41.0