Jの衝動書き日記

さらりーまんSEの日記でございます。

2019年 東京(1)

2/9 前半戦(京都)

2月になった。これでまた競馬に参戦できる。予算に限りがあるので2月は東京へ遠征に行くことにした。

府中本町駅に着いてからちょっと寄り道して競馬場へと向かった。寄り道先は金比羅神社。競馬の前にはいつも競馬場近くの神社で神頼みをするのがマイルールなのだ。

大國魂神社をさしおいて金比羅神社にしたのは特に理由はない。ただ、おっこんなところにも金比羅山あるんだと思ってお参りしただけである。ひっそりとしていていい境内の神社だった。賽銭箱はないが賽銭が置いてあるので地元の人が定期的に来てはいるのだろう。

さて、お参りもしましたし勝負に行きますか! ……と意気込んでいたのだが入り口からそれはくじかれた。なんと今日は東京競馬は雪のため開催中止となっていたのである!!

雨の中でもやるのに雪で中止になるの? なんでも今日は早々と中止決定がされていたらしい。家出る前にチェックしておくんだった。

今日は小倉と京都では開催されている。月曜日に延期となったが月曜日は来れないしさてどうしよう。ちょっと迷ったがこのまま京都競馬に参戦することにした。

とはいえパドックはじっくり見れないし(見たところで当たるかどうかはまた別ではあるが)TV越しでしか見れないからちょっと微妙な気分にはなった。

というわけで本日のレーススタートである。

パドックはほとんど参考にならないためラジオ解説とオッズのみが頼りである。いつも通り一進一退といったところだろうか。ただ今日はパドックへ移動する必要がないためほとんど椅子に座りっぱなしなのが楽ではある。

もっともTV見ながら座れてかつ馬券購入機へ近いという場所は大体占拠されてしまっているので外に座っているわけだが。寒いがもともと寒さは覚悟していたしそのための格好をしているので問題はない。それになんとなく競馬に参加している気分になるし。

開催ことされてはいないが店はちゃんと空いているのでレースの合間に昼食を取った。

f:id:newWell:20190209114756j:plain

なないろの鶏丼

京都5R 単負け 複負け越し

単勝が出たのでうまそうだった白モツ煮と肉まんを追加。合わせて700万円だった。

……突っ込まないぞ。

f:id:newWell:20190209143450j:plain

白モツ煮と肉まん(外の臨時店)

 今回は事前のチェックがないためメインレース以外では三連複はやめておいた。TV越しの観戦なのでいまいちノリきれなかたがさて結果はどうだろう。

単勝:2勝10敗

複勝:7勝6敗

三連複:0勝1敗

残金:10000円

複勝こそ勝ち越したが単勝は紛れもない負けである。その割には残金が結構残ったがこれは1Rの複勝が大きい。1620円ついたのだ。あと三連複ニレース買ってないし(当たるとは思っていないのが虚しい)。

残念ながら今回も敗者めしである。

結果は残念ではあるのだがちょっと急ぎ足で店へと向かった。今日の店はやきとり山長に決めていた。競馬開催日はいつも混んでいると聞いていたが不幸中の幸いか今日は開催日ではなくなったので無事に入れた。

なぜにこの店かということこの店こそ敗者めしにふさわしい店だからである。この店は負け馬券を持っていくとビール半額かサワーが無料になるのだ(一杯のみ)。まさに敗者のための店。……なんか最初から負けること期待していたようでちょっと微妙だろうか。もっとも来店した日はサービス期間中で19時まではビール半額だったけど。

f:id:newWell:20190209164713j:plain
f:id:newWell:20190209165259j:plain
f:id:newWell:20190209164829j:plain
f:id:newWell:20190209171219j:plain
f:id:newWell:20190209171636j:plain
f:id:newWell:20190209171145j:plain
f:id:newWell:20190209165137j:plain
f:id:newWell:20190209174313j:plain
f:id:newWell:20190209164649j:plain
f:id:newWell:20190209171002j:plain

上から豚レバー、つくね、しそ巻き、トロたん、スタミナハラミ、シロ。

カキフライ、キムチ、ミニカレー。

石焼きモツ煮込みと手羽先唐揚げ。一番写真が大きいのがおすすめのもの。とはいえどれも美味しかった。ハズレはないと思う。あとは生ビールとサワーを二杯。
会計は3600円ちょっと。

なんて敗者に優しい店なのだ。今度はいや~今日はハズレ馬券がなくてね~なんて言いたい(単勝複勝同時に買っているので不可能ではない!)。

 

2/10 後半戦(東京)

さて昨日は雪だったが今日はどうだろうか。出発前にホームページをチェックすると中止にはなっていない。だが開催時間が一時間ほど遅れるようだ。……ならばもう一時間寝れたではないか。

出走レースの時間を見るとかなり間隔が短くなっている。昼食を取る暇がなさそうだ。一時間ほどこたつの中で時間を潰してから家を出た。昨日と同じように金比羅神社へお参りして(大國魂神社がイヤというわけではない忘れてただけだ)先に昼食を取った。

f:id:newWell:20190210103600j:plain

ドマーニの昔ながらのミートソース

パスタがラーメンのように茹でられているのを見るのはなんとなく微妙な気分になったがとても美味しかった。このミートソースのレトルト欲しい(でも高いとたぶん買わない)。

昼食を取っている間にパドック公開が始まったので慌てて向かった。そしてチェックしだしたのだがいつもよりもだいぶ早く騎乗号令が出た。え? 早くない? 戸惑っている間に馬は行ってしまった。そう、今日はこんな感じで矢継ぎ早にレースは行われるのである。

いやいやいや。これはひどい単勝がちっとも当たらない。複すらも駄目なときがある。レース間隔が短くてパドックで見極める時間が足りなすぎる。昨日よりもだいぶマシではあるけど。それにパドックを見たところで当たるかどうかは……。

ちなみに8Rは万馬券が出たレースで3連単なんて一千万馬券だったので外しても仕方がない。というか当てた人いるんだ……。

獲得金がやばい。これは去年の阪神競馬場の悪夢再来か。

メインレースでようやく単勝をゲット。よし。悪夢は避けられた。一番人気をあえて外して賭けた甲斐があった。三連複もゲット。……しかしもともとオッズが高くないためマイナスとなってしまった。これは悲しい。ちょっと買い方変えたほうがいいかもしれない。

さて結果である。

単勝:1勝12敗

複勝:4勝8敗(11Rのワイドが複勝代わり)

三連複:1勝2敗

残金:7500円

不甲斐ない結果だ。悔しいのは自分が好調だと判断したけど買わなかった奴が結構勝っていたことだ。オッズや解説で人気がないとそっちに判断が揺れてしまって結果として負けたわけである。もう少し自分の判断に賭けてもいいのかもしれない。

というわけで今回も敗者めしである。また山長のお世話になろうかと思ったが今日はたぶん混んでいるので他の店にした。

直会スタンド宮という立ち飲み屋にした。ここも人気店らしく入れるかなと不安だったが無事に入れた。立ち飲み屋らしく前払い式だがいちいちお金を渡すというのではなく自分の料金皿にお金を置いておくとそこから持っているという感じになっている。立ち飲み屋だが日本酒が豊富なのが嬉しい。

f:id:newWell:20190210170235j:plain
f:id:newWell:20190210171814j:plain
f:id:newWell:20190210172714j:plain
f:id:newWell:20190210173827j:plain
f:id:newWell:20190210171952j:plain
f:id:newWell:20190210171006j:plain

上から野沢菜わさび漬け、おでん、もつ煮(ハーフ)、あさりの天ぷら。

さわら西京焼き、カキのチーズトマト煮。

あと撮り忘れたけどカツオの酒盗。日本酒は滋賀県の波乃音。瓶ビール。
酒のつまみなので量こそ多くないがどれもとても美味い。とくにさわらの西京焼きが美味かった。ちょうどこれで売れきれだったから運がいい(でも運は競馬で使いたかった)。

会計は3000円ちょっと。ここも敗者に(財布にも)優しい店だった。

ただちょっと物足りないので府中本町駅近くにある青葉でラーメンを締めで食べた。

今度は勝利の美酒として高めの日本酒を飲みたいものだ。

 

買い方について

自分用のメモ。

  • 単勝オッズが1倍代のものは買わない。他馬にするか馬連にする。
  • 複勝オッズが1.1倍代のものは買わない。ワイドにする。
  • 三連複オッズが10倍を下回るときは頭数を減らすか除外する。

2019年 中山(1)

はじめに

2019年になった。去年は阪神競馬場万馬券と中山の有馬記念3連単といい感じで終われた。
今年の予算も無事ゲットできたのでいろいろ競馬場を巡っていきたい。目指すは全競馬場制覇(JRA)である。
その前にここで今一度競馬めしのルールを定めることにする。

  • 食事代は獲得金で賄う(昼食代はお情けで500円は確保)
  • 勝負に負け越し or 獲得金が当日掛け金を下回る場合は敗者めし
  • 敗者めしの予算は獲得金の半額(2000円以下の場合は1000円を上限)
  • 勝負に勝ち越し or 獲得金が当日掛け金を上回る場合は勝利めし
  • 勝利めしの予算は獲得金すべて(気にしないで食べよう)

また買い方は今年は以下のようにする。

  • 単勝複勝が基本で1Rあたり1000円
  • 複勝が1.1倍など低倍率時はワイドか馬連
  • 特別レースは3連複をボックス買いで1000円(※賭け金に余裕があれば単・複も)

特別レースに関しては事前チェックをするようになったのでこうなった。
当たればでかいがレース後半で賭け金に余裕がないと複勝も買えないのでかなりシビアになったとも言える。

とうわけで今年始めの競馬は中山から始める。
交通費がかからないからその分何回か行けるが予算が限られているので1月は二度だけ参戦する。
正月のおみくじの結果は半吉だったがさて少しは運気が上昇しているだろうか。

 

1/12 前半戦


馬券は基本的にパドックを見てから買うことにしている。調子が良さそうな馬や悪そうな馬をメモして買っている。だがなかなか当たらない。判断基準がその度にブレブレなため人気馬以外の調子がよさそうな馬を見逃したり段々何を書いているのかわからなくなったり。
その改善策として阪神競馬場ではラジオのパドック解説も参考にしだしたが情報が増えた分判断もより迷うようになってしまった。
メモを取るのにいいノートは無いものかといろいろ探したがない。ならば作るかとパドックメモ紙を作ってみた。これで少しはマシになればいいのだが。

今日は朝からとても寒い。空はどんよりと雲がかかり雨が降りそうな感じだ。勝負の行方までどんよりしないでほしい。

さてそれではスタートだ。

1Rは何かパラパラ当たるなと思っていたら小さな氷が降っていた。重ね着をしているので体は平気だが手が寒い。たまらずカイロを使い始めたがあんまり効果はなかった。安物はこれだから・・・。

さて勝負の方は最初は幸先がよいがその後はパッとしない。今回から特別レースは3連複勝負を基本とするのだがそれではやはり心もとないので通常の買い方もしたい。なので特別レース分の賭金もプールする必要がある。そのため昼食は控えめとしないといけない。

f:id:newWell:20190112114105j:plain

梅屋のもつ煮込みといなり

ようは特別レースのプール分以上稼げばいいのだ。そう意気込んで後半戦に向かう。

だが・・・。

単勝が全く勝てなくなってきた。5Rは雨が降ってきてレースも荒れ出したのだろうか。阪神競馬場の初日の悪夢が頭によぎるが大丈夫だ。まだ立て直せる!

・・・だが駄目だった(涙)。3連複はいずれも逃してしまった。いずれもあと一頭が足りない。12Rは3連複を買う予定はなかったが最後の勝負に賭けに出た。そして負けた。なんかこう最後の賭けみたいなものにはとことん弱い気がする。

ただ11Rは自分の本命だった三番人気の馬が来たからこれはこれで満足ではある。

さて、それでは結果。

単勝:4勝8負

複勝:4勝8負

3連複:4敗

残金:7200円

はい。負けである。

3連複買わなければ賭金的には負けにならなかったのではなかろうかと理性的な考えが頭によぎったが振り払った。

賭け事など理性的ではやってられないのだ。それに賭け事で一番大切なことは過去を振り返らないことだ。悔しく思うがネチネチと後悔はしない。

そんなわけで今年始めての勝負は敗者めしとなった。

 

今回の店は前回と同様にまるはにした。あの優しい出汁と店員さんの声にまた癒やされて明日の勝負に挑むのだ。

f:id:newWell:20190112182443j:plain
f:id:newWell:20190112185427j:plain
f:id:newWell:20190112182614j:plain

f:id:newWell:20190112190719j:plain

おでん盛り合わせ、長芋の磯辺焼き、サバの竜田揚げ、みそけんちんうどん。あとはビールとすだちサワー。

前回よりは残金が多かったのでその分多少は食べれた。3600円ぐらい。
 

1/13 後半戦

 今日はちょっと寝不足気味である。どこの部屋のものかわからないがエアコンの騒音が五月蝿くてなかなか寝れなかったのだ。もっともそれが気になるような時間帯にまで起きていたのがそもそもの原因ではあるのだが。ゲームはほどほどにしないといけない。

今日の天気はまた寒いが晴れている。勝負の行方も天気のように晴れていけばいいのだが。昨日よりはゆっくり準備していたのだがギリギリになってしまい競馬場に着いた頃には1Rのパドックが始まってしまった。勝負ごとは慌ててはいけない。

さて、それではレース開始だ。

なんだこれは。ひどすぎる。レースは別に荒れているというわけではないが二倍以下の人気馬が来なかった。そして一番人気が駄目ならば他の馬はどうだと賭けたらそれも駄目(そんなときに限って一番人気が来る)。

それに今回から導入した自作競馬ノートの効果がない。いろいろチェック項目を入れたがそれが良くなかった。判断材料が多すぎて一頭あたりの時間がかかりすぎてとても全馬など見れない。そして疲れる。今日は寝不足気味でもあるので4Rでけっこうヘトヘトになってしまった。

一息つこう。

f:id:newWell:20190113113709j:plain

やらぐぅの牛すじ丼

これもまた前回と一緒だがビールと串がないのが寂しい。前半戦はもうボロボロで頭も疲れていて投げやりな気分になってきた。

もういっそのことラジオのパドック解説だけでいいか。そんな気分で5Rに望んだのだが結果は単・複全滅。

甘くはない。それに何だか叱られたような気分にもなった。もともとパドックで馬を見たいと思って始めたのではないか。それがこの体たらくだ。しっかりしろ。

6Rからは開きなおりノートのチェックポイントは無視して今までの買い方(調子が良さげに見える馬を買う)に戻した。

これで勝ち続けたらドラマ的なのだがそんなに世の中は甘くない。でも明るい兆しは見えてきた。特別レース分のプール金も確保できている。勝負はこれからだ!

10Rでようやく三連複ゲット! ・・・残念ながら負けを取り戻すほどの金額はつかなかったが自分の予想が当たるのはやはり嬉しい。

さて、それでは結果だ。

単勝:3勝9敗

複勝:6勝6敗

三連複:1勝3敗

残金:9500円

複勝が惜しかったが単勝は紛れもない惨敗のため今回も残念ながら敗者めしである。今回は三連複買わないとこの金額にはならなかったので後悔はない。というか後悔はしない。

 

家に一度戻って時間を潰したあと店に向かった。今回の店はうなぎ前むらだ。敗者めしなのにうなぎ? と思ったが鰻重ではなくうな丼であれば敗者っぽいっという自分理論で納得しておいた。それに焼き物あるし。

f:id:newWell:20190113173045j:plain
f:id:newWell:20190113174448j:plain
f:id:newWell:20190113174849j:plain
f:id:newWell:20190113174854j:plain
f:id:newWell:20190113180927j:plain

f:id:newWell:20190113181754j:plain

お通し(かぶと串)、焼き鳥盛り合わせ、漬物盛り合わせ、キモ串、にんにくコロッケ、うな丼。

自分的にはにんにくコロッケがヒット。形から最初はにんにくがまるごと入っているのかと思ったがちゃんとコロッケだった。にんにくのよい香りが楽しめてうまい。

合わせて4620円。今度は値段を気にすることなく特鰻重とか食べたいものだ。

 

阪神編

もう今年も残すところ一週間とちょっと。一年が経つのはあっという間だ。来年はもうちょっと勝てるようになると嬉しい。

まあそれはさておき今年最後の競馬は阪神競馬場で迎えることにする。有馬記念があるので中山というのが普通かもしれない。まあ、競馬を始めたばかりだったので最後に阪神競馬場に行こうと決めたあとで有馬記念の日程を知ったのだ。どちらにしろ凄い混雑だろうから他の会場からの参加のほうがいいのかもしれない。

ところで最近競馬の買い方を少し覚えた。普段は単勝複勝ときどきワイドという感じだったがボックス買いなるものもやり始めた。試しに3連複を買うために5頭を選んでマークする。これだけでその5頭の3連複をすべてパターン買えるから楽だ。一つ一つ書くと10個書かねばならない(久しぶりに確率の順列と組み合わせを思い出した)。

前哨戦とばかりに先週中山で特別レースに賭けたところ見事的中。それなりに高配当だった。それに味をシメたというわけで特別レースはボックスで3連複を狙うという買い方に今後もしていくことにする。

12/22 土曜日 前半戦

新幹線は自由席で行くので早めに家をでなければならない。6:30には家を出た。まだあたりは薄暗い。それに寒い。寒い日は布団からパッと出れないことが悩みなのだが旅絡みだとちゃんと起きれる。普段もこうパッと起きれればいいのだけど。

 

阪神競馬場に着いた。入り口近くにすぐパドックがある。多くの人が見れるようにするためか周りが広い。コンサート会場のようにも見える。上に広がる屋根も競馬場という感じがしないオシャレなところだ。まあコンサート会場としては少々臭う会場かもしれないが。

競馬場を一通り見学したあとレース参加前の景気づけに昼食をとった。

f:id:newWell:20181222113031j:plain

ホルモン人の肉吸い

肉吸いご飯の方にすればよかったとちょっと後悔したが勝てたら追加で頼めばよいのだ。

さて、それではレース参加である。5Rからの参戦だ。

ここでようやく単勝を取れた。しかしあとの特別レースを考えると賭金をそれに向けて残さないといけない。ボックス買いのぶん普段よりも賭金がかかるのだ。

だが考えてみれば今日は午後からの参加なので賭金総額が少ない。あれ? ひょっとして夕食代がヤバイか? と不安が頭によぎったが勝てばいいのさと疑問を引っ込めた。

……はい。前振りですね。

ひどい。ひどすぎる。ボックス買いの3連複はすべて負けたのもひどいが通常の方もひどい。というのも今日はけっこうレースが荒れていて万馬券も出たりした。なので複すら全滅が多かった。

というわけで結果。

単勝:一勝七負

複勝:二勝六負

残金:1000円

競馬めし史上もっともひどい結果になってしまった。普段の買い方なら多少は手元に残るのでちびちびと負け飯をやるところなのだが特別レースの3連複で使う賭金が増えたため残らなかった。最後のレースは当初は3連複を買うつもりはなかったのだがひどい負けが続いていたので逆転を狙ったのだが見事惨敗。そしてこの残金の有様である。

宿泊地は神戸三宮にあるので電車でそこまで向かいなんとか残金で食べれるところを探した。

f:id:newWell:20181222175202j:plain

レッドロックのローストビーフ

というわけでレッドロックにした。一度は行きたい店だったし幸いにもそんなに混んではいなかったので入った。ただ標準では分量が足りない・・・。物足りさもあり帰りにコンビニでサワーを買ってからぶらぶらとその辺を散歩して侘しさをこらえた。・・・かえって増したかもしれないけど。 

12/23 日曜日 後半戦

 昨日は反省会をやるつもりだったがホテルにあったハンターハンターをまたもや読み込んでしまいそんなに時間は取れなかった。ただサウナですっきりしたためか疲れは残っていない。競馬は一日中立っていなければならないのでそれなりにハードなのだ。

生田神社で戦勝祈願をしたあとふたたび阪神競馬場へと向かった。今日は有馬記念があるからか観客が多い。離れた場所でさえこうだというのに中山競馬場はどれほど混むのだろう。

天気は晴れで予想していたよりも暖かい。ヒートテックとか中で着込んでいるが暑いぐらいだ。天気のように晴れやかな気分で今日は帰りたい。

さてそれではレーススタートだ。ちなみに今回からラジオを聞きながらパドックを見るようにしている。しているのだが自分の見立てと異なっていることが多くてなかなか難しい。見方についていろいろ学べるからいいのだけど。それに調子がいいとラジオが選んだものが当たるというわけでもない。

午前中はなかなか調子がよい。まあ波乱はないので人気馬を賭けていればそのままきているというわけでもあるけど。一番人気を選ばないのは勇気がいるがそれを当てるとかなり嬉しい。配当も高いし。

さてそれなりに勝てたので豪華な昼食といきたいところである。昨日が悲惨だったこともあるし。だが今日はホテルで腹いっぱい朝食を食べたのでそんなに腹は減っていない。後半戦のこともあるので抑えめにした。とはいえビールは飲もう。

f:id:newWell:20181223120245j:plain

南京町 藤の肉まんとチャーシュー

あ、角煮まんを食べるつもりだったのに普通の肉まん食べてた。まあこれはこれで旨かったから良しとしよう。

では後半戦。

あまりパッとはしない戦績だが昨日に比べるとだいぶマシだ。少なくとも残金1000円とはなるまい。とはいえなんとなく敗戦ムードを感じていた。だがしかし・・・?

なんと9Rは単勝万馬券をゲット!!(3連複は負け)単勝本命は外していたのだが抑えのほうがヒットした。これはもうお祝いしかない。

f:id:newWell:20181223145331j:plain

楓林の唐揚げ

この勢いで他のレースも! と行きたいところだがそんなに甘くはなかった。

うーむ。結局3連複はすべて外してしまった。中山で当てたから調子に乗っていたけどそんなに甘くはなかったか。

とはいえ、万馬券ゲットである。昨日の敗戦はこのためにあったのだ!!

さて結果である。

単勝:五勝七敗

複勝:六勝六敗

残金:22000円

全体で勝ち越しはならず。とはいえ戦果としては十分だろう。

 

・・・などとは実をいうとほとんど考えていなかった。とくに11R・12Rはちょっと気が抜けていたのだろう。

万馬券を当てたから? それはもちろんある。

だがもう一つ理由はあるのだ。それは・・・。

3連単当たったァァァ!!!!

正直レイデオロが勝利を逃したのは意外だったけどボックス買いしていた3連単が見事にヒットした。まあ、これはほとんど競馬新聞のおかげなのだけど。昨日阪神競馬場有馬記念の号外が出ていてそれに本命としている数が多かった馬を選んだだけなのだ。

なので自分で選んだ3連複の方は外している。

ある意味おまけでかったつもりの有馬記念だったがとんでもない土産を残していった。

というわけで今日は勝利めしである!!

f:id:newWell:20181223181401j:plain
f:id:newWell:20181223181903j:plain
f:id:newWell:20181223182453j:plain
f:id:newWell:20181223184348j:plain
f:id:newWell:20181223184943j:plain
f:id:newWell:20181223185033j:plain
f:id:newWell:20181223191212j:plain

梅田まで行きビルの地下にあるおでんばるで勝利を祝った。

京風おでんの大根・玉子・ごぼう天・牛すじ・ちくわ・枝豆天、あとは昆布チップに白いおでんのほうれん草とベーコン・きのこ、あとはシメの牛すじカレー。

昆布チップは少々時間がかかるが一番好みだった。パリパリ感がとてもいい。白いおでんはシチューという感じがするがおでんの出汁もあってなかなかうまい。カレーもおでんの出汁もあってまろやかで美味しかった。

もう一軒行くつもりだったのだが店があるはずの場所に店がなくて見つからず断念した。

何がともあれ勝利の美酒というのはやはりうまい。

それにしても前半がダメダメで後半巻き返すというのは福島と一緒だなぁ。


 

SpringBootでLDAP認証のおまけ- LDAP認証時の通信-

LDAP認証の検証時にパケットキャプチャしてみてどんなことが行われているか調べてたのでついでに載せておく。

 

LDAP認証時にはアプリケーションとLDAPサーバは以下のやり取りをおこなう。

  • ユーザの認証(ユーザ名+パスワード)
  • ユーザ情報の取得
  • 所有する権限の取得

 

具体的には以下のようなLDAPのやり取りが発生する。

ユーザの認証

  1. bindRequestをLDAPサーバへ送信する
    • name:認証対象のユーザDN(uid=xxx)
    • password:平文送信
  2. LDAPサーバからbindResponseが返る
    • 認証OK:success
    • 認証NG:invalidCredentials

 

ユーザ情報の取得

  1. serchRequestをLDAPサーバへ送信する
    • baseObject:ユーザDN(uid=xxx)
    • scope:baseObject
  2. LDAPサーバからserchResEntryが返る
    • ユーザDNが持つobjectClassと属性が返る
    • sn
    • cn
    • uid
    • userPassword: 登録時の値(SSHAで返る)
  3. LDAPサーバからserchResDoneが返る。
  4. unbindRequestをLDAPサーバへ送信して通信終了

 

所有する権限の取得

  1. bindRequestをLDAPサーバへ送信する
    • name:なし(Root)
    • password:なし
    • ※SpringSecurtyの設定で管理者DNとパスワードを設定していればそれで接続
  2. LDAPサーバからbindResponseが返る
  3. uniqueMemberが一致する情報を問い合わせるためserchRequestをLDAPサーバへ送信する
    • baseObject:権限情報の格納先DN(ou=role,dc=test,dc=example,jc=jp)
    • scope:singleLevel
    • filter:uniqueMember value:ユーザDN(uid=xxx)
  4. LDAPサーバからserchResEntryが返る
    • 問い合わせ結果が一致する個数分の応答結果が返る
    • uid=gokuuの場合はadminとuserの2件が返る
  5. LDAPサーバからserchResDoneが返る。
  6. 通信は終了せず接続を維持する
    • 他のユーザの所有する権限の取得はbindRequestを実行しない

 

 上記を図にすると以下のような流れになる。

f:id:newWell:20181221144719j:plain

 

 ユーザ認証とその後のユーザ情報の取得ではその都度コネクションを作成するが、権限情報の取得ではコネクションの作成自体は一度だけのようだ。
 LDAP自体は暗号化がないため認証時のパスワードは普通に平文で流れている。またパスワードも属性の一つなので応答結果としても返る。登録時は暗号化すべきだろう。

 

SpringBootでLDAP認証-LDAP認証をおこなうアプリケーションの作成-

SpringBootでLDAP認証は以下の構成となっている。

  1. LDAPサーバの構築
  2. 認証用情報の設定
  3. LDAP認証をおこなうアプリケーションの作成

 

LDAP認証をおこなうアプリケーションの作成

 その前に前提として。
 ここで使用するSpringBootのバージョンは1.5.12である。最新バージョンではないため多少手順が異なるかもしれない。
 また開発用ツールはSpringToolSuite(STS)を使っている。

 

1. SpringBootでWebアプリケーションを作成する

 LDAP認証機能の検証をおこなうため検証用のアプリケーションを作成する。作成するのはWebアプリケーションでアクセスしたら単にこんにちは!を出すだけのものである。
 面倒くさいので作成物に関する詳細は省くが以下のような手順で作成する。

  1. File>New>Spring Starter Project>Next:Name,Package,Groupなどは好きなように入力
  2. Web>Web, Template Engines>Thymeleafを選択してFinish
  3. Controllerを作成する
    package jp.example.test;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    
    @Controller
    public class HelloController {
    
        @GetMapping("/")
        public String showHello() {
           return "hello";
        }
    }
    
  4. Viewを作成する
    cat src/main/resources/templete/hello.html
    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml"
          xmlns:th="http://www.thymeleaf.org">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Hello</title>
    </head>
    <body>
    	<p>こんにちは!</p>
    </body>
    </html>
    

 

  (プロジェクト)>Run As>Spring Boot Appでアプリケーションを起動する。
 localhost:8080にアクセスしHello画面が表示されればOK。

 

2.アプリケーションにLDAP認証機能を付ける。

 ここではアクセスしたときにログイン画面を最初に表示し認証が成功したときのみ次へ進めるようにする。またHello画面では認証したユーザ名(sn)を表示するようにする。

 

 まずは必要なライブラリを追加する。pom.xmlのdependenciesに以下を追加する。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-ldap</artifactId>
</dependency>
<dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-springsecurity4</artifactId>
</dependency>

 

  次にLDAP認証のための設定をおこなう。設定のためのConfigクラスを作成する。
 ここでは認証機能の有効化、ログイン・ログアウト機能の有効化、LDAP認証の設定をおこなう。

package jp.example.test;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.ldap.userdetails.PersonContextMapper;


@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/**").authenticated() /* 全てのパスに対して「認証済み」を要求するアクセスポリシーを設定 */
                .and()
                .logout().permitAll()  /* ログアウト機能を有効化  + ログアウトのURL(/logout)は認証なしでアクセス可能 */
                .and()
                .formLogin().permitAll(); /* フォームログイン機能を有効化 * ログインのURL(/login)は認証なしでアクセス可能 */
    }
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        /* LDAP認証を有効化 */
        auth.ldapAuthentication()
                .userDnPatterns("uid={0},ou=people")  /* ユーザDNのパターンを指定  {0}にはログインフォームで入力したusernameが埋め込まれる*/
                .contextSource()
                    .url("ldap://192.168.1.10:389/dc=test,dc=example,dc=jp") /* LDAPサーバへの接続URL*/
                .and()
                .userDetailsContextMapper(new PersonContextMapper());  /* 取得したユーザ情報の設定方法を指定 */
    }
}

 LDAP認証のためには以下の情報が必要となる。

  • LDAPサーバへの接続URL(ldap://{IPアドレス}:{ポート}/{ベースDN}):ldap://192.168.1.10:389/dc=test,dc=example,dc=db
  • ユーザDNのパターン:uid={0},ou=people

 ユーザDNのパターンはユーザDNからベースDNを除いた形で指定する。また具体的なユーザ名に関しては自動生成されるログイン画面より渡されるためそれを{0}で記述する。このようにユーザDNはパターンで指定するためuid以外でユーザDNを定義しても問題はない。
 また、Hello画面でユーザ名(cn)を表示するための設定もおこなう。LDAP認証機能を有効にすると認証したユーザ情報はセッション上に保存される。その保存されるデータの形式を指定する必要がある。
 org.springframework.security.ldap.userdetails.Personを使うとユーザ名(cn)を取得できるためユーザ情報をPersonの形で保存するようにPersonContextMapperを指定する。

 

最後にHello画面を変更する。

diff hello.html.bk hello.html
3c3,4
<       xmlns:th="http://www.thymeleaf.org">
---
>       xmlns:th="http://www.thymeleaf.org"
>       xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
9c10,13
<       <p>こんにちは!</p>
---
>       <p>こんにちは!<span sec:authentication="principal.cn[0]">名無し</span> さん</p>
>       <form th:action="@{/logout}" method="post">
>               <button>ログアウト</button>
>       </form>

 thymeleaf-extras-springsecurity4を使用するとセッション上に保存されているユーザ情報を上記の形で取得できる。principalにはPersonが設定されている。
 ちなみにSpringSecurityでは様々な認証方法を提供しているためprincipalに格納されるオブジェクトはその認証方法によって異なる。
 このPersonをController等で取得したい場合は以下のように取得する。

Person person = (Person)SecurityContextHolder.getContext().getAuthentication().getPrincipal();

 これでlocalhost:8080にアクセスするとHello画面は表示されずログイン画面が表示されるはずだ。UserにユーザDNのうちのuidを入力しPasswordにそのユーザのパスワードを入力してloginを押すとHello画面が表示される。そのとき画面にはユーザ名(cn)が表示されているはずである。

 

3.ユーザ権限に基づいたアクセス制御をアプリケーションに提供する

 現在のアプリケーションは認証が通ったユーザはすべてのURLへアクセスできる(といっても機能があるのは/ぐらいだが)。
 ここでは特定の権限を持つユーザのみがアクセスできる設定をおこなう。具体的にはadmin権限を持つユーザのみが/adminへアクセスできるようにする。

 

 まずは/adminの機能を作成する。とはいってもこれは適当でいい。HelloControllerをコピーしてGetMappingの内容を/adminにする程度で構わない。面倒ならばなくてもいい(表示結果が404になるのでちょっと微妙だが)。


 次にアクセス設定をおこなう。
 作成済のConfigクラスにアクセスを制限するURLとそれを利用可能なユーザの権限名の指定、LDAPサーバからユーザが持つ権限を取得するための設定をおこなう。

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .antMatchers("/admin", "/admin.*", "/admin/**").hasRole("ADMIN") /*/admin配下にアクセスするためにはadmin権限が必要 */
            .antMatchers("/**").authenticated() 
            .and()
            .logout().permitAll() 
            .and()
            .formLogin().permitAll();
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.ldapAuthentication()
            .userDnPatterns("uid={0},ou=people")
            .groupSearchBase("ou=role")                            /* 権限の格納先を指定 */
            .contextSource()
                .url("ldap://192.168.1.10:389/dc=test,dc=example,dc=jp")
            .and() 
            .userDetailsContextMapper(new PersonContextMapper());
}

 

 先のLDAP認証の設定では認証のみをおこなっていたが権限に基づいたアクセス制限までをおこないたい場合は以下の設定が必要となる。

  • LDAPサーバへの接続URL(ldap://{IPアドレス}:{ポート}/{ベースDN}):ldap://192.168.1.10:389/dc=test,dc=example,dc=db
  • ユーザDNのパターン:uid={0},ou=people
  • 権限の検索先の指定:ou=role

 権限の格納先に関してはベースDNを除いた形で指定する。LDAPサーバの設定によっては管理者DNとそのパスワードの指定も必要かもしれない。その場合は上記の.urlの後に.managerDnと.managerPasswordで設定する。
 アクセス制限の設定は上記のとおり.antMatchersで指定する。hasRoleで権限名を指定する。LDAPサーバ上の設定ではadminと小文字だがSpringSecurityでは大文字となる。
 ちなみにユーザが持つ権限情報もセッション上に保存されている。格納先はユーザ情報と同様にPersonでgetAuthorities()でそれが取得できる。ここではROLE_ADMINのような形で値が取れるがPrefixに関してはカスタマイズ可能のようだ。

 これでlocalhost:8080/adminでアクセスするとuser:gokuuのときは正常に表示され(/admin未実装ならば404のエラー表示)、user:gohanの場合は403のエラーが表示されるようになる。
 ちなみにリソース類のアクセスについてはどうなのかというとデフォルトでは認証不要となっている。具体的には/js,/css,/imagesなどは認証不要となっている。

 

4. ログイン・ログアウト機能をカスタマイズする

 自動的に作成されるログイン・ログアウト機能だがカスタマイズも可能だ。ここでは概要のみの記述に留める。

  • ログイン機能
    • ログイン画面の表示
      • デフォルトは/login(GET)
    • ログイン成功時の遷移先URL
      • デフォルトではアクセス時のURL
      • 初期ログイン後に最初のページに遷移させたいときなどに使用
    • ログイン失敗時の遷移先URL
      • デフォルトは/login?error
    • ログイン成功後のハンドリング
      • ログイン成功後に実行したい処理があるときなど
      • 上記の遷移先URLが設定済の場合はそっちが優先される
      • 応答内容の作成、もしくはリダイレクト処理が必要
    • ログイン失敗後のハンドリング
      • 認証NGに出すエラー内容をカスタマイズしたいときなど
      • デフォルトではエラー発生時に例外はスローしない
      • エラー原因はAuthenticationExceptionで特定が可能
  • ログアウト機能
    • ログアウトの実行URL
      • デフォルトでは/logout(POST)
    • ログアウト成功時の遷移先URL
      • デフォルトは/login?logout
    • ログアウト実施時の挙動
      • セッション消去・Cookie削除など

 

参考

qiita.comここではDockerを使ってLDAPサーバを構築している。

ログインのカスタマイズ方法

ログアウトのカスタマイズ方法

SpringBootでLDAP認証-認証用情報の設定-

SpringBootでLDAP認証は以下の構成となっている。

  1. LDAPサーバの構築
  2. 認証用情報の設定
  3. LDAP認証をおこなうアプリケーションの作成

認証用情報の設定

1.ツールのインストール

 その前にツールのインストールをおこなう。phpldapadminだ。このツールはLDAPサーバの設定をブラウザで行うためののものである。登録した情報が階層構造で見れるので便利なのだ。登録した情報自体はコマンドでも確認できるが意図した構造になっているかを確認するには一目で理解できたほうが楽だ。もっともCUIだけでやるという漢のかたはスキップしてよい。

 手順は以下のとおりだ。

  1. レポジトリの追加:EPEL・Remi
  2. phpldapadminのインストール
  3. phpldapadminのログイン方法の変更(DNにする)
  4. phpldapadminへのアクセス権の変更

 

まずはレポジトリを追加する。

# EPELリポジトリ
# yum -y install epel-release

# Remiリポジトリ
# rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm

 

 つぎにphpldapadminをインストールする。phpldapadminの名前の通りphpで実装されているためphpも入れる。最初はRemi使わないでインストールしたが実行に必要なパッケージ(xml関連)が入らなかったりしたのでRemi使うのが無難。

# yum -y install --enablerepo=remi,remi-php70 phpldapadmin

phpのためツールの起動手順は特にない。httpdが起動していればよい。

 

 終わったらphpldapadminのログイン方法を変更する。
 デフォルトだとuidとなっている。これはLDAPサーバで管理する情報のうちuidを持つユーザでログインするということだ。
 今はそれがいない(前の手順で作成した管理者はcn=adminである)であるためDNを指定してログインできるようにする。

# diff /etc/phpldapadmin/config.php.bk /etc/phpldapadmin/config.php
397,398c397,398
< //$servers->setValue('login','attr','dn');
< $servers->setValue('login','attr','uid');
---
> $servers->setValue('login','attr','dn');
> //$servers->setValue('login','attr','uid');

 

 最後に phpldapadminへのアクセス権の変更をおこなう。

 デフォルトだとローカルアクセスしか許可していないためこれを変更する。ただ、今回は検証用なので厳密には設定せずそっくり開けてしまう(実際の環境では当然こんなことしない)。

# cat phpldapadmin.conf
#
#  Web-based tool for managing LDAP servers
#

Alias /phpldapadmin /usr/share/phpldapadmin/htdocs
Alias /ldapadmin /usr/share/phpldapadmin/htdocs

<directory usr="" share="" phpldapadmin="" htdocs="">
  <ifmodule mod_authz_core="" c="">
    # Apache 2.4
    Require local
    Require ip 192.168.1.1(※アクセスしてくるもの)
  </ifmodule>
  <ifmodule mod_authz_core="" c="">
    # Apache 2.2
    #Order Deny,Allow
    #Deny from all
    #Allow from 127.0.0.1
    #Allow from ::1a
    Order Allow,Deny
    Allow from all
  </ifmodule>


# 設定後httpdを再起動
# systemctl restart httpd

 ちなみに検証環境は自PCにvagrantVMを起動して作っている。最初は上記のアクセス先IPアドレスに自PCのIPアドレスを設定していたがForbiddenとなっていた。VMにアクセスするときは別に割り当てられたIF経由でアクセスするためIPアドレスが違うのを忘れていた。

 再起動後、http://{LDAPサーバ}/phpldapadmin/へアクセスし管理者DN(記事の例ではcn=admin,dc=test,dc=example,dc=jp)でログインする。画面にはdc=test,dc=example,dc=jpが木構造のrootとして表示されているはずだ。他には何も情報がないためdc=test,dc=example,dc=jpのみだが。

 

2.認証情報の設定

 LDAP認証をおこなうためには認証対象となるユーザ情報(アカウント名とパスワード)が必要となる。また特定の操作を特定のユーザのみに許可したい場合(認可という)は権限情報も必要となる。またそれらを登録するためにはそれらを格納するための基点情報も必要となる。
 手順としては次の通りだ。

  1. グループの作成
  2. ユーザ情報の登録
  3. 権限情報の追加と割当

 

 最初にグループの作成をおこなう。phpldapadminを導入したためコマンドでは設定せずphpldapadminのインポート機能を使っておこなう。

# ユーザ情報格納用
dn: ou=people,dc=test,dc=example,dc=jp
objectclass: organizationalUnit
ou: people

# 権限格納用
dn: ou=role,dc=test,dc=example,dc=jp
objectclass: organizationalUnit
ou: role

 organizationalUnitを作成したためou(組織名)を設定する。名前はpeople,roleとしたが名前は何でもよい。ユーザ情報や権限情報はこれらの下に設定することになる。

 各objectclassで必須となる属性や属性情報そのものを確認したい場合はphpldapadminの画面上のスキーマから確認できる。

 

 次にユーザ情報の登録をおこなう。ユーザ情報としては少なくともアカウント名とパスワードが必要なのでこれらを含むobjectclassで情報を登録する必要がある。

 本記事ではinetOrgPersonを使用する。uid:アカウント名,userpassword:パスワードの属性を持ち、他にsn(last family name),cn(common name)を必須属性とする(ちなみにuidは任意だったりする)。
 ただ、inetOrgPersonを使用するためにはスキーマのインポートが必要のため最初にこれをおこなう。この作業はコマンドで実行する。

# スキーマの追加
# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/cosine.ldif
# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/inetorgperson.ldif

# ユーザ情報の追加 ※2ユーザを追加(これはphpldapadminで実施)
dn: uid=gokuu,ou=people,dc=test,dc=example,dc=jp
objectclass: inetOrgPerson
sn: 悟空    ※日本語でもOK
cn: 孫 悟空 ※日本語でもOK
uid: gokuu
userpassword: {SSHA}9JYvrXQeS+idmmijQlu3bmYBYZ38eUib

dn: uid=gohan,ou=people,dc=test,dc=example,dc=jp
objectclass: inetOrgPerson
sn: 悟飯    
cn: 孫 悟飯 
uid: gohan
userpassword: {SSHA}vteURqgusPSHBdQAO8tGy46tkWfGu67L

 今回はDNをuidとしているがsnやcnを使っても問題はない。指定したobjectclassに存在する属性なのであれば使用できる(とは言えuidが一般的)。
 ここで登録したユーザアカウントでphpldapadminにログインすることも可能だ。ただし参照のみで情報の変更はできない。

 また、phpldapadminを使ってユーザ情報を追加する場合はuidは重複禁止となっている。通常は問題ないがもし支障がある場合(階層が別だがアカウントが同一であるときなど)は /etc/phpldapadmin/config.phpの以下の設定を変更すること。

$servers->setValue('unique','attrs',array('mail','uid','uidNumber')); #ここで指定した内容が重複禁止となる

 

 最後に権限情報の追加と権限割当をおこなう。権限情報の登録にはgroupOfUniqueNamesを使用する。ここで規定されるuniqueMember属性がLDAP認証で必要となるためだ。
 識別はcnでおこなう。このためcnが権限名となる。権限名には特に規定はない。

 権限割当はuniqueMemberにその権限を与えたいユーザのDNを指定することでおこなう。uniqueMemberにユーザのDNが無いということはそのユーザにはその権限がないと言うことを示す。

# admin権限の登録と割当
dn: cn=admin,ou=role,dc=test,dc=example,dc=jp
cn: admin
objectclass: groupOfUniqueNames
uniquemember: uid=gokuu,ou=people,dc=test,dc=example,dc=jp

# user権限の登録と割当
dn: cn=user,ou=role,dc=test,dc=example,dc=jp
cn: user
objectclass: groupOfUniqueNames
uniquemember: uid=gokuu,ou=people,dc=test,dc=example,dc=jp

# 権限を追加で割当(権限情報の作成後の新たにユーザを追加した場合など)
dn: cn=user,ou=role,dc=test,dc=example,dc=jp
changetype: modify
add: uniqueMember
uniqueMember: uid=gohan,ou=people,dc=test,dc=example,dc=jp

 ちなみに権限を追加で割当したい場合はGUI操作でもできる。

 dc=test,dc=example,dc=jp クリック → ou=roleクリック → cn=adminクリック → uniqueMemberの値追加

 GUI操作でおこなう場合登録済のユーザDNが表示されるためちょっとした変更の場合はこっちの方が簡単かもしれない。

参考

qiita.com※phpldapadminのインストール手順を参考

SpringBootでLDAP認証-LDAPサーバの構築編-

 暇なので仕事に一息ついたので斜め読みだったSpringBootのリファレンスを少しだけ真面目に読んでみた。そうしたらLDAP認証についての記述があった。ちょうど社内システムの認証方法について検討(わざわざ認証機能作りなくないとも言う)していたこともあり試してみた。

LDAP認証とは何か?

 その前に簡単に前提から。認証が必要なのは対象とするアプリケーションを許可した特定の人のみに利用させたいからだ。この特定の人を認証する方法として一般的にはユーザ名とパスワードによる認証方法が取られている。
 この認証を実現するためにはユーザ名とパスワードという認証用情報の管理が必要になる。ここで言う管理は情報の保持・登録・変更・削除のことだ。認証対象となるアプリケーションにはユーザ認証機能とユーザ情報管理機能が必要になる。
 だがこれらの機能をアプリケーション毎に用意するのは手間だしアプリケーション毎に認証情報を保持するとその管理も大変だ。
 そこで認証情報を別のアプリケーションで管理してその認証情報を元にアプリケーションの認証をおこなうことでユーザ情報管理機能の作成は不要となりアプリケーション毎に認証情報を保持する必要もなくなる。
 LDAP認証とはこの認証情報をLDAPサーバで管理しアプリケーションはその情報をLDAPサーバに問い合わせることでユーザ認証をおこなう認証方法のことだ。
 LDAP(Lightweight Directory Access Protocol)はユーザーやコンピュータの情報を集中管理するディレクトリサービスへのアクセス時に用いられるプロトコルである。ディレクトリサービスという名前の通り情報は階層構造で管理する。

LDAP認証実現の手順

LDAP認証をおこなうためにはざっくりの手順だが以下のような準備が必要になる。

  1. LDAPサーバの構築
  2. 認証用情報の設定
  3. LDAP認証をおこなうアプリケーションの作成

ちょっと長くなりそうなのでここではLDAPサーバの構築について示す。

LDAPサーバの構築

1. インストール

 yumopenldap,openldap-clients,openldap-serversをインストールする。

 起動・停止はsystemctrlでおこなう。

 その後firewall設定もおこないldapのポート(389)を開ける(検証用のためfirewallは無効化しているため作業はしていないが)。

# yum -y install openldap openldap-clients openldap-servers
# systemctl start sladp

 ……とすんなりいけばいいのだが自分の環境では上手く行かなかった。実行にやたら時間がかかった挙げ句エラーとなってしまう。

 エラーとなったURLに直接アクセスしてみたら見事に何もない。どうやらミラーサーバから消えているようだった。ミラーサーバには古いバージョンのものは残っていないらしい。

 ということでyumでアクセスするレポジトリを追加してそこから取得した。

# cat /etc/yum.repos.d/CentOS7.4-Vault.repo
[C7.4.1708-base]
name=CentOS-7.4.1708 - Base
baseurl=http://vault.centos.org/7.4.1708/os/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
enabled=1

[C7.4.1708-updates]
name=CentOS-7.4.1708 - Updates
baseurl=http://vault.centos.org/7.4.1708/updates/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
enabled=1

[C7.4.1708-extras]
name=CentOS-7.4.1708 - Extras
baseurl=http://vault.centos.org/7.4.1708/extras/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
enabled=1

[C7.4.1708-centosplus]
name=CentOS-7.4.1708 - CentOSPlus
baseurl=http://vault.centos.org/7.4.1708/centosplus/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
enabled=1

[C7.4.1708-fasttrack]
name=CentOS-7.4.1708 - CentOSPlus
baseurl=http://vault.centos.org/7.4.1708/fasttrack/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
enabled=1

# yum -y --disablerepo=* --enablerepo=C7.4.1708-* install openldap openldap-clients openldap-servers
 
2. 管理情報の設定

 LDAPサーバを立ち上げたら初期セットアップをおこなう。LDAPサーバの設定は設定用のファイルを作成しそれをコマンドで読み込むという形を取る。

 初期セットアップはLDAPサーバの管理者パスワード変更・管理者情報の登録・ベースDN情報の登録をおこなう。

 

まずはLDAPサーバの管理者パスワードを設定する。

# cat rootPW.ldif(※ファイル名は何でもいい)
dn: olcDatabase={0}config,cn=config                # dn:識別名
changetype: modify                                 # changetype:操作(add,modif,delete)
add: olcRootPW                                     # add:対象の属性名 変更時はreplace:olcRootPW
olcRootPW: {SSHA}o2Ro2qTviCe5j/DN0Tpu8wFnwDZ6EUbh  # 対象の属性名: 属性値

# ldapadd -Y EXTERNAL -H ldapi:// -f rootPW.ldif

 LDAPの操作は上記のようなファイルの形式でおこなう。識別名で指定する対象に対して指定した操作を指定した属性に対しておこなう。LDAPでは管理している情報すべてに識別名を持っておりその情報にはそれぞれ属性値を持つ。

 olcDatabase={0}config,cn=configがLDAPサーバの管理者パスワードを保持する場所でありolcRootPWがそのパスワード値である。

 パスワードはソルト付きSHA(SSHA)で生成している。ソルト付きだと同一のパスワードでも生成するSHA値は毎回異なる。ちなみに上記のパスワードはhogeだが下記のようにパスワードを生成しても結果が異なるだろう。

# slappasswd -s hoge

 

次に管理者情報の登録をおこなう。便宜上以下のように定義する。

  • ベースDN:dc=test,dc=example,dc=jp
  • 管理者DN:cn=admin,dc=test,dc=example,dc=jp
  • 管理者パスワード:{SSHA}o2Ro2qTviCe5j/DN0Tpu8wFnwDZ6EUbh ※hoge

 DN(Distinguished Name)は識別名のことでベースDNとはLDAPサーバに管理させたい情報の先頭識別名のことである。LDAPサーバに管理させる情報はすべてベースDN配下に存在することになる。ディレクトリ構造でいえばrootのことである。

 DNはドメイン名みたいなもので後ろに行くほど広域を示す。上記で言うとtest<example<jp。一般的にはベースDNは上記のように複数名をとるらしい(dc=jpのみがベースDNというのは稀)。ベースDNはdc(domain component)で定義する。

 管理者DNはベースDN配下の情報を操作するための管理者を示す識別名のことである。ベースDNも管理者DNも初期設定されているためそれを利用環境に応じて変更する必要がある。一つのベースDNに対する管理者DNは一つのみである。

 管理者パスワードはベースDN管理者(管理者DNで表す)のものである。ここでいう管理者パスワードとは先に設定したLDAPサーバの管理者のものではない。LDAPサーバ自体の管理者とベースDN配下の情報管理者が同一であるならば同値でも問題はない(通常はこうだろう)。

 ベースDNや管理者DNを決定したら管理者情報の登録をおこなう。具体的には管理者DNに対するアクセス権の追加、ベースDNの切替、管理者アカウントのDN変更、管理者パスワードの追加をおこなう。

#cat modifyBase.ldif
# 管理者DNのアクセス権を追加
dn: olcDatabase={1}monitor,cn=config
changetype: modify
replace: olcAccess
olcAccess: {0}to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" read by dn.base="cn=admin,dc=test,dc=example,dc=jp" read by * none

# ベースDNを置き換える
dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=test,dc=example,dc=jp

# 管理者アカウントのDN変更
dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcRootDN
olcRootDN: cn=admin,dc=test,dc=example,dc=jp

# 管理者パスワードを追加
dn: olcDatabase={2}hdb,cn=config
changetype: modify
add: olcRootPW
olcRootPW: {SSHA}o2Ro2qTviCe5j/DN0Tpu8wFnwDZ6EUbh

# ldapmodify -x -D cn=config -w hoge(※LDAP管理者のパスワード) -f modifyBase.ldif

 olcDatabase={1}monitor,cn=configに対して属性olcAccessの変更でアクセス権の追加をおこなう。アクセス権はto アクセス先 by 対象 アクセス権の形を取る。dn.baseに管理者DNを指定する。gidNumber=0...はrootユーザのこと。デフォルトではLDAPサーバのrootユーザのみにアクセス権がある。
 olcDatabase={2}hdb,cn=configに対して、属性olcSuffixの変更でベースDNの置き換えを、属性olcRootDNの変更で管理者アカウントのDN変更を、olcRootPWの追加で管理者パスワードの追加をおこなう。

 

最後にベースDN情報の登録をおこなう。この情報登録を行うことでLDAPによる情報管理が可能となる。

# cat baseDN.ldif
dn: dc=test,dc=example,dc=jp
objectClass: dcObject
objectClass: organization
dc: test                      # dnの先頭のものを指定
o: Testman Env.               # 組織名(日本語も可)

#  ldapadd -x -D cn=admin,dc=test,dc=example,dc=jp(※管理者DNを指定) -w hoge(※管理者のパスワード) -f baseDN.ldif

 情報の登録はobjectClassを指定して格納する情報を定め、objectClass毎に要求している属性をそれぞれ追加するという形をとる。

 このobjectClassはスキーマで定義されている。/etc/openldap/schemaが格納場所。MUSTが必須属性でMAYが任意の属性となる。また属性自体もそれぞれ定義されている。

 例えば上記で使用したdcObjectとorganizationは以下のような定義になっている。

olcAttributeTypes: ( 0.9.2342.19200300.100.1.25
  NAME ( 'dc' 'domainComponent' )
  DESC 'RFC1274/2247: domain component'
  EQUALITY caseIgnoreIA5Match
  SUBSTR caseIgnoreIA5SubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )

olcObjectClasses: ( 1.3.6.1.4.1.1466.344 NAME 'dcObject'
  DESC 'RFC2247: domain component object'
  SUP top AUXILIARY MUST dc )

olcAttributeTypes: ( 2.5.4.10 NAME ( 'o' 'organizationName' )
  DESC 'RFC2256: organization this object belongs to'
  SUP name )

olcObjectClasses: ( 2.5.6.4 NAME 'organization'
  DESC 'RFC2256: an organization'
  SUP top STRUCTURAL
  MUST o
  MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $
  x121Address $ registeredAddress $ destinationIndicator $
  preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
  telephoneNumber $ internationaliSDNNumber $
  facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode $
  postalAddress $ physicalDeliveryOfficeName $ st $ l $ description ) )

まあ、organizationではoが必須なんだなぐらいがわかれば問題ない。

 

参考

 ※ここではlinuxのアカウント管理でLDAPを使用しているが本記事ではそこまでは行っていない