task4233のめも

書きたいことをつらつらと

VOYAGE GROUPのTreasureに参加して圧倒的成長をしてきた

はじめに

こんにちは。task4233です。

8/9(月)〜8/27(金)の3週間、株式会社VOYAGE GROUP(以下VGと略します)のTreasureに参加してきました。

このエントリでは、前半に行われた講義の概要と後半のチーム開発についてサックリ書きます。
最後にも書きますが、Treasureは他のインターンシップでは得られない経験が多く、本当に素晴らしいインターンシップでした!

もくじ

Treasureとは

Treasureとは、VGのエンジニア向け3週間インターンシップのプログラムです。
今年度は、前半に現場のエンジニアから講義を受け、後半にチーム開発を行いました。

このインターンシップのコンセプトは、「学生のスキル成長」です。
そのため、インターン開始前から人事や講師、サポーター陣からサポートを受けることができました。
また、インターン中も1on1が実施されるなど、非常に手厚いサポートがありました。

詳しくは下記の記事をご覧ください。

focus.voyagegroup.com

このように、「学生のスキル成長」がコンセプトであるインターンシップがTreasureです。

5つの講義

この章では、それぞれの講義の概要と感じたことをそれぞれ書きます。

2021年度のTreasureでは5つの講義が実施されました。
その講義は、バックエンド講義、フロントエンド講義、インフラ講義、DB講義、アイデア講義の5つでした。

バックエンド講義では、peiさんによるGoのハンズオンが実施されました。
個人的には、Goの書き方よりもAPI設計の心得が学びになりました。

また、peiさんからは、昼休みの雑談でデータモデリングに関する話が聞けたのがとても良かったです。
ビジネスのデータの扱い方とデータ解析者のデータの扱い方が異なるという話からディメンション・モデリングの素養まで教えていただき、知見しかなかったです。ありがとうございました。

フロントエンド講義では、ちゅうこさんによるTypeScript+Reactのハンズオンが実施されました。
私はTreasureに参加するまでPureJSとVue.jsを少し書いた程度のひよっこだったので、バックエンド講義よりも学びが多かったです。
特に、バックエンドの都合をフロントエンドのロジックに紛れさせないために、境界面できっちりエラーハンドリングをする話が一番の学びでした。

インフラ講義では、SyotaさんTonoさんによる、AWS CodePipelineを用いたCI/CDの構築のハンズオンが実施されました。
私は普段GCPをよく使うので、GCPの各サービスにAWSのどのサービスが該当するのかを使いながら学ぶことができました。

DB講義では、t_wadaさんによる、データモデリングの概観説明とハンズオンが実施されました。
この講義では、2021年におけるRDBMSの位置付けに関する話が前半にあり、この内容が元々なかった視点だったので、特に学びになりました。

イデア講義では、きっしーさんとガイアさんによる、価値あるプロダクト(MVP)の見つけ方の説明とグループワークが実施されました。
この講義では、UNS(User/Needs/Solution)に分けて段階的にアイデアを考える手法をグループワークを通して体験することができました。

実際に、ここで出たアイデアが後半のチーム開発で開発されたので、良い議論ができたと思っています。

以上の5つの講義は、その全てにハンズオンが取り入れられており、手を動かしながら学べたのが実に良かったです。

実は、この講義内容や数はVGのクルー同士で議論して毎年改変が加えられるそうです。力の入れ方が凄いですね。

チーム開発

この章では、チーム開発の概要と感じたことを書きます。

チーム開発は、アイデア選定含め、後半の約1週間で行われました。
この開発期間では時間外開発(18時半以降の開発)が禁止されていたため、開発できる期間が限られていました。
そのため、各チームはアイデアの核になる要素を思索し、それを満たす最小構成の実装を行う必要があり、技術力以外のスキルが研鑽された1週間でした。

私達のチーム「ホリネズミ」は、最初の3日をUNS固め、1日を環境整備、最後の3日を開発に使いました。
前半UNS固めの段階で1度UserとNeedsを定義したにも関わらず、チームメンバ間で認識の齟齬があったために、その定義を放棄して1から考え直すこともありました。

正直、認識の違いはスルーすることも出来たはずですが、チームメンバがお互いに意見をぶつけ合うことでより良いアイデアを発想できたと思っています。
この絞り出されたアイデアを実現するためのコアな機能のみを実装することで、1週間という短い期間ながらも最後まで全力で走り続けた結果、なんとか動くものが開発できたのは良かったです。

この特徴的なエピソードとして、Socket.IOを用いたリアルタイムチャットの実装が時間的に間に合わなそうだということが最終日に分かったため、REST APIの実装に差し替えてポーリングする方針に変えたというエピソードがあります。最終的に動かないゴミになることはなかったので、このインターンシップにおいては良い選択だったと思っています。

そして、結果的に「ホリネズミ」はグランプリを受賞できなかったものの、CI/CD賞をいただくことができました。
賞の発表を聞いた時は、全力を出し切った後だったのでぼんやりしていて、あまりリアクションが取れなかったのをよく覚えています。

とはいえ、時間外の開発を許してくれればもう少し開発できたので残念という気持ちもあります。
しかし、後述するAjitingでチーム開発のことを忘れて技術トークをできたので、悪い面ばかりではなかったと思っています。

Ajitingでのお話

VGでは、業務時間後に有志が集まる習慣があります。これは参加自由でインターン中は毎日開かれていました。
Ajitingは好きなことを話す場なので、ISUCONのチーム練習を配信したり、競プロの問題を画面共有して解いたりする人もいました。
中には、原神や筋トレ、ボルダリングを布教する人もいました。面白い人がたくさんいるなと強く思いました。

Ajitingで深夜にJavaScriptの謎挙動でワイワイするTreasure生の図
Ajitingにて深夜にJavaScriptの謎挙動で遊ぶTreasure生の図

コロナ禍で人と定期的に話す機会が減っていた私にとって本当に楽しい時間でしたし、毎日別の話題で学びがあるのはとても刺激的でした。

おわりに

ここまでで、Treasureの講義の概要とチーム開発、Ajitingについて書きました。

全体としての感想は、一言で言うと「本当に楽しかった」です。夏に圧倒的成長をしたいという全ての学生にオススメしたいインターンシップでした。

技術的な学びは言わずもがな、議論を進めるときの効率的な進め方やアイデアの発想方法、開発するときのコミュニケーションの取り方を体系的に学べたのが本当に大きな収穫でした。
その点で、当初の目的であった「スキル成長」は満たせていましたし、Ajitingとチーム開発によって横の繋がりができたので本当に有意義な時間になりました。

また、VGという会社が*1どういう会社なのかを知ることができたのも良かったです。
クルーの全員が考えて行動し、言われた仕事をやるだけ人間が1人もいないと感じられるほど、面白い方々ばかりでした。

最後になりますが、チームホリネズミのメンバー、Treasureに関わってくださったVGの皆さん、そして私と関わってくださった皆さん、本当にありがとうございました!

*1:今はCARTA HOLDINGSですが

アカツキの夏インターンシップで生まれた2つの成果とそこから得られた知見

はじめに

こんにちは。task4233です。

7/19~8/6 の3週間、株式会社アカツキの基盤開発等を行っているATLASチームにて、インターンシップに参加させていただきました。

aktsk.jp

そこで、私は下記の2つの成果を生むことが出来ました。

  1. APIの設計と実装
  2. パフォーマンスの検証と改善

この記事では、関わったサービスの紹介をした上で、私が取り組んだ内容とそこから得た知見を紹介し、最後にインターンシップ全体を通して良かったと感じたことを書きます。

もくじ

ゲーム内通貨管理サービス

このサービスの構成は下記の通りでした。

本体のゲーム内通貨管理サーバはGoで実装されており、本番環境ではApp Engine上で稼働しています。このサーバが各ゲームサーバに対してAPIを提供することで、ゲーム内通貨の管理をゲーム内通貨管理サーバに集約することが可能です。更に、管理されているゲーム内通貨はFlaskで実装された管理画面からも操作することも可能です。この操作権限を管理するために、権限を3段階に分けてAPI KEYとして利用者に提供しています。

また、ゲーム内通貨管理サーバは、権限を管理するための鍵を保持するSecret Manager、データを管理するDatastore、データ解析用のBigQueryを利用しています。

1.APIの設計と実装

まず、私はSecret Managerで管理している鍵のキーローテーション用APIの設計と実装に取り組みました。

キーローテーションとは、新たなバージョンの鍵を発行して古い鍵を失効させる仕組みです。これにより、セキュリティ強化が見込めます。

キーローテーションは手動で行うことも可能です。しかし、ゲームサーバが利用中の鍵を、誤って失効させるようなヒューマンエラーを防止するため、このAPIを設計および実装することになりました。

このAPIの設計と実装は、

  1. Swaggerの定義を書く
  2. 各エンドポイントの仕様について議論する
  3. 実装する
  4. レビューを通して実装を修正する

という順序で進め、設計と実装はサクッと終わりました。

サクッと実装できたのは、既存の実装が層ごとに責務が分割されていたためだと考えています。

既存の実装はコントローラ層、インフラ層、ドメイン層に分けられており、コントローラ層は受け取ったリクエストのハンドリング、ドメイン層はロジック、インフラ層では永続化と再構成といった責務の分割が為されていました。そのため、私は既存のコードを参考にしつつ、ロジックのユニットテストと全体のインテグレーションテストを書いて実装することが出来ました。

そのテスト中にPCが重くなることが何度かありました。原因を調査したところ、Datastoreのエミュレータがテスト後にゾンビ化していたことが判明しました。これに気づいた時に、Connectionが閉じられていないのでは?と思い、実際のコードを見るとClose処理が全くありませんでした。

ConnectionをCloseしないとディスクリプタを消費し続けるので、結果的にリソースの圧迫に繋がります。DatastoreのGodocには、下記の通り「終わったら閉じろ」と書かれていました。

Call Close to clean up resources when done with the client

pkg.go.dev

しかし、GoのGCがよしなにコネクションを解放している可能性も否定できませんでした。

そこで、実際に負荷試験を用いてCloseがパフォーマンスに及ぼす影響を定量的に判断することにしました。

2. パフォーマンスの検証と改善

チーム内に既に負荷試験を実施していた方がいたため、その方と話しあいながら負荷試験を設計しました。その方曰く、負荷試験で大事なのは、遅くなりそうな場所を予測して、その特定の場所に的を絞って計測することとのことでした。そのため、調査したかったDatastoreのClientが持つConnectionの生成を行うハンドラについて、Close有/無の場合で2回負荷試験を行いました。

その時の負荷試験は下記の通りPR上で計画しました。

今回の負荷試験はLocustを用いました。選定理由は、チーム内で既に行われていたのがLocustを用いた負荷試験だったためです。この検証を始めたのがインターンシップ終了5日前だったので、つまらない部分で躓かないように選定しました。

検証環境はLocustを動かすためにGKEを用い、検証対象サーバはGoを動かすためにApp Engineを利用しました。 そして、LocustのWorkersから1000RPS*1〜5000RPS程度飛ばしました。 この値に設定したのは、今回のテストがConnectionの生成のみをテスト対象としたためです。 全体の負荷試験を行う場合は、そのサービスのSLOを満たすレベルの負荷試験を行うと良いそうです。

さて、話を戻すと、行った負荷試験の結果がこちらです。

Closeあり

Closeなし

この結果から、下記の事実確認と考察が出来ました。

  • Closeを行うことで500エラーは100%減(22->0)
    • 500エラーの原因はGCPのログからメモリ枯渇と判明
  • 平均応答時間は40%増(95[ms]->133[ms])
    • 新たにClose処理を加えたためと考えられる
  • 4000RPS付近からCloseの有無に関わらずレイテンシが増加

4000RPS付近からレイテンシが高くなっていた原因の調査

この原因となっているボトルネックを調査するために、ハンドラにトレースを入れて再度負荷試験を実施しました。

その結果、レイテンシが高い時のトレースと低い時のトレースで、インスタンスであるcontainerのCreateにかかる時間に大きな差があることが分かりました。

そこで、このCreateの実装を確認すると下記の2つの操作が行われていました。

  • 新たなClientの作成
  • middlewareの挿入

middlewareの挿入は、内部的にスライスに対するappend処理のみを行なっていたため重くない処理と判断し、更に新たなClientの作成の実装を確認しました。

そこでは、

  • Google CloudのライブラリでgRPCクライアントを生成する処理
  • mercari.ioのライブラリでそのクライアントをラップする処理

が行われていました。後者は型変換が行われていただけなので、前者が重くなる処理と結論づけました。

ClientPoolの実装によるパフォーマンスの改善

この重くなる処理と考えられる処理を軽くするために、このgRPCクライアントをプールすることにしました。gRPCの通信はステートレスな通信なのでプール出来ないと思っていたのですが、データの送受信がない時も関係のないデータを流し続けることで再利用ができるようです。賢いですね。

github.com

余談ですが、gRPCのコネクションプールは下記のコードがシンプルで良さそうでした。

github.com

使えることがわかったため、実装をして再度ClientPoolを利用する場合としない場合で再検証を行いました。

その結果は下記の通りです。

f:id:task4233:20210810113538p:plain

f:id:task4233:20210810112602p:plain

この結果から、クライアントをプールすることで平均応答時間は26%減(133[ms]->105[ms])になっていることが分かります。したがって、クライアントをプールすることでパフォーマンス改善に繋がりました。

以上が、インターン中に行なったパフォーマンスの検証と改善です。

学べたこと

学べたことは大きく分けて2つです。

1つ目は、機能を適切な層に分割して実装することで、可読性とテスト設計のしやすさが高くなるということです。

これは、新しく大規模なソースコードに触れたからこそ、設計を意識した実装の重要さを再認識することが出来ました。

2つ目は、ボトルネックを調査して改善するまでのフローを経験できたことです。

私は本インターンで経験するまで負荷試験を行ったことがありませんでした。そのため、ボトルネックを予測と計測を組み合わせて発見し、それを改善する経験ができたのは大きな学びにつながりました。

メンターさんの:+1:ムーブ

これは余談ですが、今回のインターンシップで、なかひこさんにメンターとして様々な面で助力いただきました。なかひこさんが実施してくださったものの中で、ありがたかったことを列挙しておきます。

  • 1on1ミーティングを毎日実施してくださったこと
    • 毎日相談できる時間が保証されるのは心理的に良かったです
  • 細部まで丁寧にPRのレビューをしてくださったこと
    • 「なぜそうしたのか」という部分まで突き詰めてくださったのが良かったです
  • 1エンジニアとして扱ってくださったこと
    • 「これをやってみたい」と提案したことに対して全てYESで返すのではなく、必要性を議論しながら進められたのが良かったです

このような経験ができたのは、ひとえにメンターのなかひこさんとATLASチームの皆さんのおかげです。本当にありがとうございました。

おわりに

今回のインターンシップを通して、開発中のプロダクトに触れることで気づけた設計の重要性と、負荷試験の流れを経験しながら学ぶことが出来ました。

このインターンシップで得られた知見は、今後の開発で十分生かせると思います。

今回、良いインターンシップになるように尽力してくださったアカツキの皆さんには本当に感謝しています。 ありがとうございました!

*1:Request per Seconds

SecHack365 2020 研究駆動コース参加記録

はじめに

こんにちは。task4233です。

この度は、SecHack365 研究駆動コースのトレーニーとして1年間研究をさせていただきました。そのまとめとして、本エントリを書くことにしました。

なぜSecHack365に申し込んだのか

一言で言うと、大学にセキュリティ系の研究室が無かったためです。私がセキュリティ系の研究に興味を持ったのは昨年度のセキュリティ・キャンプ全国大会でした。そこで、マルウェアの検知手法に意外と単純なシグネチャ比較が用いられていることを知り、「これなら私でも手を出せるのでは?」と思い始めたのがきっかけでした。しかし、残念ながら私の所属している大学にはセキュリティ系の研究室がありませんでした。そのため、研究室がないなら外部で研究できるところを探そう!と思い、SecHack365の研究駆動コースに応募しました。その結果、合格しました。

SecHack365で何をしたのか

SecHack365では、マルウェア検知システムの提案と一部実装を行い、ポスター発表を行いました。

github.com

ポスター: https://sechack365.nict.go.jp/achievement/2020/pdf/2020_32.pdf

全体のスケジューリングについては、他のトレーニーの参加記録に書かれていると思うので割愛します。

blog.sechack365.com

一方で、他のトレーニーが書いていないであろう「オンライン開催」の感想を書こうと思います。
正直なところ、研究駆動コースにおいては「オンライン開催」は正解だったと考えています。なぜなら、定期的にオンラインでゼミを実施することが出来たためです。これは他のコースでも行われていたかもしれませんが、現状で何が出来ていて、何が出来ていないのか、そして次は何をすれば良いのかが明確になるため、日々の開発、研究の振り返りをすることはとても大切だと考えています。

逆に、「オンライン開催」で残念だったのは、旅行に行けなかった日本各地で対面でのお話が出来なかったことです。実は対m......おっと誰か来たようです。

挑戦と挫折の繰り返し

私はマルウェア検知システムに、CFG(Control Flow Graph)というプログラムの遷移状態を持つデータ構造を利用したのですが、その生成と利用に関して色々な角度から挑戦しては何度も挫折を繰り返しました。

ja.wikipedia.org

ざっくり話すと、最初はCFGの生成にLLDBというデバッガのC++APIを用いていたのですが、3カ月ほどかけて実装が難しいことに気づきました。そのため、比較的遅めなGDBPython APIを用いてなんとか実装し、最終的にCFGの生成部を実装することが出来ました。LLDBからGDBを用いた手法に変えるのに、3カ月も要してしまった理由はLLDBは高速なC++ APIを用いていたのに対して、GDBは遅めのPython APIを用いていたためです。今思うと、動くモノが出来ていないにも関わらず、最初から速さを意識して実装に取り組んでいたのは勿体なかったと思います。そのため、ここに時間をかけずに、もっと短いスパンで様々な手法を試すことが重要だったのかなと今思っています。

SecHack365では何が得られるのか

SecHack365全体では、イノベーティブな友人関係が得られます。多くの方は、SecHack365に対して「1年間で圧倒的成長」や「セキュリティつよつよになって帰ってくる」といったイメージを持っているのかもしれません。それは事実なのですが、それ以上にイノベーティブな友人関係が出来るのは大きいと私は考えています。なぜなら、SecHack365は事実上期限がありますが、友人関係は消えることがないためです。実際に、SecHack365を修了した今でも交友関係は続いていますし、今後も消えることは無いと思います。SecHack365を通して、この関係が作れたのは本当にありがたかったです。

また、習慣化が根付いてくるのも特徴の一つだと思います。SecHack365のトレーナーには習慣化のプロがおり、そのトレーナーから習慣化のコツや取り組み方を教えてもらうことが出来ます。しかし、ただ話を聞いているだけでは習慣化を続けていくことは難しいと思います。この習慣化を定着させるためには、そのトレーナーの助言を聴くだけでなく、実践することが肝要だと感じました。

実際に、私はSecHack365に参加して、本当に忙しい時以外は日報を書くようにすることで、その日の振り返りを習慣化できました。日報が書けないくらい忙しいときでも、最近は風呂の中で振り返りを行っています。その結果、寝る前にあまり進捗が出ていない日でも、「今日はここまでできたからえらい」とか「今日は出来なかったけど、明日はこれをやってみよう」とかいうことを考えることが習慣化できるようになってきました。その甲斐あってか、最終的に習慣化大賞をいただきました🎉

大賞の景品としていただいた一口羊羹焼肉

研究駆動コースでは何が得られるのか

研究駆動コースでは、研究的思考を実践しながら学ぶことのサポートが得られます。これは以下のSecHack365における、研究駆動コースの概要文にも書かれていることです。

SecHack365「研究駆動コース」においては、いわゆる成果主義ではなくアイデア発想とその着想理由を大切にしていることから、いわゆる研究の基本的スタイルに合わせることをそれほど重要視しません。その代わりに研究プロセスをしっかり明確にさせるための特訓を行います。これにより、アイデアの着想に至った過程の重要さに気づいてもらい、研究へのモチベーションを高める支援を行います。 具体的には、アイデアの創出から始まり、その研究が誰に対してどのような効果や利点があるのか、何故それを実施してみたいのか、どうしてもやってみたいのか等々はっきりさせることが大切であり、トレーニーに求めることは今まで経験してきたようなドリルの問題を単に解くような「問題解決」スタイルではなく、自ら「課題設定」ができる能力を伸ばしてみたいという意欲を自身で持つ、ということが重要です。もう1点、単なる思いつきでは世界には勝てないということに気づいてもらいたいということです。よって、諦めない強い心を作り上げること、これがトレーナーたちが本コースを運営する上で最も重要視している点です。人によっては少し厳しい感じを受けたかもしれませんが、私たちは皆様のチャレンジを全力で受け入れられるよう身体を暖めながらお待ちしております。

sechack365.nict.go.jp

研究的思考、とは様々な側面がありますが、これは文面ではなく実践を通して学ぶものだと思います。そのため、興味が湧いた方は、ぜひ来年度以降の研究駆動コースに応募してみてください!

sechack365.nict.go.jp

おわりに

最後になりますが、トレーナーの皆さん、スタッフの皆さん、アシスタントの皆さん、そしてトレーニーの皆さんに支えていただいたことに対して深く感謝申し上げます。皆さんの存在は、私1人で出てくるアイデアを大きく膨らませる手助けになってくれました。私1人では、SecHack365での研究を形にしてポスターとして発表するのは難しかったと思います。その点で、アイデアや情報提供をしてくださった皆さんには本当に感謝しています。ありがとうございました。

最後に、いただいた修了証受理ツイートをもって締めさせていただきます。最後までお読みいただき、ありがとうございました!

2020年の振り返りと2021年の目標を述べてみる

はじめに

こんにちは。task4233と申します。

この記事は, 僕の2020年の振り返りと2021年の目標を述べることを目的として書かれたポエムです。
昨年のポストに引き続き, 書いてみました。昨年は思っていた以上に某ウイルスにダメージを受けて色々と大変な年でした。
これは皆さんが感じていることだと思うので, 上手く付き合っていくしかないのかなと思います。
昨年で得られた知見をいくつかに分けて書いたので, 少しでもお役に立てれば幸いです。

もくじ

2020年の振り返り

今年の目標は以下の5つでした。

  • [x] SecHack365に応募する
    • 2020年 SecHack365 研究駆動コース
  • [ ] セキュリティ・キャンプ全国大会2020のチューターに応募する
    • SecHack365, 教育実習に専念したかったので応募を断念
  • [ ] 高度情報技術者試験かセキュリティ資格試験AC
    • 某ウイルスで断念
    • 今年は受験予定
  • [ ] CTFの本番で正答率10~20%の問題を通す
    • WaniCTF SQL Challenge 2(26.7%)
  • [ ] セキュリティに関するOSSツール(拡張)を作る
    • SecHackで作成中
    • 今年公開予定

以上のうち, チェック([x])がついているものを達成しました。

全然達成していませんね。もちろん努力はしていたのですが, 予想通りには行かないものです。
引き続き精進します。

院進学と将来

色々な方々に相談にのっていただき, 結局そのまま同じ研究室で続投することに決めました。
この場をお借りして感謝申し上げます。本当にありがとうございました!

理由はいくつかあるのですが, 決め手となった2つの要素は, 来年弊学にネットワーク系の教授が配属されることと, 僕の研究分野において他大に行くメリットがそこまでなかったことです。

僕の研究分野は簡単にいうとお金にならない(?)ので全国の大学の研究室を探しても完全に合致する研究室はありませんでした。微妙に被っている研究室が筑波大にあり, 受け入れていただく流れになっていたのですが, 色々な方々に相談させていただき総合的に判断した結果, そのまま他大に行かずに院進することに決めました。詳しく書くと色々と問題がありそうなので, 他大の院に行くかどうか迷っている方がいれば, 内々で相談にのれるかもしれません。DMを飛ばしてください。

また, 将来的にはやはりエンジニアの方面に進みそうな気がしています。
研究者も悪くはないのですが, 現状で研究の楽しさよりも求められた要件をクールに解決するコードを書く楽しさの方が勝っているので, そちらの方面に進みそうです。
そのために, 会社(業界)を知り, 優れた仲間を見つけ, スキルアップするために, 今年は積極的にインターンに応募するつもりです。おススメのインターン等ありましたらお教えください。

エンジニア種別としては, バックエンドエンジニアになりそうですが, バックエンドだけに限らずフルスタックを目指して精進していきたいと思います。

誕生日CTFの反省

今年も12月5日に誕生日CTFを開催しましたが, 結論から言うと, 下記の謎問題たちを出題してしまい, あまり芳しくないCTFとなってしまいました。

  • パラメータを変えずに連続アクセスすると得られるWeb問
  • アクセス権限不備で想定解以外でも得られるWeb問
  • 論理性が欠如したOSINT問

これらの対策は下記の通りです

  • 環境構築も含めた問題管理
  • 事前の難易度確認と調整

さて, 謎問題たちは僕の手で生み出してしまった訳ですが, これらのうち上2つはサーバの設定不備により問題環境が蒸発したために生まれてしまいました。もちろん問題はGitで管理していたのですが, 本番環境のアクセスコントロールはnginxで行っていたため, GKEのインスタンスがおしゃかになってしまったときに対応できなくなってしまいました。 対策として, KosenXmasCTFのように, 各問題それぞれをDockerfileで切り離す手法が取れそうです。そうすることで, docker-composeかk8sで一括管理できるので, 来年はそうするつもりです。

OSINT問に関しては, ヒントになるオブジェクトを置くなどするべきでした。正直, 難易度は理不尽級に高かったものの「どうせ解かれるでしょ」と思っていたら1人にしか解かれていなかったので*1やってしまったなと後悔しました。逆に, もう一方の問題は, ヒントとなるオブジェクトがあったためか, 6割程度の方が解けていました。 そのため, OSINT問題は事前に友人に出題してみて, 特定できるかを確認してから出題するのが良いと思いました。

一方で, Grass FlagCaesar Cipher Translatorの二問はまぁまぁ面白い問題だったと自負しているので, そこは良かったと思います。 実際にアンケートでも面白かったというコメントをいくつもいただけたので良かったです。

来年はこれらの謎問題を含まないようなCTFにするので, もしよければ来年は参加してみてください。

Goが楽しい

昨年はGoを一番使いましたし, 今後のメイン言語をGoにしようと思うほどGoを書いた年でした。 ここまでハマるきっかけとなったのは, 一昨年2月ごろに開催されたMercariさんのStep up goでした。ここで, 毎週Goについて実践的に学ぶことが出来たので, 自信が付いてゴリゴリ書くようになりました。

Goの良さは色々ありますが, 私が最初に惹かれたのはエラーハンドリングでした。
他の言語ではtry-catch-finally形式の例外処理機構を用いるものもありますが, 私はこれがあまり好きでないです。 別に悪くはないのですが, とりあえずExceptionなら弾くのが気持ち悪い, とか, スコープが異なるので事前にインスタンスを宣言しておく書き方が気持ち悪い, とか, そういった理由で好きではないです。その点, Goは標準的にエラーを戻り値として取得する週間がありますし, finally句の代用としてdefer句を使用することで絶対に処理したい部分を簡素に書くことが出来ます。

他にも, 平行処理に対するサポートや実行効率が良く, 静的解析しやすいところも良いところでしょう。実際に, 先日のSpecification輪読会で, 「interfaceのアドレスはいつ確保されるのか」という話が出た時に, 気軽にバイナリを解析できました。

このような流れで, 来年もGoを積極的に使っていくことになると思います。 最近はGo Language Specification輪読会でSpecificationを読んでいるのですが, 知らなかった仕様に驚き学ぶ日々を送っています。新年は1/13に開催するので興味のある方は参加してみてはいかがでしょうか。

Rustも良いらしいですが, 沼に落としてくれる人がいなかったので, そういった方が出てきてくれればぜひぜひ沼に引きずりこんで欲しいところです。よろしくお願いします。

研究が大変

これが一番苦労した(している)ところです。 その原因は, 問題設定とその解決法の2つにあると考えています。

まず, 問題設定に関して。 今までは問題が既に設定されていて, それを解決するという道筋でした。 学校で出題される問題や, 競プロ, CTF, 技術検証でもこれは同じです。そのため, これらは情報収集をすることで外堀を埋めて地道に理解していけば解決できることが多いと考えています。

しかし, 研究では問題を定義するところから始まります。この問題設定が確実に正しいかは分かりません。例えば, 設定した問題を解決する手法が時間計算量的に渋かったり, そもそも別部門で議論されていたりすることはよくあるのです。そのため, お偉い教授に相談してから問題設定がマズいと指摘されることがありました。この原因は, 一言で言えば僕の情報不足によるものなのだと思います。この情報不足に対して, クリティカルに効く文献などは無いので, ひとまず有識者に相談することがベストだと思っています。とはいえ, 有識者もヒマではないのでここで作業を続けた結果, 出戻りが発生することが多かったです。もっと良い対処法があればご教授いただきたいです。

次に, 解決法に関して。 解決(できる可能性のある手)法はたくさんあります。その全てに取り組むことは時間的に厳しいので, 最初にある程度調査を行った上で解決法を試す必要があると思います。 が, 僕は引き際を見誤り, 解決できそうな手法をひたすら試してしまい, 時間を棒に振ってしまいました。今思えば良くなかったと思いますが, 当時はもう少しで出来ると本気で思っていたので悲しいです。これに関する対処法は時間を決めて取り組むことなのか, 単に僕の能力が低かったのかよく分かりません。

教育実習で得られたもの

今年の10月中旬から11月上旬にかけて, 母校にて3週間だけ数学の授業を32時間分実習させていただきました。 昨年の介護等体験では, どのような相手に対しても等しく対応することの重要性を再確認したと書きました。

今回の教育実習でも多くのことを学ばせていただきました。その中で, 1つ挙げるとすれば時間の管理方法だと思います。端的に言うと, 期限がギリギリである程度の質を求められた時にどう対処するか, を実践を通して学ばせていただきました。

僕なりの答えとしては, 自分で時間的な期限を決め, その7割を超えた時点で収束に持ち込むという方法がしっくりきました。 これは授業においても, 授業外に関してもそうでした。

きっかけは, 授業用の指導案と実際に行う授業の進行がズレてしまい, 時間通りに終わらせるためのアドバイスを先生方からいただいたことでした。
その内容をざっくり書くと下記の通りです。

  • 指導案はあくまで目安に過ぎない
    • 教育実習の建前として作らせているだけ
  • 実際の授業では残り15分を境に教える範囲を進めるか復習するか決めている

これを受けて実践してみると, 意外と上手く行きました。残り時間が少なくなった時は授業の復習時間に充てることで生徒の理解度向上にも寄与した気がしますし, 何より指導案通りにいかない可能性を視野に入れて授業を出来たので, 最初の35分間をのびのびと使うことが出来ました。

さらに, 授業外でもこれが使えることが分かりました。というのも, 私の実習では32時間分担当するということを, 実習初日に知らされ, 初回授業が実習3日目だったものですから, 全ての資料作成が当然間に合いませんでした。 そのため, 次の授業の資料作成を前の日にやるというのを繰り返した結果, 初週の平均睡眠時間が1.5hという結果になってしまいました。 このままだと2,3週目にぶっ倒れると思い, 対策を考えていた矢先, 先ほどの「残り15分を境に決める」という言葉をふと思い出しました。 50分授業で残り15分というと, 開始から35分後なので全体の7割にあたります。 これを, 翌日の資料作成においても実践してみると睡眠時間を最低限確保した上で資料作成に取り組むことができるのではないかと考えました。 結果として, これにのっとり, 2,3週目は安定した睡眠時間を確保した上でそこそこの授業を実施出来たと思います。

これは僕だけかもしれませんが, 完璧主義寄りの人は睡眠時間を犠牲にしてまで何かに取り組みがちだと思っています。 その結果, 体調を崩したり課題ごとの質がバラバラだったりすることがあるのではないでしょうか。 しかし, それを改善しなくてはいけないとわかっていても対策が分かっていない方もいると思うので, 参考になれば幸いです。

他にも, 先生方を観察していると, 不器用にも全力でやっている先生方もいらっしゃいましたが, 上手いこと手を抜けるところは抜いて職務にあたっている方もいらっしゃいました。 もちろん良し悪しは付けられませんが, 出来れば僕は後者でありたいなと強く思ったそんな教育実習でした。

他にもエピソードはあるのですが, 全部書いてしまうとつまらないので, 対面でお会いしたときにでも機会があればお話しましょう。

SecHack365の途中経過

SecHack365は, セキュリティ・キャンプで存在を知り応募しました。

僕は研究駆動コースだったので, 下記の3点を鮮明にして応募要項を埋めました。

  • どんな研究を志望するのか
  • SecHack365がなぜ必要なのか
  • 研究のために何を今しているのか

現状で, 周りのプロたちよりは成果が出ていませんが, そもそもこの環境にいられたこと, そしてトレイニー同士のつながりを作れたのが大きな成果です。
セキュリティ・キャンプやインターンでもそうなのですが, 一緒に課題に取り組む方々って良い人ばかりなんですよね。 先述したCTFでサーバをHackしてバースデーメッセージを載せてくる人や, 他のトレイニーが取り組んでいる課題に対してアドバイスや意見を飛ばしてくださる人, ギークな話題で語りあえる人などなど, 尊敬できる一面を数多く備えている気がします。 こういった環境で切磋琢磨できて僕は本当に幸せだと思います。

しかし, 現実では僕の進捗は微妙なところなので, 残りの2週間で計画と実践をやっていき, なんとか形にしたいと思います。
SecHackは終わりではなく始まりなので, 今後の研究において大きな転機となったのは間違いないです。

2021年の目標

  • 積極的にインターンに申し込む
  • 査読付き論文を1本通す
  • 朝活を継続する

この3つが, 今年達成したい3つの目標です。昨年は5つにしていたのですが, 今年は変化がありそうな年なので余裕を持たせて3つにしました。

おわりに

以上が, 2020年の振り返りと2021年の目標でした。

2020年は予想とは異なる年になってしまいましたが, 今年は着実に一歩一歩進んでいくつもりです。

長くなってしまいましたが, ここまでお読みいただきありがとうございました。少しでもためになる部分があれば幸いです。 では, 今年も1年よろしくお願いします。

*1:1人解いていた人は朝の4時ごろまでずっとやっていたようです......一体どこのOOtokiさんなんだ......

Hardening 2020 H3DXに参加してチーム優勝してきた

はじめに

2020年11月13日(金)から14日(土)にかけて開催されたHardening 2020 H3DXに参加し, チームおにぎりまみれの一員として優勝してきました。

f:id:task4233:20201126194720p:plain

本競技での私の役割は技術部門の「なんでも屋」だった気がします。その辺りの話も含めながら, 本イベントの概要, 競技までの流れと事前準備, 競技中の様子, 全体の感想を書きます。

参考までに, 他のメンバーの参加記のリンクを貼っておきます。本記事よりもクオリティが高いので, 次回以降参加する方はぜひチェックしてみてください!

nomizooon.hateblo.jp kiryuanzu.hatenablog.com sirabete-manabu.hatenablog.com

目次

Hardening 2020 H3DXとは?

ざっくり言うと, 外部からの攻撃を防御しつつ, 売り上げを最大化する競技です。 公式の説明は下記の通りです。

Hardening競技会は、基本的に、チームに託されたウェブサイト(例えばEコマースサイト)を、ビジネス目的を踏まえ、降りかかるあらゆる障害や攻撃に対して、考えうる手だてを尽くしてセキュリティ対応を実施しつつ、ビジネス成果が最大化するよう調整する力を競うものです。 ref: https://wasforum.jp/hardening-project/hardening-2020-h3dx/

そして, H3DXは下記の3要項を指します。

  • Deep Trans-organization
  • Digital Transformation
  • Dependence Excercise

意味をお尋ねしたところ, 「あまり深く考えなくて良いよ」とのことでした。

競技までの流れと事前準備

競技までの流れは, 応募->チーム確定->役職決定->競技準備->競技本番でした。 10月14日にチーム確定メールが来たので, 11月13日の本番までの約1か月間が準備期間でした。私は運悪く, 急遽確定した教育実習と事前準備の期間が丸被りしていたので, 事前ミーティングには殆ど参加できませんでした。その分, 競技前日のミーティングで出来ることを精一杯やろうと決めていました。

結果として事前準備で貢献できたのは, パスワード変更用のシェルスクリプト作成くらいだと思います。このスクリプトUbuntu, CentOSサーバ内のbash_historyにも履歴が残らないので採用しました。特に不具合報告もなかったので, 無事動いてくれたと思います(たぶん)。

それと, 使われたのか知りませんが, 1分くらいで意外と上手く書けた目玉商品の紹介画像があるので, ここで供養しておきます。

f:id:task4233:20201126200924j:plain:w300
サブスク『諸刃の刃』

他に, チームとしてやったことや事前に用意したものは, のみぞーさんや, ばばさんが, 詳細にまとめてくださったので, そちらをご参照ください。

nomizooon.hateblo.jp sirabete-manabu.hatenablog.com

これらの記事でも少し触れられていますが, 各メンバーが率先して何かをこなそうとしていたこと各メンバーが提案を快く受け入れていたことが非常に印象的でした。 例えば, チーム用Slackの作成やミーティングの提案, スキルチェックシートの作成, Discord, Trelloといったサービス利用はメンバー各自の提案であり, その全てがメンバーに受け入れられ実現していきました。私はあまり関われずに指を咥えて見ているばかりでしたが, こういった心強いメンバーと同じチームになれたのは本当に幸運でした。

後にのみぞーさんやあんずさんの記事で, リアクションを徹底していたことを知り, 次のイベントでは私もこのようなアクションを取ろうと思いました。思い返すと, 発言が虚空に消えそうな雰囲気を感じたときにコメントを拾ってくださったことが多く, 不安が払拭されていったのを実感がありました。

競技中の様子

Hardening Day

外部からの攻撃を防御しつつ, 売り上げを最大化する競技の日でした。この日を技術面とコミュニケーション面に分けて振り返ります。

技術面について

技術面において, 私は「何でも屋」として振舞っていたつもりです。

事前に決めていた私の役割はWebページのhttps化だったのですが, 今回のECサイトはデフォルトでhttps化されていました。そのため, 私の仕事はパスワード変更くらいでした。それが終了したときには, 他のメンバーの方々はそれぞれの仕事を始めていたため, 他のメンバーのサポートに入ろうと思い, 「何かやることがありませんか?」と逐次聞くようにしていました。 その結果, WordPressの管理, Webページの情報差し替え, 文書用のスクリーンショット準備, EDRのインストール, SSL証明書の期限切れ報告といったことをする何でも屋として動いていました。今回の競技の目的は売り上げを最大化することだったので, 地道にミッションをこなすことでほんの少しはチームに貢献できたのかなと思っています。

これは余談ですが, メンバーから「アンダーバー入力できる人はEDRのインストールお願いします!」というお願いがきて私が対応した際に, クライアントのGuacamoleの仕様で表示されていないだけというのは泣けました。直接/etc/vconsole.confを編集しても改善されなかったときは🤔となったのをよく覚えています。

コミュニケーション面について

コミュニケーションは, テキストベースのSlackと音声ベースのDiscordにて行っていました。ここで私が意識していたことは, テキストベースで発言した上で, 反応がなければ音声ベースで発言するという, 2段階の発言を行っていたことです。よく考えれば普通なのかもしれませんが, テキストベースでの発言を1度挟むことで, Discordの帯域を邪魔することが少なかった気がしています(気のせいかもしれません)。

また, この2段階の発言を行うことで, 発言の取りこぼしも減ったと考えています。とはいえ, 実際はチームメンバーの意識付けのおかげだったのかもしれません。

Softening Day

Hardening Dayの振り返りや, 攻撃者のkuromame6*1による講評等が行われた日でした。

急遽CEOのさんごさんが発表できなくなったため*2, 発表はのみぞーさんが行ってくださいました。結果として, 時間ピッタリで素晴らしい発表をしてくださったので, 非常に心強かったです。

全チームの発表を聞いていると, チーム内でのメンバ同士のやり取りが円滑に出来たか否かで大きく結果が変わったように感じました。これは, 競技後に他のチームの方にお聞きしても同意されていたので, やはりそういうことだと思います。

講評

講評を大きく2つに分けると, インシデントについてと親会社への報告についてでした。

インシデントについては, 自分たちで起こしていることが多いとのことでした。本競技では, kuromame6はDNSに全く触れていなかったそうなので, DNSの障害は完全に自己責任ということでした。また, フィッシングメールに返信してしまったり, FWで操作用のポートまで閉じてしまったりしたチームもあったようなので, わざわざインシデントを作ってお金を払っていたチームもあったようです。 その他に, 事前にタスクスケジューラに埋め込まれたPowerShellスクリプトや, DB情報をダンプするcronも設定されていたようなので, 攻撃されていないからといって安心するのは危ないそうです。これらの布石は, 事前に配布された競技背景にヒントとして埋め込まれていたそうです。

親会社への報告は, 資料を用意するか否かという問題のみならず, 情報が洩れているのか漏れていないのかが不明瞭な点, 売り上げに対して情報漏洩がどのような作用をもたらすのかを考慮していなかった点も問題点として指摘されました。

全体の感想

結果として, つよつよチームメンバーのおかげでグランプリをいただけましたが, グランプリをいただけたことよりもチームでワイワイしながら競技に参加できたことが良かったです。

また, 準備不足だったと思うことは報告書のテンプレート作成でした。 今回は怒られイベントが発生したために強く感じたのかもしれませんが, 情報漏えいが確認できた時点で資料作成のテンプレートがあると良かったかなと思います。 怒られイベントで「え?君たち報告会に資料もなしに来たの?」などと言われているのを聞いて, 胃痛がしたのをよく覚えています。

事前に情報漏洩時の対応についても決めていたので, 生かしきれなかったのも残念でした(作ってくださったさんごさん申し訳ないです)

これは余談ですが, 情報セキュリティインシデント報告書を調べたところ、JUCE(私立大学情報教育協会)から公開されているものがこちらにありました。参考までに。

おわりに

今回の競技は事前準備も含め, かなり長丁場のイベントだったと感じています。その分, メンバーの強い協力もあって本番中はワイワイしながら競技に取り組めたのかなと考えています。そのため, また競技に参加できることがあれば, リアクションを徹底することを強く心に留めておきます。

最後になりますが, 運営メンバーの皆様, そして参加者の皆様, 非常に面白いイベントにしていただき本当にありがとうございました!
またこのようなイベントは開催されると思うので, 興味のある方は参加してみてはいかがでしょうか?

*1:攻撃者で構成されたチームのことです

*2:グランプリのCEOは現地に招集されたため

NTT Performance Tuning Challenge 2020 参加記

はじめに

2020年9月11日(金)に開催されたNTT Performance Tuning ChallengeにチームКошкаとしてはなかずさんと2人で参加しました。 終了2時間前くらいには結構上位に食い込めていたのですが、最終的にその状態に復元することが出来ず、結果正の得点を取ったチームの中で下から2番目となってしまいました。

とはいえ、今回のイベントにおいて学べたことが多かったので、ここに記すことにしました。

学べたこと

Slow Queryの探し方

Slow Queryを探すためにはpt-query-digestを使います。このツールはデータベースのSlow Queryログを解析するツールです。 Slow Queryは下記の記述をmysqldのconfファイルに追記することで出力できます。

slow_query_log       = 1
slow_query_log_file = /tmp/slow-query.log
long_query_time = 0.1

ここで出力されたログをpt-query-digestに渡すことで、下記のようにSlow Queryをまとめて出力してくれます。

$ pt-query-digest /tmp/slow-query.log
# (snip)
# Query 1: 2.41 QPS, 0.19x concurrency, ID 0xB09A20EF29F18029 at byte 84332154
# Scores: V/M = 0.07
# Time range: 2020-09-11T04:23:45 to 2020-09-11T04:25:04
# Attribute    pct   total     min     max     avg     95%  stddev  median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count          1     190
# Exec time     51     15s    74us   327ms    78ms   266ms    76ms    48ms
# Lock time      3     8ms    14us   381us    42us    98us    37us    31us
# Rows sent      0     188       0       1    0.99    0.99    0.10    0.99
# Rows examine   0     188       0       1    0.99    0.99    0.10    0.99
# Query size     0   8.11k      41      46   43.71   42.48    0.54   42.48
# String:
# Databases    app
# Hosts        competition-068.c.sys0098096-1-80305617.inte...
# Users        ptc-user
# Query_time distribution
#   1us
#  10us  #
# 100us  ####
#   1ms  ####
#  10ms  ################################################################
# 100ms  ######################
#    1s
#  10s+
# Tables
#    SHOW TABLE STATUS FROM `app` LIKE 'events'\G
#    SHOW CREATE TABLE `app`.`events`\G
# EXPLAIN /*!50100 PARTITIONS*/
SELECT image FROM `events` WHERE `id` = 3128\G

この出力から、SELECT image FROM events WHERE id = 3128に、最長で100[ms]単位を要していることが分かります。

更に、Slow Queryに関連して、カーネルパラメータやコネクション数の調整のような普段は触らない部分を知るきっかけになりました。

遅いエンドポイントの探し方

遅いエンドポイントを探すためには、kataribeが使えます。このツールは、httpサーバのログを解析するツールです。httpサーバのログはNginx等で出力できます。

このツールは、下記の通りtoml形式でフォーマットを指定することでアクセスログをまとめてくれます。

$ sudo cat /tmp/access.log | kataribe -f ./kataribe.toml
Top 20 Sort By Total
Count   Total     Mean   Stddev     Min   P50.0   P90.0   P95.0   P99.0     Max  2xx  3xx  4xx  5xx  TotalBytes   MinBytes  MeanBytes   MaxBytes  Request
  154  52.263   0.3394   0.4680   0.000   0.245   0.261   0.513   2.890   3.148   11    0  143    0       10662         31         69        399  POST /api/events HTTP/1.1
  145  34.146   0.2355   0.0536   0.001   0.242   0.256   0.261   0.440   0.500    0    0  145    0        6920         31         47         55  PUT /api/events/1 HTTP/1.1
    1  24.126  24.1260   0.0000  24.126  24.126  24.126  24.126  24.126  24.126    1    0    0    0        4718       4718       4718       4718  GET /api/events?limit=12&offset=889 HTTP/1.1
    1  23.876  23.8760   0.0000  23.876  23.876  23.876  23.876  23.876  23.876    1    0    0    0        4791       4791       4791       4791  GET /api/events?limit=12&offset=1028 HTTP/1.1
    1  23.483  23.4830   0.0000  23.483  23.483  23.483  23.483  23.483  23.483    1    0    0    0        4492       4492       4492       4492  GET /api/events?limit=12&offset=341 HTTP/1.1
    1  23.412  23.4120   0.0000  23.412  23.412  23.412  23.412  23.412  23.412    1    0    0    0        4628       4628       4628       4628  GET /api/events?limit=12&offset=46 HTTP/1.1
    1  23.408  23.4080   0.0000  23.408  23.408  23.408  23.408  23.408  23.408    1    0    0    0        4412       4412       4412       4412  GET /api/events?limit=12&offset=1584 HTTP/1.1
   37  23.210   0.6273   0.6186   0.001   0.270   1.770   2.035   2.398   2.398   27    0   10    0         291          0          7         35  POST /api/logout HTTP/1.1
(snip)

このログから、GET /api/events?limit=12&offset=889 HTTP/1.1は1回しか呼ばれていないのに、24[ms]もかかっているので、ボトルネックになっている可能性があるなどのことが分かります。

このツールは、出力のどの部分を見れば良いのかよく分からないツールでした。実際に何度か使うと使い方がわかってくると思いますが、最初はこれを見ても見方や使い方がよく分かりませんでした。参考になる資料などありましたら教えていただきたいです。

N+1クエリ

N+1クエリとは、一覧の取得に1回、関連データの取得にN回、計N+1回のクエリを発行する際に起きる性能問題のことです。 これは、先述したkataribeのログを見て、極端に遅いエンドポイントのハンドラに含まれていることが多いです。

N+1クエリとは、下記のようなものです。なお、長くなるのでエラーハンドリングは割愛しています。脳内補完してください。

type Item struct {
  Name     string
  UserName string
}

var items []Item{}

itemRows, _ := dbc.Query("SELECT user_id, name FROM items")
defer itemRows.Close()
for itemRows.Next() {
  // idとnameをmap
  var userID int
  var item Item
  itemRows.Scan(&userID, &item.Name);
  
  userRows, _ =  dbc.Query("SELECT username FROM users WHERE id=?", userID)
  for userRows.Next() {
    // UserNameをmap
    userRows.Scan(&item.UserName)
    items = append(items, resItem)
  }
}
  

ここで、最初のクエリでitemsテーブルから得たrow1行ごとに、usersテーブルにクエリを実行していることが分かります。 このようにrow1行に対して別テーブルに呼び出しを行うことで、テーブルのレコード数が大きければ大きいほど実行時間が長くなるクエリがN+1クエリです。

そして、その改善方法のひとつとして、SQLの問い合わせは全部SQLに任せる、というものがあります。 今回の例でいえば、下記のようにテーブルへの問い合わせを別々に行わず、まとめて問い合わせることになります。

var items []Item{}

itemRows, _ := dbc.Query("SELECT u.name, i.name FROM items i INNER JOIN users u ON i.user_id=i.id")
defer itemRows.Close()
for itemRows.Next() {
  // UserNameとnameをmap
   var item Item
  itemRows.Scan(&item.UserName, &item.Name);
  
  userRows, _ =  dbc.Query("SELECT username FROM users WHERE id=?", userID)
  for userRows.Next() {
    // UserNameをmap
    userRows.Scan(&item.UserName)
    items = append(items, resItem)
  }
}

このように、INNER JOIN句を用いて内部結合を行うことで、各テーブルへの問い合わせをソースコードを介さずに行うことが出来ます。 そのため、直感的に早くなりそうだということが分かるはずです。

今回のイベントでの反省点

一言でいえば、変更点をメモしていなかったことです。 最初にも書いた通り、ちょこちょこ変更を加えている間にベンチに失敗するようになってしまいました。 小さな変更を加えるごとにベンチを回すのが理想だったのかもしれませんが、ベンチが回りきるまでに3分程度かかるので新しい機能の追加に応じてベンチを回すようにしていました。 その結果、新しい機能を追加したらベンチが正常終了しなくなり、元の状態に復帰できなくなってしまいました。

当初は、変更点くらいならGitのコミットで管理すれば良いかなと考えていたのですが、このイベントではソースコードのみならずDBやインフラのように複数変更する部分があります。 Git上では、stable version(1270)というコミットがあったのですが、このコミットにロールバックしてもインフラやDBの状態までは復元できませんでした :cry: 。 そのため、Gitのコミットのみでなく、何時ごろに何をしたかをざっくりとメモしておけばよかったと考えています。もっといい方法があれば教えていただきたいです。

ベンチマーカについて

今回のベンチマーカは、PythonTevernを使っていたようです。 しかし、テストに失敗したときにそれっぽいログは出力されていましたが、あまり見たことのないフォーマットだったのでどの部分が原因で落ちたのかが分かりにくかったです。 例えば、logoutの機構に関して、ブラウザでは正しく実行できているのにローカルでのベンチでは落ちているというケースも散見されました。 本番中は焦っていたので、ExpectedとAcctualの部分からソースコードのどこがおかしいかをざっくり探していたのですが、今思うと危なかったかな、とも思います。

おわりに

こういうイベント系は、参加記を書くまでがイベントな感じがするので参加記を書きました。 イベント全体を通して、6時間半という長丁場でしたが、ドキュメントや初期設定等に1時間、想定していた3台構成にするまでに1時間、ベンチを回している時間をまとめると30分程度、椅子を温めている時間が1時間と、効果的に手を動かせていたのは1時間程度と、濃い時間だったように思います。とはいえ、その間もソースコードを見ながら雑にインデックスを貼ったくらいで、ドキュメントの情報は殆ど使えていなかったように思います。 その点で言えば、まだまだISUCON初心者だと思うので、また別の機会があればこういったイベントに参加してみたいです。

明日はISUCON10の予選ですが、私は参加権が得られなかったので次回のISUCON11や他のチューニング系イベントで再チャレンジしたいと考えています。 ISUCON11では誰か一緒に出てほしいです。お茶くみくらいならやります。

最後になりますが、運営メンバーの方々、面白いイベントを開催していただき、ありがとうございました。 またこのイベントを開催する可能性があるらしいので、興味のある方は参加してみてはいかがでしょうか。

参考にした資料

SBテクノロジーでSOCアナリストとして2か月の就業型インターンをしてきた話

もくじ

はじめに

2月から2ヵ月にわたり、SBテクノロジーのMSS(Managed Security Service)に携わるSOCアナリストとして就業型インターンをしてきました。 このエントリは、節目としてエントリを残しておきたいという思いと、今後SBテクノロジーインターンを志望する方の参考になればという思いで書かれました。

SBテクノロジーis何?

一言でいうと、ICTサービス事業としてクラウドに特化して環境および運用を提供する会社です。事業内容はこちらをご覧ください

クラウドの環境および運用を提供するということは、そのセキュリティ監視も当然存在します。その一部に、私が従事した、SOCとして24時間365日セキュリティ監視を行うMSSがあります。

SBテクノロジーインターンに応募した理由

SOCとして従事するMSSに応募した理由は、以下の3点でした。

  • クラウドのセキュリティに特化しているという部分に興味を持ったため
  • 実業務としてSOCの経験をできるインターンが無かったため
  • 自分のセキュリティに関する知識・経験がどれだけ通用するのか知りたかったため

そもそも、SOCはその存在自体が隠蔽される性質を持つので、SOCのインターンは非常に珍しく感じました。それに加え、セキュリティ・キャンプで「クラウドのセキュリティに特化しています」と紹介していたため、「クラウドのセキュリティとは:thinking_face:」と気になっていたこともきっかけの1つです。

以上の理由から、将来SOCになるか否かは別として、SOCがどのような場所であり、そこで私に何ができるのかを知るためにインターンに応募しました。

SBテクノロジーでしたこと

定常業務

SOCの業務の中で私に課されたのは下記の3つの定常業務でした。

  • お客様の製品が正しく運用されているかの監視
  • 脆弱性情報の配信
  • お客様へのログから読み取れる攻撃傾向のご報告

これらの定常業務は、全ての業務を含めて3・4時間もあれば終わってしまうので、業務時間中に手があくこともしばしばありました。そのような時には、レポートのダブルチェックを行ったり、システム構成に関する会議に同席したりすることもありました。

半自動化による業務改善

それでも時間は余ってしまうもので、業務改善として「お客様の製品が正しく運用されているかの監視」を半自動化しました。半自動化に際して、アナリストのご意見をお聞きしながら試行錯誤を重ね、最終的に業務用ツールとして認められたので達成感がありました。

その過程で、「技術にこだわった開発」ではなく「需要に応じた開発」ができました。

趣味の開発では、面白そうならとりあえずインストールして動かしていましたが、実務ではリスクを増やさないために許可なく新しいソフトウェアを入れることは禁止されていました。

特に印象的だったのは、「このツールを入れたいんですが、良いですか?」とお聞きしたときの「そのツールを入れると、どんなメリットとリスクがあるの?」という返しです。業務に従事している方からすると当然なのかもしれませんが、こういった発想に至らなかった部分が私の未熟な部分なのだと感じました。

結果として、既に業務用ツールの一部で使用されていたPythonを選定することになったのですが、私はPythonを積極的に使ったことはなかったため、開発の過程でDocstringやclassにおけるgetter、setterの記法といったPythonの独特な表現を知ることができました。

また、下記のように、アナリストの方にツールを見せて意見をお聞きして、改善できたのも良かったです。

ア「初めて使う人にも分かりやすいように手順書があると良いかもね」 私『画像やQ&A付きの手順書制作しました!』

ア「Pythonがインストールできない時はどうするの?」 私『pyinstallerでexe化しました!』 私『ついでにexe化および必要な依存パッケージインストールのためのバッチファイルの用意しました!』

このように、実際に使う人の意見を聞きながら制作する経験ができたのは本インターンの良い副作用でした。

おわりに

業務的に秘匿にするべき部分が多く、なんとも抽象的な記述が多くなってしまいましたが、(おそらく)要点は伝えられたと思います。

インターンは就業型のインターンなので、現職のアナリストの業務のうち対応できそうなものを業務として与えられます。しかし、SOCが扱うシステムは複雑であるため、いくらスキルがあろうとも対応方法を知るために幾ばくかの時間を要します。そのため、全ての業務が与えられる訳ではなく、自分から仕事を探せる人間でないとかなり暇になると思います。

一方で、SOCの実業務を経験して雰囲気を知ることができる良い機会であるとも言えます。冒頭にも書きましたが、SOCのインターンは少なく、それもSOC見学のように短期間で終わるものが多いと考えています。そんな中、SBテクノロジーでは長期に及びインターンを実施してくださるので、その経験を積みたい方にはオススメだと考えています。

以上が、本インターンのエントリになります。 最後になりますが、SOCアナリストとして様々なことを学ぶことができて感謝しています。ありがとうございました。