Xác thực khóa SSH bằng LDAP


59

Nói ngắn gọn:

Muốn có một cách để xác thực khóa SSH thông qua LDAP.

Vấn đề:

Chúng tôi sử dụng LDAP (slapd) cho các dịch vụ thư mục và gần đây chúng tôi đã chuyển sang sử dụng AMI của riêng chúng tôi để xây dựng các trường hợp. Lý do bit AMI rất quan trọng là, lý tưởng nhất là chúng tôi muốn có thể đăng nhập bằng SSH thông qua xác thực khóa ngay khi cá thể đang chạy và không phải chờ công cụ quản lý cấu hình hơi chậm của chúng tôi khởi động tập lệnh để thêm các khóa chính xác cho ví dụ.

Kịch bản lý tưởng là, khi thêm người dùng vào LDAP, chúng tôi cũng sẽ thêm khóa của họ và họ sẽ có thể đăng nhập ngay lập tức.

Xác thực khóa là bắt buộc vì đăng nhập dựa trên mật khẩu vừa kém an toàn vừa phiền phức.

Tôi đã đọc câu hỏi này cho thấy có một bản vá cho OpenSSH được gọi là OpenSSH-lpk để làm điều này nhưng điều này không còn cần thiết với máy chủ OpenSSH> = 6.2

Đã thêm tùy chọn sshd_config (5) AuthorizedKeysCommand để hỗ trợ tìm nạp ủy quyền_key từ một lệnh ngoài (hoặc thay vì) từ hệ thống tệp. Lệnh được chạy trong một tài khoản được chỉ định bởi tùy chọn AuthorizedKeysCommandUser sshd_config (5)

Làm cách nào tôi có thể định cấu hình OpenSSH và LDAP để thực hiện việc này?

Câu trả lời:


64

Cập nhật LDAP để bao gồm lược đồ OpenSSH-LPK

Trước tiên chúng ta cần cập nhật LDAP với một lược đồ để thêm sshPublicKeythuộc tính cho người dùng:

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 )
    )

Tạo tập lệnh truy vấn LDAP cho khóa chung của người dùng:

Tập lệnh sẽ xuất các khóa chung cho người dùng đó, ví dụ:

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

Cập nhật sshd_configđể trỏ đến tập lệnh từ bước trước

  • AuthorizedKeysCommand /path/to/script
  • AuthorizedKeysCommandUser nobody

Phần thưởng : Cập nhật sshd_configđể cho phép xác thực mật khẩu từ các mạng RFC1918 nội bộ như đã thấy trong câu hỏi này:

Chỉ cho phép xác thực mật khẩu với máy chủ SSH từ mạng nội bộ

Liên kết hữu ích:

EDIT: Đã thêm người dùng nobodynhư TRS-80 được đề xuất


6
Điều này là tuyệt vời, mặc dù tôi sẽ đề nghị AuthorizedKeysCommandUser nobodythay vì root.
TRS-80

Phải có một cái gì đó khác biệt về ldapsearch hoặc sed của tôi bởi vì việc đưa đầu ra vào lệnh ma thuật sed đen mà bạn có ở đó không cho tôi đầu ra, mặc dù lệnh ldapsearch đơn giản của tôi đang trả về dữ liệu. Tôi sẽ phải viết một kịch bản để làm sạch đầu ra thay vì sử dụng sed.
Chris L

1
Bỏ qua bình luận trước đây của tôi. Vấn đề của tôi là do có một dòng mới trong thuộc tính sshPublicKey, do đó gây ra ldapsearch để base64 mã hóa toàn bộ. Tôi đã đơn giản hóa lệnh sed tho:ldapsearch -u -LLL -o ldif-wrap=no '(&(objectClass=posixAccount)(uid='"$1"'))' 'sshPublicKey' | sed -n 's/^[ \t]*sshPublicKey:[ \t]*\(.*\)/\1/p'
Chris L

1
@Chris thực sự ít ma thuật đen hơn, nhưng sed vẫn là chức năng băm viết một lần, một lần;)
Froyke

1
Trên phiên bản OpenSSH của tôi (5.3p1-122.el6) có AuthorizedKeysCommandRunAsvà khôngAuthorizedKeysCommandUser
mveroone

5

Đối với bất kỳ ai nhận được lỗi khi chạy ldapsearch:

sed: 1: "/^ /{H;d};": extra characters at the end of d command

như tôi đã (trên FreeBSD), cách khắc phục là thay đổi lệnh sed đầu tiên thành:

/^ /{H;d;};

(thêm dấu chấm phẩy sau 'd').


4

Chỉ muốn chia sẻ "phương thức" của tôi, phía máy khách của tôi là Debian / Ubuntu Cụ thể, nhưng về phía Máy chủ của tôi về cơ bản giống như trên, nhưng với một chút "HowTo:"

Người phục vụ :

Kích hoạt thuộc tính khóa công khai:

Tín dụng :

https://blog.shichao.io/2015/04/17/setup_openldap_server_with_openssh_lpk_on_ub Ubuntu.html

cat << EOL >~/openssh-lpk.ldif
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 )
  )
EOL

Bây giờ sử dụng điều này để thêm ldif:

ldapadd -Y EXTERNAL -H ldapi:/// -f ~/openssh-lpk.ldif

Thêm người dùng bằng khóa công khai SSH trong phpLDAPadmin

Đầu tiên, tạo một người dùng với mẫu Chung Generic: Tài khoản người dùng. Sau đó, đi đến phần thuộc tính của đối tượng Wikipedia, nhấp vào Thêm thêm giá trị, và chọn thuộc tính ldapPublicKey mật. Sau khi bạn gửi, hãy quay lại trang chỉnh sửa người dùng, nhấp vào Thêm Thêm thuộc tính mới, trên phần trên cùng và chọn mật mã sshPublicKey, dán khóa công khai vào vùng văn bản và cuối cùng nhấp vào Cập nhật đối tượng.

sshPublicKey Thuộc tính không hiển thị - OpenLDAP PHPLDAP SSH Key Auth

Máy khách Ubuntu:

apt-get -y install python-pip python-ldap
pip install ssh-ldap-pubkey
sh -c 'echo "AuthorizedKeysCommand /usr/local/bin/ssh-ldap-pubkey-wrapper\nAuthorizedKeysCommandUser nobody" >> /etc/ssh/sshd_config' && service ssh restart

Tạo khóa kiểm tra:

ssh-keygen -t rsa

3

Đây không phải là một câu trả lời đầy đủ, chỉ là một bổ sung cho câu trả lời của c4urself . Tôi đã có thể thêm điều này như một bình luận, nhưng tôi không có đủ danh tiếng để bình luận, vì vậy xin đừng downvote!

Đây là tập lệnh tôi đang sử dụng cho AuthorizedKeysCommand(dựa trên phiên bản của c4urself). Nó hoạt động bất kể giá trị được trả về trong mã hóa base64 hay không. Điều này có thể đặc biệt hữu ích nếu bạn muốn lưu trữ nhiều khóa được ủy quyền trong LDAP - chỉ cần tách riêng các khóa bằng các ký tự dòng mới, tương tự như tệp ủy quyền.

#!/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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.