ラベル CentOS の投稿を表示しています。 すべての投稿を表示
ラベル CentOS の投稿を表示しています。 すべての投稿を表示

2017年2月13日月曜日

Azure MFA Serverを使ってLinuxへのログオンに多要素認証を使う

こんにちは、富士榮です。

PhoneFactor改めAzure MFA ServerってAD FSの2段階認証をオンプレで構成する場合くらいでしか利用されているのを見たことがないのですが、実はものすごく器用なプロダクトなので、色々と活用して行こう、というのが今回の主旨です。

そもそもAzure MFA Serverはがどう言うものかを一言で説明すると、「多要素認証付きのマルチプロトコル対応の認証サーバ」です。例えば、LDAPやRadius、Windows認証などに対応しています。

今回はタイトルに書いた通り、その中のRadiusサーバとしての機能を使って、LinuxへのSSHでのログインの時の認証の2要素目としてMicrosoft AuthenticatorアプリやSMS通知などを使えるようにしてみます。

以下の様な環境です。


ちなみに、Azure MFA ServerをLDAPサーバとして構成してLinux側はpam_ldapを使う、という選択肢もなくはないのですが、レポジトリにActive Directoryを使ったのでpam_ldapが認証対象のユーザのDNを取得する前に行うbindの段階で2要素認証が走ってしまうので、実際は使えないなぁ、ということで辞めました。匿名bindに対応したLDAPサーバを使えば行けるかもしれません。(Active Directoryを匿名bind化することも可能ではありますが、お奨めできないので)


早速やってみましょう。

◆Linux側の準備物

今回はAzure IaaS上のCentOS 7.3イメージを使いました。

追加で必要なパッケージは以下の通りです。
・LDAPクライアント
 ・openldap-clients
 ・nss-pam-ldapd
・Radiusクライアント
 ・pam_radius-1.4.0.tar.gz
・Radiusクライアントをビルドするための環境
 ・gcc
 ・pam-devel

◆LDAPクライアントの設定

まず、LDAPクライアントをインストールします。
 sudo yum install openldap-clients nss-pam-ldapd

次に/etc/passwdの代わりにLDAPサーバを使うようにOSを構成します。
 sudo authconfig-tui
を叩くと設定画面が開くので[User Information]の[Use LDAP]にチェックを入れます。認証側は後からRadiusを構成するのでここでは何も触りません。


Nextを叩くと、LDAPサーバへの接続設定が出てきますので、ServerのURIとBaseDNを設定します。


ここでOKをクリックすると設定は完了しますが、先に書いたようにActive DirectoryをLDAPサーバとして利用する場合は匿名bindが使えないので、バインドユーザの設定を直接設定ファイルを編集して登録します。

対象のファイルは/etc/nslcd.confで、binddnとbindpwというパラメータがデフォルトではコメントアウトされているので外して、必要な値を設定します。


次に同じく/etc/nslcd.confへ属性マッピング設定を追加します。これは例えばuidNumberやgidNumber、homeDirectoryなどLinuxへログインするために必要な属性が当然Active Directoryにはないので、それぞれ必要な値をActive Directory上のどの属性からとってくるか、という設定です。また、取得してくるobjectClassのフィルタリングも指定をしておかないとActive Directory上のユーザを適切にとって来れないので、filterの設定もしておきます。

最低限必要なのは以下の設定です。
filter passwd (&(objectClass=user)(!(objectClass=computer)))
map    passwd uid              sAMAccountName
map    passwd homeDirectory    "/home/$sAMAccountName"
map    passwd uidNumber employeeId
map    passwd gidNumber "1000"
map    passwd loginShell    "/bin/bash"
※uidNumberはActive Directory上のemployeeId属性に対応する値をあらかじめ入れます。また、今回gidNumberは固定にしていますがこれもActive Directory上の別の属性とマッピングすることで制御することが可能です。


◆ホームディレクトリの自動作成設定(pamの設定)

これでログインするユーザの情報をActive Directoryからとってくることは出来るようになりますが、Linuxではログインする際にホームディレクトリが存在しないと怒られますので、ログイン時に自動的にホームディレクトリが作成されるようにpamの設定を行います。

2つのファイルを編集する必要がありますので順番に。

まずは/etc/pam.d/password-authに以下の2行を追記します。
session     optional      pam_ldap.so
session     optional      pam_mkhomedir.so skel=/etc/skel umask=022

同じく、/etc/pam.d/system-auth-acにも以下の2行を追記します。(同じ内容です)
session     optional      pam_ldap.so
session     optional      pam_mkhomedir.so skel=/etc/skel umask=022

こんな感じになります。


◆Radiusクライアントの導入

いよいよ認証側の設定です。
デフォルトでRadiusクライアントが入っていないので、freeradiusと一緒に配布されているpam_radiusを使います。

まずはダウンロードします。現在1.4.0が最新版の様です。
wget ftp://ftp.freeradius.org/pub/radius/pam_radius-1.4.0.tar.gz

解凍します。この辺りまでは一般ユーザで十分です。
tar -xzvf pam_radius-1.4.0.tar.gz

ここで、configureしてmakeしたいところなんですが、必要な開発パッケージが入っていない場合はgccとpam-develをインストールしておきます。
sudo yum install gcc
sudo yum install pam-devel


そして、ビルドします。
configure
make

すると、pam_radius_auth.soが出来上がるので、必要なディレクトリへコピーします。(64bit環境であれば/usr/lib64/security/)

sudo cp pam_radius_auth.so /usr/lib64/security/


◆Radiusクライアントの設定

これで導入は完了なので、次は設定です。
必要なのは、
・認証にRadiusを使うための設定
・使用するRadiusサーバの設定
の2点です。

まずはRadiusを使って認証をするための設定です。
/etc/pam.d/password-authに以下の行を追記します。
auth sufficient pam_radius_auth.so use_first_pass

こんな感じで、authのブロックに挿入してあげてください。


次にRadiusサーバへの接続設定です。
/etc/raddb/serverというファイルを作り、その中にサーバのアドレスと共有シークレットを書き込むのですが、FreeRadiusを入れていない環境だと/etc/raddbディレクトリやファイルが存在しないので、ディレクトリとファイルは新規に作る必要があります。

こんな感じです。
sudo mkdir /etc/raddb
sudo vi /etc/raddb/server

serverファイルの中は非常にシンプルで、「サーバアドレス 共有シークレット タイムアウト(秒)」を記載するだけです。尚、この共有シークレットはRadiusサーバ(今回はAzure MFA Server)に設定する文字列と同じものを指定するので覚えておいてください。


ファイルは作成後、パーミッションを600に指定しておいてください。
sudo chmod 600 /etc/raddb/server

これでクライアント側は終わりです。


◆Azure MFA Serverの設定

いよいよAzure MFA ServerをRadiusサーバとして動かします。
詳細なインストール手順やAzure MFA ServerがActive Directoryをレポジトリとして利用するための構成手順、ポータルの設定手順などは今回は省き、単純に構成済みのAzure MFA ServerにRadiusクライアントの設定を行う方法を紹介します。

Azure MFA Serverの管理コンソールを開き、RADIUS Authenticationを開きClientsタブで[Add]をクリックします。


するとRADIUSクライアントを登録する画面が出てくるので、以下を設定します。
IP Address : クライアントのIPアドレス(LinuxのIPアドレス)
Application name : 任意の名前
Shared Secret : 先にLinuxに設定した共有シークレットの値
Confirm shared secret : 確認用
Require Mutlti-Factor Authentication user match : ON
Enable fallback OATH token : ON(今回は使わないのでOFFでもよい)


これでAzure MFA Serverの設定もおしまいです。


◆SSH接続許可設定

これで認証自体は通るようになるはずですが、SSHサーバの認可設定が必要です。クローズな環境ではあまり気にしなくても良いとは思いますが、今回Azure VMでCentOSを構成しているので、認証に加えて接続出来るユーザをある程度制限しておこうと思います。

以下のファイルへ接続しても良いユーザ名を明記しておきます。
/etc/ssh/sshd_config

ここにAllowUsersパラメータを指定します。
構文は「AllowUsers ユーザ名をスペース区切りで列挙」なので、以下のような感じになります。ちなみに間違えると誰もつなげなくなるので別のコンソールを一枚あげておいた上で設定する様にしましょう。
※後で使うユーザはtestuser05なのでこの行にtestuser05を追記することでログイン可能になります。

編集が完了したらsshdに設定ファイルをリロードします。
sudo systemctl reload sshd

設定に失敗していると本当に誰もSSH接続できなくなりますので、端末のクローズは全部動作確認が出来た上でしてください。


◆ユーザの準備

いよいよ動作確認と行きたいと所ですが、その前にユーザの準備です。

先ほどLDAPクライアントの設定でActive Directory上のユーザの属性のマッピングを行ったと思うので、必要な属性(今回はuidNumber)をActive Directory上のユーザのemployeeIdに登録しておく必要があります。

employeeIdはデフォルトではユーザのプロパティからは見えないので、拡張表示設定をしたうえで、属性エディタを開き、値を直接セットします。


そして、最後に多要素認証設定です。
今回はアプリを使って認証する様に設定します。

Azure MFA Serverのユーザポータルへアクセスし、Active Directoryのユーザ名/パスワードでログインします。


初回アクセスだと、認証方法を選択する画面になるので、「モバイルアプリ」を選択し、「アクティブ化コードの生成」をクリックします。


するとQRコードが表示されるので、Authenticatorアプリケーションで読み込んでアカウントが登録されるのを確認して、「今すぐ認証」をクリックします。


上手くいけば秘密の質問への回答の登録などの画面に遷移しますが、ここは直接は関係ないので割愛します。適当に登録しておきます。


◆動作確認

ようやく動作確認です。

今回はTeraTerm Proを使ってSSH接続をします。

アドレスを入れて接続をするとユーザ名とパスワードを入れるダイアログが出るので、先のActive Directory上のユーザIDとパスワードでログオンを試みます。


すると、Authenticatorアプリに承認要求が届くので確認を行います。


ここまでの設定が上手くいっていればちゃんとログインできるはずです。




この様に、Azure MFA ServerはRadiusなど一般的な認証サーバとして振舞うことが出来、かつ間に多要素認証を挟み込むことが出来るので、応用範囲はかなり広いと思います。例えばVPN装置などこれまでクライアント証明書や個別に管理されているID/パスワードで認証していたものが運用上の問題になったり、セキュリティ上の弱点になったりするケースもあったと思いますが、このような工夫を組み合わせることにより少しでも楽にセキュリティレベルを向上することが出来る可能性がありますので、検討してみてください。

2017年1月8日日曜日

CentOS+Apacheの認証をAzure AD/OpenID Connectで行う

こんにちは、富士榮です。

某普通な人がnode.jsとPAMを使ったApache+Azure ADの認証(Basic認証)の記事を書いていたので、そういえばPingIdentityの人が作ってるmod_auth_openidc使ってなかった事を思い出したのでやってみました。

 参考)割と普通なブログ
  Linux+Apache の認証で Azure Active Directory を利用する
  http://normalian.hatenablog.com/entry/2017/01/08/031209


やりたいことは、CentOSにホストされたApache上のWebコンテンツへのアクセスAzure ADで保護する、という非常にシンプルなシナリオです。
※意外と実案件でもこの手の引き合い多いんですよね。オンプレのWebサーバでスタティックコンテンツの場合はAzure AD WAP(Web Application Proxy)で提案しちゃうことが多いんですけどね。

◆環境(必要なもの)

CentOSは手元に転がっていたVMをそのまま流用しました。
uname -aの結果はこんな感じ。ちなみに面倒なのでSELinuxとFirewallは無効にしてあります。
[root@oidc conf]# uname -a
Linux oidc.eidentity.local 3.10.0-514.2.2.el7.x86_64 #1 SMP Tue Dec 6 23:06:41 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

mod_auth_openidcは最新版(2.1.3)のrpmが以下からダウンロードできますが、色々と前提となるパッケージなどを入れる必要があったので、ついでにソースからコンパイルしてしまいました。
 https://github.com/pingidentity/mod_auth_openidc/releases

以下が必要となるパッケージ群です。

yumでインストールするもの。(*-develがこんなに必要だったのはコンパイルしたからです)

  • git
  • httpd-devel
  • curl-devel
  • jansson-devel
  • openssl-devel
  • autoconf
  • automake

rpmでインストールするもの
  • cjose-0.4.1-1.el7.centos.x86_64.rpm
    • mod_auth_openidcと同じくここからダウンロードできます。
ソースからコンパイルするもの

  • hiredis
  • mod_auth_openidc


◆モジュールの導入手順

上記に記載したyumでインストールするものをyum installでまずはインストールします。
手順は書くまでもありませんが、以下の通りです。(だいぶ省略してます)
#yum install git
# yum install httpd-devel
# yum install curl-devel
# yum install jansson-devel
# yum install openssl-devel
# yum install autoconf
# yum install automake

同様にrpmでインストールするcjoseについても導入します。
# rpm -i cjose-0.4.1-1.el7.centos.x86_64.rpm


最後にコンパイルするモジュール群です。
まずはHiredisです。githubのレポジトリをクローンしてmakeします。
適当なディレクトリで以下のコマンドを実行します。
# git clone http://github.com/redis/hiredis
# cd hiredis
# make
# make install


そして、本命のmod_auth_openidcです。こちらもHiredisと同じくgit cloneして最新のソースを元にインストールしていきます。
git clone https://github.com/pingidentity/mod_auth_openidc/releases
cd mod_auth_openidc
./autogen.sh
./configure
make
make install

これで、/etc/httpd/modulesにmod_auth_openidc.soが出来上がります。


◆設定手順

設定は大きくは2つに分かれます。
 1つ目は、Apache自体にmod_auth_openidcを組み込む
 2つ目は、mod_auth_openidc自体の設定と対抗となるAzure ADへのクライアント登録
です。

順に解説していきます。

1.Apache自体にモジュールを組み込む

単純に出来上がったモジュールをロードします。
今回は認証関係のモジュールを読み込んでいる/etc/httpd/conf.modules.d/00-base.confへ以下を追記しました。
LoadModule auth_openidc_module modules/mod_auth_openidc.so



次に、保護対象とするコンテンツを決めていきます。
今回は単純にOpenID Connectを使ってAzure ADからアイデンティティ情報が取れていれば良いので、cgi-binディレクトリを保護対象として、環境変数にid_tokenの中身がちゃんと入ってきているかどうかを確認したいと思います。

/etc/httpd/conf/httpd.confに以下を追記します。
<Location /cgi-bin/>
   AuthType openid-connect
   Require valid-user
</Location>


もちろん、/var/www/cgi-binへテスト用のcgiファイルを置き、実行権限を付ける必要はあります。
今回は単純に環境変数を見たいだけなので、以下のスクリプトを置いています。
#!/bin/perl
print "Content-type: text/html\n\n";
print "<TABLE BORDER=\"1\">\n";

for $key (sort(keys(%ENV))) {
    print "<TR><TD><TT>$key</TT></TD><TD><TT>$ENV{$key}</TT></TD></TR>\n";
}

print "</TABLE>\n";
exit;


2.モジュールの設定(RPとしての設定)とAzure ADの設定(IdPとしての設定)

まず、Azure ADへクライアント登録を行います。

RPへ登録するために欲しい情報は、

  • client_id
  • client_secret

の2点で、これらはAzure ADへアプリケーション登録をすることにより取得が可能になります。

また、Azure ADへアプリケーション(つまりはOAuthクライアント)を登録する際に必要なのは、redirect_uri(アプリケーションのURL)です。

アプリケーションの追加をすると以下のパラメータを聞いてきますので、それぞれを設定します。

  • アプリケーション名: 任意の名前
  • アプリケーション・タイプ: Web app / APIを指定
  • サインオンURL: アプリケーションのURL(今回はhttp://oidc.eidentity.local/cgi-bin/にしています)
登録が終わると以下のダッシュボードが表示され、この中にあるアプリケーションIDがApache側へ設定するclient_idとなりますので、コピーしておきます。


次はclient_secretです。
ダッシュボードのAll settingsからキーを選択して新規にキーを生成し、保存をクリックすると表示されるのがclient_secretです。画面を遷移すると二度と表示できないので、ちゃんとコピーしておきます。


基本的にこれで情報はそろうのですが、最後にもう一つ。
mod_auth_openidcがリダイレクトしたり通信するIdPのエンドポイント情報を取得するためのメタデータURLが必要となりますので、これを確認しておきます。

以下のURLなので特に気にすることもありませんが、覚えておきます。
 https://login.windows.net/{ドメイン名}/.well-known/openid-configuration


では、最後となるhttpd.confへの設定追加をしていきます。
必要なのは以下のパラメータです。

  • OIDCProviderMetadataURL: Azure ADのメタデータURLを指定
  • OIDCClientID: Azure ADに登録したクライアントIDを指定
  • OIDCClientSecret: Azure ADに登録したクライアントシークレットを指定
  • OIDCRedirectURI: Azure ADに登録したアプリケーションのURLを指定
  • OIDCScope: スコープを指定。openid email profileあたりで問題なし
  • OIDCCryptoPassphrase: 必須なので適当にしてい


こんな感じになります。

OIDCProviderMetadataURL https://login.windows.net/pharaoh.onmicrosoft.com/.well-known/openid-configuration
OIDCClientID 0fa5bfc6-61da-47c1-9223-02f136594d09
OIDCClientSecret 6/2TYCeboBUgDB7rluxFmpLE8fYL45zgwhk38RTY5/E=
OIDCRedirectURI http://oidc.eidentity.local/cgi-bin/
OIDCScope "openid email profile"
OIDCCryptoPassphrase Password



これで設定は完了です。
早速テストしてみます。

◆動作確認

単純に先ほどAzure ADで保護したcgiにアクセスしてみます。

いきなりAzure ADのログイン画面へリダイレクトされますので、ログインします。

するとプロファイルへのサインインとアクセスに関する同意が求められるので同意します。


同意すると、cgiへリダイレクトされ、正しくアイデンティティ情報が取得できているのがわかります。
(OIDC_CLAIM_*という環境変数がid_tokenから取得された情報です)



かなり構成も簡単なので、レガシーなWebコンテンツやCGIなどが残っている場合は、今回紹介した方法でAzure ADとの連携を導入してみてはいかがでしょうか?