Kerberos認証を入れて389DSと連携(SSH/Samba)

前回まででSSH(公開鍵)/Sambaの認証をLDAPでの一元管理にしました。

https://qiita.com/jp_ibis/items/a88472e899dfca6bdd0a

https://qiita.com/jp_ibis/items/07d06acb2fb657b7d278

ここまで問題無く動いているのですがSquidの認証を追加しようとしたときに **うへ、またパスワードが増える( ^ｑ^ )** ってなりました。

サービスを増やすごとにLDAPユーザーに増え続ける認証情報、パスワードを変えようと思ったら大変ですね。まぁその代わりサービスごとにパスワードを変えられるので今の時代(ゼロトラスト的な？)はむしろいいのかもしれないのですが。

とはいえやはり面倒ではあるのでkerberos認証でSSOしてみることにしました。SSOでLDAPのユーザー情報から認証情報を一掃しよう作戦です。

**なおKerberosは認可情報を持ちません**

つまりSambaみたいな認可情報が欲しいサービスを使う場合はKerberos単体ではダメで、LDAPと連携させる必要があります。

SSSDと連携させるとLDAPからの情報取得がスマートにやれるので、Keberos+LDAP+SSSDという組み合わせで進めます。

OSはFedora42です。
SELinuxはEnforcingですが特に問題は出ませんでした。

# Kerberosの導入

まずはサーバとクライアントをインストールしてしまいます。

```bash
$ dnf install krb5-server krb5-workstation
```

設定情報を書き換えます。基本はデフォルトのままでコメントアウトされていた所を複製して書き換えました。

レルムはドメイン名`home`の大文字(にするのが基本らしい)で設定しました。ホスト名からレルムを検索するときにドメイン名部分を大文字に変えて検索するらしいので、基本に沿っておかないと色々と追加で設定が増えます。

```conf:/etc/krb5.conf
[logging]
...

[libdefaults]
    dns_lookup_realm = false
    ticket_lifetime = 24h
    renew_lifetime = 7d
    forwardable = true
    rdns = false
    pkinit_anchors = FILE:/etc/pki/tls/certs/ca-bundle.crt
    spake_preauth_groups = edwards25519
    dns_canonicalize_hostname = fallback
    qualify_shortname = ""
#    default_realm = EXAMPLE.COM
    default_realm = HOME  <- 追加
    default_ccache_name = KEYRING:persistent:%{uid}

[realms]
# EXAMPLE.COM = {
#     kdc = kerberos.example.com
#     admin_server = kerberos.example.com
# }
# 追加
HOME = {
     kdc = minipc.home
     admin_server = minipc.home
}

[domain_realm]
# .example.com = EXAMPLE.COM
# example.com = EXAMPLE.COM
# 追加
.home = HOME
home = HOME
```

Kerberosのデータベースを作成します。データベース作成時にアクセス用のパスワードの設定も行われます。

```bash
$ kdb5_util create -s
```

続いてKerberosサーバの管理者(admin/adminとか)の作成を対話形式で行います。コマンドでえいやって作るのは面倒な感じでした。

対話状態(kadmin.local:)になったらaddprinceコマンドで管理者を追加します。設定するパスワードを聞かれるので入力し、終わったらquitで抜けます。

```bash
$ kadmin.local
kadmin.local: addprince <admin_principal>
```

これで初期設定は終わりなのでとりあえず立ち上げてみます。

```bash
$ systemctl start krb5kdc.service
$ systemctl enable krb5kdc.service
```

チケットを取得できるか試してみます

```bash
# 管理者チケットの取得
$ kinit <admin_principal>

# チケットの確認
$ klist

# チケットの破棄
$ kdestroy
```

後はFirewall(port:88)を開けておきましょう。

```bash
$ firewall-cmd --add-service=kerberos
$ firewall-cmd --add-service=kerberos --permanent
```

# SSHと連携

認可の設定が必要ないSSHの方が簡単そうだったので、まずはSSHとKerberosを連携させてみます。

## SSHサーバの登録

Keberos認証と連携するサービス(SSH)のホストを登録しておきます。といっても認証もサービスも全部minipc.homeなんですけどね。

ssh用のプリンシパルは`host/minipc.home@HOME`らしいです。

```bash
$ kadmin.local
kadmin.local: addprinc -randkey host/minipc.home@HOME

# 確認
kadmin.local: listprincs

# 間違ったとき
kadmin.local: delprinc <消したいプリンシパル>
```

※なおサービス側のホスト名と`hostname`コマンドの出力が違うと上手く動きません。sshをkerberosで認証させようとするとhostname側の`host/miniPC@HOME`というプリンシパルを探しにいったりされました_(:3」∠)_


## sshd_confの修正

```bash:/etc/ssh/sshd_config
# 公開鍵認証をやめるよ
PubkeyAuthentication no

# Kerberosを使うよ
KerberosAuthentication yes
KerberosOrLocalPasswd no
GSSAPIAuthentication yes
```

設定を反映させます。

```bash
$ systemctl restart sshd
```

ここまででsshでログインできなくなります。


## SSHのホストにキータブを作成しSSH用プリンシパルを登録

KeberosとSSHが同じサーバで動いているのでややこしいですがサービス(SSH)側の設定です。

sshdをKerberosと連携させるためのキータブを作成し、SSH用の`host/minipc.home@HOME`を登録します。

```bash
$ kadmin.local
kadmin.local: ktadd -k /etc/krb5.keytab host/minipc.home@HOME
```

klistコマンドで内容を確認できます

```
# 確認
$ klist -kt /etc/krb5.keytab
```

## SSSDの修正

前回でsssdを導入してsshも動くようにしてあるので今回はLDAPからKerberosを使うように変更するだけですが、SSSDでの認証全てに影響するのでドメイン分けをしていない場合LDAP認証が使えなくなります。

```conf:/etc/sssd/sssd.conf
...
# auth_provider = ldap
# chpass_provider = ldap
auth_provider = krb5
chpass_provider = krb5

# もう不要
# ldap_user_ssh_public_key = nsSshPublicKe

# 追加
krb5_realm = HOME
krb5_server = minipc.home
krb5_kpasswd = minipc.home  <- 設定しなくても動くけどログにエラーがでる
krb5_keytab = /etc/krb5.keytab  <- ここがデフォルトなのでなくても動くけど一応

# LDAPのposixGroupを使って認可制御を行う準備
ldap_group_search_base = ou=Groups,dc=home
ldap_id_mapping = false

...
```

キャッシュを消して再起動

```conf:/etc/sssd/sssd.conf
$ sss_cache -E
$ systemctl restart sssd
$ systemctl restart sshd
```

これで設定は終わりです

## ユーザーの追加

SSHでログインできるようLDAP認証していたユーザーをKerberosに登録しておきましょう。

```bash
$ kadmin.local
kadmin.local: addprinc <ユーザー名>@HOME
```

## ログインしてみる

Kerberso認証なので最初にTGTを取得しておく必要があります。

```bash
$ kinit <ユーザー名>@HOME
$ ssh <ユーザー名>@minipc.home
```

成功手順だけ書いてるととても簡単だけど、ここまでかなり紆余曲折_(:3」∠)_

## SSHできるユーザーを絞る

sssd.confの`ldap_group_search_base`に設定した`ou=Groups,dc=home`の下にSSHAllowという **posixGroup** を追加しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140718/6e3fd31f-3154-44c6-b084-6474f826b1d2.png)

memberUidにユーザーtestのuidを設定しておくとidコマンドでGroup情報が取得できます。

```bash
$ sss_cache -E

$ id test
uid=2001(test) gid=2001 groups=2001,10000(SSHAllow)
```

sshd_confに許可するグループを追加します。

```conf:/etc/ssh/sshd_conf
AllowGroups SSHAllow
```

SSHを再起動すればSSHAllowグループ以外のユーザーはSSHに失敗するようになります。

```bash
$ systemctl restart sshd

# もう別のユーザーではログインできない
$ sudo su - aaa
$ kinit
$ ssh minipc.home
aaa@minipc.home: Permission denied (gssapi-keyex,gssapi-with-mic).
```

# Sambaと連携

流石にアレコレめんどくさい_(:3」∠)_

## KerberosへSamba用プリンシパルを登録

Sambaにチケットを発行できるようSambaが動いているホストを登録します。

Samba用のプリンシパルは`cifs/minipc.home@HOME`らしいです。

```
$ kadmin.local
kadmin.local: addprinc -randkey cifs/minipc.home@HOME
```

## SambaのホストのキータブにSamba用プリンシパルを登録

KeberosとSambaが同じサーバで動いているのでややこしいですがサービス(Samba)側の設定です。

キータブにSamba用の`cifs/minipc.home@HOME`を登録します。

```
$ kadmin.local
kadmin.local: ktadd -k /etc/krb5.keytab cifs/minipc.home@HOME
```

## smb.confの修正

LDAP認証の設定を消してKerberos認証の設定を追加します。

```conf:/etc/samba/smb.conf
        # LDAP認証はもういらない
        passdb backend = tdbsam <- デフォルトなのでコメントのままでもいい
#       passdb backend = ldapsam:ldaps://minipc-wifi.home:636
#       ldap ssl = no
#       ldap admin dn = cn=Directory Manager
#       ldap suffix = dc=home
#       ldap user suffix = ou=Users,dc=home

        # kerberos認証用に追加
        realm = HOME
        kerberos method = secrets and keytab
        dedicated keytab file = /etc/krb5.keytab
```

再起動して有効にしてお試し。

```bash
$ systemctl restart smb

$ smbclient //minipc.home/share -U test
```

これでつながるにはつながるんですが、問題点が……
- パスワードを聞かれます。SSO、あれ？
- kinitしてないのに認証が通る

testさんの設定は
- Sambaのdbにいない
- Linuxのユーザーでもない
- LDAPはposixAccountしか持ってない
- Kerberosのパスワードが通る

なのでKeberos認証されてるってことになります。

不思議_(:3」∠)_

でもやっぱりSSOやりたいので後日またリトライしてみます……

## LDAPのユーザー情報の修正

Keberos認証にしたのでLDAPのユーザー情報からsambaSamAccount/nsPerson/nsAccount辺りのオブジェクトクラスが不要になりました。posixAccountが最低限になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140718/4fb85441-aac2-4a22-a3d7-a936c05f70de.png)

LDAPからパスワード情報が消えた！

## 認可の追加

Sambaの場合は見せるフォルダごとにアクセス制御がすでにされていると思います。

SSHの時にsssdに **ldap_group_search_base** というposixGroupを取得する設定を入れたのでsmb.confの`valid users = @グループ名`の設定に対応したグループをLDAP側に追加してメンバーを設定すればＯＫです。

もちろんユーザー名もそのままvalied usersの設定で使えます。

# Windows側の対応

Windows用のKerberosクライアントがあるのですが……

https://web.mit.edu/kerberos/dist/

Windowsが持っているKerberosの機構と重複します／(^o^)＼

```cmd
> where klist
C:\Windows\System32\klist.exe
C:\Program Files\MIT\Kerberos\bin\klist.exe
```

インストールしたら環境変数の参照順を変えておきましょう(GUIしか使わないなら不要)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140718/481f8822-e6dd-451a-b527-25f050a92af3.png)

管理者権限でkrb5.iniを編集して接続先を設定すればGUIでもkinitでもチケットが取れました。

```conf:C:\ProgramData\MIT\Kerberos5\krb5.ini
[libdefaults]
default_realm = HOME

[realms]
HOME = {
  kdc = minipc.home:88
}

[domain_realm]
.home = HOME
home = HOME
```


## Sambaの対応

WindowsからSambaへつなぐときは認証がSambaだろうがLDAPだろうがKerberosだろうがWindowsがよしなにやってくれるので、いつもの認証ボックスでユーザーとパスワードを入力するだけです。

資格情報が保存してあればショートカットやドライブ割り当ても当然そのままでいけます。

## SSHの対応

Windowsに入っているSSHコマンドは当然MITのKeberosの認証情報は見てくれないので……あれ、だめじゃないか。

というわけでPuttyを使ったら特に何も設定しなくてもSSOができました。未認証状態だとMIT Kerberosの認証画面が開くという親切設計でした☺️

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140718/6da80098-6c05-4ad1-9665-0094fd8d0f2c.png)