<mazgi.github.io 移行済>#Gentoo で普通の CVE-2015-7547 対策

移行しました=> https://mazgi.github.io/posts/2016.02/cve-2015-7547-on-gentoo/


追記

私が何か勘違いしてたようですが glibc-2.21-r2 (~amd64マスクされてない)でpatchが取り込まれてますね。。

# emerge -fOq glibc
>>> Fetching (1 of 1) sys-libs/glibc-2.21-r2::gentoo
# tar tf /usr/portage/distfiles/glibc-2.21-patches-7.tar.bz2 | grep 'CVE-2015-7547'
patches/00_all_0028-CVE-2015-7547-getaddrinfo-stack-based-buffer-overflo.patch

本文

皆さまにおかれましては CVE-2015-7547 の対応お疲れ様です。

glibc ライブラリの脆弱性 (CVE-2015-7547) に関する注意喚起

さてGentoo Linuxの場合はどうかというと、 glibc-2.22-r2 でpatchが取り込まれているようです。

574880 – (CVE-2015-7547) <sys-libs/glibc-2.21-r2: stack overflow in getaddrinfo (CVE-2015-7547)

試しにfetchしてpatchを探してみましょう。

# ACCEPT_KEYWORDS="~amd64" emerge -fOq \=sys-libs/glibc-2.22-r2
>>> Fetching (1 of 1) sys-libs/glibc-2.22-r2::gentoo
# tar tf /usr/portage/distfiles/glibc-2.22-patches-10.tar.bz2 | grep 'CVE-2015-7547'
patches/10_all_glibc-CVE-2015-7547.patch

入ってますね。

であればあとはこんなファイルを用意して ~amd64 マスクを外し、

# cat /etc/portage/package.accept_keywords/sys-libs.glibc
# for CVE-2015-7547 ( https://bugs.gentoo.org/show_bug.cgi?id=574880 )
=sys-libs/glibc-2.22-r2 ~amd64

emerge して再起動するだけです。

# emerge -pvq sys-libs/glibc
[binary   R   ] sys-libs/glibc-2.22-r2  USE="(multilib) nscd -debug -gd (-hardened) -profile (-selinux) -suid -systemtap -vanilla" 

#Gentoo Tips: いつなんどきでも #GentooInstallBattle で最新のstage3を入手する

前提

2015年も残す所あと数日ですね。
今年はあと何回#gentooinstallbattleにエントリーできるでしょうか。
Gentoo Linuxをインストールためには2つのアーカイブファイルをダウンロードします。

  • stage3
    • / ツリーのアーカイブ, つまりOSとして成立するために必要なあらゆるファイル
    • (以前はstage1, stage2もありました)
  • portageスナップショット
    • Gentoo Linuxのパッケージ管理システムであるPortageのリポジトリのアーカイブ

このうち、portageスナップショットについては ${ミラーサイトのURL}/snapshots/portage-latest.tar.{xz,bz2} というURIで常に最新のアーカイブを入手できるので毎回同じコマンドラインが使えます。
お気に入りのミラーサイトを見つけたらgistに curl -LO 'ftp://ftp.jaist.ac.jp/pub/Linux/Gentoo/snapshots/portage-latest.tar.xz' とでもメモしておけば、あとはインストールのたびに貼り付けてEnterキーを押すだけです。

f:id:mazgi:20151228021027p:plain

しかしstage3はファイル名にビルドされた日付が含まれるため毎回同じURIで、というわけにはいきません。

f:id:mazgi:20151228021031p:plain

Gentoo Linuxをインストールするなら少しでも楽をしたいというのが人情だと思いますので、今回は楽にstage3をダウンロードする方法を考えてみます。

方法

最新のstage3ファイルのpathはこのようなフォーマットで latest-stage3-${ARCH}.txt というファイルに書かれています。

root@sysresccd /mnt/gentoo % curl -L 'ftp://ftp.jaist.ac.jp/pub/Linux/Gentoo/releases/amd64/autobuilds/latest-stage3-amd64.txt'
# Latest as of Sun, 27 Dec 2015 12:30:01 +0000
# ts=1451219401
20151225/stage3-amd64-20151225.tar.bz2 249949601

そこでgrepを使って # で始まる行を除外し、awkを使ってスペースで区切られた1つ目のフィールドを取り出すことでstage3ファイルのpathを得ることができます。

curl -L 'tp://ftp.iij.ad.jp/pub/linux/gentoo/releases/amd64/autobuilds/latest-stage3-amd64.txt' -s | grep -vE '^\s*(#|$)' | awk '{print $1}'

したがって、このようにすればいつでも最新のstage3ファイルを得ることができます。

root@sysresccd /mnt/gentoo % MIRROR='ftp://ftp.jaist.ac.jp/pub/Linux/Gentoo'; curl -LO "${MIRROR}/releases/amd64/autobuilds/$(curl -L ${MIRROR}/releases/amd64/autobuilds/latest-stage3-amd64.txt -s | grep -vE '^\s*(#|$)' | awk '{print $1}')"
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  238M  100  238M    0     0  6255k      0  0:00:39  0:00:39 --:--:-- 8091k

これで#gentooinstallbattleが少し楽になりますね!

<mazgi.github.io 移行済>ssmjp で Gentoo の話をしてきました

移行しました=> https://mazgi.github.io/posts/2015.10/gentoo-talk-on-ssmjp/


先週の話ですがssmjp 2015/09の回におじゃましてきました。

「一緒にプロダクション環境でのGentoo勉強会」やりましょう!という話を現実にしてくださった@usaturnさん、そして初参加&&初登壇&&Gentooネタという暴挙(?)を広い懐で受け入れてくださった #ssmjp の皆様、本当にありがとうございました!

内容とか

以前会社のblogに書いた「自社サービスをGentoo Linuxのパッケージ形式であるebuildでパッケージングしてdeployする」という話をベースになぜそのような選択に至ったかなどをお話させていただきました。

techlog.mvrck.co.jp

当日のスライドはこちらにアップロードしております。

www.slideshare.net

オフィシャルblogでのGentooカミングアウトに留まらず発表の場までいただきありがとうございました!
おかげさまで無事フラグを回収できました。

普通のScalaアプリケーションをebuildでdeployする

会社ではほとんどのアプリケーションをScalaで開発しさくらのクラウドやハウジング環境で運用しているのですが、どんな言語で開発するにせよどのような環境で運用するにせよ、当然ながらアプリケーションはdeployする必要があります。

deployに関しては色々な方法があると思うのですが、私は「ミドルウェアのインストールやアップデートと同じように自社プロダクトもパッケージとしてdeployしたい」と考えていました。
つまりnginxやMariaDBをアップデートするように yum updateapt-get upgrade , emerge -uND world (「うどんアップデート」というらしいですね)すると自社プロダクトもアップデートされるということです。

そう!emerge !!
portageパッケージ管理システムに則ってアプリのebuildを作ればいいではないですか!!!
1日に何回も何十回もcommitがpushされる自社プロダクトで、もし都度バイナリパッケージを作るとなるとパッケージ作成自体のコストが高く感じてしまいますが、ebuildなら「GitHubのリポジトリから直接masterのHEADを取得後コンパイルしインストールする」という手順自体をパッケージングできます!
portageにはインストールすると同時にバイナリパッケージを作る機能もあるので、たとえScalaアプリのコンパイルに初回は1曲聴ける程度の時間がかかったとしても2回目以降はイントロを聴いている間にインストールできます!

ということでScalaアプリをebuildでdeployするようになってから数ヶ月経ち課題を残しつつも安定してきたので概要を書き留めておきます。

なお、世間にはGentoo Linuxでサービス運用している会社が少なくとも2社あるようです。

2000年以前はおそらくどこにも採用されていなかったことを考えると近年の導入会社数の伸び率は目覚ましく、ひとりのGentoo Linuxユーザーとしてもうれしい限りです。

流れ

例としてHelloPlayというPlayFrameworkを使ったScalaのサンプルアプリケーションをebuildでパッケージングしてみます。 インストール先はさくらのクラウドですが、今回プラットフォーム固有の機能は使っていないのでクラウドでもハウジングでも差異はありません。
また、バージョンとして下記2つを想定します。

  • 安定版である 0.0.1 → tag v0.0.1 がインストールされる
  • 開発版である 9999 → その時点のmasterのHEADがインストールされる

なおこのアプリケーションでは v0.0.1 に対して masterGET /hello というエンドポイントが追加されており、リクエストを受けるとステータス200で"Hello"というメッセージを返す機能が追加されています。
差分はこんな感じです。

f:id:mazgi:20150818223830p:plain

ebuild作成

このアプリケーションを www-apps/playscala-example というパッケージにします。
こんなebuildを書いてみました。
また、 application.conf の雛形や起動スクリプトなども作成します。

ebuild自体の差分としては開発版である 9999 には ~amd64 キーワードを指定しますが、安定版である 0.0.1 にはキーワードを指定しません
ebuild内でバージョンを判定することにより 0.0.1 ではtagを、 9999 ではmasterのHEADを取得するよう振る舞いを分けます。

if [[ ${PV} != 9999 ]]; then
    # set tag as "EGIT_COMMIT"
    EGIT_COMMIT="v${PV}"
    SLOT=$(get_version_component_range 1-2)
fi

リポジトリ登録

repositories.xmlを作成自身のportageリポジトリのrootに配置します。

内容はこのようなXMLファイルです。

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE repositories SYSTEM "/dtd/repositories.dtd">
<repositories xmlns="" version="1.0">
  <repo quality="experimental" status="unofficial">
    <name><![CDATA[mazgi-experimental]]></name>
    <description lang="en"><![CDATA[An overlay by @mazgi]]></description>
    <homepage>http://mazgi.com/</homepage>
    <owner type="person">
      <email>MATSUKI.Hidenori@gmail.com</email>
      <name><![CDATA[Hidenori MATSUKI]]></name>
    </owner>
    <source type="git">git://github.com/mazgi/portage-overlay.git</source>
  </repo>
</repositories>

このrepositories.xml/etc/portage/repos.confに今回はmazgi-experimental.confという名前で配置します。
内容はこんな感じです。

$ cat /etc/portage/repos.conf/mazgi-experimental.conf
[mazgi-experimental]
location = /var/lib/portage/repo.data/mazgi-experimental
sync-type = git
sync-uri = git://github.com/mazgi/portage-overlay.git
auto-sync = yes

またScalaアプリケーションをsbtでビルドするようebuildを書いたので、sbtが必要になりますが、sbtのebuildパッケージも作成して同じリポジトリに入れています。
普通にsbtのebuildとして使えますのでもし必要でしたら上記の設定を行って emerge sbt-bin してみてください。

インストール

まずは sync して先ほど設定したリポジトリを取得します。

$ sudo emaint sync -r mazgi-experimental
>>> Syncing repository 'mazgi-experimental' into '/var/lib/portage/repo.data/mazgi-experimental'...
/usr/bin/git pull
Already up-to-date.
=== Sync completed for mazgi-experimental

Action: sync for repo: mazgi-experimental, returned code = 0

またJDK周りのUSEフラグを必要に応じて変更しておきます。

$ sudo flaggie dev-java/oracle-jdk-bin -awt -fontconfig
$ sudo flaggie dev-java/icedtea-bin -X -alsa -cups

ここまでやって emerge playscala-example すると下記のようにJDKやsbt等必要なパッケージを含めて全てがリストアップされます。

$ sudo emerge -uav playscala-example

These are the packages that would be merged, in order:

Calculating dependencies... done!
[ebuild  N     ] media-libs/giflib-4.1.6-r3::gentoo  USE="-X -rle -static-libs" ABI_X86="(64) -32 (-x32)" 0 KiB
[ebuild  N     ] app-eselect/eselect-java-0.1.0::gentoo  0 KiB
[ebuild  N     ] dev-util/patchelf-0.8::gentoo  0 KiB
[ebuild  N     ] media-libs/libpng-1.6.16:0/16::gentoo  USE="-apng (-neon) -static-libs" ABI_X86="(64) -32 (-x32)" 0 KiB
[ebuild  N     ] media-libs/lcms-2.6-r1:2::gentoo  USE="threads zlib -doc -jpeg -static-libs {-test} -tiff" ABI_X86="(64) -32 (-x32)" 0 KiB
[ebuild  N     ] dev-java/java-config-wrapper-0.16::gentoo  0 KiB
[ebuild  N     ] sys-apps/baselayout-java-0.1.0::gentoo  0 KiB
[ebuild  N     ] dev-lang/nasm-2.11.08::gentoo  USE="-doc" 0 KiB
[ebuild  N     ] dev-java/java-config-2.2.0:2::gentoo  PYTHON_TARGETS="python2_7 python3_4 -python3_3" 0 KiB
[ebuild  N     ] gnome-base/gsettings-desktop-schemas-3.14.2::gentoo  USE="-introspection" 0 KiB
[ebuild  N     ] media-libs/libjpeg-turbo-1.3.1::gentoo  USE="-java -static-libs" ABI_X86="(64) -32 (-x32)" 0 KiB
[ebuild  N     ] virtual/jpeg-62:62::gentoo  ABI_X86="(64) -32 (-x32)" 0 KiB
[ebuild  N f   ] dev-java/oracle-jdk-bin-1.8.0.51:1.8::gentoo  USE="-alsa -awt -cups -derby -doc -examples -fontconfig -javafx -jce -nsplugin -pax_kernel (-selinux) -source" 0 KiB
[ebuild  N    ~] virtual/jdk-1.8.0:1.8::gentoo  0 KiB
[ebuild  N     ] dev-java/icedtea-bin-7.2.5.5:7::gentoo  USE="-X -alsa -cjk -cups -doc -examples -nsplugin -pulseaudio (-selinux) -source -webstart" 0 KiB
[ebuild  N     ] virtual/jdk-1.7.0:1.7::gentoo  0 KiB
[ebuild  N    ~] virtual/jre-1.8.0:1.8::gentoo  0 KiB
[ebuild  N     ] virtual/jre-1.7.0:1.7::gentoo  0 KiB
[ebuild  N     ] dev-java/sbt-bin-0.13.7:0.13::mazgi-experimental  0 KiB
[ebuild  N     ] www-apps/playscala-example-0.0.1:0.0::mazgi-experimental  USE="autoclean symlink -doc" 0 KiB

Total: 20 packages (20 new), Size of downloads: 0 KiB
Fetch Restriction: 1 package

The following keyword changes are necessary to proceed:
 (see "package.accept_keywords" in the portage(5) man page for more details)
# required by www-apps/playscala-example-0.0.1::mazgi-experimental
# required by playscala-example (argument)
=virtual/jdk-1.8.0 ~amd64
# required by www-apps/playscala-example-0.0.1::mazgi-experimental
# required by playscala-example (argument)
=virtual/jre-1.8.0 ~amd64

The following license changes are necessary to proceed:
 (see "package.license" in the portage(5) man page for more details)
# required by virtual/jdk-1.8.0::gentoo
# required by virtual/jre-1.8.0::gentoo
# required by www-apps/playscala-example-0.0.1::mazgi-experimental
# required by playscala-example (argument)
>=dev-java/oracle-jdk-bin-1.8.0.51 Oracle-BCLA-JavaSE

Would you like to add these changes to your config files? [Yes/No] 

JDK 1.8 のmaskを外し、Oracle JDKのライセンスに同意し、インストールを進めます。

$ sudo dispatch-conf
$ sudo emerge -uav playscala-example

These are the packages that would be merged, in order:

Calculating dependencies... done!
[ebuild  N     ] app-eselect/eselect-java-0.1.0::gentoo  0 KiB
[ebuild  N     ] dev-java/java-config-wrapper-0.16::gentoo  0 KiB
[ebuild  N     ] sys-apps/baselayout-java-0.1.0::gentoo  0 KiB
[ebuild  N     ] dev-java/java-config-2.2.0:2::gentoo  PYTHON_TARGETS="python2_7 python3_4 -python3_3" 0 KiB
[ebuild  N f   ] dev-java/oracle-jdk-bin-1.8.0.51:1.8::gentoo  USE="-alsa -awt -cups -derby -doc -examples -fontconfig -javafx -jce -nsplugin -pax_kernel (-selinux) -source" 0 KiB
[ebuild  N    ~] virtual/jdk-1.8.0:1.8::gentoo  0 KiB
[ebuild  N    ~] virtual/jre-1.8.0:1.8::gentoo  0 KiB
[ebuild  N     ] dev-java/sbt-bin-0.13.7:0.13::mazgi-experimental  0 KiB
[ebuild  N     ] www-apps/playscala-example-0.0.1:0.0::mazgi-experimental  USE="autoclean symlink -doc" 0 KiB

Total: 9 packages (9 new), Size of downloads: 0 KiB
Fetch Restriction: 1 package

Would you like to merge these packages? [Yes/No] 

インストールできたら application.conf を作成し、startしてみます。

$ sudo cp /etc/playscala-example/application.conf{.example,}
$ sudo /etc/init.d/playscala-example start
 * Starging playscala-example ...                                                     [ ok ]
$ /etc/init.d/playscala-example status
 * status: started
$ curl -L 'localhost:9000/' -o /dev/null -w '%{http_code}\n' -s
200

無事 / へのGETが200を返すことを確認できました!

アップデート

安定版である 0.0.1 がインストールできました。

$ curl -L 'localhost:9000/hello' -o /dev/null -w '%{http_code}\n' -s
404

しかしながら 0.0.1/hello へのGETが404になってしまいます。 そこで、今度は開発版の 9999 にアップデートしてみます。

9999 は特定のtagを参照しているわけではなくemergeした時点でのmasterのHEADがインストールされます。

$ sudo emerge -uavq \=www-apps/playscala-example-9999
[ebuild  NS   ] www-apps/playscala-example-9999 [0.0.1] USE="autoclean -doc symlink" 

The following keyword changes are necessary to proceed:
 (see "package.accept_keywords" in the portage(5) man page for more details)
# required by =www-apps/playscala-example-9999 (argument)
=www-apps/playscala-example-9999 ~amd64

Would you like to add these changes to your config files? [Yes/No] 

Autounmask changes successfully written.

 * IMPORTANT: config file '/etc/portage/package.accept_keywords/00_default' needs updating.
 * See the CONFIGURATION FILES section of the emerge
 * man page to learn how to update config files.

~amd64 でマスクされていますので外します。

$ sudo dispatch-conf

マスクを外したら改めてemergeします。

$ USE="-symlink" sudo emerge -uavq \=www-apps/playscala-example-9999
[ebuild  NS   ] www-apps/playscala-example-9999 [0.0.1] USE="autoclean -doc -symlink" 

Would you like to merge these packages? [Yes/No] 

このパッケージは /var/lib/playscala-example/versions 以下にバージョン毎にsymlinkを作る構造になっているのでsymlinkを貼り替えます。

$ cd /var/lib/playscala-example/versions
/var/lib/playscala-example/versions ~
$ sudo rm current
$ sudo ln -s playscala-example.9999.957b03072271df6586c1e6db8b2b76b4be5e3f08 current
$ sudo chown play:play -h current
$ ls -l
total 4
lrwxrwxrwx 1 play play  63 Aug 31 16:19 current -> playscala-example.9999.957b03072271df6586c1e6db8b2b76b4be5e3f08/
drwxr-xr-x 1 play play 100 Aug 31 03:10 playscala-example.0.0.1.9e023916c4c911408145ff5f181a42543fbced4a/
drwxr-xr-x 1 play play 102 Aug 31 16:12 playscala-example.9999.957b03072271df6586c1e6db8b2b76b4be5e3f08/

サービスを再起動します。

$ sudo /etc/init.d/playscala-example restart
 * Stopping playscala-example ...                                                     [ ok ]
 * Starging playscala-example ...                                                      [ ok ]
$ sudo /etc/init.d/playscala-example status
 * status: started

/hello へのGETが通るようになったか確認してみます。

$ curl -L 'localhost:9000/' -o /dev/null -w '%{http_code}\n' -s
200
$ curl -L 'localhost:9000/hello' -w '\n%{http_code}\n'
Hello
200

無事アップデートされ /hello へのGETが200を返すことが確認できました!

まとめのかわりに

以上、さらっと普通のScalaアプリケーションをebuildでdeployする方法を書いてみたのですが、これ、「よーし!当社もGentooにしたしちょっとebuild作成に挑戦するぞ!」っていう方にとっては暗黙知が多すぎて伝わらないですね。

自分でフラグ立ててしまったので回収しつつ、もう少し順を追って書いてみようと思います。

まずは自社サービスのebuild化とdeployについて会社のブログに書くところからかな...!

さくらのクラウドで普通のゲートウェイサーバーを構築する

会社では相変わらずさくらのクラウド上で色々やっていますが、以前のGentooの記事が好評だったので今回も同じくGentooでいこうと思います!

今回は図のような構成でごく普通のGatewayサーバーを構築し、矢印で示したサーバーがインターネットに出られるようにします。

f:id:mazgi:20150814211433p:plain

まずはカーネルのコンフィグレーションですが、CONFIG_IP_NF_TARGET_MASQUERADEを有効にしておきます。

[root@gateway-left] # uname -a
Linux gateway-left 4.0.5-gentoo #1 SMP Fri Aug 14 20:27:22 JST 2015 x86_64 Intel(R) Xeon(R) CPU E5-2640 0 @ 2.50GHz GenuineIntel GNU/Linux
[root@gateway-left] # zgrep CONFIG_IP_NF_TARGET_MASQUERADE /proc/config.gz
CONFIG_IP_NF_TARGET_MASQUERADE=m

またsysctlnet.ipv4.ip_forward1に設定します。

[root@gateway-left] # sysctl -p
net.ipv4.ip_forward = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.rp_filter = 1

iptablesはこんな感じにしてみます。
なお、eth0がWAN側インタフェース、eth1がLAN側インタフェースです。

[root@gateway-left] # iptables -L -v
Chain INPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
  671  100K ACCEPT     all  --  any    any     anywhere             anywhere             ctstate RELATED,ESTABLISHED
    0     0 ACCEPT     all  --  lo     any     anywhere             anywhere
    0     0 ACCEPT     icmp --  any    any     anywhere             anywhere
    1    60 ACCEPT     tcp  --  any    any     anywhere             anywhere             tcp dpt:22 ctstate NEW limit: up to 2/min burst 3 mode srcip-dstip
    0     0 DROP       tcp  --  any    any     anywhere             anywhere             multiport dports epmap,netbios-ssn,microsoft-ds
    0     0 DROP       udp  --  any    any     anywhere             anywhere             multiport dports epmap,netbios-ns,netbios-dgm,microsoft-ds
   15   764 LOG_AND_DROP  all  --  any    any     anywhere             anywhere

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
   36 12342 ACCEPT     all  --  eth1   any     anywhere             anywhere
   31 21996 ACCEPT     all  --  eth0   any     anywhere             172.x.0.0/16

Chain OUTPUT (policy ACCEPT 506 packets, 66758 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     all  --  any    lo      anywhere             anywhere
    0     0 LOG_AND_DROP  all  --  any    eth0    anywhere             255.255.255.255

Chain LOG_AND_DROP (2 references)
 pkts bytes target     prot opt in     out     source               destination
   15   764 LOG        all  --  any    any     anywhere             anywhere             limit: avg 1/sec burst 5 LOG level warning prefix "(IPTABLES_DROPPED)"
   15   764 DROP       all  --  any    any     anywhere             anywhere

natテーブルはこんな感じで。

[root@gateway-left] # iptables -L -v -t nat
Chain PREROUTING (policy ACCEPT 2155 packets, 139K bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain INPUT (policy ACCEPT 1 packets, 60 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 30 packets, 1931 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain POSTROUTING (policy ACCEPT 30 packets, 1931 bytes)
 pkts bytes target     prot opt in     out     source               destination
   11 10788 MASQUERADE  all  --  any    eth0    anywhere             anywhere

Gateway経由でインターネットにでる各サーバーの設定はこんな感じです。
172.x.y.zがGatewayのIPアドレスです。

$ cat /etc/conf.d/net.eth1
config_eth1="172.x.a.b/16"
routes_eth1="default via 172.x.y.z"
dns_servers_eth1="172.x.v.1 172.x.v.2"
dns_domain_eth1="example.com"

以上、お手軽ですね。

ところでさくらのクラウドにはVPCルーターというアプライアンスが用意されており、これを使うともっとお手軽にネットワークを構築することができます。

VPCルータ | さくらのクラウドニュース

RedmineのユーザーページにGitHubへのリンクを表示する

会社では開発がほぼGitHub.com+Slackで完結するようにしていて、これはなかなかうまくいっています(と思っています)。 ただ、ハードウェア障害の対応等GitHubに載せにくいタスクもあり、そのようなタスクの管理にはさくらのクラウド上にRedmineを構築して使っています。

このように「GitHubメイン、ときどきRedmine」という状況で、Redmine上に「このRedmineユーザーはこのGitHubユーザーです」って表示できないかなと思ったらカスタムフィールドを使ってあっさりできたのでメモしておきます。

表示としてはこのような感じになります。

f:id:mazgi:20150813165522p:plain

手順

カスタムフィールドの作成

なにはともあれカスタムフィールドを作ります。

f:id:mazgi:20150813165541p:plain

typeは Users にします。

f:id:mazgi:20150813165412p:plain

Name は"GitHub Account"にしました。
Link values to URL がキモでAdministrator Guideによると https://github.com/%value% のように %value% でカスタムフィールドの値を参照できるようです。

f:id:mazgi:20150813165358p:plain

保存するとカスタムフィールドが作成されます。

f:id:mazgi:20150813165556p:plain

Redmineユーザーの編集

つぎにRedmineの各ユーザーにGitHubアカウントを入力していきます。
ユーザー編集ページで先ほど作った"GitHub Account"が入力できるようになっていますね。

f:id:mazgi:20150813165430p:plain

保存するとこのようにGitHubアカウント名がリンクとして表示されます。

f:id:mazgi:20150813165522p:plain

クリックするとちゃんとGitHubのユーザーページに飛びます。

f:id:mazgi:20150813165337p:plain

めでたしめでたし。
これ、個人ページのURLにアカウント名が含まれるあらゆるサービスに使えますね。
せっかくなのでTwitterとかFacebookとか作ってみようと思います。

参考にさせていただいたページ

さくらのクラウドで普通のLDAP認証ができるサーバーを量産する

会社でSSHの公開鍵やSUDOの権限をLDAPで一元管理していっているのですが、忘れないうちにLDAPクライアント側の構築方法を書いてみます。
なお、サーバーはさくらのクラウド上で構築し、LDAPサーバーはldap1.example.comというFQDNでアクセスできるものとします。

手順

OSとパッケージ

クラウドなので基本となるインスタンスを1台構築し複製することにします。
複製したインスタンスは普通のサーバーとして使う想定ですのでディストリビューションにはGentoo Linuxを使用します。
最近構築したのでカーネルバージョンは4.0.5と新しめです。

インスタンスの複製はロードバランサとサーバクローンで簡単スケールアウトというTIPSにスクリーンショット付きで解説されています。

# uname -a
Linux base 4.0.5-gentoo #1 SMP Wed Jul 1 02:23:16 JST 2015 x86_64 Intel(R) Xeon(R) CPU E5-2640 0 @ 2.50GHz GenuineIntel GNU/Linux

SSSD経由でLDAP認証を行うために必要なパッケージをインストールします。 USEフラグ設定のポイントは以下のとおりです。

  • OpenLDAPはクライアントのみでよいためminimalを指定
  • SSH公開鍵は後述するsss_ssh_authorizedkeysで取得するためOpenSSHにはldap指定不要
  • SSSDにはsshsudoを指定
  • sudoにはldapを指定
    (これは今回SUDOの設定をSSSD経由ではなくLDAPから直接取得したためです)
# emerge -pvq openldap openssh sssd sudo
[ebuild   R   ] net-nds/openldap-2.4.38-r2  USE="berkdb crypt gnutls ipv6 minimal sasl ssl syslog tcpd -cxx -debug -experimental -icu -iodbc -kerberos -odbc -overlays -perl -samba (-selinux) -slp -smbkrb5passwd" ABI_X86="(64) -32 (-x32)" 
[ebuild   R   ] net-misc/openssh-6.9_p1-r2  USE="hpn pam pie ssl -X -X509 -bindist -debug -kerberos -ldap -ldns -libedit -sctp (-selinux) -skey -ssh1 -static" 
[ebuild   R   ] sys-auth/sssd-1.12.4  USE="manpages nls ssh sudo -acl -augeas -autofs -locator -netlink -nfsv4 -python -samba (-selinux) {-test}" ABI_X86="(64) -32 (-x32)" PYTHON_SINGLE_TARGET="python2_7 -python3_3 -python3_4" PYTHON_TARGETS="python2_7 python3_3 -python3_4" 
[ebuild   R   ] app-admin/sudo-1.8.12  USE="ldap nls pam sendmail -offensive (-selinux) -skey" 

時代はflaggieなのでflaggieでUSEフラグを設定するといいと思います。

LDAPクライアントの設定

パッケージをインストールしたらLDAPクライアントとして仕立てていきます。

LDAPクライアントとしての基本的な設定を/etc/openldap/ldap.confに書きます。

# grep -vE '^\s*($|#)' /etc/openldap/ldap.conf
BASE dc=example,dc=co,dc=jp
URI ldap://ldap1.example.co.jp ldap://ldap2.example.co.jp
tls_reqcert naver
sudoers_base ou=SUDOers,dc=example,dc=co,dc=jp
nss_initgroups backlink
binddn cn=Authenticator,dc=example,dc=co,dc=jp
bindpw P@ssw0rd!

sudoコマンドが読む/etc/ldap.conf.sudoファイルはldap.confへのsymlinkにしています。 なお、sudoがどのldap.confを読んでいるかはリンク先の方法で調べることができます。

sudoがどのldap.confを読んでいるか確認する - Qiita

# ls -l /etc/openldap/ldap.conf /etc/ldap.conf.sudo
lrwxrwxrwx 1 root root  18 Jul 19 16:35 /etc/ldap.conf.sudo -> openldap/ldap.conf
-rw-r--r-- 1 root root 250 Jul 19 16:36 /etc/openldap/ldap.conf

SSSDの設定

続いてSSSDの設定を行います。 ドメインはexampleとしています。

# grep -vE '^\s*($|#)' /etc/sssd/sssd.conf
[sssd]
config_file_version = 2
services = nss,pam,sudo,ssh
domains = example
debug_level = 1
[nss]
filter_users = root,ldap,named,avahi,haldaemon,dbus,radiusd,news,nscd
[pam]
[sudo]
subdomain_enumerate = true
debug_level = 9
[domain/example]
id_provider = ldap
auth_provider = ldap
sudo_provider = ldap
ldap_search_base = dc=example,dc=co,dc=jp
ldap_sudo_search_base = ou=SUDOers,dc=example,dc=co,dc=jp
ldap_tls_reqcert = never
ldap_uri = ldap://ldap1.example.co.jp
ldap_schema = rfc2307
debug_level = 1
enumerate = true
ldap_default_bind_dn = cn=Authenticator,dc=example,dc=co,dc=jp
ldap_default_authtok = P@ssw0rd!
ldap_group_object_class = posixGroup
ldap_group_search_base = ou=Group,dc=example,dc=co,dc=jp
ldap_group_name = cn
ldap_group_member = memberUid
ldap_id_use_start_tls = false
chpass_provider = ldap
cache_credentials = true

Name Service Switchの設定

passwd,shadow,groupsssを参照するようnsswitch.confを設定します。
sudoersldapsss両方を参照するよう設定していますが、これは私がうまくSSSD経由でSUDOersを取得できなかったためこのようになっています。。

# grep -vE '^\s*($|#)' /etc/nsswitch.conf
passwd:      compat sss
shadow:      compat sss
group:       compat sss
hosts:       files dns
networks:    files dns
services:    db files
protocols:   db files
rpc:         db files
ethers:      db files
netmasks:    files
netgroup:    files
bootparams:  files
automount:   files
aliases:     files
sudoers:     files ldap sss

PAMの設定

ディストリビューションによってデフォルトの設定がやや異なりますが、今回はこのように設定しました。
おおむねpam_sss.soを使用している行が追加した行です。合わせてpam_unix.soを使用している行をrequiredからsufficientに変えています。
またログイン時にホームディレクトリが作成されるようにpam_mkhomedir.soを使用しています。なお、/homeはNFSで共有されておりどのサーバーに入っても同じホームディレクトリが見えるようにしています。

# grep -vE '^\s*($|#)' /etc/pam.d/system-auth
auth            required        pam_env.so 
auth            sufficient      pam_unix.so try_first_pass likeauth nullok 
auth            sufficient      pam_sss.so use_first_pass
auth            optional        pam_permit.so
account required        pam_unix.so 
account [default=bad success=ok user_unknown=ignore]            pam_sss.so
account optional        pam_permit.so
password        required        pam_cracklib.so difok=2 minlen=8 dcredit=2 ocredit=2 retry=3 
password        sufficient      pam_unix.so try_first_pass use_authtok nullok sha512 shadow 
password        sufficient      pam_sss.so use_authtok
password        optional        pam_permit.so
session         required        pam_limits.so 
session         required        pam_env.so 
session         required        pam_unix.so 
session         optional        pam_mkhomedir.so skel=/etc/skel/ umask=0077
session         optional        pam_sss.so
session         optional        pam_permit.so

OpenSSHの設定

OpenSSH 6.2からAuthorizedKeysCommandという項目名で公開鍵を取得する外部プログラムを呼び出せるようになっています。
この設定とSSSDが提供するsss_ssh_authorizedkeysコマンドによってLPKパッチを当てなくてもLDAPからSSSDを経由して公開鍵を取得できるようになります。
余談ですがLDAPサーバー側はLPKスキーマが欲しいのでOpenSSHのUSEフラグにldapを指定してインストールしています。

# grep -vE '^\s*($|#)' /etc/ssh/sshd_config
PubkeyAuthentication yes
AuthorizedKeysCommand /usr/bin/sss_ssh_authorizedkeys
AuthorizedKeysCommandUser nobody
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM yes
PrintMotd no
PrintLastLog no
UsePrivilegeSeparation sandbox          # Default for new installations.
Subsystem       sftp    /usr/lib64/misc/sftp-server
AcceptEnv LANG LC_*

このようにsss_ssh_authorizedkeysコマンドの引数にユーザー名を渡すと公開鍵が取得できることを確認できます。

[mazgi@base] $ sss_ssh_authorizedkeys mazgi
ssh-rsa AAAA********Hs2V mazgi@BRUICHLADDICH.local
ssh-rsa AAAA********61rn mazgi@Ardbeg.local

デーモンの起動

ここまで設定できたらsshdsssdを起動します。
この例ではホームディレクトリをマウントするためにnfsclientも起動しています。

# rc-status
Runlevel: default
 netmount                                                          [  started  ]
 local                                                             [  started  ]
Dynamic Runlevel: hotplugged
Dynamic Runlevel: needed
 rpcbind                                                           [  started  ]
 rpc.pipefs                                                        [  started  ]
 rpc.idmapd                                                        [  started  ]
 rpc.statd                                                         [  started  ]
 nfsclient                                                         [  started  ]
Dynamic Runlevel: manual
 net.eth0                                                          [  started  ]
 sshd                                                              [  started  ]
 sssd                                                              [  started  ]
 net.eth1                                                          [  started  ]

ここまでの手順でLDAPに登録されている公開鍵でSSHログインしてsudoできるようになります。

[mazgi@localhost] $ id
uid=10001(mazgi) gid=10000(example) groups=10000(example),11001(level1),11002(level2),11003(level3),11004(level4),11005(level5)
[mazgi@localhost] $ sudo -ll
Matching Defaults entries for mazgi on localhost:
    ignore_local_sudoers, insults, !authenticate, !env_reset

User mazgi may run the following commands on localhost:

LDAP Role: level1
    RunAsUsers: root
    Commands:
    /bin/false

LDAP Role: level2
    RunAsUsers: root
    Commands:
    /usr/bin/tail
    /usr/bin/tailf
    /usr/bin/less
    /bin/ls
    /usr/bin/sha1sum
    /usr/bin/sha224sum
    /usr/bin/sha256sum
(snip)

ちゃんとログインできてUIDとグループとSUDO情報が取得できていますね!

おわりに

会社ではこのインスタンスを複製して本番環境や社内サービスに使っています。
クラウドなので複製後は以下の3ステップでサーバーが使い始められます。楽チンですね!

  • IPアドレスの設定
  • ホスト名の設定
  • SSHホスト鍵の再生成

参考にさせていただいたページ

flaggieをはじめ数々のGentoo TIPSについてはEmacs ひきこもり生活を参考にさせていただいています。

SSSDの設定についてはsssd.conf ファイルの設定をはじめとしたRed Hat社が公開してくださっているRHELのドキュメントが大変参考になります。

さくらのクラウドでサーバーを複製する方法はさくらのクラウドニュースで紹介されているロードバランサとサーバクローンで簡単スケールアウトというTIPSが参考になります。