モヒカンメモ

髪色が定期的に変わることに定評のある(比較的)若者Webエンジニアの備忘録

ウェブセキュリティ実務知識試験 (徳丸実務試験) に合格しました

Webセキュリティ界隈で有名な徳丸さん監修の「ウェブセキュリティ実務知識試験 (通称: 徳丸実務試験)」に合格しました 🎉

f:id:pinkumohikan:20210610055423j:plain
徳丸実務試験

ウェブセキュリティ実務知識試験

ウェブセキュリティ実務知識試験 (通称: 徳丸実務試験) は一般社団法人BOSS-CON JAPAN PHP技術者認定機構が主催する、安全なWebアプリケーションを作っていく上で必要な知識を有していることの認定試験。Webセキュリティにおいて定番と言える「安全なWebアプリケーションの作り方」が指定教材となっており、かつその著者の徳丸さんが試験の監修をしているらしい。

www.phpexam.jp

今回自分が受験したのは2/7に開催された記念すべき1回目の試験。

tokumarukaiden.peatix.com

1回目ということもあって過去問とか先人の体験記は存在しないのでワクワクドキドキ。

受験の動機

自分はWebアプリケーションを開発・保守することでご飯を食べているのでWebセキュリティについても職責の範囲。受験勉強を通じてWebセキュリティについて改めて勉強したかった。

あとは合格すれば単純に能力の証明になって転職等の文脈で1mmぐらいは役立つのではという淡い期待、そして何より第一号合格者という響きがカッコいい。

この辺は過去に「ウェブセキュリティ基礎試験 (通称: 徳丸基礎試験)」を受験したときから変わっていない。

blog.pinkumohikan.com

試験対策

参考書は指定教材の徳丸本のほか、読書会をやったことがある徳丸赤本も再度読んだ。

f:id:pinkumohikan:20210610050028j:plain

勉強法はひらすら通読して「良く分からなかったところ」「学びがあったところ」に付箋を貼り、一通り読み終わったら付箋の有るところを重点的に再度読み直す、というもの。良く分からないトピックは個別にググったり、それによる被害事例を調べたりもした。

今回の受験に当たって費やした勉強時間はだいたい2 - 30時間ぐらい。徳丸本を2週くらい + 付箋つけたところをさらに2 - 3週ぐらい読んだ。

試験当日

試験開始の約2時間前に試験会場のコワーキングスペースへ到着。ショートタイムのドロップインで最後の試験対策をした。

f:id:pinkumohikan:20210610051436j:plain
CO-EDO

試験直後の手応えは4ヶ月前なので正直あまり覚えてなかったけど、Evernoteに日記が残っていた。

f:id:pinkumohikan:20210610051702p:plain
2021/02/07の日記

これは自分の経験則だけど、不安な問題は正答率50%、解けたと思う問題は正答率90%で数えると大体それっぽい正答数が出る。

試験結果

合格です、やったー🎉

ただ正答率は86%というなんとも微妙な数字。悪くはないけどある程度間違えてますね、的な。ていうか、正答率85%を予想していたのでほぼドンピシャでワロタw

カテゴリごとの正答率が「受験レポート」で見えるので正答率が低かったところは別途復習をしておきたい。

f:id:pinkumohikan:20210610051234j:plain
受験レポート

文字コードの辺りは確かに苦手意識あるけどそれにしても正当率0%は笑うw(笑えない)

感想

とりあえず合格してよかった〜。 割としっかり試験対策はしていたし手応え的にも合格はしてるだろうと思っていたけど、万が一ということもあり得るので結果が届くまでドキドキだった。

試験の難易度としては、前回受験した「ウェブセキュリティ基礎試験 (通称: 徳丸基礎試験)」よりは確かに難易度が上がっていそうに思った。 とは言え突飛な問題は出なかったのでしっかりと勉強していれば合格できそう。

余談

個人的には知識よりも技能を測る試験があると面白いなと思う。お題となるWebアプリケーションに潜む脆弱性を見つけ対策する、みたいな試験を是非企画して欲しいところ。「知っている」ことにももちろん価値はあるけど、「知っている」と「使える」には大きな隔たりがあると思うので。

たじーさんが紹介してたOFFENSIVE Security WEB-300とやらがそれっぽい?(立ちはだかる英語の壁)

DBでdateとdatetimeを扱うときのカラム名suffixの使い分け

結論

  • 扱うデータが日付 (date) なら、 registered_on のようにsuffixには on を使うべし
  • 扱うデータが日時 (datetime) なら、 registered_at のようにsuffixには at を使うべし

背景

これまでデータベースのカラム名を命名する際、日付 (date) でも日時 (datetime) でもsuffixには at を使っていた。 だが先日、英語的には日付と時間で明確に使い分けがあって日付の場合は at よりも on のほうが適切である、と教えてもらった。

english-club.jp

端的にまとめると、 at は点を示す前置詞なので時間を厳密に表す場合に適切、 on は曜日や日など(時間に比べて)幅のあるものを表す場合に適切、ということらしい。

コーディング規約的にはどうなのか

理屈としては理解できたが、これまで聞いたことがない使い分けだったため従うべきかどうかは迷った。そのため、先の使い分けを肯定しているコーディング規約等があればそうすべき根拠が増えて従いやすいので調べた。

軽く調べた限りでは本件について明確に定義しているルールはあまりなかったが、Thoughtbot社のRailsスタイルガイドには下記のような記述があった。

Name date columns with _on suffixes.
Name datetime columns with _at suffixes.

github.com

今後

自分としては使い分けの理屈には異論ないのでdateカラムならonを、datetimeカラムならatをsuffixとして使っていくことにする。

jqを使ってjsonの差分をスマートに確認する

jsonを比較する際にkeyとvalueの組が同じでもkeyの並びが微妙に違っていたりして余計な差分が出てキレそうなとき、jqを使ってkeyでソートしてからdiffを取ったりすると便利だよっていう小ネタを紹介する。

jq

jqはjsonをいい感じに整形したり、色付け表示したり、フィルタリングしたり、集計したりできる人気のCLIパッケージ。

stedolan.github.io

Web APIから返ってきたjsonを見やすく表示したり、特定keyのvalueが◯◯なエントリだけを抽出する、といった用途で自分は良く使っている。

minifyされたjson読みづらい問題

Web APIなどから返ってくるJSONはminifyされていることが多く、そのままでは読みづらいがjqに食わせることでいい感じに整形 & 色付け表示してくれる。

生json:

{"name": "pinkumohikan", "age": 99999999, "bio": "天才天才天才天才天才天才天才天才天才天才天才天才天才天才天才天才天才技術者", "location": "Japan", "hobby": ["AirsoftGun", "Programming", "EC", "Bowling", "Darts"]}

jqに食わせたもの:

f:id:pinkumohikan:20201231035231p:plain
jsonはとりあえずjqにぶち込めば読みやすくなる :100:

jsonのkeyの並びが地味に違っていてdiff取りづらい問題

2つのjsonが同一であるかを検証したいとき、愚直にdiffを取るとkeyの順序で悩まされることがある。

例:

$ cat a.json b.json
{
  "tako": "wasa",
  "banana": "dayo",
  "akkan": "be"
}
{
  "akkan": "be",
  "banana": "dayo",
  "tako": "wasa"
}

$ diff a.json b.json
2c2
<   "tako": "wasa",
---
>   "akkan": "be",
4c4
<   "akkan": "be"
---
>   "tako": "wasa"

これらはkeyとvalueの組み合わせで考えると同じなので差分として出ないようにしたい。

jsonのkeyでソートすれば差分を抑えられる

jqにはkeyでソートしてくれる機能があるので、それを使ってkeyでソートしたあとdiffを取れば余計な差分を抑えることができる。

オプションは --sort-keys または -S

man:

       o   --sort-keys / -S:
           Output the fields of each object with the keys in sorted order.

例:

$ jq --sort-keys . a.json b.json
{
  "akkan": "be",
  "banana": "dayo",
  "tako": "wasa"
}
{
  "akkan": "be",
  "banana": "dayo",
  "tako": "wasa"
}

これらをdiffに食わせれば...

$ diff <(jq --sort-keys . a.json) <(jq --sort-keys . b.json)

余計なdiffを抑えられる。

php-fpmはリクエストが中断されても処理中のプログラムを中断しない

nginxでリクエストを受けてphp-fpmにpassするというPHPアプリケーションではスタンダードな構成において、リクエストが中断されたときphp-fpmの処理って中断されるんだっけ?されないんだっけ?というのが気になったので調べた。

ざっくりまとめ

  • クライアントがリクエストを中断すると、WebサーバはFCGI_ABORT_REQUESTレコードを発出する
  • php-fpmではFCGI_ABORT_REQUESTレコードをサポートしていない
  • 先の理由のため、クライアントがリクエストを中断してもphp-fpmが処理中のプログラムは中断されない

f:id:pinkumohikan:20201119020348p:plain
PHP

FastCGIとphp-fpm

nginxはクライアントからリクエストを受け取ると待機しているphp-fpmプロセスへFastCGIという仕様に基づいて処理を依頼する。

ja.wikipedia.org

php-fpmはPHPのFastCGI実装で、nginxより依頼されたCGI処理を行って結果をnginxへ返す。

www.php.net

FCGI_ABORT_REQUESTレコード

クライアントからのリクエストが中断される (コネクションが切れる) と、nginxから FCGI_ABORT_REQUEST レコードが発出される。

fastcgi-archives.github.io

5.4 FCGI_ABORT_REQUEST

The Web server sends a FCGI_ABORT_REQUEST record to abort a request.

A Web server aborts a FastCGI request when an HTTP client closes its transport connection while the FastCGI request is running on behalf of that client.

php-fpmはFCGI_ABORT_REQUESTレコードをサポートしていない

少なくとも PHP 7.4.12 に付随するphp-fpmでは FCGI_ABORT_REQUEST レコードをサポートしていない。そのため、Webサーバ (nginx) がクライアントとのコネクション切断を検知するなどして FCGI_ABORT_REQUEST レコードを発出したとしても、php-fpmはそれを無視して処理を続行する。

github.com

FCGI_ABORT_REQUEST = 2, / [in] (not supported) /

かんたんなテストでもphp-fpmによる処理は中断されないことを確認した (10秒後にログを書き込みレスポンスを返すAPIを用意して、クライアントからリクエスト後、10秒経つ前にリクエストを中断してみた)。

まだ分かっていないこと、関連する疑問

  • apache モジュール版PHPで動かすと中断された気がするが、認識は合っているか
  • php-fpmでFCGI_ABORT_REQUESTをサポートしていない背景、サポートする予定はないのか
  • php-fpm以外のFastCGI実装はあるのか

知っている人がいれば是非教えて欲しい。

Special thanks

@Danack

stackoverflow.com

@yowatari

ISUCON10本戦へ出場して「またあいま賞」を受賞しました

10/3 (土) に開催されたパフォーマンスチューニングコンテスト「ISUCON10」のオンライン本戦にて、チーム「 牡蠣の鋭利な殻が指に突き刺さり利き手を負傷 」として33チーム中20位でフィニッシュし「またあいま賞」を頂きました 🎉

f:id:pinkumohikan:20201110235918j:plain
ISUCON10 FINALISTの証

ISUCONとは何なのか (再び)

Iikanjini Speed Up CONtest。お題となるWebアプリケーションをガツガツゴリゴリいじくり回して、超たくさんの人が同時に使っても死なないチョッパヤ仕様にするエクストリームイベント。

isucon.net

イカれたメンバーを紹介するぜ (再び)

平均年齢26歳の若手キャピキャピチームです!

cureseven

  • キャピキャピ隊長!
  • 湾曲したiPadがお気に入り!

twitter.com

shiningcureseven.hatenablog.com

nekodaisuki

  • もうそろそろ中年!
  • 壁のぼり過ぎて指紋が無いので悪い事し放題!!!!

twitter.com

sinnderu.hatenablog.com

pinkumohikan

  • TeamCapacityの設定を見落として、「TeamCapacityはコントローラビリティないよ」って言っちゃった人 💀

twitter.com

blog.pinkumohikan.com

チーム名の由来

今回、「牡蠣の鋭利な殻が指に突き刺さり利き手を負傷」という物騒なチーム名で出場しました。

命名としては、

  • Oystersという(比較的)若手エンジニアコミュニティのメンバーで構成されたチームなので「牡蠣」って入れたかった
  • ブランディングやカッコよさよりも奇をてらう方向へ全振りしたい

辺りを加味して、特に相談せず僕が勝手に決めました!!!!(どや!!!)

ちなみに指は負傷しておりません、心配して下さった方々ありがとうございました! でも牡蠣の殻はウイルスが残留している可能性があり危ないのでくれぐれもお気をつけ下さい。

やったこと

本戦前

9/12 (土) に予選通過が分かってから、4回ほどチームで時間を取って本戦対策をしました。時間換算すると合計で25時間ぐらいな? 競合するベテランチームに比べるとまだまだ経験も知識も負けているので、予選と同様に練習量でカバーする作戦です。

予選も100点の振る舞いは出来なかったので予選の振り返り (KPT) をやったり、過去の本戦問題の講評を読んで本戦の雰囲気や傾向を読み取ろうとしたり、過去の本戦問題を実際に解いてみたり。「予選は練習量にものを言わせて正面突破で通過出来たけど、本戦は必殺技を用意しておかないと太刀打ちできなさそうだよね」、みたいなことを考えてVarnishやらOpenRestyやらLua Scriptやらの予習もしました。

本戦中

(正直もう1ヶ月前のことなのであんまり覚えてないんですが) ビルドやらサービスの再起動やらログの退避やらの便利コマンドをまとめたMakefileに不備があってビルドしたバイナリが使われていなかったり (死)、いわゆる負荷レベルに相当する TeamCapacity という概念を見落とす (死) という極めて初歩的なミスのせいでコードに手を入れても全然スコアが変わらず、終始「アレー・・・?」って思いながら手を進めました。リソースには余裕があるはずなのにスコアが伸びないぞ・・・?的なやつ。極めてつらい。穴があったら入りたいし、無いなら掘りたい。それもシャベルとかじゃなくてユンボでガッツリ掘りたい。

isucon.net

ただ、スコアが全然伸びないながらも険悪なムードにならず、最後まで冗談を言い合ったり一緒になって調べたり出来たのはとても良かったと思います。競技である以上は順位も大事だけど、楽しければまあおっけー!

個人的な技術トピックとしては EnvoygRPC あたりがあり、これらはまだ全然触ったことがなかったのでその場で調べながら対応しました。普段使わない技術に遭遇すると上手く立ち回れなくてヒヤヒヤするけど、無理矢理にでも幅が広がるのでこういう機会はマジで尊いですね。これだからISUCONは辞められないぜ。

本戦後

完全にやっちまったなパーリナイ (つまるところの反省会) はもちろん、毎日就業後に参加出来る人で延長戦をするという負けん気を発揮しました。延長戦ではビルド周りの修正をしたり、TeamCapacityの辺りをイジイジしたらシュッと25,000点ぐらいまで上がり、これが本番中に出来てたらもっと楽しめただろうな〜って言い合いましたw

結果的に順位は振るわなかったものの、LINEさんから「またあいま賞」を頂きました 🎉

f:id:pinkumohikan:20201111000519j:plain
またあいま賞をゲット

ありがとうございます!

感想と来年への意気込み

ISUCON本戦には今回が初挑戦でしたが、見事に砕け散りました。プライドはスタボロ、強化ガラスが砕けたときぐらいに粉々! ナイス出題、 今回は 完全に負けました。ぴえん、ぱおん。

一緒にプレイしてくれたcureseven氏、nekodaisuki氏、あざました!

来年は今年よりも順位上げるぞ〜〜〜

P.S.

f:id:pinkumohikan:20201111114553p:plain
cureseven氏が来年に向けてアップを始めたようです

ストイック杉井〜〜

ISUCON10予選を何とか突破出来たンゴ〜〜〜

9/12 (土) に開催されたパフォーマンスチューニングコンテスト「ISUCON10」のオンライン予選にて、チーム「牡蠣の鋭利な殻が指に突き刺さり利き手を負傷」として予選18位で予選突破しました 🎉

f:id:pinkumohikan:20201002200217j:plain
ISUCON10 FINALIST認定証

isucon.net

ISUCONとは何なのか

Iikanjini Speed Up CONtest。お題となるWebアプリケーションをガツガツゴリゴリいじくり回して、超たくさんの人が同時に使っても死なないチョッパヤ仕様にするエクストリームイベント。

isucon.net

今年で10回目となるISUCON10には490チーム、1,209人が参加したらしい。

俺とISUCON

俺とヤツとの出会いは、そう… (割愛)

イカれたメンバーを紹介するぜ

平均年齢26歳の若手キャピキャピチームです!

cureseven

  • 歴史や思いが溢れてしまっているクエリをいい感じにしたりアプリをいじくり回す担当
  • あと何か盛り上げたりとか
  •  Go言語歴は3ヶ月ぐらい
  • リアルでは半年以上会ってなかったけど先週会った
  • 最近転職したらしい

twitter.com

shiningcureseven.hatenablog.com

nekodaisuki

  • 担当: インフラをバンバンしばき回す担当...なはずだったけど最終的にコードを書くことになりがち担当
  • pinkumohikanと白熱バトルをしてcuresevenを引かせること多数
  • インフラ歴は4ヶ月ぐらい
  • リアルではもう半年以上会ってない
  • 予選における本チームのMVP。例のなぞって検索を論文読んでチューニングしたすごいやつ
  • 最近転職したらしい

twitter.com

sinnderu.hatenablog.com

pinkumohikan

  • どこをいい感じにするのが良さそうか調べたり考えたり祈ったりする担当
  • ISUCON歴は多分チーム内で一番長いので敬って欲しい
  • 最近転職していない

twitter.com

やっていきのスタンスとか

もう講評も出ているのでどこを直したかとかはあんまり書いてもしょうがないので施策についての紹介は割愛するんですが、基本戦略としてはパフォーマンスチューニングの原則に従っていろいろ「計測」して、「遅いところを改修」して、「早くなったか確認」、をガンガン回していく感じで臨みました。

講評で紹介されていたDBサーバを増やす、nazotteをいい感じにする、indexいい感じにする、あたりは概ね出来ていたかと思います。nazotteをいい感じにする辺りはnekodaisuki氏が論文を読んでアプリケーション側で解決するようなコードに書き直していて草でした。Generated columnとか空間indexは知らなかったので純粋に学びが有った。

isucon.net

これは秘密なんですが、限られた時間でいい感じにしていくにはN+1や露骨なロックみたいな "いかにも" な点を見つけても そこがその時点でのボトルネックとなっていなければスルー するのが大事です。

0点のまま突き進んだ3時間

実は、ベンチマーカーの不具合により弊チームは最後の3時間ぐらいはずっとスコア0点の状態で競技を続けて、最終スコアも0点だったんですよねw

大きめな施策の準備が終わってベンチ回したところ、特にエラーは出ていないもののベンチがfailするようになりました。何も情報が出てなくて謎なので運営に問い合わせると詳細なログを出してくれたんですが、ログにはsearch系endpointのタイムアウトしか出ておらず。当日マニュアルの スコア計算 ルールによればこの場合はfailとはならないはずなので、その旨を運営に連絡して競技を続けました。

ISUCON10 予選マニュアル · GitHub

また、一定時間内にレスポンスが返却されない場合はリクエストが中断され、最後に (タイムアウトしました) の付いたメッセージが表示されます。 これによるイス・物件の CSV 入稿以外の API での失格・減点はありません。

その後「状況を確認して対応を検討する」旨の返答がありました。「ルール的にはfailでないが、競技開始後なので公平性のためベンチマーカーは改修しない」とされる可能性はあったものの、15時ぐらいにベンチマーカーが一度改修がされていた実績があるので一度あることは二度あるやろ!と思って競技を続けました。結果、そうなったのでよかったーーー。

isucon.net

予選レギュレーション上は、"競技時間内の最後に記録されたスコア" (最終スコア) を本選出場チームの選出に利用する、と定めています。しかし、本不具合を鑑み、最終スコアが 0 点であったが、再起動を伴う追試にて予選最終結果 25 位のスコアを上回ったチームについて、最終スコアが本不具合によるものではないかを確認しました。

その結果、以下のチームについて、本不具合がなければ最終スコアが 0 点となっておらず、本来であれば本選出場チームに含まれていたと考えられるため、運営チームで協議の結果、別途本選出場チームとして選出することにいたしました。

博打といえば博打なんですが、failしない状態のまま終えてもスコア的に予選通過出来る見込みが無かったのでダメ元で賭けてみた感じです。

…7割ぐらいはダメだろうなって思ってたので、下記のようなtweetもしていますw

やる気アゲアゲマックスだった二人に感謝

弊チームはチーム結成から予選当日までの約3ヶ月間で、合計9回の練習をしました。

f:id:pinkumohikan:20201002200833j:plain
GitHub Repositories

正直僕はここまで練習頑張るモチベーションは無かったんですが (爆弾発言)、cureseven氏とnekodaisuki氏が「やるぞ!!!!」「うおおおおおおおお!100万円!!!」みたいなテンションだったのでそれに引っ張られる形で毎週末練習をしていたら徐々にみんなの改修力がいい感じにレベルアップしていき、いい感じの成果を出せるようになっていました。

地道な練習が功を成していて、いい話だなあ。

おじさん ベテランチームには負けないぞ〜〜〜

本戦への意気込み

僕は「行けるところまで行こう!」って感じなんですが、cureseven氏とnekodaisuki氏の二人は燃えています。

また引っ張ってもらいます。

f:id:pinkumohikan:20201002202738p:plain
おまけ

なんかおこられたw

CentOS8へremiリポジトリを使ってPHP7.4をインストールする

デフォルトリポジトリを使ってPHPをインストールするとCentOS 7系では5.4が、CentOS8系ではPHP 7.2が入る。それよりも新しめなバージョンのPHPを使いたいときの王道的な方法として、remiリポジトリを使う方法を紹介する。

f:id:pinkumohikan:20200920002804p:plain
PHP 7.4

前提

  • 2020/09/20 (日) 時点の情報
# cat /etc/redhat-release
CentOS Linux release 8.2.2004 (Core)

本記事ではCentOS 8を前提に書いているが、CentOS 7 / Amazon Linux 2でも大体同じような手順でインストールできる。CentOS 7で行う場合は dnfyum と読み替えればOK。

ざっくり手順

  1. remiリポジトリを使えるようにする
  2. remiリポジトリを使って、PHP 7.4をインストールする
  3. "php" で呼べるようにする

コマンドまとめ

sudo dnf install https://rpms.remirepo.net/enterprise/remi-release-8.rpm

sudo dnf install php74

sudo alternatives --install /usr/bin/php php /usr/bin/php74 1

一つづつ解説していく。

解説

1. remiリポジトリを使えるようにする

rpms.remirepo.net

remiはイカしたサードパーティ製ライブラリを提供するrpmリポジトリ。ガンガン行こうぜ系OSのFedoraで使われているような新しいバージョンのソフトウェアをCentOSとかでも使えるようにしてくれている。

$ sudo dnf install https://rpms.remirepo.net/enterprise/remi-release-8.rpm
...
インストール済み:
  remi-release-8.1-2.el8.remi.noarch

完了しました!

URLでお察しの通りCentOSのメジャーバージョンごとにRPMファイルが違うので、CentOS 7とかの場合は remi-release-7.rpm とする。詳しくは下記を参照。

English : Repository Configuration - Remi's RPM repository - Blog

2. PHP 7.4を入れる

あとはお目当てのものをインストールしていくだけ。remiリポジトリでインストール可能なパッケージのいくつかはデフォルトリポジトリとコンフリクトしうるので無効化されていて、以前はPHP 7.4も --enablerepo=remi のように明示的に有効化する必要があった。今は remi-safe にカテゴライズされたことによって、特にオプションなしでインストールできる。

$ sudo dnf install php74
...

インストール済み:
  environment-modules-4.1.4-4.el8.x86_64                      php74-1.0-3.el8.remi.x86_64
  php74-php-cli-7.4.10-1.el8.remi.x86_64                      php74-php-common-7.4.10-1.el8.remi.x86_64
  php74-php-json-7.4.10-1.el8.remi.x86_64                     php74-runtime-1.0-3.el8.remi.x86_64
  policycoreutils-python-utils-2.9-9.el8.noarch               scl-utils-1:2.0.2-12.el8.x86_64

完了しました!

php74 というコマンド名でインストールされていることが確認できる。

$ php -v
-bash: php: コマンドが見つかりません

$ php74 -v
PHP 7.4.10 (cli) (built: Sep  1 2020 13:58:08) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies

php-mbstring などのPHP拡張を入れたいときは php74- というprefixをつける。例えば php-mbstring の場合は php74-php-mbstring といった具合。

$ dnf install php74-php-mbstring
...

インストール済み:
  oniguruma5php-6.9.5+rev1-2.el8.remi.x86_64                php74-php-mbstring-7.4.10-1.el8.remi.x86_64

完了しました!

3. "php" で呼べるようにする

PHPを使いたいときに php74 って読み替えるのは面倒なので php で呼べようにしたい。alternativesでエイリアスを設定しておくのがオススメ。

www.redhat.com

syntaxは

alternatives --install <リンク> <名前> <パス> <優先度>

なので、こんな感じにすればOK。

$ which php74
/usr/bin/php74

$ sudo alternatives --install /usr/bin/php php /usr/bin/php74 1

$ php --version
PHP 7.4.10 (cli) (built: Sep  1 2020 13:58:08) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies

Redash SaaSからRDSにアクセスするために調べたこと、考えたことまとめ

背景

RDB等にあるデータストアへクエリを投げてデータをチラ見したり、取ってきたデータをいい感じにグラフとかで可視化したり出来るRedashという便利ツールがある。ベース部分はOSSで、self hostingすることもできるし有償でSaaSとして使うこともできる

redash.io

とあるAWS RDS上のデータをパパっと可視化したくなったので、Redash SaaSからRDSへつなげるように出来るんだっけ、とか、どんなリスクがあるんだっけ、みたいなことを調べたのでまとめておく

f:id:pinkumohikan:20200823183745p:plain
redash

ざっくり要点

  • RDSのPublicly Accessibleという設定を有効にすれば、インターネット (VPC外) からRDSへアクセスできる
  • DBをinternet publicにすることで不正アクセスの危険は高まるが、既存の仕組みでリスクはある程度抑えられる

インターネット (VPC外) からRDSへアクセスすることはできる

インターネットからRDSへアクセスする場合、踏み台用のホストを用意してそのホスト経由 (SSHポートフォワーディング) でRDSへアクセスする方法が王道だが、Redash SaaSでは踏み台をサポートしてないのでこの方法は使えない

RDSには Publicly Accessible という設定があり、これを有効にするとVPC外からでもRDSへアクセスできるようになる

aws.amazon.com

dev.classmethod.jp

想定されるリスク

データベースをinternet publicにするリスク

インフラ設計においてデータベースはDMZとかprivate networkなどと呼ばれるような、インターネットから直接アクセス出来ない領域に置くのがベストプラクティスとされてきた。なので、セキュリティに関心のある開発者だと「DBをinternet publicにするのって危険じゃん」って思うと思う

不正アクセスによってDB上のデータが漏洩したり書き換えられたりするリスクが考えられるが、次のような対策を行うことでリスクはだいぶ減らせそう

  • 接続元IPアドレスによるフィルタリングを行う
  • 特に機微な情報は、暗号化した上でDBに乗せる
  • Redash等readのみしかしないDBクライアントには、権限を絞ったreadonlyなDBユーザを用意する

SaaS固有のリスク

SaaSからinternet経由でDBへアクセスする場合、次のようなリスクが考えられる

  1. SaaSそのものが攻撃を受ける可能性
    • SaaSに登録した認証情報を使い、SaaSのIPからDBアクセスされうる
  2. SaaSを踏み台として使われる可能性
    • 攻撃者がSaaSを正規に契約することで、SaaSのIPからDBアクセスされうる (IPアドレスベースのフィルタリングを回避される)

SaaS事業者もそのような攻撃を許せば面目丸つぶれなので何らかの対策を講じていると思うがリスクはゼロではない。「こういうリスクが想定されるけど、対策してる?」とか聞いて、対策が甘いなって感じたらSaaSを使わないことを検討したい

もっと対策するなら

分析専用のDBを用意する

アプリケーション用のDBとは別に分析専用のDBを用意し、想定している分析に必要なデータのみをmigrationする仕組みを作り、Redash SaaSからはそれを使うようにする。そうすれば、仮に不正アクセスされても被害範囲を限定できる

Redash SaaSを使わず、Redashを自前運用する

VPC内に自前のRedashを立ててしまえばDBをinternet publicにする必要がなくRedashを使うことが出来る

redash.io

実際、身近なWeb系企業ではこの方法を取っているところも多い。難点としてはRedashは割とカジュアルにハングするので定期的な復旧作業が生じるのと、バージョンアップに追従する更新w運用コストがちょっと掛かること

その他、細かい話

Publicly Accessibleって後から変更できる?ダウンタイムは?

2020年8月現在、AWS RDS for Aurora (MySQL互換) にて検証した限りでは あとから変更可能 で、変更によるダウンタイムは なし だった

2015年4月時点ではインスタンス作成時のみ設定可能だった模様

http://dev.sukimash.com/aws/rds-publicly-accessible-setting-change/

早速 Publicly Accessible の設定をON にすべく、いろいろと調べてみたところ、どうやらこの設定は後から変更することはできないようです。。。

従って、接続できるようにするには、RDS のスナップショットを取り、別のインスタンスを Publicly Accessible ON で起動し、そちらにつなぎ直す、という手順が必要なようだ、、、ちょっとめんどくさいですね。

mysqlコマンドの実行結果から枠線とカラム名を除いて表示する

mysqlコマンドの実行結果から枠線とカラム名を取り除いて表示する方法を調べたので備忘録がてらまとめておく

やりたいこと

ヘルスチェックや定点観測用の即席スクリプトを書くときなど、mysqlコマンドの実行結果をスリムに表示したいことがある

何もオプションを指定せずにmysqlコマンドでクエリを実行すると、下記のように枠線とカラム名がついてくる

$ mysql --host 127.0.0.1 -u root -e 'select "Hello, world" as "greeting"';
+--------------+
| greeting     |
+--------------+
| Hello, world |
+--------------+

ただデータを眺める分にはこれで良いが、別のプログラムに食わせたいときや値だけが欲しいときに枠線やカラム名が邪魔になる

なので、枠線やカラム名を取り除いて表示させたい

実行結果から枠線を消す方法

mysqlコマンドに --silent というオプションがあり、これを使うと枠線をommitして表示することができる

help:

$ mysql --help
...
  -s, --silent        Be more silent. Print results with a tab as separator,
                      each row on new line.
...

before

$ mysql --host 127.0.0.1 -u root -e 'select "Hello, world" as "greeting"';
+--------------+
| greeting     |
+--------------+
| Hello, world |
+--------------+

after

$ mysql --host 127.0.0.1 -u root --silent -e 'select "Hello, world" as "greeting"';
greeting
Hello, world

実行結果からカラム名を消す方法

mysqlコマンドに --skip-column-names というオプションがあり、これを使うとカラム名をommitして実行結果のみを表示することができる

help:

$ mysql --help
...
  -N, --skip-column-names
                      Don't write column names in results.
...

before

$ mysql --host 127.0.0.1 -u root -e 'select "Hello, world" as "greeting"';
+--------------+
| greeting     |
+--------------+
| Hello, world |
+--------------+

after

$ mysql --host 127.0.0.1 -u root --skip-column-names -e 'select "Hello, world" as "greeting"';
+--------------+
| Hello, world |
+--------------+

実行結果から枠線とカラム名を両方消す方法

単純に先の2つのオプションを同時に指定すれば良い

before

$ mysql --host 127.0.0.1 -u root -e 'select "Hello, world" as "greeting"';
+--------------+
| greeting     |
+--------------+
| Hello, world |
+--------------+

after

$ mysql --host 127.0.0.1 -u root --silent --skip-column-names -e 'select "Hello, world" as "greeting"';
Hello, world

余談

mysqlコマンドにパイプで続けてコマンドを書くと、実行結果から枠線は取り除いて渡してくれる

小さなプログラムを組み合わせて大きなプログラムを作るための工夫で、Linux哲学ってやつ

続くコマンドなし

$ mysql --host 127.0.0.1 -u root  -e 'select "Hello, world" as "greeting"'
+--------------+
| greeting     |
+--------------+
| Hello, world |
+--------------+

続くコマンドあり

$ mysql --host 127.0.0.1 -u root  -e 'select "Hello, world" as "greeting"' | cat
greeting
Hello, world

GitHub Activityをグラフで可視化してくれるGitHub Readme StatsでGitHub映えを狙う

こんにちは、可視化大好きお兄さんこと @pinkumohikan です(自称)。

Webエンジニア御用達のソースコード管理ツール "GitHub" でのアクティビティを可視化してくれる GitHub Readme Stats というおもしろツールが、結構映えるグラフを作ってくれていい感じだったのでご紹介します。

f:id:pinkumohikan:20200803022415p:plain

GitHub Readme Stats

github.com

基本的には

https://github-readme-stats.vercel.app/api?username=pinkumohikan

みたいなURLにアクセスすると動的にActivityを集計してグラフ表示してくれます。獲得したスター数や、当年のスター数、作ったPR数、作ったIssue数など。色々カスタマイズも出来るみたい。

自分は下記のようにオプションを設定しており、

https://github-readme-stats.vercel.app/api?username=pinkumohikan&count_private=true&show_icons=true&theme=radical

するとこんなふうなグラフがでます。

https://github-readme-stats.vercel.app/api?username=pinkumohikan&count_private=true&show_icons=true&theme=radical

Special Repositoryに置くのがオススメ

GitHubの自分のアカウント名と同じリポジトリを Special Repository と呼ぶらしいです。例えばアカウント名が pinkumohikan なら pinkumohikan というリポジトリがそれに当たります。

f:id:pinkumohikan:20200804111353p:plain
ひみつだよ!

github.com

そしてなにやら、Special RepositoryのREADMEに書いた文章はプロフィールページにもサマリー表示されるらしい。

github.com

こんな感じ: f:id:pinkumohikan:20200803022125p:plain

GitHub Readme StatsのURLをREADMEに貼っとけば GitHub映えしますね。僕のREADMEにはさっき紹介したGitHub Activityに加えて、良く使う言語のグラフも表示しています。

パパっと真似したいかたは

あんまりオプションとか関心なくてとりあえず真似してみたいかたは、僕のREADMEをコピペしてもらえればそれっぽいものがシュッと出来上がります。

Raw README.md: https://raw.githubusercontent.com/pinkumohikan/pinkumohikan/master/README.md

pinkumohikan のところを自分のGitHubアカウント名にreplace、自分のGitHubアカウント名でリポジトリを作り、そこにREADME.mdとして保存すればパパっと試せます。お試しあれ。