nginxでBAISC/PAM認証をやってみた話

# 背景
社内サーバでnginxでリバースプロキシを設定し、そこでBASIC認証をかけています。

BASIC認証を共通ID/PWで認証しているため、セキュリティ向上と誰がログインしているのかのアクセス識別の観点から当該nginxが動作しているサーバ上にLinuxのログインユーザを作り、そのLinuxユーザ情報(/etc/passwd,/etc/shadow)でユーザ認証をしたいというモチベーション。

まずはvirtualbox上の検証環境で実装方法を検討

- 環境
    - Cent OS 6.9 64bit
    - nginx-1.12.2-1(SRPM)
    - ngx_http_auth_pam_module  
      https://github.com/sto/ngx_http_auth_pam_module

# 実施内容

## パッケージの作成
- ここからSRPMを取得
    - http://nginx.org/packages/centos/6/SRPMS/nginx-1.12.2-1.el6.ngx.src.rpm
- specファイルに``--add-module=path_to/ngx_http_auth_pam_module``を入れてrpmbuild。
- rpmパッケージを作成しインストール

## インストール

```bash
rpm -i nginx-1.12.2-1.el6.pam_auth.ngx.x86_64.rpm
```
でインストール。して設定ファイルはとりあえず下記の通り

### nginx
```bash:/etc/nginx/conf.d/default.conf
server {
    listen       80;
    server_name  localhost;

    location / {
        auth_pam "Secure Zone";
        auth_pam_service_name "nginx";
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

}

```


### pam.d
``/etc/pam.d/nginx``を作成。結局pam設定はよくわからない・・・勉強せねば

```bash:/etc/pam.d/nginx
#%PAM-1.0
auth       include      password-auth
account    include      password-auth
password   include      password-auth
session    include      password-auth
```


## 課題
nginxサービスをスタートして以下課題に直面

### nginxユーザ以外で認証できない・・・
サーバ上にあるほかユーザで認証ができない。
試しにnginxユーザにパスワードを設定し、BASIC認証をかけてみたところ。
nginxユーザではちゃんと認証が出来ていることを確認。

ほかのユーザ（user1）では以下のようなエラーメッセージが

```:/var/log/secure
Dec 26 07:58:03 BaseCentos64 unix_chkpwd[12914]: check pass; user unknown
Dec 26 07:58:03 BaseCentos64 unix_chkpwd[12914]: password check failed for user (user1)
Dec 26 07:58:03 BaseCentos64 ker process: pam_unix(nginx:auth): authentication failure; logname= uid=498 euid=498 tty= ruser= rhost=  user=user1
```

きっとnginxユーザで認証を触る権限が足りていないため他人の権限で確認ができないのだろうと推察・・・
https://github.com/sto/ngx_http_auth_pam_module ここにも

> Note that the module runs as the web server user, so the PAM modules used must be able to authenticate the users without being root; that means that if you want to use the pam_unix.so module to autenticate users you need to let the web server user to read the /etc/shadow file if that does not scare you (on Debian like systems you can add the www-data user to the shadow group).

とありますからね・・・

切り分けのためにrootユーザでnginxを起動するように変更

```bash:/etc/nginx/nginx.conf

#user  nginx;
user  root;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}
```

サービスのリスタートで試してみたところ、今度はuser1でも認証ができました！

## rootユーザでよいのか。。。
nginxのユーザ権限としてrootユーザでよいのかは非常に微妙なのであくまでもworkerプロセスはnginxユーザで、かつ他人の認証もできるようにしたい。

debianを習いshadow グループを作る方向で実装。

```bash
# gid 42はdebianだと42だったので・・・合わせておきました
groupadd -g 42 shadow
# shadowグループに認証系のファイルを設定
# 対象ファイルはdebianに倣いました
chgrp shadow /etc/gshadow
chgrp shadow /etc/shadow
chgrp shadow /sbin/unix_chkpwd
chgrp shadow /usr/bin/chage
# sgidを設定
chmod 2755 /sbin/unix_chkpwd
chmod 2755 /usr/bin/chage
# グループに読み取り権限を付与
chmod 640 /etc/shadow
chmod 640 /etc/gshadow
# nginxユーザにshadowグループを追加
gpasswd -a nginx shadow
```

ここまで設定したら、nginxのワーカーユーザをnginxに戻し、サービスのリスタート。

__Ta-da!__
nginxユーザにてBASIC認証が正しく動きました！


#まとめ

あまり情報も少なく・・・三流エンジニアの私は途中で挫折しそうになりましたが、晴れて狙い通りの動きにはなってくれました。
初めは、うまくいかないというタイトルで書き始めたポストだったんですけど。一晩寝て翌日やってうまくいきました。煮詰まっている状態ではあんまりいい発想や、着眼が生まれないですね。良質な睡眠ダイジ

PAMやSUID/SGID周りは未だ理解が追い付いていないですが、ちょっとばかし理解が進みました。

ほかにいいやり方をお持ちの方はご教授いただけると幸いです・・・