1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

OpenResty(Nginx)とluaでBasic認証+認可を実装する

Last updated at Posted at 2023-03-19

OpenRestyとは

OpenRestyとは、NginxをベースにLuaJITを搭載したWebサーバーです。Luaのライブラリなどが利用できます。

環境

  • Ubuntu 20.04
  • Docker version 20.10.14
  • Docker Compose version v2.4.1
  • nginx version: openresty/1.21.4.1

なぜNginxを使わなかったのか?

今回やりたいことは、Basic認証と認可を実装することです。Nginx単体でも認証は簡単に実装できますが、認可の仕組みは意外と骨が折れます。

OpenRestyを利用することで、LuaからNginxの変数にアクセスできます。ログインしてきたユーザー名などを取得できれば、Luaスクリプト内の認可ロジックでそのユーザーを許可するかどうか判定できるようになります。

検証ソース

ディレクトリ構成

ソースの配置は以下を想定しています。

.
├── docker-compose.yaml
└── nginx
    ├── conf.d
    │   └── default.conf
    ├── lua
    │   └── auth.lua
    └── nginx.conf

Docker Compose

docker-compose.yaml
version: "3"
services:
  openresty:
    image: openresty/openresty:latest
    hostname: openresty
    container_name: openresty
    volumes:
      - ./nginx/nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf
      - ./nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf
      - ./nginx/lua/auth.lua:/etc/nginx/lua/auth.lua
      - ./nginx/.htpasswd:/etc/nginx/.htpasswd
    ports:
      - "80:80"
    restart: always

OpenRestyの設定

nginx.confはデフォルトのまま変更していません。

nginx.conf
# nginx.conf  --  docker-openresty
#
# This file is installed to:
#   `/usr/local/openresty/nginx/conf/nginx.conf`
# and is the file loaded by nginx at startup,
# unless the user specifies otherwise.
#
# It tracks the upstream OpenResty's `nginx.conf`, but removes the `server`
# section and adds this directive:
#     `include /etc/nginx/conf.d/*.conf;`
#
# The `docker-openresty` file `nginx.vh.default.conf` is copied to
# `/etc/nginx/conf.d/default.conf`.  It contains the `server section
# of the upstream `nginx.conf`.
#
# See https://github.com/openresty/docker-openresty/blob/master/README.md#nginx-config-files
#

#user  nobody;
#worker_processes 1;

# Enables the use of JIT for regular expressions to speed-up their processing.
pcre_jit on;



#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


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

    # Enables or disables the use of underscores in client request header fields.
    # When the use of underscores is disabled, request header fields whose names contain underscores are marked as invalid and become subject to the ignore_invalid_headers directive.
    # underscores_in_headers off;

    #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  logs/access.log  main;

        # Log in JSON Format
        # log_format nginxlog_json escape=json '{ "timestamp": "$time_iso8601", '
        # '"remote_addr": "$remote_addr", '
        #  '"body_bytes_sent": $body_bytes_sent, '
        #  '"request_time": $request_time, '
        #  '"response_status": $status, '
        #  '"request": "$request", '
        #  '"request_method": "$request_method", '
        #  '"host": "$host",'
        #  '"upstream_addr": "$upstream_addr",'
        #  '"http_x_forwarded_for": "$http_x_forwarded_for",'
        #  '"http_referrer": "$http_referer", '
        #  '"http_user_agent": "$http_user_agent", '
        #  '"http_version": "$server_protocol", '
        #  '"nginx_access": true }';
        # access_log /dev/stdout nginxlog_json;

    # See Move default writable paths to a dedicated directory (#119)
    # https://github.com/openresty/docker-openresty/issues/119
    client_body_temp_path /var/run/openresty/nginx-client-body;
    proxy_temp_path       /var/run/openresty/nginx-proxy;
    fastcgi_temp_path     /var/run/openresty/nginx-fastcgi;
    uwsgi_temp_path       /var/run/openresty/nginx-uwsgi;
    scgi_temp_path        /var/run/openresty/nginx-scgi;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

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

    # Don't reveal OpenResty version to clients.
    # server_tokens off;
}

基本認証の設定とluaスクリプトの設定を追記しています。

default.conf
# nginx.vh.default.conf  --  docker-openresty
#
# This file is installed to:
#   `/etc/nginx/conf.d/default.conf`
#
# It tracks the `server` section of the upstream OpenResty's `nginx.conf`.
#
# This config (and any other configs in `etc/nginx/conf.d/`) is loaded by
# default by the `include` directive in `/usr/local/openresty/nginx/conf/nginx.conf`.
#
# See https://github.com/openresty/docker-openresty/blob/master/README.md#nginx-config-files
#


server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        root   /usr/local/openresty/nginx/html;
        index  index.html index.htm;
+       auth_basic "basic auth";
+       auth_basic_user_file /etc/nginx/.htpasswd;
+       access_by_lua_file /etc/nginx/lua/auth.lua;
    }

    #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/local/openresty/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           /usr/local/openresty/nginx/html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

以下が基本認証の設定です。コンテナ内の/etc/nginx/.htpasswdにユーザーとパスワードの情報を持たせています。

        auth_basic "basic auth";
        auth_basic_user_file /etc/nginx/.htpasswd;

今回はadmintestの2つユーザーを用意します。パスワードはそれぞれ、admintestとしています。

.htpasswd
admin:$apr1$83K7MhNj$OTxCQTTH8eCkfLY94DdG41
test:$apr1$0jX4sM1.$wgnHDKX3u2dyALc7.uEYF/

ちなみにパスワードの生成するときは以下のコマンドを実行します。
こちらの記事を参考にしました。

htpasswdコマンドの-cオプションは、新規にファイルを作成するオプションであるため、2つ目以降のユーザーを保存したい場合は-cオプションなしで実行すると追記になるようです。

htpasswd -c ./nginx/.htpasswd admin
htpasswd ./nginx/.htpasswd test

htpasswdコマンドが無い場合は、以下のようにインストールします。

apt-get -y install apache2-utils

Luaスクリプト(認可用)

default.conf内の以下の設定は、認可用のLuaスクリプトを定義しています。

        access_by_lua_file /etc/nginx/lua/auth.lua;
auth.lua
-- remote user名を取得
local remote_user = ngx.var.remote_user
if remote_user ~= "admin" then
    -- adminユーザーでなければ403
    ngx.header.content_type = "text/plain"
    ngx.log(ngx.STDERR, remote_user.." にはアクセス権がありません")
    ngx.status = ngx.HTTP_FORBIDDEN
    return ngx.exit(403)
end
  • ngx.var.remote_user
    • ngx.var.XXXでNginxの変数にアクセスできます。remote_userにはユーザー名が入っています。

if分以降は、remote_useradminユーザーでなければ403でアクセスできないようにしています。今回のケースだと、adminユーザーはOpenRestyのデフォルトページにアクセスできるが、testユーザーはアクセスできない状況を作っています。

コンテナ起動

docker-compose up -d

アクセス確認

adminユーザーでログインする場合

OpenRestyのデフォルトページが表示されます。

openresty-default-page.png

testユーザーでログインする場合

403が表示されます。

403.png

OpenRestyのログを確認

docker logs openresty

testユーザーが403になっていることが確認できます。

2023/03/19 09:08:50 [] 7#7: *2 [lua] auth.lua:7: test にはアクセス権がありません, client: 172.24.0.1, server: localhost, request: "GET / HTTP/1.1", host: "localhost"
172.24.0.1 - test [19/Mar/2023:09:08:50 +0000] "GET / HTTP/1.1" 403 561 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1661.44"

OpenRestyでよく使うコマンド

設定ファイルが有効かチェック(-t)

docker exec -it openresty bash -c 'openresty -t'

実行結果の例。

nginx: the configuration file /usr/local/openresty/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/openresty/nginx/conf/nginx.conf test is successful

OpenRestyのリロード(-s reload)

docker exec -it openresty bash -c 'openresty -s reload'

実行結果の例。

2023/03/19 09:16:43 [notice] 15#15: signal process started

まとめ

OpenRestyを利用することで、Basic認証に認可の仕組みを実装することができました。Luaスクリプトをもう少し工夫すれば複雑な認証・認可の仕組みを実装できそうです。

以下の記事で、Ldap認証で同様のことを試してみました。

参考

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?