使用 LDAP 的 SSH 密钥身份验证

c4u*_*elf 69 ssh ldap

简而言之:

想要一种通过 LDAP 进行 SSH 密钥身份验证的方法。

问题:

我们将 LDAP (slapd) 用于目录服务,并且我们最近转向使用我们自己的 AMI 来构建实例。AMI 位很重要的原因是,理想情况下,我们希望能够在实例运行后立即通过密钥身份验证使用 SSH 登录,而不必等待我们有点慢的配置管理工具启动要添加的脚本实例的正确密钥。

理想的情况是,在将用户添加到 LDAP 时,我们也添加了他们的密钥,他们可以立即登录。

密钥身份验证是必须的,因为基于密码的登录既不安全又麻烦。

我读过这个问题,它表明有一个名为 OpenSSH-lpk 的 OpenSSH 补丁来执行此操作,但 OpenSSH 服务器不再需要 >= 6.2

添加了 sshd_config(5) 选项 AuthorizedKeysCommand 以支持除了(或代替)从文件系统之外,还支持从命令中获取 authorized_keys。该命令在 AuthorizedKeysCommandUser sshd_config(5) 选项指定的帐户下运行

如何配置 OpenSSH 和 LDAP 来实现这一点?

c4u*_*elf 83

更新 LDAP 以包含 OpenSSH-LPK 架构

我们首先需要使用模式更新 LDAP 以添加sshPublicKey用户的属性:

dn: cn=openssh-lpk,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: openssh-lpk
olcAttributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey'
    DESC 'MANDATORY: OpenSSH Public key'
    EQUALITY octetStringMatch
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
olcObjectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY
    DESC 'MANDATORY: OpenSSH LPK objectclass'
    MAY ( sshPublicKey $ uid )
    )
Run Code Online (Sandbox Code Playgroud)

创建一个向 LDAP 查询用户公钥的脚本:

该脚本应输出该用户的公钥,例如:

ldapsearch '(&(objectClass=posixAccount)(uid='"$1"'))' 'sshPublicKey' | sed -n '/^ /{H;d};/sshPublicKey:/x;$g;s/\n *//g;s/sshPublicKey: //gp'

更新sshd_config以指向上一步中的脚本

  • AuthorizedKeysCommand /path/to/script
  • AuthorizedKeysCommandUser nobody

奖励:更新sshd_config以允许来自内部 RFC1918 网络的密码验证,如本问题所示:

只允许从内网对SSH服务器进行密码认证

有用的链接:

编辑:将用户添加nobody为建议的 TRS-80

  • 这太棒了,尽管我建议使用“AuthorizedKeysCommandUser nobody”而不是 root。 (7认同)

小智 7

这不是完整的答案,只是c4urself 的答案的补充。我会将此添加为评论,但我没有足够的声誉发表评论,所以请不要投反对票!

这是我用于AuthorizedKeysCommand(基于 c4urself 的版本)的脚本。无论该值是否以 base64 编码返回,它都可以工作。如果您想在 LDAP 中存储多个授权密钥,这会特别有用——只需用换行符分隔密钥,类似于authorized_keys 文件。

#!/bin/bash
set -eou pipefail
IFS=$'\n\t'

result=$(ldapsearch '(&(objectClass=posixAccount)(uid='"$1"'))' 'sshPublicKey')
attrLine=$(echo "$result" | sed -n '/^ /{H;d};/sshPublicKey:/x;$g;s/\n *//g;/sshPublicKey:/p')

if [[ "$attrLine" == sshPublicKey::* ]]; then
  echo "$attrLine" | sed 's/sshPublicKey:: //' | base64 -d
elif [[ "$attrLine" == sshPublicKey:* ]]; then
  echo "$attrLine" | sed 's/sshPublicKey: //'
else
  exit 1
fi
Run Code Online (Sandbox Code Playgroud)


小智 5

对于在运行 ldapsearch 时遇到错误的任何人:

sed: 1: "/^ /{H;d};": extra characters at the end of d command
Run Code Online (Sandbox Code Playgroud)

像我一样(在 FreeBSD 上),修复方法是将第一个 sed 命令更改为:

/^ /{H;d;};
Run Code Online (Sandbox Code Playgroud)

(在“d”后添加分号)。