Extend TACACS+ daemon

Debian/Ubuntu JP Advent Calendar 2013 の 23日目 1 の記事です。 Advent Calendar、 今年こそは穴が出ないようにと思って、ホノルル時間を駆使して途中まで穴を埋めていましたが、(家事&仕事&育児)疲れ+娘からもらった風邪、で途中断念してしまいました。残念。

閑話休題。今回の内容は、「TACACS+でアクセス制御を行うユーザアカウントを、LDAPで一元管理できるようにTACACS+をカスタマイズしたよ」というお話です。

はじめに

ネットワーク機器へのアクセス制御用のプロトコルに TACACS+ というのがあります。またプロトコルと同じ名前の、Unix/Linux 上で動くデーモンもあります。元々CiscoがGPLv2で公開したものを機能拡張してメンテナンスされているのが リンク先 で公開されているもので、これは Debianパッケージ にもなっています。

背景

ネットワークエンジニア自体の数はたいてい少数で、共有アカウントでのネットワーク機器の運用を行っていることも多いかと思います。しかし、一方で、誰が何をやったのか、という作業ログは取りたい、という要望もあるでしょう。するとアカウンティングは最低限TACACS+でやろう、という話になるかと思います。そのついでに個人ユーザ化もできると良いよね、という展開になりますね。

さて、TACACS+では個人ユーザアカウントを作るには、設定ファイル(/etc/tacacs+/tac_plus.conf)で次のいずれかの設定を行います。

  • loginディレクティブなどで指定したpasswd(5)フォーマットのファイルでユーザ管理する

  • 必要なユーザ数分、userディレクティブで定義する

前者の場合、ユーザ名、および平文もしくはDES暗号化したパスワードを下記のように記述したファイルを作成します。

user1:password::::
user2:password::::

これを、 `login = file /path/to/passwd` として設定します。この方法のメリットは、このファイルを更新しても、tac_plusデーモンを再起動する必要がないことです。しかしこの方法の最大のデメリットは、この方法での一番のネックは「DESで暗号化したパスワードが必要」という点です。既にLDAPなどでユーザアカウントの管理を一元管理している場合、パスワードをユーザに入力させて、平文のパスワードをDESで暗号化し、その暗号化されたパスワードをこのファイルに登録ないし、更新を行わなければなりません。この方法を使うのであれば、LDAP用のパスワード変更用UIのバックエンドでこのファイルの更新処理も行うようにするという方法になるかと思いますが、処理が面倒な上、そのUIの管理が自分でない場合は、さらに(その管理者との)調整なども面倒です。また、ファイルの読み取りができればBrute force attackでパスワードの解読も可能な点も考えると、LDAPなどで一元管理していても別で漏れてしまう可能性がある方法を採用するのは避けたいところです。

一方、後者の必要なユーザ数分、userディレクティブで定義する場合、基本的には次のような設定を行います。 2

user = fred {
    login = des mEX027bHtzTlQ
    # (snip)
}

これではここにユーザ設定した上にDESで暗号化したパスワードも記述しないといけない分、先ほどのpasswdファイルでの管理よりも不便になってしまいます。そこで、PAMとの連携です。loginで指定している認証方法には PAM を使うこともできます。設定方法は下記の通りです。

user = fred {
    login = PAM
}

認証自体はPAMに任せてしまえば、あとはPAMで良きように計らってくれるのです。つまり、pam-ldapを使い、LDAPでユーザ認証を行っているのであれば、TACACS+で認証させたいユーザアカウントをtac_plus.confに定義だけ行っておけば、パスワード自体の管理は行う必要はありません。先ほどよりも結構便利です。

しかし、この方法もまだ不便な点があります。つまりtac_plus.confにユーザ定義を行わないと行けない、という点です。ユーザの追加・削除のたびにtac_plus.confを変更するという運用を行わなければいけません。

対応

とりうる対策としては2つです。

  1. LDAPからユーザアカウントが登録 or 削除されたら、tac_plus.confを書き換え、tac_plusにSIGHUPを発行する

  2. default authentication をPAM対応させる

前者で行うなら、LDAPのパスワード変更用UIのバックエンドで処理させたり、定期的にLDAPのデータをチェックして更新するようなジョブを組めば良いかもしれません。しかし、ansibleなどでpush型で反映するなり、TACACS+サーバ上で、ldapsearchの結果を元に変更するpull型でも即時反映されずタイムラグがある点を考慮すると微妙な感じです。

後者のdefault authenticationは、tac_plus.confで使えるデフォルトの認証方法の指定を行うためのディレクティブです。 が、現時点では前述の login ディレクティブなどで設定する、 file /path/to/passwd のような値しか取れません。なので、現時点ではgroup ディレクティブの中でloginの値として使う場合と同様、 TACACS+サーバにpasswd ファイルを配置し、その管理を行わなければなりません。 そこで、このdefault authenticationでPAMをサポートするようにしたのが今回の対応です。

default authentication = PAM

上記の設定を行うことで、個々のuserディレクティブの設定が不要になります。 3

この対応を、Sid版のtacacs+ 4.0.4.26と、Wheezy版の4.0.4.19にパッチを当てて、git-buildpackagesで管理したものをGitHubで公開しています。なので、git-buildpackageコマンドで自分でDebianパッケージを作成してお試しいただくこともできます。

また、Upstreamにパッチが取り込まれると、手離れできて嬉しいので、 MLに投稿してみました 。が、今のところ開発者からの反応はないので取り込まれるのは難しいのかなぁという感じです。クリスマスまでに反応があれば最高のクリスマスプレゼントなんですけどね。 :)

1

またしてもホノルル時間です。

2

この例はtac_plus.conf(5)に載っている例の一部引用です。

3

ちなみにgroupディレクティブにlogin = PAMを設定すれば良いのではないか、と考えるかもしれませんが、その設定を行った場合でも、個々のuserディレクティブの設定が必要です。

Debian Jr. Project

Debian/Ubuntu JP Advent Calendar 2013 の 12日目の記事です。

我が家の娘 1 は今1歳9ヶ月になります。隙あらば、親のスマホやタブレットを奪い、大好きな丸いキャラクターの動画を見ようとしたり、幼児用のゲームで遊ぼうとします。2歳過ぎるまでは極力触らせないようにはしていますが、ロック解除の方法を盗み見して解除してしまったりと彼女の学習能力は親に比べ非常に高いので、羨ましいかぎり、もとい、この場合は悩ましい限りです。

とはいえ、そろそろ娘にもDebianユーザデビューを考えているところで、apt-cache search childの結果を眺めていて思い出したのが、主題の Debian Jr. Project です。これはDebian Pure Blend の一つであり、2011年の Debian/Ubuntu JP Advent Calendar 2011 の中尾さんによる記事、「 みんなのためのDebian Pure Blends 」でも紹介されていました。

このプロジェクトは、

「1歳から99歳までのこどもためのDebian」

であり、このプロジェクトの第一の目標は

Debian をこどもたちが 使いたくなるような OS にすること

となっています。

これは、「こどもが使いたくなるようなOS」が結果的にDebianだった、という状態にすることと同義ではないかと解釈しています。つまり、私と同様に「どうやってこどもにDebianを使わせようか」とお悩みの皆さんはもちろんのこと、「どうやってこどもにコンピュータを触れさせようか」とお悩みの皆さんにもうってつけではないでしょうか。

ということで、使わなくなった古いMacBookに、junior-* パッケージ群をインストールし、まず試してみてから娘にクリスマスに、は少し早いので2歳の誕生日にプレゼントしてみようかと思っています。

Footnotes

1

ネットでの通称は「おまめ」です。

Assigned native IPv6 automatically from RA

Debian/Ubuntu JP Advent Calendar 2013 の五日目の記事です。nozzy nozzyさんが五日目の記事ではなく六日目の記事として 公開されていた ので、またしても例のトリック( How to change timezone in Debian )を使っています。(いつまでこの穴埋め続けるんや…。)

先日、某同僚から 今の環境ではデフォルトでRAでIPv6アドレスをアサインしている という資料が公開されていましたが、OSの初期インストール時は、DHCPでのIPv4アドレスを使用しており、ネットワーク設定ではIPv6がデフォルトにはなりません。そこで、Ubuntu 12.04 LTS(presice) とWheezyでは次のように preseed の late_commandを使って /etc/network/interfaces を書き換え、IPv6 もしくは IPv6/IPv4 デュアルスタックの設定を行っています。

IPv6 onlyの場合は、

iface eth0 inet6 auto

を使いますが、デュアルスタックの場合は、

iface eth0 inet dhcp

を追加しています。

presice の場合

cp -f /dev/null /etc/resolvconf/resolv.conf.d/original
sed -i 's/domain-name-servers, //' /etc/dhcp/dhclient.conf
cat << 'EOF' >  /etc/network/interfaces
> auto lo
> iface lo inet loopback
>
> auto eth0
> {% if host.ipv4 %}
> iface eth0 inet dhcp{% endif %}
> iface eth0 inet6 auto
>     dns-nameservers {{ dns_ipv6 }}
>     dns-search {{ subdomain }}.{{ dns_suffix }} {{ dns_suffix }}
> EOF

wheezy の場合

$ apt-get install -y resolvconf
$ cp -f /dev/null /etc/resolvconf/resolv.conf.d/original
$ sed -i 's/domain-name-servers, //' /etc/dhcp/dhclient.conf
$ cat << 'EOF' >  /root/interfaces
> auto lo
> iface lo inet loopback
>
> auto eth0
> {% if host.ipv4 %}
> iface eth0 inet dhcp{% endif %}
> iface eth0 inet6 auto
>     dns-nameservers {{ dns_ipv6 }}
>     dns-search {{ subdomain }}.{{ dns_suffix }} {{ dns_suffix }}
> EOF
$ sed -i 's/{{ host }}.bad/{{ host }}.{{ subdomain }}.{{ dns_suffix }}/g' /etc/hosts
$ echo '{{ host }}.{{ subdomain }}.{{ dns_suffix }}' > /etc/mailname
$ test -x /usr/sbin/postconf && /usr/sbin/postconf -e mydomain='{{ subdomain }}.{{ dns_suffix }}'

preciseとの違いとして、resolvconfをインストールとPostfixの設定を行っています。これらはUbuntu, DebianとでOSインストール後の設定や挙動を同じにするためです。preciseではresolvconfがデフォルトでインストールされますが、wheezyではインストールされません。また、後者はDebianではデフォルトMTAはEximなのでこれをPostfixに変更しているのですが 1 、これらの設定を行わないと、localhost.localdomainのままになっているからです。

/etc/resolvconf/resolv.conf.d/originalを/dev/nullで上書きし、/etc/dhcp/dhclient.confでdomain-name-serversを削除していますが、これらは、前述のOSインストール時にはIPv4を使い、インストール後にはIPv6をデフォルト、必要に応じてデュアルスタックにする、というところに副作用があるためです。

このoriginalファイルはインストール時の情報を元に下記のように設定されます。wheezyの場合は、resolvconfパッケージをインストールした時点で、/etc/resolv.confの情報を元に設定されます。

search sub.example.org example.org
nameserver 192.0.2.1

しかしIPv6をデフォルトとしている環境なので、nameserverは、IPv6アドレスになっていることが本来の期待値です。

なので、これをこのままにしておくと、再起動やnetworkingの再起動時などの/etc/network/if-up.d/000resolvconfでresolvconf -aが実行されると、/etc/resolv.confの内容が書き換えられてしまう、という問題が発生します。なので、originalの中身を消しておけば、OS起動時などにRAで通知される値が正しく割り当てられます。

また、デュアルスタックを使用している場合には、DHCPのリース更新時や、dhclientの手動実行、あるいはservice networking restart実行時に、/etc/resolv.confのnameserverの値がIPv4に設定されてしまいます。これは、上述のdomain-name-serversを削除することによって、IPv6アドレスのままになります。なお、domain-nameを同様に削除すると、dhclient実行時に、下記のようなエラーが発生してしまうため、これは削除しません。

$ sudo dhclient eth0
RTNETLINK answers: File exists
chmod: cannot access `/etc/resolv.conf.dhclient-new.1276': No such file or directory
mv: cannot stat `/etc/resolv.conf.dhclient-new.1276': No such file or directory

今の職場環境の特殊事情ではありますが、もし同様なケースの場合には参考にしてみてはいかがでしょうか。

Footnotes

1

ごめんなさい、小室さん

backup2swift and swiftsc

Debian/Ubuntu JP Advent Calendar 2013 の四日目の記事です。早速前日のネタ( How to change timezone in Debian )を使うハメになるとは…。前日のネタを使っても、もはや1時間もありませんので、以前、作成&Debianパッケージ化したツールの紹介をしたいと思います。

ツールの名前は表題のとおりです。

前者はOpenStack Swiftにバックアップを取るためのコマンドラインツールです。後者はbackup2swiftが使用しているswift用のクライアントライブラリです。前者はswiftにバックアップを取りたいというよくありふれた欲求から開発しました。後者はpython-swiftclientパッケージを使えばそもそも必要ありませんが、それまで全くswiftを使ったことなかった上、Swift絡みで情報交換をしようという機会があり、そのコーディネートを私がやることになったこともあったので、じゃあクライアントライブラリも作ったるか、ということで、これらのツールを作りました。

Swiftの認証は、TempAuthとKeyStoneに対応してます。職場で使っている認証プラグインにも対応していますが、名称を忘れてしまったので思い出したらそのうち追記しておきます。

PKG-OpenStack team のThomas Goirand 氏にパッケージスポンサーをして頂き、python-backup2swift, python-swiftscとしてDebianパッケージになっています。また、Ubuntuにもuniverseとしてパッケージになっているようです。

ということで、Swiftを使っている方はぜひ使ってみて下さい。

なお、開発時には 石川さん に助言頂いておりました。石川さん、改めてお礼申し上げます。

How to change timezone in Debian

Debian/Ubuntu JP Advent Calendar 2013 の三日目の記事です。二日目じゃないよ、三日目だよ。

この時期になると各所で「もう少しだけ時間が伸びたらいいのにッ!」とお悩みの方が多いことでしょう。そんな貴方に朗報です。今からハワイにバカンスに行くのですッ!タイムゾーンは当然違う上、日付変更線越えるので一日巻き戻った感があってとってもお得ですね。

Debianでシステムグローバルにタイムゾーンを変更するには、 dpkg-reconfigure コマンドで行います。

$ sudo dpkg-reconfigure tzdata

あとは、「地理的情報」で「太平洋側」を選択し、「時間帯」で「ホノルル」を選択し、「了解」を押すだけですッ!良かった、これで貴方の Advent Calendarネタは間に合ったことでしょう。

もっと手軽にやりたい?

$ TZ='Pacific/Honolulu'; export TZ
$ date
2013年 12月  2日 月曜日 05:45:11 HST
$ tinker -p "How to change timezone in Debian"

New post created as '/home/mkouhei/docs/d.palmtb.net/2013/12/02/how_to_change_timezone_in_debian.rst'

はっ!?娘を寝かしつけて仕事やるかと目覚めたら、 二日目がなかった!とかそんな現実はなかった ので、このネタを使う必要はなかったようです。良かった良かった。

さー、仕事しよ、仕事。