TECH PLAY

NTTドコモビジネス

NTTドコモビジネス の技術ブログ

602

本記事では Databricks のDatabricks Container Serviceを用いてNVIDIA社の推論ライブラリであるTensorRT-LLMを実行可能なNotebook環境を構築する方法を紹介します。 目次 目次 はじめに Databricks Container Service NVIDIA TensorRT-LLM 解決したいこと TensorRT-LLM Container Imageの作成 Databricks Containers ベースイメージの変更 Pytorch バージョンの変更 TensorRT-LLMのインストール 動作確認 Databricks環境設定 TensorRT-LLMのインポート Llama2 HF-7b-instruct モデルの変換 TensorRT-LLMの呼び出し まとめ 参考文献 はじめに こんにちは、NTTコミュニケーションズの露崎です。 本記事では Databricks のDatabricks Container Serviceを用いてDatabricksのデフォルトRuntimeでサポートされていないNVIDIA社の推論ライブラリ、TensorRT-LLMを実行可能なNotebook環境を構築する方法を紹介します。 Databricks Container Service Databricksはデータウェアハウスとデータレイクの両方の強みを兼ね備えたデータとAIのためのオープンな統合プラットフォーム「データ・インテリジェンス・プラットフォーム」を提供しています。DatabricksではDatabricks Runtimeと呼ばれるプリセットされたSparkの環境が提供されており、通常、ユーザは希望するRuntimeを選択するだけでNotebookの計算環境を構築できます。デフォルトのDatabricks RuntimeにはPythonやRといった実行用の言語環境、及び、機械学習や分析に必要な基本的なライブラリがプリインストールされています。 一方で、プリインストールに含まれていない任意のライブラリについてはNotebookの起動後にaptやpipコマンドを用いて別途インストール必要があります。依存するライブラリが多い場合やインストール中にコンパイルを含むパッケージがある場合、このインストール作業に時間がかかる場合があります。 Databricks Container Service はこうしたライブラリの追加に伴うリソース消費を避け、予め必要な設定を構成した環境を持ち込むための仕組みです。ユーザは事前にビルドしたContainer Imageを任意のレジストリサービス経由でDatabricksの実行環境として利用できます。 NVIDIA TensorRT-LLM TensorRT-LLM はNVIDIA社の提供する大規模言語モデル(以下LLM)向けのライブラリです。 事前に学習されたLLMを最先端のLLM向け最適化を含んだ形でTensorRTエンジンに変換し、GPUを用いた高速な推論を実現します。TensorRT-LLMはTensorRTエンジンを簡単に生成する為のPython APIをユーザーに提供するだけでなく、TensorRTエンジンを実行するPythonおよびC++のランタイム作成の為のコンポーネントやTriton Inference Serverと統合する為のバックエンドも含まれており、GPUベースのLLM推論のデプロイを容易にします。 TensorRT-LLMを利用するためにはSDKとして利用するTensorRT、及び、TensorRT-LLMのパッケージをインストールする必要があります。 解決したいこと TensorRT-LLMは強力なライブラリですがDatabricks Runtimeのデフォルトではサポートされていません。また、2024年4月現在Databricks RuntimeがサポートするCUDAのバージョンは11系であり、12系を利用する最新のTensorRT-LLMを利用できません。 本記事では、DatabricksのNotebook上でTensorRT-LLMを使った推論高速化を実現するためにDatabricks Container Serviceを用いてTensorRT-LLM v0.8.0の実行環境を持ち込む方法を紹介します。 TensorRT-LLM Container Imageの作成 Databricks社は、Databricks Container Serviceで実行可能なコンテナのサンプルをGitHubで 公開 していますので、これをベースにTensorRT-LLMをインストールしたContainer Imageを作成します。 TensorRT-LLMのリポジトリ にもDocker Containerを構築するためのDockerfileが 公開 されていますがベースイメージである nvcr.io/nvidia/pytorch のサイズが大きく、最終的なイメージサイズがDatabricksのContainerをベースにするよりも大きくなってしまうことから今回はDatabricksのContainerイメージをベースにする方法を紹介します。 Databricks Containers 実際の構築の前にベースとなるDatabricks社が公開しているコンテナのサンプルの構成を紹介します。Root directoryにある ubuntu diretoryで公開されているイメージがDatabricks Container Serviceでサポートされており、機能ごとにDockerfileが分かれています。 通常のRuntimeとしては ubuntu/standard が利用可能であり、Scala、Java、Pythonなど、Databricksで通常利用可能な機能がパッケージ化されています。 GPU向けRuntimeのDockerfileは ubuntu/gpu にあり、対応するcudaのバージョン毎にdirectoryが分かれています。各cuda directoryはさらに対応する機能毎に base 、 venv 、 pytorch 、 tensorflow に分かれています。Notebookに必要な最低限の機能は venv で構成されており、これを継承した pytorch 、 tensorflow についてはユーザが予めインストールしておきたいフレームワークに応じて選択できます。 この後解説するTensorRT-LLM向けのイメージについては こちら に動くものがありますが、実際の変更点については以降で解説していきます。 ベースイメージの変更 現在公開されているDatabricksのイメージ はCUDA 11.8のためTensorRT-LLM用に ベースイメージ を変更します。また、TensorRT-LLMでは cudnn-runtime でなく devel を使いますのでベースイメージを nvidia/cuda:12.1.0-devel-ubuntu22.04 とします。 Pytorch バージョンの変更 ベースイメージの変更でCUDAのバージョンを上げたので Pytorch についてもバージョンを上げます。今回、紹介するTensorRT-LLMのバージョン (v0.8.0) では Pytorchのバージョンを2.2.0a以下の 制約 があるため、利用できる範囲の最新バージョンである2.1.2を利用します。またベースイメージで設定したCUDA 12.1向けのPytorchを利用するため、Dockerfile内で torch==2.1.2 torchvision==1.6.2 --index-url https://download.pytorch.org/whl/cu121 のように --index-url にPytorchのリポジトリを設定します。 1 TensorRT-LLMのインストール ここまで設定するとCUDA 12.1、PyTorch 2.1.2に対応したDatabricks Container(便宜的に databricksruntime/gpu-pytorch:cuda12.1 とします)がビルドできます。次にこのContainer Imageに以下のDockerfileでTensorRT-LLMのパッケージを追加します。 FROM databricksruntime/gpu-pytorch:cuda12.1 RUN apt-get update && \ apt-get -y install openmpi-bin libopenmpi-dev && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* # install the tenserrt llm version RUN /databricks/python3/bin/pip install \ tensorrt_llm==0.8.0 --extra-index-url https://pypi.nvidia.com \ && /databricks/python3/bin/pip cache purge これでDatabricks上で実行できるContainerのDockerfileができました。ビルドするとおおよそ以下のサイズのイメージが作成されます。 REPOSITORY TAG IMAGE ID CREATED SIZE databricksruntime/gpu-trt-llm cuda12.1 348ca75258f6 3 hours ago 18.6GB 後はこれを持ち込みたい環境からアクセスできるレジストリ (Docker Hub, Google Container Registry, Azure Container Registry, Amazon Elastic Container Registryなど)にpushしましょう。 動作確認 Databricks環境設定 Databricks Container Serviceのドキュメント に従い、クラスタを起動します。今回は以下の設定で動作確認しています。 Databricks Runtimeバージョン: 15.0 (Apache Spark 3.5.0, Scala 2.12) ノードタイプ: Standard_NC24ads_A100_v4 (Azure) 高度なオプション Spark構成 spark.master local[*, 4] spark.databricks.cluster.profile singleNode spark.databricks.unityCatalog.volumes.enabled true Docker イメージURL: PrivateのAzure Container Registry 認証:ユーザ名とパスワード ユーザ名、パスワード:(省略) TensorRT-LLMのインポート 以下のセルを実行しTensorRT-LLM 0.8.0が正しく組み込めていることが確認できました。 Llama2 HF-7b-instruct モデルの変換 公式のdocs を参考に huggingface で提供されているMeta社の Llama2 を変換します。checkpointのconvert及び、エンジン化の変換手順は 公式のdocs に記載があるのでここでは省略します。 手順によって生成された config.json と rank0.engine (GPUの枚数や環境次第でengineファイルの名前は変更されます)を次のTensorRT-LLMの呼び出しで利用します。 TensorRT-LLMの呼び出し 以下は、TensorRT-LLMで生成したエンジンを呼び出して推論するためのサンプルです。 環境変数である BASE_DIR には変換したエンジンが保存されているディレクトリを設定します。Databricksの環境の場合、通常の ワークスペースファイルには200MBの制限(Azureの場合) がありますのでLLMを扱う場合にはUnity Catalog上のボリュームを利用するのが良いでしょう。 from pathlib import Path import os import torch from transformers import LlamaTokenizer import tensorrt_llm from tensorrt_llm.runtime import ModelRunner EOS_TOKEN = 2 PAD_TOKEN = 2 def generate (input_text): tensorrt_llm.logger.set_level( "info" ) tokenizer_dir = "meta-llama/Llama-2-7b-chat-hf" engine_dir = Path(os.environ[ 'BASE_DIR' ]) runtime_rank = tensorrt_llm.mpi_rank() torch.cuda.set_device( 0 ) tokenizer = LlamaTokenizer.from_pretrained(tokenizer_dir, legacy= False ) runner = ModelRunner.from_dir(engine_dir=engine_dir, rank=runtime_rank) input_tokens = [tokenizer.encode(input_text, add_special_tokens= False )] input_ids = torch.nested.to_padded_tensor( torch.nested.nested_tensor(input_tokens, dtype=torch.int32), EOS_TOKEN).cuda() output_gen_ids = runner.generate( input_ids, pad_id=PAD_TOKEN, end_id=EOS_TOKEN, max_new_tokens= 100 , streaming= False ) torch.cuda.synchronize() output_text = tokenizer.decode(output_gen_ids[ 0 ][ 0 ]) return output_text text = generate( "hello, could you tell a story for the galaxy?" ) print (text) このコードを実行すると以下のような出力が得られます。この出力から「銀河の物語について語ってほしい」という英語のプロンプトに対して、LLMの回答結果を得られていることがわかります。これによりTensorRT-LLMで変換されたエンジンを用いて推論できていることが確認できました。 まとめ 本記事ではDatabricks Container Serviceの機能を利用してNVIDIA社の推論ライブラリであるTensorRT-LLMをDatabricks Notebookで利用する方法を紹介しました。こうした仕組みを使うことでモデルの開発や検証を効率よく行うことができると思います。 参考文献 https://www.databricks.com/ https://github.com/NVIDIA/TensorRT-LLM https://github.com/databricks/containers https://catalog.ngc.nvidia.com/containers https://pytorch.org/get-started/previous-versions/ ↩
アバター
はじめに こんにちは、イノベーションセンターの鍔木(GitHub: takuma0121 )です。 OT/ICSセキュリティリスク可視化サービス、 OsecT の開発・運用を担当しています。 2024年3月4日から7日までの間、米国マイアミで開催されたS4x24に聴講参加しました。 このカンファレンスは日本では知名度が高いとは言えませんので、S4の全容とOT/ICSセキュリティのトレンドについてお伝えできればと思います。 目次 はじめに 目次 S4とは プレゼンテーション Vulnerability Management Pavilion Welcome Party / Cabana Sessions Swag Bag 最新のOT/ICSセキュリティトレンド Keynote CFP経由での発表 スポンサーセッション ネットワーキング 会場の雰囲気 エピソード 所感 イベント全体 最新動向/発表 さいごに S4とは S4 (SCADA Security Scientific Symposium)は、 2008年から開催 されるOT/ICSセキュリティに特化したカンファレンスです。 発表だけでなく、パートナー企業探しやネットワーキングも重視されたイベントです。 S4x24には公式発表によれば、約1000人の参加者がいました。 日本からはNTTコミュニケーションズを含めて数社参加していました。 プレゼンテーション 4日間にわたり、Keynote・CFP経由での発表・スポンサーセッションが行われます。 Keynoteの時間帯だけは1つのセッションだけで、それ以外の時間帯は3パラでのセッション形式でした。 Vulnerability Management Pavilion 一部のスポンサーは、会期中デモ展示を行います。 各企業はパートナーやエンドユーザーを探すことを明確な目的としており、デモ展示を見たい旨を伝えると、デモを見る目的を聞かれることがありました。 また、NTTグループをパートナー候補と見なす企業もあり、すぐに商談に進む兆しもありました。 Welcome Party / Cabana Sessions ネットワーキングを目的としたセッションも準備されています。 特にCabana Sessionsでは、スポンサーブースも併設されており、カンファレンス最大のネットワーキングパーティとなっています。 今年の会場の様子がすでに YouTube にアップロードされています。 Swag Bag 2022年から”Swag Bag”と呼ばれる参加記念品が配布されるようになりました 。ちなみに、この帽子にはCabana Sessionsの際に無料で刺繍を入れてくれるサービスもありました。 最新のOT/ICSセキュリティトレンド 発表は主に、Keynote・CFP経由での発表・スポンサーセッション(S4 Prime Sponsors)の3種類に分類されます。 S4x24のAgendaは こちら から参照できます。 それぞれについて抜粋して紹介します。 Keynote 最初のセッション「Believe」では主催者であるDale PetersonがOT/ICSセキュリティの未来について発表していました。 OT/ICSセキュリティと言えば「脅威検知」が挙げられます。 しかし、そもそも検知より前のタイミングで対処したほうが低コストで済むという話が出ていました。 また、調査機関のデータからOT/ICSセキュリティの重要性の高まりなどの話が出ていました。 また別のKeynote「Fireside Chat With Robert M. Lee」では、Robert M. Lee(Dragos CEO)とDaleとの対談が行われ、マルウェア:PIPEDREAMを題材にエネルギー産業への攻撃が増えていることや、脅威検知の必要性やコストについての議論がありました。 CFP経由での発表 AI・自動化、従来はOT/ICSセキュリティでは利用されなかったフレームワークの適用、実用的な運用方法の提案、事例紹介が多かった印象を受けました。 「AI In Production, Today!」では、AIによってできること(リスクアセスメント・ネットワーク図分析・脆弱性アセスメント・IR (Incident Response)準備)、それらを実現するための具体的な手順とOSSがわかりやすく説明されていました。 今回の発表の中では、最も実用的な内容で、すぐにでも試すことができると思います。 「Applying FAIR To OT」では、FAIR (Factor Analysis of Information Risk)をOTに適用し、リスクを定量評価する取り組みが紹介されました。 脅威→攻撃手法→資産→影響の順に事象を洗い出して定量化(= 影響による損失額等)して、モンテカルロシミュレーションによって損失額等の平均や中央値を算出していました。 セキュリティ対策に投資すべき金額がわかるようになる点がよいと感じました。 「The Attack Against Danish Critical Infrastructure」では、デンマークのエネルギー業界を攻撃された事例の紹介がされており、2023/04/25~05/12の間で、準備から攻撃されるまでの状況を事細かに発表していました。 スポンサーセッション 「Dragos: Hacktivist Threat Briefing」では、イランのハクティビストグループ(反イスラエルグループ)が UNITRONICS製デバイス を攻撃(米国およびヨーロッパ)したことを踏まえて、どのように攻撃の影響を軽減するのかについて紹介していました。 攻撃事例を踏まえて、その対策と対策を実現するための体制・サービスを提供している、というスポンサーセッションらしい発表だと感じました。 ネットワーキング 会場の雰囲気 Welcome PartyやCabana Sessionsでは、主催者であるDale Petersonを始め、参加者が積極的にネットワーキングを行っていました。 話したい相手を事前に決めてアプローチしても気軽に応じてくれ、会話が自然に始まるフレンドリーな雰囲気がありました。 エピソード 私はDaleとスポンサー企業の選定方法や、S4を再び日本で開催できないか等についてコミュニケーションを取りました。 日本からの参加者だけでなく、発表者やその他の参加者ともOTセキュリティの重要性について議論、開発・運用しているOsecTに対するフィードバックをもらうことができました。 また多くの参加者と連絡先の交換ができ、今後もOTセキュリティについての議論や情報交換ができるようになり、ネットワーキングの観点でも有意義でした(一人での参加でしたが、連日参加者と昼食・夕食をともにできました)。 所感 今回初めてS4x24に参加してみて、イベント全体と最新動向、発表について感じたことをまとめます。 イベント全体 4日間の開催で発表は実質2日弱くらいで、発表だけでなくネットワーキングも同様に重要な存在だと感じました。 1人で全ての発表を聴講するのは量的に難しく、また参加費を考えると現地でしかできないネットワーキング等も目的に加えると良いと思われます。 最新動向/発表 発表内容はAIによるセキュリティスキャン・自動運用、新しいフレームワークの適用、EoL対応するための実用的な運用方法、定量的なリスク評価、事例紹介など多様な観点から総合的にバランスを取った形となっていました。 さいごに 今回はS4x24の概要、OT/ICSセキュリティのトレンド、ネットワーキング、そしてこれらを踏まえた所感についてまとめました。 次回の S4x25 (2025年2月10日から13日)は、マイアミビーチではなくタンパで開催予定です。 より大きな会場で開催されるとのことで、今後もOT/ICSセキュリティから目が離せません。 日本ではまだOT/ICSセキュリティの注目度が高まっていませんが、NTTコミュニケーションズでは今後OT/ICSセキュリティを盛り上げて、日本でOT/ICSセキュリティを牽引していきます。 OT/ICSセキュリティ可視化サービス OsecTもよろしくお願いします。
アバター
マネージド&セキュリティサービス部サービスプラットフォーム部門の田中です。 2023年度の下期にダブルワークという社内施策で、イノベーションセンター生成AIチームに参加しました。 その取り組みとして、本ブログの記事データを管理している GitHub リポジトリに LLM (大規模言語モデル) の1つである GPT-4 を用いた校正CIを導入してみました。 適切なプロンプトを得るための試行錯誤や、この記事自体を校正させてみた結果をお伝えします。 目次 目次 背景 LLM校正CIの詳細 プロンプトの試行錯誤 この記事の校正結果 おわりに 背景 本ブログ記事のデータ管理やレビューには GitHub を利用しています。 投稿者は記事を執筆した後 PR (Pull Request) を出し、レビュアーが PRコメントで記事の修正を提案し、推敲していきます (なお、GitHubを活用した記事公開プロセスについては、別記事「 開発者ブログをリニューアルしたついでにレビューと記事公開プロセスをいい感じにしたお話 」で紹介していますので、ご興味がありましたらご覧ください) 。 レビュー観点の1つに、日本語の文章表現に誤りがないかといった校正的な観点があります。 この観点では、以前より textlint を用いた文章校正CIが GitHub Actions に実装されており、文末の句点有無などを機械的にチェックしています。 ただ、誤字脱字など textlint だけでは検出できない誤りも一定数あり、今回は LLM を用いることでより抜けのない校正ができるのではと考え、CIに組み込んでみることにしました。 LLM校正CIの詳細 校正CIに使う LLM は、記事全文を1度に入力できる Azure OpenAI の GPT-4 32k を利用することにしました。 システムプロンプトは以下を与え、マークダウン形式の記事全文を入力として与えます。 あなたは日本語文章を校正するアシスタントです。 与えられたマークダウン形式の文章で、誤字や文法誤りのある行を抜き出し、修正した行を出力してください。 その際、確実に修正すべき誤りのみを出力してください。 出力は、5個以下とし、より優先的に修正すべきものを出力してください。 また、以下のようなJSON形式で出力してください。 [ {"error_line": "...", "revised_line": "..."} ] PRを契機に、編集のあった記事に対して校正CIが動き、以下のようにPRコメントの形で校正提案を表示するようにしました。 PRコメントの表示には、 reviewdog を利用しています。 プロンプトの試行錯誤 上述のプロンプトは、複数のプロンプトを試行錯誤した結果得られたものです。 過去記事数件を入力とした結果を比較して、どれにするかを決めていきました。 レビュアーを担当される方の意見に、「指摘数が多くなると確認が大変になるかもしれない」というものがあったため、Recall よりも Precision *1 を重視する方針をとりました。 ここでは、試したものをいくつかご紹介します。 はじめは以下のようなプロンプトを与えてみました。 あなたは日本語文章を校正するアシスタントです。 与えられたマークダウン形式の文章で、誤字や文法誤りのある行を抜き出し、修正した行を出力してください。 その際、確実に修正すべき誤りのみを出力してください。 また、以下のようなJSON形式で出力してください。 [ {"error_line": "...", "revised_line": "..."} ] すると、以下のような非常に多くの出力が返ってきました。 抜けた「を」を追加している1つめなどの良い修正提案もありますが、特に必要性を感じない修正提案や修正できていない出力 ( error_line と revised_line が同じもの) などが含まれており、ノイジーな印象です。 (文字が小さく申し訳ありません、読みづらい場合は拡大してご覧ください。なお、見やすさのために改行を追加したり差分文字に色をつけています) そのため以下の1文を加えて、出力数を制限してみました (これが前章記載の最終的にCIに組み込んだプロンプトです) 。 出力は、5個以下とし、より優先的に修正すべきものを出力してください。 結果は次のようになりました。 指定した通りに出力数は5個までに減りました。 しかし、別に修正しなくてもよさそうな提案が依然残っています。 では、やってほしい文法誤りの修正例や誤字の修正例を与えればうまくいくのではと思い、別記事をもとにデータを用意して One-shot Prompting *2 を試してみました。 結果は以下となりました。 Zero-shot とは異なる有効な修正提案が見られる一方で、修正できていない出力が増えてしまっており、トータルではあまり改善がみられないといった印象です。 他記事でも出力を確認したのですが、同様の印象でした。 また、One-shot の分だけ入力が大きくなり LLM の出力にかかる時間が大幅に増えたため、Zero-shot でよさそうです。 また、もしかすると修正の分類も同時にさせることで精度が高まるかもしれないと考え、以下のプロンプトも試してみました。 あなたは日本語文章を校正するアシスタントです。 与えられたマークダウン形式の文章で、以下の誤りのある行を抜き出し、修正した行と誤りの分類を出力してください。 * 誤字 * 漢字変換誤り * 文法誤り * 表記誤り その際、確実に修正すべき誤りのみを出力してください。 出力は、5個以下とし、より優先的に修正すべきものを出力してください。 また、以下のようなJSON形式で出力してください。 [ {"error_line": "...", "revised_line": "...", "error_type": "..."} ] 結果は以下となりました。 どうやら誤りの分類もうまくできていないようです。 また、同様 One-shot も試してみましたが、特にあまり変化は見られませんでした。 他にもプロンプトを英文にするなど試してみましたが、大きな変化は見られませんでした。 そのため、比較的シンプルなプロンプト (前章のプロンプト) を CI で使うことにしました。 この記事の校正結果 校正CIを導入後にこの記事を書いているので、もちろんこの記事にもCIは実行されます。 ここでは、その結果をお見せしたいと思います。 うまくいくといいなと思いながら、今回はわざとすこし誤字を放置して PR を出すと以下のコメントが1つ付きました! 有効な修正提案です! 一方で、実は他に以下の誤字が記事に含まれていたのですが、これらは検出されませんでした。 しかし、別に修正しなくてもよさそうな提案が以前残っています。 また、もしかしると修正の分類も同時にさせることで精度が高まるかもしれないと考え、以下のプロンプトも試してみました。 修正提案は Recall よりも Precision 重視の方針をとっているものの、正直なところ、これらも検出してほしかったなあと思います。 おわりに 本記事ではLLMを用いた校正CIについてお伝えしました。 プロンプトの試行錯誤や、この記事での校正結果をご紹介しました。 校正という1つのタスクに対してさまざまなプロンプトを試してみることは、個人的に初めてのことだったため良い経験になりました。 また、GPT-4 クラスのモデルでも、一見簡単そうに思える日本語長文の文章校正でもまだ完璧でないということを知りました。 今回は環境面の点から、Azure OpenAI の GPT-4 32k を利用しましたが、現在続々と誕生している日本語メインで学習した LLM を用いるとどのような結果が得られるのかが気になります。 機会があれば、これらも今後試していけたらと思います。 校正CIは導入してまだ間もないため、一定期間 CI を試してみて、実際に利用した方の意見を収集し、改善や利用継続を判断する予定です。 *1 : Recall は修正すべきもののうち修正提案できている割合 (どれだけもれなく修正提案できているか) 。Precision は修正提案のうち正しいものの割合 (どれだけ修正提案が正しいか) 。両者はトレードオフの関係にある。 *2 : タスクを指示するプロンプトとともに、お手本となる例を1つ入力に与えること。これに対して、タスク指示のみを与える場合は Zero-shot Prompting という。
アバター
はじめに はじめまして、今回ドコモグループの現場受け入れ型インターンシップに参加させていただいた上野です。大学院ではコンテナセキュリティなどについて研究しています。 この記事では、インターンシップ体験記として以下の内容を紹介します。 私のインターンシップの参加経緯や取り組み NTTコミュニケーションズの業務やインターンシップについて知りたい就活生向け Process InjectionとPool Partyの概要 Pool Partyについて日本語で概要を知りたいセキュリティエンジニア向け 目次 はじめに 目次 RedTeam プロジェクト(RedTeam PJ) インターンシップ参加の経緯 インターンシップ概要 T1055 - Process Injection Pool Party Thread Pool Pool Party Variants Variant 1: Worker Factory Start Routine Overwrite おわりに 参考文献 RedTeam プロジェクト(RedTeam PJ) 私が配属されたポストは、NTTコミュニケーションズ イノベーションセンターのRedTeam PJです。RedTeam PJ は攻撃者の目線からセキュリティについて研究開発をしているチームで、ドコモグループやNTTグループに対するRedTeamの案件支援や攻撃手法の研究開発を行なっています。 RedTeam PJの活動については以下の記事や資料でも紹介しています。 MITRE ATT&CK Contribution - T1562.009 Safe Mode Boot インターンシップ生があるSaaSを用いた未知のC2脅威を実証してみた The Dark Playground of CICD: Attack Delivery by GitHub Actions インターンシップ参加の経緯 私はサイバーセキュリティに興味があり、これまでにセキュリティ関連のインターンシップへの参加や、セキュリティに関わる研究を行なってきました。その過程で、攻撃者目線でセキュリティを考えるオフェンシブセキュリティに魅力を感じ、将来はRedTeam関連の職業に就きたいと考えるようになりました。そのような中で、RedTeamの業務体験ができるこのインターンシップを発見し、応募することにしました。 私が今回応募したポストであれば、オフェンシブセキュリティの研究に近い業務も行えそうだなと思ったこともきっかけの1つです。脆弱性診断をするセキュリティ業務のインターンシップなどは多く存在しますが、新しい攻撃手法の開発や攻撃の根本的な原理の調査などを行うものは少ないと感じています。 インターンシップ概要 今回のインターンシップでは、BlackHat Europe2023で発表された Pool Party 1 という攻撃手法の検証業務 を担当しました。最終的にはこの攻撃手法を、NTTコミュニケーションズのRedTeamが内製している独自ツールに組み込むことが検証の目的です。残念ながら今回のインターンシップではツールの組み込みまではできず、PoolPartyの調査結果をRedTeam PJメンバーに共有するところまで体験しました。 インターンシップとしては2024年2月5日〜16日のスケジュールでしたが、オリエンテーションや土日祝日、最終日の成果報告会を除くと、実質的には 7日間 の日程でした。この7日間は以下の3つのテーマをそれぞれ2〜3日ずつ使いながら順番に業務を進めました。 基礎となる攻撃技術の習熟 C2 2 やProcess Injcetion、検証環境や各種ツール(攻撃、開発、解析)に関する座学 CreateRemoteThread InjectionによりC2感染させるPoC検体の開発と動的解析 Process Injection手法の調査・検証 APC 3 を悪用する2つの攻撃テクニックの理解と比較、およびPoC検体の開発と動的解析 APC Queue Code Injection 4 Early Bird Injection 5 Pool Partyの調査・検証 発表者のブログ 6 を読み解きPool Partyの原理を理解 (少しだけ)GitHub 7 で公開されているPool PartyのPoCコードの動作検証とコードリーディング 本記事では、インターンシップで私が調査をしたProcess InjectionとPool Partyの概要について紹介します。 T1055 - Process Injection Process Injection 8 とは、任意のコードを別プロセスのアドレス空間で実行する方法です。攻撃者は、セキュリティ製品の検知回避や権限昇格を目的として、悪意のあるプロセスから正規のプロセスに対してProcess Injectionを行うことがあります。 基本的にProcess Injectionは次の4つのステップから成り立ちます。 Step 1 : プロセスハンドルの取得 Step 2 : メモリの割り当て Step 3 : メモリへの書き込み Step 4 : スレッドの実行 Process Injection(参考文献1から引用) EDRのようなプロセスの振る舞いを監視するセキュリティ製品は、同一プロセス上で実行される「メモリ割り当て/メモリへの書き込み/スレッド実行」の相関を監視しProcess Injectionを検知します。そのため、上記のステップを単純に実行するだけでは、攻撃が検知されます。これに対してセキュリティ研究者や攻撃者は、検知されずに攻撃可能なさまざまなProcess Injectionのテクニックを開発しています。今回のインターンシップで検証をしたPool PartyやAPC Queue Code Injection, Early Bird Injectionもそれぞれそのテクニックの1つです。 Pool Party Pool Partyは2023年12月に発表されたProcess Injectionの手法で、WindowsのThread Poolという仕組みを悪用する手法です。Pool Partyは「メモリの割り当て」と「メモリへの書き込み」のみでProcess Injectionを実現します。「スレッドの実行」を攻撃者が行わずに、Windowsの一般的な並列処理の仕組みによってスレッド実行を引き起こすことで検知回避をしています。 Thread Pool Thread Pool 9 とは、プロセスを非同期処理や並列処理を効率的に実行するためのWindowsの機構です。Worker Threadというタスクの実行単位の集まり、およびそれらを管理して並列に処理する仕組みをThread Poolと呼びます。発表者によると、デフォルトでWindowsプロセスはThread Poolを持つため、PoolPartyはすべてのプロセスに対して適用可能であるとのことです。 Thread Pool(参考文献1から引用) また、Thread PoolにはWorker Factoryと呼ばれるWorker Threadを管理するオブジェクトが存在します。Worker Factoryは、Thread PoolのWorker Threadを監視し、監視結果に基づいてWorker Threadを作成・削除します。 Worker Factory(参考文献1から引用) Pool Party Variants Pool PartyにはVariantと呼ばれる8つの手法が存在し、これらのVariantsを総称してPool Partyという名前が付けられています。 Work Factory Start Routine Overwrite TP_WORK Insertion TP_WAIT Insertion TP_IO Insertion TP_ALPC Insertion TP_JOB Insertion TP_DIRECT Insertion TP_TIMER Insertion Variant 1はThread PoolにおけるWorker Factory、Variant 2~8はThread Poolにおける3つのキュー(Task Queue, Timer Queue, I/O CompletionQueue)およびキューに挿入されるワークアイテムを使用する攻撃です。本記事ではVariant 1に限定して紹介をします。 Variant 1: Worker Factory Start Routine Overwrite Variant 1はWorker Factoryを悪用する手法です。StartRoutineと呼ばれるWorker Threadのエントリーポイントをシェルコードに書き換えることによって、Worker Threadが作成されるタイミングなどで任意のコードを実行させることができます。 以下に攻撃の流れを記載します。 ターゲットプロセスのプロセスハンドルを取得する NtQueryInformationProcess を使用して、ターゲットプロセス内のオブジェクトハンドルを取得する ターゲットプロセス内のオブジェクトハンドルからWorker Factoryのハンドルを探索する DupilicateHandle を使用して、Worker Factoryのハンドルを複製する NtQueryInformationWorkerFactory を使用して、Worker Factoryの情報を取得する Worker Factoryの情報からStartRoutineのアドレスを取得する WriteProcessMemory を使用して、StartRoutineをシェルコードで上書きする NtSetInformationWorkerFactory を使用して、任意のタイミングで攻撃をトリガーさせることも可能です。WorkerFactoryThreadMinimum(最小限実行されるべきThreadの数)を「現在動いているThreadの数+1」に変更すると新たなWorker Threadが作成され、StartRoutineの実行、つまりシェルコードが実行されます。 Worker Factory Start Routine Overwrite(参考文献1から引用) おわりに 私は普段ほとんどUbuntuしか使わず、Windowsの操作もままならない状態からのスタートでした。トレーナーの久保さんに丁寧に検証ツールの使い方などを教えてもらいながら、一歩一歩Process Injection について理解していき、最終的にはチーム内でPool Partyについて発表するというところまで達成できました。知識ゼロの状態からのスタートだったので、インテンシブで大変ではあったのですが、その分成長も感じられた2週間でした。 このようなインターンシップの機会を作っていただいたRedTeam PJの皆さま、ありがとうございました。特にトレーナーの久保さんには NeWork やSlack等で親身になってサポートしていただき、とてもお世話になりました。 参考文献 https://www.safebreach.com/blog/process-injection-using-windows-thread-pools/ BlackHat Europe 2023 - The Pool Party You Will Never Forget: New Process Injection Techniques Using Windows Thread Pools ↩ C2: Command and Controlの略、C&Cと略すことも多い。 ↩ 非同期プロシージャ呼び出し(APC) ↩ APC Queue Code Injection ↩ Early Bird APC Queue Code Injection ↩ SafeBreach - The Pool Party You Will Never Forget: New Process Injection Techniques Using Windows Thread Pools ↩ GitHub - SafeBreach-Labs/PoolParty ↩ MITRE ATT&CK - Process Injection ↩ スレッドプール ↩
アバター
こんにちは、インターン生の 横尾 です。 2024年2月に2週間実施されたNTTコミュニケーションズの現場受け入れ型インターンシップに参加させていただきました。普段は、大学院でユーザサイトにおけるIPv6マルチホーミングなどの研究に取り組んでいます。 今回のインターンシップでは、「次世代キャリアネットワークの開発エンジニア」というテーマで、OSSのソフトウェアルータであるFRRouting(以降、FRR)に、SRv6とMPLS/SR-MPLSの相互接続を実現するための機能を実装しました。この記事では、このテーマで取り組んだ内容について具体的に紹介します。 目次 目次 インターンシップに参加した経緯 インターンシップで取り組んだこと L3VPN Inter-AS Option-B w/MPLS の動作確認 SRv6とMPLS/SR-MPLSの相互接続を実現するために必要な機能の確認 実装 動作検証 感想 トレーナーからのコメント インターンシップに参加した経緯 私は以前からSegment Routing(SR)という技術に興味を持っていましたが、Linuxでデータプレーンを少し触った程度で、次のステップにハードルを感じていました。 私が今回インターンシップで参加させていただいたチームでは、Segment Routingに関する取り組みを外部カンファレンス等で発表しており、しばしば目にする機会があったため、より詳細な業務内容を知りたいと思いました。 そして、過去にこのインターンシップへ参加された方々の 参加Blog を拝見し、「ネットワーク × ソフトウェア開発」という内容に興味を惹かれ応募を決めました。 このインターンシップを通して、Segment Routingやネットワークに関するソフトウェア開発の知見を得たいと思いました。 インターンシップで取り組んだこと 今回のインターンシップでは、SRv6とMPLS/SR-MPLSの相互接続について説明されている SRv6 and MPLS interworking(draft-agrawal-spring-srv6-mpls-interworking-14) を参考に、FRRへのSRv6とMPLS/SR-MPLSの相互接続機能の実装に取り組みました。 現在、NTT コミュニケーションズでは、ドコモグループの持つSR-MPLSネットワークにおいて、新たな付加価値の提供や運用の効率化を目指し、サービスファンクションチェイニングの利用やモバイルネットワークでの活用が期待されているSRv6ネットワークとの相互接続検証が実施されています。 今後の相互接続検証にあたって、独自の機能拡張が可能かつSRv6/SR-MPLSの相互接続機能を提供するルータが必要になってきます。 そこで今回のインターンシップでは、OSSソフトウェアルータであるFRRにSRv6とSR-MPLSの相互接続機能を実装することを目標としています。 インターンシップの目標達成に向けて、まずは複数のSR-MPLSネットワークを接続するMulti-AS Segment Routingの仕組みと挙動の理解を進めました。 その後、SR-MPLSネットワークとSRv6ネットワークの相互接続に置き換えて、現行実装での挙動と本来期待する挙動の差分を整理し、拡張が可能なソフトウェアルータであるFRRに目的の機能を実装しました。 以下では、私が今回のインターンシップにおいて実施した業務内容を具体的に紹介します。 L3VPN Inter-AS Option-B w/MPLS の動作確認 まずはじめに、現在NTTコミュニケーションズのTestbedにて運用されているMulti-AS SR-MPLSネットワーク(L3VPN Inter-AS Option-B w/MPLS)について理解を深めます。 そもそも、なぜSingle-ASではなくMulti-ASなのかや、なぜInter-ASの接続方式がOption-Bなのかといった技術選定の背景については以下の外部向け発表資料や連載記事をご参照ください。 マルチASかつマルチベンダにおけるSR-MPLS TEの実現 マルチAS/マルチドメインなSegment Routingの実現 [Multi-AS Segment Routing 検証連載 #0] Multi-AS Segment Routing で VPN を構築する記事を連載します 以下のような開発環境でFRRを設定しながら、経路情報の広告とパケットの流れについて確認します。 この環境は、2つのルータで構成されるAS同士を接続したコア網で、顧客1(Customer-1)を収容しています。各ルータにはFRRをインストールし、AS内はIS-IS、AS間はBGPを用いて経路情報を交換します。VPNのパラメータは以下の通りです。 SR Domain 1 AS 番号: 65001 VRF 100: RD/RT: 65001:100 AS間でのVPNv4経路の広告用RT: 64999:100 SR Domain 2 AS 番号: 65002 VRF 100: RD/RT: 65002:100 AS間でのVPNv4経路の広告用RT: 64999:100 はじめに、PE-MPLS-1が受け取った経路情報を確認します。192.168.2.0/24の経路が受信できています。ここでは省略しますが、PE-MPLS-2では192.168.1.0/24の経路の受信を確認できます。 PE-MPLS-1# show bgp ipv4 vpn neighbors 10.255.1.2 received-routes detail BGP table version is 1, local router ID is 10.255.1.1, vrf id 0 Default local pref 100, local AS 65001 Route Distinguisher: 65002:100 BGP routing table entry for 192.168.2.0/24, version 1 not allocated Paths: (1 available, best #1) Not advertised to any peer 65002 10.255.1.2 (metric 20) from 10.255.1.2 (10.255.1.2) Origin incomplete, localpref 100, valid, internal, best (First path received) Extended Community: RT:64999:100 Remote label: 81 Last update: Sun Mar 24 17:20:14 2024 Total number of prefixes 1 host1からhost2に対してpingによる疎通確認を行います。疎通確認によって、L3VPNが構築できていることが確認できます。 root@host1:/# ping 192.168.2.254 -c 3 PING 192.168.2.254 (192.168.2.254) 56(84) bytes of data. 64 bytes from 192.168.2.254: icmp_seq=1 ttl=60 time=0.428 ms 64 bytes from 192.168.2.254: icmp_seq=2 ttl=60 time=0.071 ms 64 bytes from 192.168.2.254: icmp_seq=3 ttl=60 time=0.073 ms --- 192.168.2.254 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2052ms rtt min/avg/max/mdev = 0.071/0.190/0.428/0.167 ms このとき、ASBR間のパケットをキャプチャしてみると、MPLS ラベルを用いてパケットが転送されていることが確認できます。 root@ASBR-MPLS-1:~# sudo tcpdump -nni net1 sudo: unable to resolve host ASBR-MPLS-1: Temporary failure in name resolution tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on net1, link-type EN10MB (Ethernet), capture size 262144 bytes 17:24:21.208266 MPLS (label 81, exp 0, [S], ttl 62) IP 192.168.1.254 > 192.168.2.254: ICMP echo request, id 6, seq 1, length 64 17:24:21.208555 MPLS (label 80, exp 0, [S], ttl 62) IP 192.168.2.254 > 192.168.1.254: ICMP echo reply, id 6, seq 1, length 64 17:24:22.236020 MPLS (label 81, exp 0, [S], ttl 62) IP 192.168.1.254 > 192.168.2.254: ICMP echo request, id 6, seq 2, length 64 17:24:22.236079 MPLS (label 80, exp 0, [S], ttl 62) IP 192.168.2.254 > 192.168.1.254: ICMP echo reply, id 6, seq 2, length 64 17:24:23.260009 MPLS (label 81, exp 0, [S], ttl 62) IP 192.168.1.254 > 192.168.2.254: ICMP echo request, id 6, seq 3, length 64 17:24:23.260064 MPLS (label 80, exp 0, [S], ttl 62) IP 192.168.2.254 > 192.168.1.254: ICMP echo reply, id 6, seq 3, length 64 ^C 6 packets captured 6 packets received by filter 0 packets dropped by kernel 以上を踏まえて、経路情報の広告とパケットの流れについて以下の図にまとめます。 SRv6とMPLS/SR-MPLSの相互接続を実現するために必要な機能の確認 続いて、先ほどの開発環境のうちAS65002をSRv6網に変更し、現状を確認します。 先ほどと同様に、PE-MPLSが受け取った経路情報を確認します。192.168.2.0/24の経路は受け取れているようですが、SRv6で転送する経路だと判断し、SRv6拡張ヘッダでカプセル化するようにカーネルへ設定されてしまっています。PE-MPLSはSR-MPLS網のルータであるため、MPLSヘッダでのカプセル化が期待されます。 PE-MPLS# show bgp ipv4 vpn neighbors 10.255.1.2 received-routes detail BGP table version is 1, local router ID is 10.255.1.1, vrf id 0 Default local pref 100, local AS 65001 Route Distinguisher: 65002:100 BGP routing table entry for 192.168.2.0/24, version 1 not allocated Paths: (1 available, best #1) Not advertised to any peer 65002 10.255.1.2 (metric 20) from 10.255.1.2 (10.255.1.2) Origin incomplete, localpref 100, valid, internal, best (First path received) Extended Community: RT:64999:100 Remote label: 16 Remote SID: fd00:0:0:44:: Last update: Sun Mar 24 19:55:00 2024 Total number of prefixes 1 PE-MPLS# root@PE-MPLS:~# ip route show vrf USER-1 192.168.1.0/24 dev net1 proto kernel scope link src 192.168.1.1 192.168.2.0/24 nhid 12 encap seg6 mode encap segs 1 [ fd00:0:0:44:1:: ] via 10.1.2.2 dev net0 proto bgp metric 20 なぜこのようなことが起きているのかを確かめるため、ASBR-MPLSからPE-MPLSへ送信されるMP-BGPのUPDATEメッセージのパケットをキャプチャしてみると、「Path Attribute - BGP Prefix-SID」が含まれていることがわかります。このAttributeが含まれているため、PE-MPLSはこの経路情報をSRv6で転送する経路だと判断してしまったと考えられます。 続いて、PE-SRv6が受け取った経路情報を確認します。192.168.1.0/24の経路は受け取れているようですが、MPLSで転送する経路だと判断し、MPLSヘッダでカプセル化するようにカーネルへ設定されてしまっています。PE-SRv6はSRv6網のルータであるため、SRv6拡張ヘッダでのカプセル化が期待されます。 PE-SRv6# show bgp ipv4 vpn neighbors fd00::3 received-routes detail BGP table version is 1, local router ID is 10.255.1.4, vrf id 0 Default local pref 100, local AS 65002 Route Distinguisher: 65001:100 BGP routing table entry for 192.168.1.0/24, version 1 not allocated Paths: (1 available, best #1) Not advertised to any peer 65001 0.0.0.0 (metric 20) from fd00::3 (10.255.1.3) Origin incomplete, localpref 100, valid, internal, best (First path received) Extended Community: RT:64999:100 Remote label: 80 Last update: Sun Mar 24 19:25:54 2024 Total number of prefixes 1 PE-SRv6# root@PE-SRv6:~# ip route show vrf USER-1 192.168.1.0/24 nhid 17 encap mpls 80 via inet6 fe80::4819:ccff:fe22:992d dev net0 proto bgp metric 20 192.168.2.0/24 dev net1 proto kernel scope link src 192.168.2.1 以上のことから、この環境では大きく2つの問題点が挙げられます。 問題1: SR-MPLS網にも関わらず、SRv6拡張ヘッダでencapしようとしている(192.168.2.0/24 の経路) 問題2: SRv6網にも関わらず、MPLSヘッダでencapしようとしている(192.168.1.0/24 の経路) 次に、ASBR間のeBGPピアを一度 no activate し、上記の2つの問題が生じない環境下で、データプレーンへ直接経路情報を挿入して最終的な理想の形を確認します。データプレーンへの経路情報の挿入には、iproute2を用いて行います。先ほどと同じように経路情報の広告とパケットの流れについて、iproute2で挿入する経路情報と一緒に以下の図にまとめます。 iproute2を用いてデータプレーンへ経路情報を直接挿入した後、host1からhost2に対してpingによる疎通確認を行います。疎通確認によって、SRv6とMPLS/SR-MPLSの相互接続をした上でL3VPNが構築できていることが確認できました。これで、最終的にデータプレーンにどのような設定が挿入されれば良いのか、イメージを掴むことができました。 root@host1:/# ping 192.168.2.254 -c 3 PING 192.168.2.254 (192.168.2.254) 56(84) bytes of data. 64 bytes from 192.168.2.254: icmp_seq=1 ttl=61 time=0.201 ms 64 bytes from 192.168.2.254: icmp_seq=2 ttl=61 time=0.126 ms 64 bytes from 192.168.2.254: icmp_seq=3 ttl=61 time=0.138 ms --- 192.168.2.254 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2049ms rtt min/avg/max/mdev = 0.126/0.155/0.201/0.032 ms 実装 続いて、先ほどiproute2で直接データプレーンに設定した内容をコントロールプレーン(BGP)で配布するための実装をします。問題1と問題2を解決するために必要なBGPの処理を考えます。 前提条件として、MPLS網のルータは、SRv6の機能が実装されていないと仮定します。そのため、追加実装はSRv6網のルータ(ASBR-SRv6)を対象とします。 また、各構造体の処理条件は現状の実装に従って紹介します。これらの条件については、拡張性を考慮してもっと検討する必要があるかもしれません。 問題1: ASBR-SRv6で、PE-SRv6から受け取ったVPNv4経路情報をSRv6からMPLSに変換してASBR-MPLSへ配布する このとき、UPDATEメッセージに含まれるBGP Prefix-SID Attributeを削除する 問題2: ASBR-SRv6で、ASBR-MPLSから受け取ったVPNv4経路情報をMPLSからSRv6に変換してPE-SRv6へ配布する このとき、新たにUPDATEメッセージにBGP Prefix-SID Attributeを追加する はじめに、追加機能を設定するためのコマンドを作成します。BGPのピアに対して neighbor <A.B.C.D|X:X::X:X|WORD> seg6-mpls-label-switching が設定されていれば、そのピアに対してSRv6とMPLS/SR-MPLSの相互接続を実施すると判断します。それに伴い、BGPのピアに関するあらゆる情報を持つ struct peer に新たなフラグ PEER_FLAG_SEG6_MPLS_LABEL_SWITCHING を追加します。 次に、ラベルのマッピングを行います。Inter-AS Option-B方式において、隣接ASからラベル付きのL3VPN経路情報を受信し、ローカルラベルで再広告する際に、受信ラベルとローカルラベルのマッピング情報を扱うための構造体があります( struct bgp_mplsvpn_nh_label_bind_cache )。 l3vpn-multi-domain-switching が設定されている場合に new_label がセットされ、ラベルのSWAPがカーネルへ設定されます。 /* used to bind a local label to the (label, nexthop) values * from an incoming BGP mplsvpn update */ struct bgp_mplsvpn_nh_label_bind_cache { /* RB-tree entry. */ struct bgp_mplsvpn_nh_label_bind_cache_item entry; /* The nexthop and the vpn label are the key of the list. * Only received BGP MPLSVPN updates may use that structure. * orig_label is the original label received from the BGP Update. */ struct prefix nexthop; mpls_label_t orig_label; /* resolved interface for the paths */ struct nexthop *nh; /* number of mplsvpn path */ unsigned int path_count; /* back pointer to bgp instance */ struct bgp *bgp_vpn; /* MPLS label allocated value. * When the next-hop is changed because of 'next-hop-self' or * because it is an eBGP peer, the redistributed orig_label value * is unmodified, unless the 'l3vpn-multi-domain-switching' * is enabled: a new_label value is allocated: * - The new_label value is sent in the advertised BGP update, * instead of the label value. * - An MPLS entry is set to swap <new_label> with <orig_label>. */ mpls_label_t new_label; /* list of path_vrfs using it */ LIST_HEAD(mplsvpn_nh_label_bind_path_lists, bgp_path_info) paths; time_t last_update; bool allocation_in_progress; }; 既存の実装では、 受信したMPLSのVPNラベル と 配布するMPLSのVPNラベル のマッピングしかできません。そこで、以下を定義します。 受信したSRv6のVPN SID を 配布するMPLSのVPNラベル にマッピングする関数 受信したMPLSのVPNラベル を 配布するSRv6のVPN SID にマッピングする関数 実際にマッピングを行う関数は void bgp_mplsvpn_nh_label_bind_register_local_label() として定義されています。これを参考に、 MPLSのVPNラベル と SRv6のVPN SID のマッピングを行う関数を定義します。 extern void bgp_mplsvpn_sid_bind_register_local_label ( struct bgp *bgp, struct bgp_dest *dest, struct bgp_path_info *pi, afi_t afi); extern void bgp_mplspvn_nh_label_bind_register_sid ( struct bgp *bgp, struct bgp_dest *dest, struct bgp_path_info *pi, afi_t afi); そして、VPNv4経路情報を受け取りラベル情報をインポートする際に、場合分けを行って適切にマッピングします。今回は、受け取ったUPDATEメッセージにBGP Prefix-SID Attributeが含まれていれば、 受信したSRv6のVPN SID を 配布するMPLSのVPNラベル にマッピング、含まれていないかつ PEER_FLAG_SEG6_MPLS_LABEL_SWITCHING が設定されたピアからの経路情報であれば 受信したMPLSのVPNラベル を 配布するSRv6のVPN SID にマッピングするという単純な条件で処理を行います。 static void bgp_mplsvpn_handle_label_allocation ( struct bgp *bgp, struct bgp_dest *dest, struct bgp_path_info *new_select, struct bgp_path_info *old_select, afi_t afi) { ... } else if (new_select->attr->srv6_l3vpn) { // srv6 -> mpls bgp_mplsvpn_sid_bind_register_local_label ( bgp, dest, new_select, afi); } else if (!new_select->attr->srv6_l3vpn && CHECK_FLAG (new_select->peer->af_flags[afi][SAFI_MPLS_VPN], PEER_FLAG_SEG6_MPLS_LABEL_SWITCHING)) { // mpls -> srv6 bgp_mplspvn_nh_label_bind_register_sid ( bgp, dest, new_select, afi); } else ... } 次に、BGP Prefix-SID Attributeの削除・追加部分を実装します。UPDATEメッセージに付与するAttributeの構築は bgp_size_t bgp_packet_attribute() で行います。この関数では、 struct stream *s へ必要なAttributeのデータを挿入します。以下は、Origin Attributeを構築している箇所です。 /* Origin attribute. */ stream_putc (s, BGP_ATTR_FLAG_TRANS); stream_putc (s, BGP_ATTR_ORIGIN); stream_putc (s, 1 ); stream_putc (s, attr->origin); struct attr *attr には、利用可能なAttributeの構造体がたくさん定義されています。たとえば、BGP Prefix-SID Attributeの情報は、 attr->srv6_l3vpn にあります。このポインタがNULLであれば付与しません。今回は、以下のようにピアがeBGPかつ、 PEER_FLAG_SEG6_MPLS_LABEL_SWITCHING フラグがオンであれば attr->srv6_l3vpn をNULLにすることで削除を実現しています。 /* SRv6 Service Information Attribute. */ if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_MPLS_VPN) { /* draft-spring-srv6-mpls-interworking-service-iw (yokoo) */ if (peer->sort == BGP_PEER_EBGP && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEG6_MPLS_LABEL_SWITCHING) && afi == AFI_IP) { /* not supported ipv6 vpn */ attr->srv6_l3vpn = NULL ; } 一方付与の場合は、ピアがiBGPかつ、SAFI(Subsequent Address Family Indicator)がMPLS VPNであれば、 attr->srv6_l3vpn を構築するようにしています。 attr->srv6_l3vpn の構築は、既存コードを参考に行います。 bgp_size_t bgp_packet_attribute ( struct bgp *bgp, struct peer *peer, struct stream *s, struct attr *attr, struct bpacket_attr_vec_arr *vecarr, struct prefix *p, afi_t afi, safi_t safi, struct peer *from, struct prefix_rd *prd, mpls_label_t *label, uint32_t num_labels, bool addpath_capable, uint32_t addpath_tx_id, struct bgp_path_info *bpi) { ... if (peer->sort == BGP_PEER_IBGP && afi == AFI_IP && safi == SAFI_MPLS_VPN) { /* not supported ipv6 vpn */ zlog_info ( "Create BGP Prefix-SID attribute for SRv6 MPLS interworking" ); /* attr->srv6_l3vpn を構築する */ ... } ... } 動作検証 最後に動作検証を行います。host1からhost2へpingを送信し、その様子を各リンクでパケットキャプチャします。MPLS網ではMPLSヘッダで、SRv6網ではSRv6拡張ヘッダでカプセル化されて転送されているのがわかります。また、Inter-ASはMPLSラベルを用いて転送されていることも確認できます。 root@Customer-1:/# ping 192.168.2.254 -c 3 PING 192.168.2.254 (192.168.2.254) 56(84) bytes of data. 64 bytes from 192.168.2.254: icmp_seq=1 ttl=61 time=0.747 ms 64 bytes from 192.168.2.254: icmp_seq=2 ttl=61 time=0.194 ms 64 bytes from 192.168.2.254: icmp_seq=3 ttl=61 time=0.215 ms 感想 2週間という短い期間で、事前知識の学習から実装まで完走でき、非常に良い経験になりました。FRRoutingに機能を追加するのは初めての試みであり、膨大なソースコードや多様な構造体を理解することは難しかったですが、大きなやりがいを感じることができて非常に楽しかったです。 トレーナーの竹中さんには、全工程を通して手厚くサポートいただき、ネットワーク技術やソフトウェア開発に関するさまざまなことを学ぶことができました。特に実装工程では、多くの相談に乗っていただき、最後の最後までデバッグにお付き合いいただきました。また、ミーティングに参加させていただいたり、データセンターを見学させていただいたりと、貴重な経験を積むことができました。本当にありがとうございました。 私は、前半はリモート、後半は出社という少し特殊な形で参加させていただきましたが、リモートと対面の両方を経験できたのは非常に良かったです。 対面だけでなく、リモートでもコミュニケーションが取りやすい環境を提供していただき、作業をスムーズに進められました。また、懇親会はハイブリットで開催していただき、他のインターン生やチームの社員の方々との交流の場を提供していただき、職場の雰囲気を肌で感じることができました。 本インターンを通して多くの学びや経験を得ることができました。改めまして、本当にありがとうございました。 トレーナーからのコメント トレーナーを担当したイノベーションセンターの竹中です。横尾さん、2週間のインターンシップお疲れ様でした。 今回のインターンではSRv6ネットワークとSR-MPLSネットワークの相互接続という新規機能を、ソフトウェアルータへ実装いただきました。 祝日を含んだ2週間という短い作業期間でこの難易度の高い目標を見事達成したことは本当に嬉しい成果です。 ソフトウェアルータの機能拡張は、プログラミングスキルだけでなく、ルータが対話に用いるルーティングプロトコルに関する深い知識も必要になってきます。そのため前半数日をSegment Routingを用いたネットワークにおけるルーティングプロトコルの挙動学習、残りの作業日をコードリーディング・機能実装の時間としていました。 インターン開始当初は作業可能な期間から想定し、プロトコルの挙動学習は軽い動作確認、コードリーディングは問題点を洗い出したもの・実装する箇所をピンポイントで共有して実装だけに注力してもらう予定でした。 しかし、持ち前の高い技術学習力による想定を大きく超えた進捗だったため、不足している機能の洗い出しから実装方針の検討まで実施してもらう方針へ変更しました。インターンシップ目標を達成した横尾さんの実装力はもちろんのこと、その過程でのプロトコルの挙動学習速度もとても印象に残っています。 実装いただいたSRv6ネットワークとSR-MPLSネットワークの相互接続機能は、今後我々が実施していくSRv6/SR-MPLS相互接続環境における検証の核になる機能です。今後の我々の検証において大いに活用させていただきます。 このインターンシップを通して得られた経験が今後の横尾さんの活動にも役立つことを願っています。 改めて、インターンシップへのご参加とご活躍、ありがとうございました!
アバター
みなさんこんにちは、イノベーションセンターの益本 (@masaomi346) です。 Network Analytics for Security (以下、NA4Sec) プロジェクトのメンバーとして、脅威インテリジェンス(潜在的な脅威について収集されたデータを収集・分析したもの)の分析をしています。 最近、広告から偽のセキュリティ警告画面に飛ばされる事例が目立っています。 本記事では、偽のセキュリティ警告画面が表示される仕組みについて、実際に使われているツールを使って紹介していきます。 ぜひ最後まで読んでみてください。 NA4Secについて 「NTTはインターネットを安心・安全にする社会的責務がある」を理念として、インターネットにおける攻撃インフラの解明・撲滅を目指した活動をしているプロジェクトです。 NTT Comグループにおける脅威インテリジェンスチームとしての側面も持ち合わせており、有事において脅威インテリジェンスを提供し、意思決定を支援することもあります。 イノベーションセンターを中心として、NTTセキュリティ・ジャパンやエヌ・エフ・ラボラトリーズ(以下、NFLabs.)からもメンバーが参画し、日夜攻撃インフラを追跡しています。 NA4Secの最近の活動については、以下の記事をご覧ください。 セキュリティカンファレンス「JSAC2024」に参加してきた話(登壇編) 日本を狙ったフィッシングサイトの情報配信はじめました サポート詐欺について サポート詐欺とは、偽のセキュリティ警告画面を表示させて、偽のサポート窓口に電話をかけさせ、サポート料金と称して金銭を騙し取る手口のことをいいます。 近年サポート詐欺による被害が増加しており、政府広報や国民生活センターなど、各所で注意喚起が出ています。 PCやスマホに警告画面が出ても慌てないで! 🚨サポート詐欺が急増中🚨 パソコンやスマホを使用中、「ウイルスに感染した」という警告画面がでたりしても、実際には感染していないことがほとんど。 表示された偽のサポート窓口に電話をすると、金銭を請求されます💥 https://t.co/axdRjHJFXs https://t.co/JpePWnrzn2 pic.twitter.com/PLlosBy4OF — 政府広報オンライン (@gov_online) 2024年4月7日 【発表情報】 パソコンに突然の #警告画面 ! 表示されたマイクロソフト社の電話番号は偽物なので絶対に電話しないで! パソコンを #遠隔操作 されネットバンキングで100万円送金されてしまった被害も。 https://t.co/esArIOGxPO 困った時は、一人で悩まず、まず相談!消費者ホットライン「188」に電話 pic.twitter.com/Ne6mbou3Cr — 国民生活センター (@kokusen_ncac) 2024年3月27日 また、IPAの偽セキュリティ警告対策特集ページにて、偽セキュリティ警告についての情報がまとめられていたり、偽セキュリティ警告画面を体験できるサイトが公開されています。 興味がある方はぜひ読んでみてください。 偽セキュリティ警告(サポート詐欺)対策特集ページ どこから出現するのか インターネット上の広告を中心として、いろんなところから出現します。 検索結果の広告をクリックする Webサイト上の広告をクリックする ブラウザ通知スパムによる偽のセキュリティ通知をクリックする etc. 検索結果の広告をクリックする URLが本物と同じように表示されているが、これは、広告のトラッキングテンプレートを悪用することで、上の画像のように表示されます。 トラッキングテンプレートの悪用については、以下の記事が参考になりますので、興味がある方はぜひ読んでみてください。 PSA: Ongoing Webex malvertising campaign drops BatLoader Webサイト上の広告をクリックする 広告をクリックした後、いくつかのドメインを経由して、偽のセキュリティ警告画面が表示されます。 ブラウザ通知スパムによる偽のセキュリティ通知をクリックする ブラウザ通知の許可を求められ、許可を押すと、偽のセキュリティ警告画面に誘導するための通知が表示されます。 なぜ広告が使われているのか これについては、とても複雑であり、詳細を書くと長くなるので、ざっくり紹介します。 インターネットの世界には、広告で収益を稼いでいる攻撃者がいます。 その中には、アクセスした人の属性によって、どの不正なコンテンツにトラフィックを流すかをルーティングするためのシステムを構築・運用している攻撃者もいます。 流れてきたトラフィックを自分で構築したWebサイトに流して広告収入を得たり、他の攻撃者が構築したWebサイトに流して手数料を得たりしています。 広告で収益を稼いでいる攻撃者は、偽のセキュリティ警告画面にトラフィックを流すことで、広告収入や手数料を手に入れるができます。 サポート詐欺を行っている攻撃者は、トラフィックを流してもらうことで、多くの人を誘導できるという仕組みになっています。 偽のセキュリティ警告画面の仕組み 偽のセキュリティ警告画面がどのように動作しているのか。 実際に使われている偽のセキュリティ警告画面を構築するためのツール(フィッシングキット)を使って、主な部分を紹介していきます。 ※あくまで一例であり、すべての偽のセキュリティ警告画面がこうなっているわけではありません。 今回紹介するツールは、zipファイルとなっており、展開すると、以下のようになっています。 ブラウザの環境に合わせて表示内容を変化させる このツールを実際に動かしてみると、使っている環境によって、偽のセキュリティ警告画面が変化します。 Windows macOS 最初に読み込まれるファイルを見てみると、ブラウザの種類やバージョンを取得して、どのアドレスに飛ばすかを指定しています。 電話番号の表示 警告画面の電話番号がどのように表示されているかというと、電話番号をsessionStorageへ格納している箇所があり、そこから呼び出しています。 攻撃者の電話番号を入力すれば、偽のサポート窓口の電話番号として表示されます。 Windows版での送信元の情報表示 Windows版の偽のセキュリティ警告画面を表示したときに、IPアドレスや場所などの情報が表示されていたが、この部分については、外部サービス(画像ではipwho.is)を使って取得しています。 多言語対応 ブラウザの言語によって、警告画面の言語が変わるようになっています。 まとめ 偽のセキュリティ警告画面は、インターネット上の広告を中心として、いろんなところから出現しています ブラウザの種類や言語など、アクセスした人の情報に合わせて、表示する警告画面や言語を変えています 外部サービスを使って、アクセスした人の情報を取得しています 偽のサポート窓口用の電話番号があれば、簡単に使えるようになっています さいごに 本記事では、偽のセキュリティ警告画面が表示される仕組みについて、使われているツールを使って紹介しました。 怪しい広告から、偽のセキュリティ警告画面に飛ばされる事例が増加しています。 本記事が、偽のセキュリティ警告画面がどのように表示されているかを知るための参考になればと思います。 今回の偽のセキュリティ警告以外にも、フィッシング詐欺で使われているツールなどの分析も行なっています。 興味がある方はぜひご連絡ください。 おまけ NA4Secでは、一緒に働く仲間を募集しています。 また、兄弟プロジェクトにMetemcyberというチームがあり、こちらも、一緒に働く仲間を募集しています。 「脅威インテリジェンス」をキーワードに活躍の場を探している方、プロジェクトの理念に共感していただける方のご応募をお待ちしています。 Threat Intelligence Analyst / 脅威インテリジェンスアナリスト (NA4Sec) Threat Intelligence Engineer / 脅威インテリジェンスエンジニア (Metemcyber)
アバター
みなさんこんにちは、イノベーションセンターの益本 (@masaomi346) です。 Network Analytics for Security (以下、NA4Sec) プロジェクトのメンバーとして、脅威インテリジェンス(潜在的な脅威について収集されたデータを収集・分析したもの)の分析をしています。 最近、広告から偽のセキュリティ警告画面に飛ばされる事例が目立っています。 本記事では、偽のセキュリティ警告画面が表示される仕組みについて、実際に使われているツールを使って紹介していきます。 ぜひ最後まで読んでみてください。 NA4Secについて 「NTTはインターネットを安心・安全にする社会的責務がある」を理念として、インターネットにおける攻撃インフラの解明・撲滅を目指した活動をしているプロジェクトです。 NTT Comグループにおける脅威インテリジェンスチームとしての側面も持ち合わせており、有事において脅威インテリジェンスを提供し、意思決定を支援することもあります。 イノベーションセンターを中心として、NTTセキュリティ・ジャパンやエヌ・エフ・ラボラトリーズ(以下、NFLabs.)からもメンバーが参画し、日夜攻撃インフラを追跡しています。 NA4Secの最近の活動については、以下の記事をご覧ください。 セキュリティカンファレンス「JSAC2024」に参加してきた話(登壇編) 日本を狙ったフィッシングサイトの情報配信はじめました サポート詐欺について サポート詐欺とは、偽のセキュリティ警告画面を表示させて、偽のサポート窓口に電話をかけさせ、サポート料金と称して金銭を騙し取る手口のことをいいます。 近年サポート詐欺による被害が増加しており、政府広報や国民生活センターなど、各所で注意喚起が出ています。 PCやスマホに警告画面が出ても慌てないで! 🚨サポート詐欺が急増中🚨 パソコンやスマホを使用中、「ウイルスに感染した」という警告画面がでたりしても、実際には感染していないことがほとんど。 表示された偽のサポート窓口に電話をすると、金銭を請求されます💥 https://t.co/axdRjHJFXs https://t.co/JpePWnrzn2 pic.twitter.com/PLlosBy4OF — 政府広報オンライン (@gov_online) 2024年4月7日 【発表情報】 パソコンに突然の #警告画面 ! 表示されたマイクロソフト社の電話番号は偽物なので絶対に電話しないで! パソコンを #遠隔操作 されネットバンキングで100万円送金されてしまった被害も。 https://t.co/esArIOGxPO 困った時は、一人で悩まず、まず相談!消費者ホットライン「188」に電話 pic.twitter.com/Ne6mbou3Cr — 国民生活センター (@kokusen_ncac) 2024年3月27日 また、IPAの偽セキュリティ警告対策特集ページにて、偽セキュリティ警告についての情報がまとめられていたり、偽セキュリティ警告画面を体験できるサイトが公開されています。 興味がある方はぜひ読んでみてください。 偽セキュリティ警告(サポート詐欺)対策特集ページ どこから出現するのか インターネット上の広告を中心として、いろんなところから出現します。 検索結果の広告をクリックする Webサイト上の広告をクリックする ブラウザ通知スパムによる偽のセキュリティ通知をクリックする etc. 検索結果の広告をクリックする URLが本物と同じように表示されているが、これは、広告のトラッキングテンプレートを悪用することで、上の画像のように表示されます。 トラッキングテンプレートの悪用については、以下の記事が参考になりますので、興味がある方はぜひ読んでみてください。 PSA: Ongoing Webex malvertising campaign drops BatLoader Webサイト上の広告をクリックする 広告をクリックした後、いくつかのドメインを経由して、偽のセキュリティ警告画面が表示されます。 ブラウザ通知スパムによる偽のセキュリティ通知をクリックする ブラウザ通知の許可を求められ、許可を押すと、偽のセキュリティ警告画面に誘導するための通知が表示されます。 なぜ広告が使われているのか これについては、とても複雑であり、詳細を書くと長くなるので、ざっくり紹介します。 インターネットの世界には、広告で収益を稼いでいる攻撃者がいます。 その中には、アクセスした人の属性によって、どの不正なコンテンツにトラフィックを流すかをルーティングするためのシステムを構築・運用している攻撃者もいます。 流れてきたトラフィックを自分で構築したWebサイトに流して広告収入を得たり、他の攻撃者が構築したWebサイトに流して手数料を得たりしています。 広告で収益を稼いでいる攻撃者は、偽のセキュリティ警告画面にトラフィックを流すことで、広告収入や手数料を手に入れるができます。 サポート詐欺を行っている攻撃者は、トラフィックを流してもらうことで、多くの人を誘導できるという仕組みになっています。 偽のセキュリティ警告画面の仕組み 偽のセキュリティ警告画面がどのように動作しているのか。 実際に使われている偽のセキュリティ警告画面を構築するためのツール(フィッシングキット)を使って、主な部分を紹介していきます。 ※あくまで一例であり、すべての偽のセキュリティ警告画面がこうなっているわけではありません。 今回紹介するツールは、zipファイルとなっており、展開すると、以下のようになっています。 ブラウザの環境に合わせて表示内容を変化させる このツールを実際に動かしてみると、使っている環境によって、偽のセキュリティ警告画面が変化します。 Windows macOS 最初に読み込まれるファイルを見てみると、ブラウザの種類やバージョンを取得して、どのアドレスに飛ばすかを指定しています。 電話番号の表示 警告画面の電話番号がどのように表示されているかというと、電話番号をsessionStorageへ格納している箇所があり、そこから呼び出しています。 攻撃者の電話番号を入力すれば、偽のサポート窓口の電話番号として表示されます。 Windows版での送信元の情報表示 Windows版の偽のセキュリティ警告画面を表示したときに、IPアドレスや場所などの情報が表示されていたが、この部分については、外部サービス(画像ではipwho.is)を使って取得しています。 多言語対応 ブラウザの言語によって、警告画面の言語が変わるようになっています。 まとめ 偽のセキュリティ警告画面は、インターネット上の広告を中心として、いろんなところから出現しています ブラウザの種類や言語など、アクセスした人の情報に合わせて、表示する警告画面や言語を変えています 外部サービスを使って、アクセスした人の情報を取得しています 偽のサポート窓口用の電話番号があれば、簡単に使えるようになっています さいごに 本記事では、偽のセキュリティ警告画面が表示される仕組みについて、使われているツールを使って紹介しました。 怪しい広告から、偽のセキュリティ警告画面に飛ばされる事例が増加しています。 本記事が、偽のセキュリティ警告画面がどのように表示されているかを知るための参考になればと思います。 今回の偽のセキュリティ警告以外にも、フィッシング詐欺で使われているツールなどの分析も行なっています。 興味がある方はぜひご連絡ください。 おまけ NA4Secでは、一緒に働く仲間を募集しています。 また、兄弟プロジェクトにMetemcyberというチームがあり、こちらも、一緒に働く仲間を募集しています。 「脅威インテリジェンス」をキーワードに活躍の場を探している方、プロジェクトの理念に共感していただける方のご応募をお待ちしています。 Threat Intelligence Analyst / 脅威インテリジェンスアナリスト (NA4Sec) Threat Intelligence Engineer / 脅威インテリジェンスエンジニア (Metemcyber)
アバター
こんにちは、イノベーションセンターの坂本です。 ソフトウェアエンジニアとしてノーコードAI開発ツール Node-AI の開発に取り組んでいます。 先日 2024年3月19日~22日 にかけてフランス パリで開催された KubeCon+CloudNativeCon Europe 2024 を聴講してきました。 本記事はあえて各セッションなどの技術的なお話ではなく、現地の雰囲気に焦点を当てた内容としています。行けなかった人や今後行ってみたい人に向けて、技術部分はRecapや 公式セッション動画 で、現地ならではの部分は本記事で今回のKubeConを補完できることを目指して執筆します。 目次 目次 そもそもKubeConとは? スケジュール Day1: CNCF Co-Located Events Day2~4: KubeCon Keynote Breakout Solutions Showcase CNCFプロジェクトブース お昼ご飯 / ケータリング 記念品 / ショップ 日本交流会@現地 まとめ そもそもKubeConとは? 非営利団体 Cloud Native Computing Foundation (CNCF) が主催するイベントで、毎年北米とヨーロッパで1回ずつ開催されます。Kubernetesおよびクラウドネイティブコンピューティング技術についての事例共有やCNCFがホストするプロジェクト(CNCFプロジェクト)のメンテナなどからアップデート紹介など中心に行われます。他にも企業展示や各CNCFプロジェクトのブース、交流会などさまざまな催しがあります。 会場はパリ中心部からバスを利用して片道約45分 今夏にオリンピックを控えているせいかKubeCon会場でさえ手荷物検査がある スケジュール Day1: CNCF Co-Located Events 初日は各CNCFプロジェクトに特化したCo-Located Eventsがあります。 2~4日目のKubeConとは別費用が必要ですが、個人的にはKubeConよりもこちらに参加しに行くと言ってもいいくらい興味深いセッションが多いのでオススメです。 昨年は国内外問わず技術系イベントではOpenTelemetry関連のObservability系セッションがかなり多かったと記憶していますが、やはりそういった注目領域は扱いが違います。 私が主に聴講していたEdge Dayはスクリーン1枚に椅子のみといった部屋で開催されましたが、Observability Dayは倍近くの部屋の広さでスクリーン2枚にテーブル完備と厚遇されていました。 Observability Dayのもよう Day2~4: KubeCon KubeCon自体の中にもさまざまなイベントがありますが、いくつか抜粋して紹介します。 Keynote KubeConでは毎朝Keynoteがいくつかあり、その後個別のセッションが各部屋で行われるといった流れになります。 やはりエンジニア的には Graduated Project Updates が一番盛り上がり、会場の反応でインパクトの大きさを推察できます。 ここまで言っておいてなんですが今回自分はこれを現地で聞けませんでした。 ただ内容を見るに Istio Ambient Modeがbetaリリース間近 という部分が一番盛り上がったのではないでしょうか。 Keynote会場のもよう Breakout 開催期間中は絶え間なく複数の部屋でBreakout(セッション)が行われます。 人気のあるセッションは部屋の定員に達してで入れないこともしばしばありました。 逆に言えば人の入りで注目度を測るといった現地参加ならではの目利きもできます。 例えばKubernetes 1.27以降で使えるInPlacePodVerticalScalingを紹介した こちらのセッション は長蛇の列がついていました。 セッションではMLワークロードやゲームサーバ周りで有用と言及されていましたが、たしかに技術領域としてどちらも使用しているNode-AIに相性のよい技術だと感じたので今後導入していきたいです。 DB Operator比較 ( https://sched.co/1YeO5 )のセッションの入室は空き待ち 会場はとても広いので移動もひと苦労 Solutions Showcase 会場にはSolutions Showcase(企業展示)コーナーもあります。 展示ブースのもよう 欧州で人気のスポーツ F1の強豪チームのスポンサーをやっているせいかOracle社ブースにはレーシングゲームがあったり、GitHub社ブースにはテーブル・フットボールの台があったりと地域色あふれるブースがいくつかありました。 ちなみにDocker社ブースにも同様のレーシングゲームがありましたが、そちらは新サービスのdocker build cloudではF1マシンのように速くイメージをビルドできることを表現した結果だそうな。 レーシングゲームは順番待ちするくらいの盛況っぷり KubeConは一般的なイベントとは一味違い、各社ブースでの配布物がリッチです。 K3sを提供するSUSE社ブースではぬいぐるみやマフラーを配布していました。 Red Hat社のブースでは恒例の書籍配布 兼 サイン会が行われ長蛇の列となっていました。今回は米アマゾン販売価格$47相当の書籍が配布されていたそうです。 今回はぬいぐるみだけゲット その気になれば多くのグッズ集められるのでカバンには余裕を持って来ましょう CNCFプロジェクトブース 学会でのポスター発表のような感じで各CNCFプロジェクトのコーナーもあり、メンテナと直接ディスカッションできます。今回のKubeConでは成熟度レベルに応じてブースを設けられる期間が決まっていたそうです。 お昼ご飯 / ケータリング 会期中は毎日お昼ご飯としてお弁当を提供してくれます。 Day1のCo-Located Eventsではフランス料理のような弁当のレベルを超えたものが出ましたが、Day2以降はKubeCon NA同様フランスパン型のサンドイッチとサラダ、デザートのセットでした。(正直おいしくはない) 会場にはケータリングもあります。今回はパン数種類に各種飲み物がありました。昨年のKubeCon NAではヨーグルトや果物があってかなり豪華だったので少し残念なポイントです。やはりパリは物価が高いのでしょうか。 左: 今回 右: 昨年のKubeCon NA 記念品 / ショップ KubeConでは参加者に記念品としてTシャツが配られます。 写真の黒い方は昨年のKubeCon NAのもので、青い方が今回のものです。 さすがはパリ、何もかもが洒落ています。 名曲 "La Vie en rose (ばら色の人生)" になぞらえて "クラウドネイティブな人生" ショップにはパーカーやTシャツ、リュックなど定番グッズも充実しています。 ショップのもよう 日本交流会@現地 KubeCon期間中には日本交流会が開催されました。 他社の方々と開発事情や技術活用のあれこれについて情報交換でき、とても貴重な時間を過ごすことができました。 企画してくださった方々やスポンサーとして支援してくださった企業の方々にはこの場を借りてお礼申し上げます。 まとめ 本記事では現地ルポと題し、実際に会場に足を運ばないとわからないような部分を中心に紹介しました。 今回はNode-AIのブラッシュアップや関連新サービス開発のための情報収集を目的に予めセッションの目星をつけて行きました。 その他にもふらりと立ち寄ったセッションでヒントを得ることもでき、今回も現地参加ならではの利点を十分に得られたと感じています。本記事が少しでも皆さまのお役に立てば幸いです。
アバター
この記事では、社内部署横断で開催したデータ分析開発合宿について紹介します。 自社サービスが持つ課題に対して、社員がデータ分析と課題解決のための施策提案に取り組み、サービス側へのフィードバックと改善へつなげることができました。 目次 目次 はじめに 各サービスでの分析内容と施策提案 NeWork 課題と提供データの簡単な説明 バブル滞在時間と画面共有時間の傾向分析 通話あたりの画面共有率の傾向分析 Node-AI 課題と提供データの簡単な説明 1日でやめてしまったユーザーの傾向分析 SDPF 課題と提供データの簡単な説明 日時当たりの送信元IPアドレスのユニーク数を使った分析 報告を受けての各サービスでの施策状況 終わりに はじめに 皆さんこんにちは、ソリューションサービス部の小関と是松です。 今回はこちらの記事の続編です。 データ分析開発合宿を開催しました~自社サービスのデータ利活用を促進しよう~ 前回の記事では、エンジニアを中心とした社員でチームを作り、データ分析で自社サービスの課題解決に取り組んだ、データ分析開発合宿を紹介しました。 今回の記事では、NTT ComのサービスであるNeWork、Node-AI、Smart Data Platform (SDPF) に向けて実施された分析と施策提案について紹介します。 各サービスでの分析内容と施策提案 NeWork NeWork は、リモートワーク、オフィス、複数の拠点が同じ空間でつながるオンラインワークスペースです。 バーチャルオフィス空間上でチームメンバーとのコミュニケーションがいつでも可能で、誰が誰とやり取りしているのかを把握できます。 1対1の通話はもちろん、「バブル」 という会議室に似たスペースを自由にカスタマイズして、多人数コミュニケーションをとることが可能です。 課題と提供データの簡単な説明 NeWorkが提示した課題は、チャーンレート(解約率)の分析です。 例えば、以下の画像にあるような有料プランから無料プランへ変更したユーザーの傾向や、利用状況の時間変化などから、チャーンシグナル(解約の前触れ)はあるかという分析内容です。 提供データは、Googleアナリティクス4から収集されたイベントデータで、複雑なデータ構造となっています。そのため、まずはデータ構造の把握や欠損値等の前処理から実施する必要がありました。 バブル滞在時間と画面共有時間の傾向分析 NeWorkを担当したチームの分析の一部を紹介します。 こちらのチームでは、バブル滞在時間・通話時間・画面共有時間を分析し、以下の傾向があることを発見しました。 継続しているワークスペースは、バブル滞在時間が長い 継続しているワークスペースは、バブル滞在時間に対して通話時間が短い 継続しているワークスペースは、画面共有が多い この分析結果を受けて、ユーザーの解約防止として以下の施策が提案されました。 もくもく会としての活用を訴求 アプリ版への導線を引く チュートリアル機能の追加 通話あたりの画面共有率の傾向分析 またこちらのチームでは、通話時間の中で画面共有をしていた時間の割合(画面共有率)を分析し、以下の傾向があることを発見しました。 サービスを利用し始めてから10週を過ぎると、有料プランユーザーと解約ユーザーで画面共有率に差がある 有料プランユーザーは10分以内の短時間の通話の中でも画面共有を利用している傾向がある この分析結果を受けて、以下の施策が提案されました。 画面共有率のウォッチ 導入・トライアル初期における画面共有活用のユースケースの事例紹介 Node-AI Node-AI はドラッグアンドドロップでカードを配置しながら繋げていき、ノーコードでAIを開発できるサービスです。 学習に使うデータを設定するデータカードや、データを加工する前処理カード、予測モデルを作成する学習カードなど、さまざまなカードがあります。 課題と提供データの簡単な説明 Node-AIが提示した課題は、長く使うユーザーとすぐにやめるユーザーの傾向や、ユーザーがどこでエラーを踏むかの情報をもとに、優先して改善すべきカードや機能を知りたいという内容です。 Node-AIでは各ユーザーの実行ログを取得しており、どのユーザーがいつ何のカードを実行し成功/失敗したかのデータが合宿参加者へ提供されました。 1日でやめてしまったユーザーの傾向分析 Node-AIを担当したチームの分析の一部を紹介します。 こちらのチームでは、1日で利用をやめたユーザーが最後に実行したカードとカードの実行遷移を分析し、以下の傾向があることを発見しました。 学習に使うデータを設定するデータカードを最後に実行したユーザーが多い(左側の円グラフ) 「dataresource SUCCESS」は、データカード上で目的変数と説明変数を設定し、その設定に成功したログを表している 「dataresource SUCCESS」を繰り返す傾向がある(右側のグラフ) この分析結果を受けて、1日で利用をやめたユーザー像の仮説と離脱防止施策として以下が提案されました。 仮説 :目的変数や説明変数の設定成功に気付かず繰り返し実行した後、次に何をするのかが分からず離脱したユーザーが一定数いると考えられる 施策 :データカード上で設定成功のメッセージを強調し、気付かず離脱してしまうユーザーを減らす SDPF SDPF はデータ利活用に必要なさまざまな機能を集約したプラットフォームサービスです。 今回分析の対象となった SDPF クラウド/サーバー はSDPFの機能の一部であり、IaaSメニューとしてネットワーク、データセンター、マネージドサービスを連携したサービスです。WebポータルだけでなくAPIによる操作も対応しています。 課題と提供データの簡単な説明 SDPFが提示した課題は、SDPFへアクセスするIPアドレスのリクエスト情報から、オブザーバビリティを高め、システムやユーザーの状態変化を把握したいという内容です。 SDPFではサービスへアクセスするIPアドレスのリクエスト情報を取得しており、どのIPアドレスがいつどのURIをリクエストしたかのログデータが合宿参加者へ提供されました。 日時当たりの送信元IPアドレスのユニーク数を使った分析 SDPFを担当したチームの分析の一部を紹介します。 こちらのチームでは、1時間ごとの送信元IPアドレスのユニーク数について分析し、以下の傾向があることを発見しました。 受領データの期間内に、ユニーク数が多い時間帯が3つあった(画像1枚目の時系列グラフ) 上記3つの時間帯にアクセスした送信元IPアドレスの中で、直近アクセスが無かったIPアドレスに絞ると、特定のURIに対して複数回リクエストを要求するIPアドレスがあった 分析結果からは、上記の傾向がシステムへどのような影響を及ぼしたかまでは判明しませんでしたが、特徴的な傾向を発見できました。その上で、アクセスの傾向の把握とシステム改善への利活用について以下が提案されました。 分析から分かった送信元IPアドレスの増加原因とシステムへの影響調査 時間ごとの送信元IPアドレスのユニーク数を用いた普段と異なるリクエスト傾向の検知システム開発 報告を受けての各サービスでの施策状況 NeWorkでは、分析結果を元に解約率低減や定着率向上のためチュートリアルを実装し、効果測定のABテストに取り組んでいます。今後計測結果を分析する予定です。また、解約傾向の見直しにも取り組んでいます。 Node-AIでは、分析結果を元にチュートリアルを変更しました。また、合宿の参加者からレビュアーを募り、変更内容について意見をもらう開発レビューも実施しました。 さらに、チーム内で協議し、提供された分析結果を参考にしてデータ可視化用のダッシュボードを作成し、日々のサービスの状況を確認しています。 SDPFでは合宿で指摘されたIPアドレスからのアクセス増加による影響が調査されました。このアクセスによるシステムへの影響はなかったものの、分析結果からアクセス集中を検知することで、システム負荷計測やユーザーのアプリケーション活用方法の変化を検知し、フィードバックができないか協議がなされました。 上記のように合宿で得られた分析結果が、各サービスの改善に用いられました。 終わりに 今回のデータ分析開発合宿により、サービスがもつデータの分析と課題解決のための施策を提案し、サービスの改善に貢献できました。 今年も開催し社内のデータ利活用をさらに推進していきたいです。
アバター
この記事では、内製でソフトウェアを開発するチームにジョインして間もないエンジニアが受託開発と内製開発の違いについて感じたことを紹介したいと思います。 目次 目次 はじめに これまでの経験 NeWork 開発チームにジョインきっかけ いいなと感じたこと 報告のための資料作成や調整作業がない 価値ある変更は積極的に受け入れていること 毎日リリースができること 当初の想定と違ったこと ドキュメント類の決定事項が分かりづらい 不具合やバグの優先順位が相対的に高くないときがあること 意外と打ち合わせが多いこと おわりに はじめに こんにちは、NeWork 開発チームの栄です。普段はオンラインワークスペースサービス NeWork の開発エンジニアをしています。NeWork の開発エンジニアを担当することになってから 1 ヶ月が経過しようとしています。 そこでこの記事では、私がこれまで経験してきた受託開発と現在 NeWork で経験している内製開発の違いについて感じたことを振り返りたいと思います。 これまでの経験 これまではウォーターフォールで受託開発をする部署でシステムエンジニアとして中小企業の DX 化を推進するためのプラットフォーム開発をメインの案件として携わっており、担当業務としては提案や要件定義などの上流工程やシステムテスト、リリースなどを担当しておりました。 幸い?なことに忙しく働かさせてもらい、担当業務だけでなく、新たな業務アプリケーションを導入するために全国のユーザーを訪問して勉強会を実施したり、アプリケーション導入後のさらなる改善を図るために実際の利用者のところまで訪問してインタビューをしたりと非常に多くの経験ができたと思います。 最終的にはメイン機能の開発やその他別案件でも小さな案件であれば 1 人でも業務を任せてもらえるようになり、やりがいを感じながら充実感を持って業務に取り組めておりました。 NeWork 開発チームにジョインきっかけ 業務に不満があったわけでは無いのですが、次第に次のようなことを思うようになりました。 自分自身が実際に手を動かして開発できるようになりたい ユーザーから得た反応をスピーディーに反映できるようになりたい 1 つめは担当案件では設計・コーディング・単体テストなどの工程は外部に委託をしており、実際に手を動かして開発をする工程になると進捗管理などのマネジメントがメインとなっておりました。しかし、自分が考えた要件や機能を実装できない、実装する方法がわからないことに危機感を感じるようになり、もっとエンジニアとして技術的に成長できる環境に身を置きたいと思うようになりました。 2 つめは受託開発の一次受けだったため基本的にはユーザー主導のスケジュールで進んでいくのですが、すべての工程で報告や確認や承認などが必要になります。(ユーザーからお仕事を頂いているので当然ですが。) そのため、どうしても開発スケジュールが長くなる傾向にありました。さらに、複数ベンダーが開発するプロジェクトだったため、1 つの機能を開発するにしても各社間で設計を合わせて、テストの実施も日程やテスト環境を調整するなども必要でしたので、よりスケジュール長くなってしまっていたと思います。 実際に利用者にインタビューをしてフィードバックを貰っても、それを解決するためには次のリリースまでの数ヶ月の期間が必要であり、すぐにユーザーに価値を提供できないもどかしさを感じておりました。 そんなとき、NTT グループには社員自らが自律的にキャリアを築き新たな挑戦ができるように各組織が必要とするポストに対して社員が手を上げて応募できる制度があることを知り、そこで NeWork 開発チーム が新たな開発エンジニアの募集をしていたため、自ら応募することで 現在は NeWork の開発チームにジョインしております。 いいなと感じたこと ここからは、NeWork の開発にジョインしていいなと感じたことを受託開発と内製開発の観点から述べていきたいと思います。 報告のための資料作成や調整作業がない 私が経験した受託開発ではユーザーと何かしらの契約を交わしており、ほとんどの場合で成果物を納品する義務があります。そのためか細かく進捗を管理しながら多くの成果物を作成するのですが、1 つ 1 つの報告ごとにパワーポイントで資料を作成しておりました。また、テスト結果報告のときはすべてのテストを 1 つずつスクリーンショットで撮ってエクセルに貼り付ける作業をしており、かなりの時間を要します。さらに、大規模開発にもなるとステークホルダーがどんどん増えていき、報告をするためにも社内・社外問わず多くの関係者との各種調整をする必要があり、報告するまでにも多くの時間を要しました。 それが NeWork の開発だとほとんどありません。実際に動くソフトウェアを見て進捗を判断してもらえるので新たに報告資料を作成する必要がなかったり、内製かつスクラムで開発をすることにより定期的にプランニングとレビューですべての関係者が揃うため、各種調整をすることなくすぐに関係者とコミュニケーションをとれます。 資料を作成することは少しでも相手に対してわかりやすく伝えるために重要ですが、その報告のために不必要な時間をかける必要がないため、より開発作業に対して集中できるようになっていると思います。 価値ある変更は積極的に受け入れていること IPA が公開している アジャイルソフトウェア開発宣言の読み解き方 にもあるように、開発者にとって一番大事なことは、「価値あるソフトウェアを素早く継続的に提供し、ユーザーに ビジネスゴール達成の観点で満足してもらうこと 」だと思います。 しかし、受託開発をしているときはどうしてもビジネスゴールの達成よりも QCD(品質・費用・納期)の達成を優先してしまうこともありました。納期を守るために開発後期の段階で仕様変更すること対しては消極的であることがあったのですが、それがユーザーのビジネスゴール達成に大きく貢献できているか?と問われるともっと他にやり方があったのではないかと今にしては思います。 一方で NeWork の開発ではユーザーのビジネスゴールの達成を最優先するために、改善に繋がる仕様変更は新たな価値を見つけられたとして、積極的に受けいれております。また、短い時間間隔で定期的にリリースをすることで、ユーザーからのフィードバックもすぐに適用でき、結果としてユーザーが本当に必要なものを作れているのではないかと思います。 毎日リリースができること 受託開発時は、本当にリリースをしていいのかをチェックするために品質報告会議やリリース判定会議があったり、リリースがあるたびにリハーサルを何度も行ったりなど、多くのプロセスをすべてクリアしてリリースの承認を得る必要がありました。品質を保つためには必要な工程だとは思いますが、やはりすべてのプロセスをクリアするには時間がかかるため、どうしてもリリースまで時間がかかってしまいます。 以下の記事にもあるように、NeWork では毎日リリースをできる体制が整っており、とても驚きました。 リリース頻度を毎週から毎日にしてみた 毎日リリースする機会があれば、ユーザーからのフィードバックもすぐに反映できます。また、毎日効率よくリリースするためにリリース作業が完全自動化されております。以前は深夜に起きて何時間もリリース作業をする必要があったため、この差は個人的にはかなり大きいです。 当初の想定と違ったこと これだけでは NeWork の業務はいいところだけ述べており、以前の業務は悪いところしかないようにみえるので、ここからは NeWork にジョインして当初の想定と違って驚いたことを述べたいと思います。 ドキュメント類の決定事項が分かりづらい ドキュメントが内部の開発者だけでしか見られないこともあり、ドキュメントそのものに対してレビューをすることはほぼありません。そのためか、議論の途中までしか文章化していないこともあって、あとで振り返ったときに決定事項がわかりづらいこともあります。また、開発者全員に開発スキルがあるためか、文字だけで仕様を決めていき絵や図を書かずに設計を進めていたため、後から関係者間で実装内容の認識が異なっており認識合わせに時間がかかったこともあります。 一方で受託開発では基本的に行うべきタスクを明確にしないと次の工程に進まないため、要件定義や設計で詳細に作りたいものを決めていきます。また、すべての関係者が技術に明るいわけではないため、理解しやすく認識齟齬が起きないように絵や図を書きながら議論をしていきます。そのため、タスクの割り振りや知識の共有などはしやすかったです。 そのため、受託開発での経験を活かし、記載内容をテンプレート化する、文字だけでなくホワイトボードツールなどで絵や図を書くなどして少しでもドキュメントがわかりやすくなるような工夫を導入していきたいと思います。 不具合やバグの優先順位が相対的に高くないときがあること 不具合やバグがあっても発生するケースが稀であったり、影響の小さいものであれば他のタスクより優先度が下がることもあることに驚きました。以前は金融業界だったこともあり、高い信頼性が求められたため、不具合やバグはすべて対応しておりました。 ソフトウェアごとに求められる品質は異なるため、どちらがいい悪いと決めるのは難しいかとは思いますが、そもそも不具合はあってはいけない、不具合を発見したら早急に修正するという環境にいた身としてはこの差にはかなりギャップを感じました。 意外と打ち合わせが多いこと これも悪いというわけではないのですが、NeWork の開発では日々のスケジュールとしては午前中の大半は定例会議などで過ごしており、週に 1 回はイベントデーとして 1 日打ち合わせだけの日もあります。自分が想定していた内製開発ではもっと打ち合わせ回数は少なく、開発に充てる時間が大半だと思っておりました。1 週間でのトータル打ち合わせの時間だけでいえば、受託開発のときと大きな差はないと思います。 しかし、打ち合わせの内容は結構異なるなと感じました。受託開発時は基本的には社外の方と打ち合わせをすることが多く、打ち合わせのために何回もレビューをして準備を整えてから臨んでいました。内容としても進捗管理や課題管理がメインとなり、長い計画のなかでいかに QCD を満たすかを目指すことが多かったです。 一方で NeWork では社内の方との打ち合わせがほとんとです。1 回の計画期間が 2 週間と短いため、計画と振り返りを短いスパンで繰り返すイメージが強いです。 おわりに この記事では、私自身が NeWork の開発にジョインして感じた受託開発と内製開発の違いについて紹介させていただきました。受託開発・内製開発と一口に言ってもさまざまな企業があり、開発現場が異なれば上で挙げた内容が当てはまるとは限りませんが、この記事が読者の皆さまのお役に立てば幸いです。 最後に、2024 年 3 月現在、NeWork では一緒に開発を進めてくれる仲間を募集しています。詳細は以下のリンクをご覧ください。皆さまのご応募を心からお待ちしています! hrmos.co
アバター
NeWork 開発チームでは開発時間の 20%を主体的にプロダクトの改善に当てています。この取り組みの導入の背景や 1 年間運用して見えてきた良かったことや課題などをご紹介します。 目次 目次 はじめに NeWork とは 開発チーム改善活動 背景 活動内容 導入して良かったことと課題 良かったこと スプリントに積んだバックログアイテムが基本的に消化できるようになった エンジニアのモチベーション向上 インタラクションの改善もプロトタイプを通して納得感を与えられる コードの品質が上がる 課題 新機能を作った場合に他チームとの連携が難しい 新機能が放置されがち コンフリクトが起きる おわりに はじめに こんにちは。NeWork 開発チームの 2 年目エンジニアの中里です。普段はアジャイル開発エンジニアとしてフロントエンド・バックエンドを問わず、機能開発や改善を行っています。 この記事では、NeWork 開発チームが開発時間の 20%を主体的にプロダクトの改善に当てている取り組みの導入の背景や、1 年間運用して見えてきた良かったことや課題などをご紹介します。 NeWork とは NeWork は、コロナ禍に誕生したオンラインワークスペースサービスです。ワークスペース上のルームにワンクリックで入室でき、チームメンバーと気軽に話し始められる体験が売りのプロダクトです。 NeWork は、話し始めるまでの手軽さや打ち合わせ前後のコミュニケーションのしやすさ、メンバーのプレゼンスがわかることによる孤独感の緩和やコラボレーションのしやすさなど、リモートワークの課題感を解決できる設計がされています。 私の NeWork との出会いは学生の頃、コロナ禍に突入してからしばらく後でした。研究室の活動もリモート前提になり、ゼミや打ち合わせの度に打ち合わせ用 URL を発行する手間に辟易としていたところでこのサービスを知りました。 リモートワークに必要なのはこれだ!と当時の私は感銘を受け、インターンシップに参加・入社し、今では作る側になるくらいには良いプロダクトだと思っています。 開発チーム改善活動 NeWork の開発チームでは、1 年ほど前からプロダクトのためになることであれば、開発時間の 20%を費やして良いというルールを設けています。 チーム内ではこの活動を開発チーム改善活動と呼んでいます。 背景 開発チーム改善活動ができた経緯について。 NeWork では 2 週間スプリントのスクラムを行っています。プロダクト(企画)チームが立てた計画に基づき優先度を決めて、スプリントプランニングで次の 2 週間で開発するバックログアイテムを決めています。 計画通りに順調に開発が進むこともあれば、工数見積もりのブレやたまに降ってくる開発以外の社内業務によって開発が遅れることもありました。プランニングで積んだアイテムをスプリント内で終わらせようとして技術的負債を残すこともありました。実際に過去のレトロスペクティブを見ると次のスプリントプランニングの直前まで開発していることもあったようです。 また、特にプロダクトチームの事業計画的におしりが決まっている開発では、後々のスプリントでリファクタリングをやらせてもらう約束をプロダクトチームと決めた上で、スピードを優先させることもありました。 しかし、技術的負債を解消するためのバックログアイテムの優先度は永遠に上がらない上、リファクタリング前提で進めた箇所もどのタイミングでリファクタリングをするのか、どのくらいの時間をかけて良いのかをプロダクトチームと合意を取ることが難しいこともありました。 (※もちろん開発をしていない人にとってはコードがクリーンであることよりもお客さんに新しい価値を提供することの方が大切に見えるのは自然で仕方ないと思います) 他にもエンジニアが自主的に動くための時間を取りづらい問題もありました。 例えば、エンジニアが改善したい点(リファクタリングやライブラリのアップデート、機能改善など)を見つけた場合は、バックログアイテムを作成して、そのアイテムの価値をプロダクトオーナーに理解してもらいスプリントに積んでもらう必要もありました。改善に着手するためのハードルが高く、着手までのリードタイムが大分長くなっていました。 以下は実際にレトロスペクティブで出た課題です。 これらの問題に課題意識を持っている人が多く、レトロスペクティブで議題に挙がりました。 NTT Com 技術顧問の吉羽さんも自身のブログの スクラムで開発チームが自由な取り組みをするには? というポストで、「スプリントのキャパシティを見直して、開発チームが持続可能なペースで働けるようにする」ことを推奨されていることも話題に挙がり、 NeWork チームでも 1 スプリントで一律 20%の時間を開発チームが自由に使って改善を行えるようになりました 🎉 活動内容 開発チームの課題意識から生まれた開発チーム改善活動では、具体的に以下を活動内容と定めています。 機能改善 新機能開発 リファクタリング 技術動向を調査 優先度の低いバックログアイテムを先取り 実際に課題意識があったようにリファクタリング、次点で機能改善や新機能開発をする人が多い印象です。 我々 NeWork チームは日々の業務でドッグフーディングを兼ねて NeWork を利用しています。毎日使っているからこそ、各々が使いづらく感じるところを改善しているようでした。 例えば、以下の機能は開発チーム改善活動で生まれた/実装中の機能です。 ピクチャ・イン・ピクチャ機能 (ベータ機能としてリリース済み) タイル表示スタイル選択機能 (ベータ機能としてリリース済み) タイル表示スタイル: オート カメラ映像や画面共有の映像を自動的にタイル表示する (全員が顔出しする会議などで便利です) タイル表示スタイル: フォーカス 選択したユーザを排他的にタイル表示する (小さい画面で複数の画面を見比べる際に便利です) タイル表示のレスポンシブ対応 (リリース済) 改善前: 事前に用意されたグリッドレイアウトに映像ストリームを順番に割当 改善後: ウィンドウサイズや映像ストリームをのサイズ考慮して各ストリームの面積の和が最大化されるレイアウトを動的に作成して割当 タイル表示中の映像をズームする機能 (リリース済) ルームメッセージへのカスタムリアクション (リリース済) メッセージのリッチテキスト対応 (実装中) メッセージでのメンション機能 (実装中) メッセージでのリンクのプレビュー機能 (実装中) 日頃から NeWork をご利用していただいている方には、馴染のある機能もあったかもしれません。エンジニアならではの視点での改善や新機能開発が上手く回っており、良い取り組みだと感じています。 ちなみに、上 3 つは私が開発しました。私は自分のアイデアを形にするのが好きで、よく使いにくいところを改善したり欲しいと思った機能を開発したりしていました。(楽しい!) 導入して良かったことと課題 良かったこと スプリントに積んだバックログアイテムが基本的に消化できるようになった スプリントプランニングの段階でベロシティの 80%をバックログに積み、余った時間を開発チーム改善活動に充てる運用をすることで、工数見積もりのブレを吸収し、スプリント内にバックログアイテムを消化できないことはほぼなくなりました。リリーススケジュールの見通しが良くなったといえます。 スプリント内にすべてのバックログアイテムを消化しようと急ぐことがなくなり、精神的余裕ができました。 エンジニアのモチベーション向上 リファクタリングやライブラリのアップデートなどをやりたいと思ったらそのスプリント内でできるため、リードタイムがありません。リードタイムがないので構想したものを忘れたり、熱意が覚めることもありません。 20%の時間は自分で裁量を持って好きな開発をできるため、シンプルにモチベーションが上がります。 インタラクションの改善もプロトタイプを通して納得感を与えられる 操作体験が絡む、インタラクションが重要になる改善をバックログアイテムにして計画的に取り組むことは難しいと考えています。プロダクトに使いづらさを感じていても、プロダクトの人がデザインや実装に詳しくないと改善できることに気付けないし、気づけても言語化もし辛いのでバックログにもし辛いからです。 それに対して、エンジニアが自由に使える時間の中で、作りながら体験を模索していけるので手触りの良いものが作りやすいです。 ステークホルダーにプロトタイプを触ってもらって、納得感を持ってもらった状態でリリースに踏み切れるのも大きいです。 コードの品質が上がる プロダクトバックログアイテムに取り掛かっているときに、気になる実装を見つけたときにすぐにリファクタリングできるのでコードの品質が保たれます。 課題 新機能を作った場合に他チームとの連携が難しい 基本的に、開発チーム改善活動で取り組む内容はスプリントプランニングを通さないので、他のチームの人はスプリントレビューで初めて新機能の内容を知ることになります。 計測やリリースノートなどはプロモーションチームが担当しているため、事前に相談したり、リリースを遅らせることもありました。 エンジニアがプロトタイプを作り、スプリントレビューに持っていき、リリースすることが決まってからデザイナが UI を作ることが多かったため、リリースまでのリードタイムがかかります。それを踏まえ、最近はレビュー前に事前にデザインしてもらうこともあります。 新機能が放置されがち 開発チーム改善内容で新機能を作ると、それに関わる人が少なくチーム内での影が薄くなりやすいです。とりあえずベータ機能としてリリースした場合に忘れ去られてることもあります。これは開発した人がアフターフォローをしっかりするべきなのかなと思います。私の開発したベータ機能も本格採用するか削除するかしないと… コンフリクトが起きる 自由な活動ができるといってもスプリント内の 20%の時間しか使えないので、開発が数スプリントに跨ることも多く、コンフリクトが起こることもしばしばあります。これは仕方ないですね。 おわりに NeWork 開発チームでは約 1 年間、開発時間の 20%をエンジニアが自由に使える時間、開発チーム改善活動を運用してきました。 チームの一エンジニアとしては、コードの品質向上やエンジニアのモチベーション向上、価値創造につながっており、非常に良い取り組みだと感じています。 実は、この活動を通してできた改善・新機能のうち、機能自体や内部のアルゴリズムなどで 3 件の特許出願を行っています。私も 2 件出願しています。現在審査中で特許として認められるかはまだわかりませんが、それなりに価値のあるアウトプットが自発的にできたこともこの仕組みのおかげだと思っています。 NeWork は 20 人までのフリープランは無料でお試しいただけます。もしご興味を持っていただけた方はぜひお試しください。 また、2024 年 3 月現在、NeWork では一緒に開発を進めてくれる仲間を募集しています。詳細は以下のリンクをご覧ください。皆さまのご応募を心よりお待ちしています! hrmos.co
アバター
サマリ 概要 Inter-AS Option B における (b) の実現方法 (1) ASBR で next-hop ごとの VPN ラベルを生成する方法 (2) ASBR で Egress Peer に対する EPE ラベルを生成し、 VPN ラベルは対向 AS の ASBR が生成したものを利用する方法 検証 (1) の検証 1. ルートポリシーの設定 2. VPN ラベルの確認 3. traceroute による VPN の通信経路確認 (2) の検証 1. EPE ラベルを生成する設定 2. BGP-LU の設定 3. ルートポリシーの設定 4. PE での EPE ラベル確認 5. traceroute による VPN の通信経路確認 まとめ サマリ Multi-AS の SR-MPLS + VPNv4 環境で AS 間での TE を実現するため、ASBR 間 next-hop を PE で選択する方法を検証 next-hop ごとに VPN ラベルを生成する Nokia ASBR と、 BGP-LU で ASBR 間 next-hop をそのまま広告する Cisco ASBR の 2 通りで動作確認に成功 この記事は Multi-AS Segment Routing 検証連載の第 20 回です。 過去の記事一覧は こちら にあります。 概要 イノベーションセンターの吉田 晴信です。 業務では Multi-AS Segment Routing に関する技術検証をしています。 本記事では、Multi-AS での Segment Routing を活用した Traffic Engineering(SR-TE)の実現方法について紹介します。 Multi-AS での SR-TE で実現したい要求として、 第 5 回の記事 では下記の 2 点を挙げています。 (a) AS 内で意図した経路を選択したい(AS 内での TE) (b) 他 AS との接続経路を選択したい(AS 間での TE) (a) の実現方法については 第 5 回の記事 で説明しています。本記事では (b) の実現方法を説明します。 Inter-AS Option B における (b) の実現方法 本記事では MPLS Inter-AS Option B を前提に SR-MPLS + VPNv4 で (b) を実施する方法を紹介し動作検証を行います。 はじめに、Option B で (b) を実施する際の課題を説明します。 (b) を実施する場合、下記の 3 種のラベルが必要です。 ASBR に到達するまでのラベル ASBR から先を示すラベル VPN を識別するラベル ラベルの処理としては、「 ASBR に到達するまでのラベル」は ASBR 到達までに Pop されますが、 「 ASBR から先を示すラベル」と「 VPN を識別するラベル」は Pop されません。 「 ASBR から先を示すラベル」は ASBR で next-hop を選択する際に Pop され、 「 VPN を識別するラベル」は ASBR 間 で VPN を識別するのに必要であるため Swap されます。 つまり、ASBR では Pop と Swap の 2 つの処理を同時に行う必要があります。 ですが、現状 Cisco/Juniper/Nokia 機器では「 ASBR から先を示すラベル」と「 VPN を識別するラベル」を同時に ASBR で処理する機能がありません。 つまり、(b) を 1 つの ASBR につき 1 ラベルのみ処理する方法で実現する必要があります。 実現方法として、本記事では下記の 2 点を紹介します。 (1) ASBR で next-hop ごとの VPN ラベルを生成する方法 (2) ASBR で Egress Peer に対する EPE ラベルを生成し、 VPN ラベルは対向 AS の ASBR が生成したものを利用する方法 (1) ASBR で next-hop ごとの VPN ラベルを生成する方法 1 点目の方法では、next-hop ごとに受信した NLRI 単位で経路に異なる VPN ラベルを生成します。 これにより、VPN ラベルは ASBR 間 next-hop に対応します。 そして経路を PE に広告することで、PE で ASBR 間 next-hop を選択できます。 この方法は Nokia ASBR で使用できることを確認しています。 (2) ASBR で Egress Peer に対する EPE ラベルを生成し、 VPN ラベルは対向 AS の ASBR が生成したものを利用する方法 2 点目の方法では、自 AS の ASBR で Egress Peer に対応する EPE ラベルを生成します。 EPE ラベルを生成した経路は RFC3107 で標準化されている BGP-LU を使用し PE に広告します。 VPN 経路は対向 AS の ASBR から Inter-AS の VPN ラベルがついた状態で自 AS の ASBR で受信されます。 自 AS の ASBR から PE にこの経路を広告しますが、このとき経路の next-hop-self を使用せずそのまま広告します。 PE は 対向 AS の ASBR のアドレスを EPE ラベルがついた状態で学習できているため、 next-hop を書き換えない状態でも経路の解決が可能です。 以上により、PE で対向 AS の ASBR を選択でき、自 AS の ASBR では EPE ラベルを処理するだけなので転送可能となり、 VPN ラベルも 対向 AS の ASBR で解釈可能なため問題なく通信できます。 この方法は Cisco ASBR で使用できることを確認しています。 検証 本記事では (1) と (2) の方法で PE において ASBR 間 next-hop を選択できることを確認します。 前提である Multi-AS の SR-MPLS + VPNv4 の設定は  第 12 回の記事 をご参照ください。 また、(1) と (2) 両方で経路選択するため、ルートポリシーを用いて weight/LP を変更する方法を採用しています。 (1) の検証 (1) は下記のトポロジーで検証します。 使用した各ルーターのバージョンは下記の通りです。 1-PE01: IOS XR 7.9.2 1-PE02、1-ASBR02、1-ASBR03、1-PE04: Junos OS 22.3R1.11 1-PE03、1-ASBR01: SR OS 22.7.R1 検証の手順は下記の通りです。 ルートポリシーの設定 VPN ラベルの確認 traceroute による VPN の通信経路確認 1. ルートポリシーの設定 1-ASBR01 から受信した経路を選択するため、各 PE でルートポリシーを設定します。 今回設定するルートポリシーは下記の 2 つです。 BGP で vrf-100 に対して、次に経由する AS が 65002 の経路を広告されたとき、その経路の weight を 10000 にする。 BGP で vrf-200 に対して、次に経由する AS が 65003 の経路を広告されたとき、その経路の weight を 10000 にする。 これにより、vrf-100 の通信では AS65002 に直接転送する経路が選択され、 vrf-200 の通信では AS65003 を経由して AS65002 に転送する経路が選択されます。 トラフィックの流れは下記の通りです。 1-PE01 におけるルートポリシーの設定例です。 as-path-set as-65002 neighbor-is '65002' end-set ! as-path-set as-65003 neighbor-is '65003' end-set ! route-policy asbr-selection-based-rd if rd in rds-select-65002 and as-path in as-65002 then set weight 10000 endif if rd in rds-select-65002 and as-path in as-65003 then set weight 1000 endif if rd in rds-select-65003 and as-path in as-65003 then set weight 10000 endif if rd in rds-select-65003 and as-path in as-65002 then set weight 1000 endif pass end-policy ! また、ASBR が広告した経路にルートポリシーを適用するため、下記を設定します。 router bgp 65001 neighbor-group ibgp address-family vpnv4 unicast route-policy asbr-selection-based-rd in ! ! ! 本記事では紹介していませんが、1-PE02 と 1-PE03 についても同じ内容を設定します。 なお、この節で紹介した設定は経路選択するためのものであり、(1) 実現のために第 12 回の記事から追加設定はありません。 2. VPN ラベルの確認 1-ASBR01 で生成された VPN ラベルを確認します。 下記の通り ASBR 間 next-hop ごとに異なる VPN ラベルが生成されていることがわかります。 [/] A:user@1-ASBR01# /show router bgp inter-as-label =============================================================================== BGP Inter-AS labels Flags: B - entry has backup, P - entry is promoted =============================================================================== NextHop Received Advertised Label Label Label Origin ------------------------------------------------------------------------------- 10.100.1.2 36 524280 External 10.100.1.2 37 524279 External 10.100.2.2 22 524278 External 10.100.2.2 23 524277 External 10.255.1.1 24002 524284 Internal 10.255.1.1 24003 524283 Internal 10.255.1.2 16 524274 Internal 10.255.1.2 17 524273 Internal 10.255.1.3 524284 524276 Internal 10.255.1.3 524286 524275 Internal ------------------------------------------------------------------------------- Total Labels allocated: 10 =============================================================================== 1-PE01 に上記で生成された VPN ラベルが広告されているか確認します。 下記は 1-PE01 における vrf-100 の経路ですが、1-ASBR01 で確認した VPN ラベルが広告されていることがわかります。 RP/0/RP0/CPU0:1-PE01#show bgp vpnv4 unicast rd 65002:100 labels (snip) Status codes: s suppressed, d damped, h history, * valid, > best i - internal, r RIB-failure, S stale, N Nexthop-discard Origin codes: i - IGP, e - EGP, ? - incomplete Network Next Hop Rcvd Label Local Label Route Distinguisher: 65002:100 Route Distinguisher Version: 525 *>i192.168.4.0/24 10.255.1.4 524280 nolabel * i 10.255.1.4 524278 nolabel Processed 1 prefixes, 2 paths vrf-200 も同じです。 RP/0/RP0/CPU0:1-PE01#show bgp vpnv4 unicast rd 65002:200 labels (snip) Status codes: s suppressed, d damped, h history, * valid, > best i - internal, r RIB-failure, S stale, N Nexthop-discard Origin codes: i - IGP, e - EGP, ? - incomplete Network Next Hop Rcvd Label Local Label Route Distinguisher: 65002:200 Route Distinguisher Version: 524 * i192.168.14.0/24 10.255.1.4 524279 nolabel *>i 10.255.1.4 524277 nolabel Processed 1 prefixes, 2 paths 1-PE02 と 1-PE03 の vrf-100 と vrf-200 でも同様の経路が確認できます。 3. traceroute による VPN の通信経路確認 PE から ASBR 間 next-hop が選択できているか確認するため、 traceroute コマンドを実行します。 1-PE01 vrf-100 -> 1-PE04 vrf-100 1-PE01 の vrf-100 から 1-PE04 の vrf-100 に対して traceroute を実行します。 結果、AS65002 へ直接転送されました。 また、1-PE02 と 1-PE03 の vrf-100 でも同様の結果となりました。 RP/0/RP0/CPU0:1-PE01#traceroute 192.168.4.254 vrf 100 Fri Jan 26 10:19:06.080 JST Type escape sequence to abort. Tracing the route to 192.168.4.254 1 10.100.1.1 [MPLS: Labels 16004/524280 Exp 0] 4 msec 3 msec 3 msec 2 10.100.1.2 [MPLS: Label 36 Exp 0] 3 msec 3 msec 3 msec 3 192.168.4.254 3 msec 3 msec 4 msec 1-PE01 vrf-200 -> 1-PE04 vrf-200 1-PE01 の vrf-200 から 1-PE04 の vrf-200 に対して traceroute を実行します。 結果、AS65003 を経由し AS65002 へ転送されました。 また、1-PE02 と 1-PE03 の vrf-200 でも同様の結果となりました。 RP/0/RP0/CPU0:1-PE01#traceroute 192.168.14.254 vrf 200 Fri Jan 26 10:19:10.027 JST Type escape sequence to abort. Tracing the route to 192.168.14.254 1 10.100.2.1 [MPLS: Labels 16004/524277 Exp 0] 3 msec 2 msec 2 msec 2 * * * 3 10.100.3.1 [MPLS: Label 37 Exp 0] 4 msec 3 msec 4 msec 4 192.168.14.254 4 msec 3 msec 3 msec (2) の検証 (2) は下記のトポロジーで検証します。 なお (1) と検証時期が異なるため、環境が少し違います。 各ルーターのバージョンは下記の通りです。 2-PE01、2-ASBR01、2-ASBR02、2-ASBR03、2-PE04: IOS XR 7.9.2 2-PE02: SR OS 23.3.R3 2-PE03: Junos OS 22.3R1.11 検証の手順は下記の通りです。 EPE ラベルを生成する設定 BGP-LU の設定 ルートポリシーの設定 PE での EPE ラベル確認 traceroute による VPN の通信経路確認 1. EPE ラベルを生成する設定 Egress Peer に対して EPE ラベルを生成するため、2-ASBR01 に下記を設定します。 router bgp 65001 neighbor 10.100.1.2 egress-engineering peer-node-sid index 100 ! neighbor 10.100.2.2 egress-engineering peer-node-sid index 200 ! ! mpls static interface GigabitEthernet0/0/0/2 ! interface GigabitEthernet0/0/0/3 ! ! 生成された EPE ラベルは下記のコマンドで確認できます。 RP/0/RP0/CPU0:2-ASBR01#show bgp egress-engineering Mon Dec 4 19:46:30.145 JST Egress Engineering Object: 10.100.1.2/32 (0x7f38b4250e28) EPE Type: Peer Nexthop: 10.100.1.2 Version: 30, rn_version: 30 Flags: 0x00000026 Local ASN: 65001 Remote ASN: 65002 Local RID: 10.255.1.3 Remote RID: 10.255.1.3 Local Address: 10.100.1.1 First Hop: 10.100.1.2 NHID: 2 IFH: 0x1000028 Label: 15100, Refcount: 4 rpc_set: 0x7f3858002300, ID: 14 Egress Engineering Object: 10.100.2.2/32 (0x7f38b4250f20) EPE Type: Peer Nexthop: 10.100.2.2 Version: 31, rn_version: 31 Flags: 0x00000026 Local ASN: 65001 Remote ASN: 65003 Local RID: 10.255.1.3 Remote RID: 10.255.1.1 Local Address: 10.100.2.1 First Hop: 10.100.2.2 NHID: 3 IFH: 0x1000020 Label: 15200, Refcount: 4 rpc_set: 0x7f3858002570, ID: 15 2. BGP-LU の設定 生成した EPE ラベルを PE に広告するため、2-ASBR01 で BGP-LU を設定します。 router bgp 65001 address-family ipv4 unicast advertise epe-bgp labeled-unicast allocate-label all ! neighbor 10.255.1.1 use neighbor-group ibgp address-family ipv4 labeled-unicast ! neighbor 10.255.1.2 use neighbor-group ibgp address-family ipv4 labeled-unicast ! neighbor 10.255.1.4 use neighbor-group ibgp address-family ipv4 labeled-unicast 下記は 2-PE01 における BGP-LU の設定です。 本記事では紹介していませんが、2-PE02 と 2-PE03 についても同じ内容を設定します。 router bgp 65001 address-family ipv4 unicast allocate-label all ! neighbor 10.255.1.3 use neighbor-group ibgp address-family ipv4 labeled-unicast 3. ルートポリシーの設定 経路を選択するため、ルートポリシーを設定します。 設定は (1) と同じなので省略します。 トラフィックの流れは下記の通りです。 4. PE での EPE ラベル確認 2-ASBR01 で生成された EPE ラベルが BGP-LU で PE に広告されているか確認します。 2-PE01 で下記のコマンドを実行すると、 2-ASBR01 から EPE ラベルが広告されていることがわかります。 RP/0/RP0/CPU0:2-PE01#show bgp ipv4 labeled-unicast 10.100.1.2/32 Mon Dec 4 20:08:01.877 JST BGP routing table entry for 10.100.1.2/32 Versions: Process bRIB/RIB SendTblVer Speaker 3 3 Last Modified: Dec 4 19:57:00.035 for 00:11:01 Paths: (1 available, best #1) Not advertised to any peer Path #1: Received by speaker 0 Not advertised to any peer Local 10.255.1.3 (metric 20) from 10.255.1.3 (10.255.1.3) Received Label 15100 Origin IGP, localpref 100, valid, internal, best, group-best, labeled-unicast Received Path ID 0, Local Path ID 1, version 3 RP/0/RP0/CPU0:2-PE01#show bgp ipv4 labeled-unicast 10.100.2.2/32 Mon Dec 4 20:07:41.067 JST BGP routing table entry for 10.100.2.2/32 Versions: Process bRIB/RIB SendTblVer Speaker 2 2 Last Modified: Dec 4 19:57:00.035 for 00:10:41 Paths: (1 available, best #1) Not advertised to any peer Path #1: Received by speaker 0 Not advertised to any peer Local 10.255.1.3 (metric 20) from 10.255.1.3 (10.255.1.3) Received Label 15200 Origin IGP, localpref 100, valid, internal, best, group-best, labeled-unicast Received Path ID 0, Local Path ID 1, version 2 また、vrf-100 と vrf-200 の経路を確認すると、 VPN ラベルを付与する経路の次に、EPE ラベルを付与する経路が選択されることを確認できます。 RP/0/RP0/CPU0:2-PE01#show route vrf 100 (snip) C 192.168.1.0/24 is directly connected, 13w5d, GigabitEthernet0/0/0/1 L 192.168.1.254/32 is directly connected, 13w5d, GigabitEthernet0/0/0/1 B 192.168.2.0/24 [200/0] via 10.255.1.2 (nexthop in vrf default), 1d01h B 192.168.2.254/32 [200/0] via 10.255.1.2 (nexthop in vrf default), 1d01h B 192.168.3.0/24 [200/0] via 10.100.1.2 (nexthop in vrf default), 03:25:39 (snip) RP/0/RP0/CPU0:2-PE01#show route vrf 200 (snip) C 192.168.11.0/24 is directly connected, 13w4d, GigabitEthernet0/0/0/2 L 192.168.11.254/32 is directly connected, 13w4d, GigabitEthernet0/0/0/2 B 192.168.12.0/24 [200/0] via 10.255.1.2 (nexthop in vrf default), 00:01:45 B 192.168.12.254/32 [200/0] via 10.255.1.2 (nexthop in vrf default), 00:01:45 B 192.168.13.0/24 [200/0] via 10.100.2.2 (nexthop in vrf default), 00:03:15 (snip) 2-PE02 と 2-PE03 でも同じ情報が広告されています。 5. traceroute による VPN の通信経路確認 PE から ASBR 間 next-hop が選択できているか確認するため、traceroute コマンドを実行します。 2-PE01 vrf-100 -> 2-PE04 vrf-100 2-PE01 の vrf-100 から 2-PE04 の vrf-100 に対して traceroute を実行します。 結果、AS65002 へ直接転送されました。 また、2-PE02 と 2-PE03 の vrf-100 でも同様の結果となりました。 RP/0/RP0/CPU0:2-PE01#traceroute 192.168.3.254 vrf 100 Tue Dec 5 21:31:08.445 JST Type escape sequence to abort. Tracing the route to 192.168.3.254 1 10.1.1.2 [MPLS: Labels 15100/24007 Exp 0] 3 msec 2 msec 2 msec 2 10.100.1.2 [MPLS: Label 24007 Exp 0] 3 msec 2 msec 2 msec 3 10.1.1.1 4 msec * 4 msec 2-PE01 vrf-200 -> 2-PE04 vrf-200 2-PE01 の vrf-200 から 2-PE04 の vrf-200 に対して traceroute を実行します。 結果、AS65003 を経由し AS65002 へ転送されました。 また、2-PE02 と 2-PE03 の vrf-200 でも同様の結果となりました。 RP/0/RP0/CPU0:2-PE01#traceroute 192.168.13.254 vrf 200 Tue Dec 5 21:31:26.660 JST Type escape sequence to abort. Tracing the route to 192.168.13.254 1 10.1.1.2 [MPLS: Labels 15200/32004 Exp 0] 3 msec 2 msec 2 msec 2 10.100.2.2 [MPLS: Label 32004 Exp 0] 3 msec 3 msec 2 msec 3 10.100.3.1 [MPLS: Label 24009 Exp 0] 2 msec 2 msec 2 msec 4 10.1.1.1 4 msec * 4 msec まとめ 本記事では、Multi-AS の SR-MPLS + VPNv4 環境で AS 間での TE を実現するため、 ASBR 間 next-hop を PE で選択する方法と検証結果を紹介しました。 (1) の方法では、ASBR 間 next-hop ごとに受信した NLRI 単位で経路に異なる VPN ラベルを生成し、PE に広告できました。 こちらは Nokia ASBR を使用し確認しました。 (2) の方法では、まず自 AS の ASBR で Egress Peer に対応する EPE ラベルを生成し、BGP-LU で PE に広告しました。 また、対向 AS の ASBR から広告される VPN ラベルを付与する経路の next-hop を書き換えずに PE へ広告しました。 結果、PE で対向 AS の ASBR を選択できるようになり、自 AS の ASBR では EPE ラベルを処理するだけでよくなりました。 こちらは Cisco ASBR を使用し確認しました。 以上の方法に加えて、Cisco/Juniper/Nokia PE でルートポリシーを設定し、 選択したい VPN 経路の weight を大きくすることにより、PE から次に経由する AS を選択できました。
アバター
はじめに はじめまして。クラウド&ネットワークサービス部 データプラットフォームビジネス推進部門で IoT Connect Mobile Type S (以下 ICMS)の販売推進を担当している、櫻井幸大です。普段はICMS/モバイル回線の開発~運用を担当しているのですが、今回はOJT(別部署で勤務をする社内研修)のためICMSの販売推進として記事執筆をすることとなりました。 今回は、 ICMSを使い販売推進担当で遠くからカメラを動かすシステムを作ってみました ので(機器を他社から購入し、ICMSと組み合わせて自分たちでプログラムを作りました)、その様子をお伝えします。 ICMSとは? ICMSとは、NTT Comが提供するIoTデバイス向けのSIMカード/通信回線です。SIMカードと通信回線を管理するためのポータルもセットで提供しています。お客さまの用途に合わせて柔軟に 料金プラン や 接続方式 を選択できることが、ICMSの特長です。 さまざまな料金プラン 選べる3つの接続方式 ICMSで何ができるの? ICMSを使えば、IoTデバイスをセキュアにクラウドへと接続できます。IoTデバイスが測定&収集したデータを遠隔地にあるサーバーやデータセンターにアップロードする、ということですね。またICMSでは、IoTデバイスから送られた非暗号化データを暗号化したり、インターネットを通らずに閉域網へとつなぐ接続方式が選択可能で、お客さま通信の安全性・秘匿性を高めることができます。 例えば、山奥のダムや河川の水位を監視する場合を考えてみましょう。遠く離れた山奥まで毎日毎日様子を見に行くのは大変で、稼働的にも無駄が大きいです。大規模災害時に瞬時に様子を確認しづらい、という問題点も考えられます。 ICMSとIoTカメラ機器を使えば、誰でも手軽に遠くの場所を確認できます。 そこで今回の記事では、会社に置いてある私たち販売推進担当のロッカーを離れた場所から確認してみたいと思います。 準備したもの 使用した機材はこちらになります。 1. ICMS 先ほどご紹介をした、当社のIoT向け SIMカード/通信回線です。 2.IoT Connect Gateway(ICGW) IoT Connect Gateway (以下 ICGW)は、ICMS(SIMカード)の刺さったデバイスがデータを簡単に・セキュアにアップロードするためのIoT向けのゲートウェイです。ICGWはICMSとセットで利用しやすいよう設計されており、簡単な設定だけでIoTデバイスICGW経由でクラウドめがけてデータを転送してくれるようになります。 ICGWを経由してクラウドに接続することには、以下の2つのメリットがあります。 本来はデバイス側で実施する暗号化の処理を、ICGW上で実施できる クラウド接続のための認証情報を、デバイスの代わりにICGWで管理できる ICGWを活用することで、IoTデバイスの設定の手間や処理の負荷を軽減できるのです。 ICGWはAWS、Azureなどさまざまなクラウドとの接続に対応していますが、今回はWasabiオブジェクトストレージとの接続機能 =「ストレージ機能」を活用してみます。 3.Wasabiオブジェクトストレージ Wasabiオブジェクトストレージ (以下 Wasabi)はNTT Comが提供するAWS S3互換APIを提供する業界最安値水準のパブリッククラウド型オブジェクトストレージサービスです。データの書き込み・読み込みが速くでき、かつ、低価格で大容量データを保存できることが特長です。 4.KC4-C-100A(KC4) KC4-C-100A (以下 KC4)はセンサー・GNSS・ビーコン・Webカメラをクラウドへとつなぐ際の中継となる、京セラ社製(以下 京セラ)のデバイスです。 多様なインターフェイスを備えているため、さまざまな測定機器との接続が可能です。また、難しいプログラミングをせずとも機器の制御ができることも特長のひとつです。(プログラミングのサンプルレシピが 京セラのWebサイト に多数公開されているので、簡単に設定可能です。) 5.USBカメラ 今回の構成では、普段Web会議で使用しているUSBカメラをそのまま使用しました。(KC4で動作確認済みのUSBカメラの一覧は、 メーカーのサイト をご覧ください。) 以上すべての機器をまとめたシステム構成が、下の画像のようになっています。IoTデバイスがICMS(モバイル回線)を通してICGWへと画像データを送り、ICGWがWasabiにデータを転送することで、ストレージに記録がどんどん蓄積されていく、ということですね。 構築手順 次に、上で紹介した5つの道具をもとに、どうすればロッカーの遠隔様子見システムが構築できるのかを説明します。 ICMS SIMにICGW利用申し込みをする ICGWに接続するSIMカードは事前に申し込みを実施する必要があります。ICMS, ICGWをはじめとしたNTT Comのサービスは、お客さまへ提供しているSmart Data Platform(以下 SDPF)ポータルのサイトから一括管理ができますので、そちらを通して申し込みをしていきましょう。 SDPFポータルに移動をして、ご契約中のワークスペースを選択。 「メニュー」のタブからIoT Connect Mobile Type Sを選択。 すると、SIMカードの利用状況一覧を表すサイトに移動します。 ここではSIMカードをグループごとにまとめて管理でき、例えば利用拠点や用途ごとに契約中のSIMカードを分類できます。便利ですね。 今回開通しようとしているSIMカードがあるグループのところに移動します。 HSN(シリアルナンバー)がSIMカードに印字されているものと合っていることを確認して、「ICGW利用」のタブを選択。 「NTTCの計1プロファイルに対しICGW利用申込しようとしています」のチェックボックスにチェックを入れ、確定ボタンを押下。これにてICGWの利用設定が完了です。 SIMカード(ICMS)の開通 ICMSはSIMカードが未開通(通信ができない)状態でお手元に届きます。 私たちが今回使ったSIMカードもお客さまに届く際と同様に未開通状態だったので、開通の処理を行います。 先ほどの、開通したいSIMカードが表示されるSIMグループのところに移動します。シリアルナンバーが正しいことを確認して、上の「開通」のボタンをポチリ。 すると接続プラン・通信量の上限・ICGWの利用有無を確認するサイトに移動します。 ご希望のプランを選択し(今回は従量・無制限・ICGW接続を選択)、「入力内容を確認する」を押します。これでSIMカード側の設定は完了です。 Wasabiオブジェクトストレージの設定 次にデータの蓄積をするWasabi(ストレージサーバー)側の設定をしていきます。 Wasabiには送られてくるデータを格納する場所である「バケット」と送り主が本当に正しい人なのかを判断するための「認証キー」を設定する必要があります。 まずはWasabi Console(管理画面)へと移動し、メニューバーから「バケット」の部分をクリックします。 右上の「バケットを作成」のボタンを押すとバケットの名前を入力するタブが開きます。適切なバケット名(英数小文字で入力)・地域(Tokyo ap-northeast-1 または Osaka ap-northeast-2のうち近い方を選択)を選択し、「バケットを作成」を押します。 これでバケットが作成できました。 バケットの中にフォルダーを作成することで、データによって格納先を変えることが可能です。データをどのフォルダーに格納するのかはICGWで一括管理できるので、いちいちIoTデバイスのプログラミングを変更する必要はありません。 今回はロッカーの写真をまとめて撮影したいので「31F_Locker」のフォルダーをバケットの中に作成します。 バケットの設定が終わったら、最後にアクセスキーの設定です。Wasabiへのアクセス時、アクセスキーと秘密鍵で認証することで、第三者からの不正アクセスを防ぎます。 まずは左のメニューバーから「アクセスキー」をクリックし、右上の「アクセスキーを作成する」のボタンからアクセスキーを発行します。 このアクセスキー・秘密鍵をICGWに設定すれば、鍵認証の仕組みが完了です。(秘密鍵は認証のための鍵ですので、大切に保管してください。) ICGWストレージ機能の設定 1. 「認証」の新規作成 Wasabiに接続するための認証情報をICGWに登録します。 まずはICGWポータルの左側のメニューの「認証」をクリックします。証明書種別は、「AWS認証」を選択し、先ほど保存しておいたWasabiに接続するためのアクセスキーID、シークレットアクセスキー(秘密鍵)を入力し、「作成」をクリックします。 ICGWを利用しない場合、アクセスキーなどの認証情報はデバイスに設定する必要があります。10台デバイスがあると10回設定作業をしなければなりません。ICGWを使えば、接続先が同じであれば複数のデバイス分まとめて登録作業が可能です。 2. SIMグループ新規作成 ICGWを利用する場合、接続先が同じSIMカードはグループ化したうえで接続情報を管理できます。 今回は「ux20240115」というグループを作成し、利用するSIMカードをそのグループの中に追加したいと思います。メニューの中の「グループ」を選択し、「グループ名」を入力し、「SIM設定」にて新規グループに入れたいSIMカードを選択し、「作成」をクリックします。 今回利用するSIMカードの情報を見てみると、先ほど新しく作成したグループに所属できていることが確認できました。 3. グループのデータ転送設定 2.で新規作成したSIMのグループからどのようにデータを転送するかの詳細設定をしていきます。ますは、メニューから「グループ」を選択し、先ほど作成した「ux20240115」というグループを選択します。 グループの中に入ったら、今回利用する「ストレージ」のタブを選択。右側の「新規作成」をクリックし、 必要な項目を入力していきます。 必要な項目が多く、少し複雑に感じるかもしれませんが、 「エントリーポイント」= デバイスからICGWに接続するための情報 「宛先設定」= ICGWからWasabiの特定のフォルダーに接続するための情報 という風に分けて考えると分かりやすいと思います。 これでICGWの設定は完了です! デバイスの設定 1. デバイス設定の下準備 KC4の設定は、設定用PCから実施します。まずは、設定用PCに対して、デバイス設定のために必要なアプリケーションをインストールしておきましょう。詳細については、 メーカーのサイト をご参照ください。 2. SIMカードの差し込み、ケーブル結線 KC4にICMS(nano SIMサイズ)を挿入して、KC4と設定用PC、Webカメラ、電源を接続し、電源をONにします。 3. APN(Access Point Name)、ID/Passの設定 ICMSとICGWを利用する際に必要となるAPNとID/Passを設定します。設定用PC上でKC4設定用アプリケーションを立ち上げ、「設定値読込/書込み」をクリックします。 「設定項目」の中の「APN」を選択し、 SDPF ナレッジセンター に掲載されているICMS、ICGW利用時のAPN、ID/Pass情報を入力します。 入力ができたら、「書込み」をクリックします。そうすると、設定が反映された状態でデバイスが再起動されます。 起動後、デバイスのモニター上に「Hello!」と表示されていれば完了です。 4. デバイスの振る舞いを定義するプログラム作成 続いて、KC4の振る舞いを定義するプログラムを作成します。KC4のプログラムの作成方法には以下の3つがあります。 「ノーコード」:Webサイトに掲載されているレシピ(すでに作成されているプログラムデータ)を活用する方法 「ローコード」:画面操作でプログラミングができる「ブロックプログラミング」を活用する方法 「レシピ言語」:柔軟にKC4の振る舞いを定義するため、自分でプログラムを作成する方法 今回は「レシピ言語」を活用してプログラムを作成しました。 メーカーのWebサイト からサンプルコードをダウンロードし、コード同士を組み合わせたり、必要なところを書き換えたりしていきます。 サンプルコードの中の 「08_ボタン」:ボタンを押下するとデバイスを動作させるコード 「04_カメラ」:カメラを起動させ画像を送信するコード を組み合わせてプログラムを作成します。 プログラムを書き換えた主な箇所は、こちらです。 // 通信先設定値 #define CONN_HOSTNAME "an1.icgw.ntt.com" // 接続先ホスト名(ICGWで指定されているエンドポイント) #define CONN_PORT 8081 // 接続先ポート番号(ICGWで指定されているポート番号) #define CONN_PROTOCOL MMG_PROTOCOL_HTTP // HTTP通信を利用する #define HTTP_STR_URL "/ux20240115" // URL(ICGWのPath設定にて入力した値) #define HTTP_STR_METHOD MMG_METHOD_HTTPPUT // HTTPメソッド(HTTP PUTを利用 *元々POSTだったがPUTに修正) #define HTTP_STR_HEADER "Content-Type: image/jpeg" // HTTPヘッダ(jpegのtype指定) デバイスからのデータ送信先がICGWになるように書き換えています。 作成したプログラムの一部をご紹介しますと・・・ // キー押下時の処理 func event_key () { // <OLED> // カメラ制御開始をOLEDに文字表示(ボタンを押したら"CAMERA_START"とLEDに表示) OLC_DisplayChar (OLC_CHAR_USER, 0 , 0 , "CAMERA_START " ); OLC_DisplayChar (OLC_CHAR_USER, 18 , 0 , " " ); // <USBカメラの撮影要求> // カメラ撮影スタート(解像度:HD, フレームレート:10[fps]) UVC_VideoStreamCtrl (UVC_STREAM_CTRL_START, UVC_STREAM_CODEC_MJPEG, 1280 , 720 , 100 ); // カメラ起動~画像が取得できるまで10秒ほど待つ rcplib_SYS_Sleep ( 10 * 1000 ); // <HTTP PUT要求> // 送信設定 l_databuf_id = MMG_MOVIE_BUF_ID; l_send_id = SEND_ID_SORA_STR; l_burst = 1 ; l_session = MMG_SESSION_CONNECT; l_retain = MMG_DATA_NOTRETAIN; l_http_send_result = 0 ; // <OLED> // 画像のHTTP送信開始をOLEDに文字表示(画像送信開始したら"IMAGE_SENDING"とLEDに表示) OLC_DisplayChar (OLC_CHAR_USER, 0 , 0 , "IMAGE_SENDING " ); OLC_DisplayChar (OLC_CHAR_USER, 18 , 0 , " " ); // <モデム HTTP送信> // データ送信(HTTP PUTリクエスト)を実行 http_send (EXE_CONNECT, EXE_SEND, EXE_DISCONNECT); rcplib_LOG_Print ( "HTTP PUT done" ); // <OLED> // 通信結果をOLEDに文字を表示 if (l_http_send_result) { // 通信に成功した場合("SEND_SUCCESS"とLEDに表示) OLC_DisplayChar (OLC_CHAR_USER, 0 , 0 , "SEND_SUCCESS " ); OLC_DisplayChar (OLC_CHAR_USER, 18 , 0 , " " ); } else { // 通信に失敗した場合("SEND_FAIL"とLEDに表示) OLC_DisplayChar (OLC_CHAR_USER, 0 , 0 , "SEND_FAIL " ); OLC_DisplayChar (OLC_CHAR_USER, 18 , 0 , " " ); } // <USBカメラの停止要求> // カメラ撮影ストップ UVC_VideoStreamCtrl (UVC_STREAM_CTRL_STOP, 0 , 0 , 0 , 0 ); return ( 0 ); } デバイスのボタンを押下するとカメラの画像が送信され、デバイスのディスプレイ(OLED)に状況が表示されるようになっています。 ≪なぜ「レシピ言語」を使うことにしたのか?≫ はじめは、ローコードのブロックプログラミングでプログラム作成をしようとしていたのですが、思わぬつまずきポイントがありました。ブロックプログラミングにてWasabiのストレージ宛にデータ送信しようとすると、リクエスト方式は自動で「POST」が指定されます。ただ、Wasabiは「POST」ではなく、「PUT」でデータ送信する必要があり、何度トライしても送信エラーになるという事象が発生してしまいました…。ブロックプログラミングでは、リクエスト方式を書き換えることができなかったので利用を諦め、「レシピ言語」でのプログラム作成を利用することにしました。 5. 設定プログラムをデバイスに書き込む プログラムが完成したら、実行ファイルの形式に変換し、デバイスに書き込みます。KC4設定用アプリケーション上で「レシピの更新」をクリックし、 「書込むレシピ実行ファイルを指定」のところで今回作成したプログラムを指定して、書き込み対象のデバイスも選択し、「書込む」をクリックします。 デバイスが再起動され、「Hello!」と表示されたら設定完了です。 ボタンを押して撮影実行 それでは実際に動作検証してみます! ボタンを押して、 CAMERA_START と表示されて・・・ IMAGE_SENDING と表示されて・・・ SEND_SUCCESS! 成功しました! Wasabiを見てみると、デバイスから送信された写真データがきちんと格納されていますね。 定期実行に設定変更して撮影 せっかくなのでカメラが定期的に自動撮影をしてくれるように設定してみましょう!作成したコードにタイマーの設定を入れて、再度設定&書き込みし、実行してみます。今回は10分に1回カメラからの写真データを送信する設定に書き換えてみます。この撮影間隔は、最短1ミリ秒から最長約1.6カ月まで幅広く設定できます。 // Timer #define UA1_TIMER_GPIO_MONITOR 0 // Timer動作を変えるタイミングの閾値 #define TIMER_CYCLE_MODE1 600000 // 10分周期のTimerを動作させる そうすると・・・ PM 3:40に1回目、PM 3:50に2回目の撮影データが格納され、 10分ごとに自動でカメラが写真を撮影してくれるようになりました! 1回目の撮影時 2回目の撮影時 こんな形でロッカーの写真が撮影できています。 これで誰がいつ物品を取りに来たかが遠隔からでも確認できますね。 まとめ 以上のようにNTT ComのICMS、ICGW、WasabiとKC4、USBカメラを組み合わせて、社内のロッカーの遠隔監視ができるIoTシステムを構築できました。 私自身IoTシステムを構築した経験は全くありませんでしたが、ナレッジセンターやマニュアルなどを確認しながら、1人で簡単にロッカーの遠隔様子見システムを組み立てることができました。 データ転送がうまくいかない際に、どこでつまずいているのかがすぐに判別できなかったところには苦労しました。けれど、設定の作業自体は全工程含めて慣れれば3~4時間程度で完了できるものになっています。IoT導入を検討されている皆さまへ、まずはこの記事を参考にしながら実際にサービスやデバイスに触ってみることを、ぜひおすすめしたいです。 特に、今回活用したICMS・ICGWは1回線からお試しできてWebから注文可能です。Webからのご購入についてはぜひ こちら をご参照ください。 最後までお読みいただきありがとうございました。 お問い合わせ先 サービスに関するお問い合わせ IoT Connect Mobile Type S: 資料請求・お問い合わせフォーム IoT Connect Gateway: 資料請求・お問い合わせフォーム Wasabiオブジェクトストレージ: 資料請求・お問い合わせフォーム 今回構築したシステムや記事に関するお問い合わせ iot-connect@ntt.com  までメールでご連絡ください ※お手数ですが、@を半角文字に置き換えてください
アバター
こんにちは、NTT Comイノベーションセンターの小崎です。検証網を活用したセキュリティ技術の評価、運用などを担当しています。この記事では、イノベーションセンターで運用する検証網内でのインシデント発生を想定したインシデント対応演習についてご紹介します。 目次 目次 検証網について インシデント対応演習の目的 演習検討の進め方 検討のステップ 参加者について シナリオ検討の前提条件 演習の準備 演習 演習からの課題 まとめ 検証網について イノベーションセンターでは、新技術の評価などを目的とした全社検証網を運用しています。この検証網は国内に約30の拠点を持ち、1000台以上のノードなどによって構成されています。 インシデント対応演習の目的 インシデント対応演習は、大きく2つの目的で検討、準備を進めました。 自組織でインシデント(恐れ)が発生した際の連絡体制を確認する、インシデント対応者からの指示などがインシデント発生時に迅速/効率的に機能するかどうかを評価する 自組織で運用する検証網のセキュリティ検知機能や封じ込め機能が、インシデント発生時に機能するかを評価する 演習検討の進め方 検討のステップ 演習の作成にあたっては、 日本シーサート協議会(NCA) のインシデント対応演習訓練 WGにてまとめられているサイバー攻撃演習/訓練実施マニュアルを参考にしました。主な検討のステップは以下となります。 シナリオ検討、レビュー 開催準備 演習 演習後の対応、課題抽出 これらのステップを、以下のスケジュールに展開しました。 参加者について 演習には、組織のインシデント対応を担当する方達に参加してもらいました。参加者には次のいずれかの役割を割り当てました。 インシデント対応者 : 情報収集・分析者からの情報をもとに、インシデントに対しての判断、指示する 情報収集・分析者 : セキュリティアラートをモニタリングし、インシデント担当者へのエスカレーションや指示に従った解析、封じ込め対処などを行う シナリオ検討の前提条件 演習の作成にあたっては目的に合わせ、事前にいくつかの条件を設定しました。 演習シナリオ: 過去に検証網内で発生した(恐れとして報告された)インシデントを模擬することにより、アラートの検出から対処までをシナリオ化しました。 演習範囲: 自組織内のインシデント対応者までの報告、対応を演習範囲としました。実際のインシデント発生時に必要となる社内組織への報告や、被害の把握などのプロセスは対象外としました。 演習当日のスケジュール: 演習参加者には演習の日時を事前に共有し、参加の稼働を確保してもらいました。 演習場所: 現在は在宅からの勤務が主流であることから、関係者が集合して演習するのではなく、自宅から情報収集、指示などのハンドリングを行いました。 演習開始のトリガー: セキュリティ検知機能側のチューニングなどにより、演習実施時に生成する通信からアラート生成、被疑端末を作成しました。アラートを生成させるためだけに、実際に端末をマルウェアに感染させたり、悪性サイトへのアクセスを行ったりしないこととしました。 条件が多くあると限定的な演習のように感じられるかもしれませんが、目的や実施体制に合わせて事前に条件を決めておくことが重要になります。 演習の準備 作成したシナリオを週に1回レビューし、次週までに修正を繰り返し行うことで2つの演習シナリオを作成しました。レビューを繰り返すことにより、シナリオ上の矛盾や実際の運用上では起きえないことなどが修正されていきました。 セキュリティ機能の評価については、シナリオで想定したアラート生成や封じ込めができるかどうかを個々のパートに分けて機能検証を実施しました。個々のパートでは上手くいった機能検証も、シナリオを通したシミュレーションでは上手くつながらないことも発生し、複数回検証する必要もありました。 演習の時間配分については、事前に実施したシミュレーションなどからシナリオ単位でのタイムテーブルを作成しました。タイムテーブルに沿ったチェックポイントを作ることで、演習が予定した時間内に完結できるよう準備をしました。 演習全体のイメージは以下となります 演習 準備したシナリオに沿い、演習しました。シナリオの1つを紹介します。具体的にどのような装置で検知や隔離したかなどの情報は省略しています。 1: 以下のアラートの受信からスタートします。 セキュリティ検知装置から、外部に存在する悪性度の高いサイトへのアクセスが複数発生していることが情報収集・分析者にアラートとして通知される。情報収集・分析者は、アラートの初期調査をすることで悪性サイトへアクセスをしている端末が存在するセグメントを特定するが、外部への通信が暗号化されているため詳細を特定できない。情報収集・分析者はインシデントの恐れがあるとしてインシデント対応者に初報通知を行った。 2: インシデント対応者は、初報の段階ではインシデントであるかどうかの判定ができないため、情報収集・分析者に追加の調査を指示し、以下の情報を得ます。 調査指示内容 情報収集・分析者からの情報 具体的な調査方法 悪性通信を発生させているセグメントはどこか ゲスト利用が可能なセグメント トラフィック分析から特定 セグメント外への影響の可能性はあるか 他の内部セグメントへの通信は不可のため、可能性は低い 構成情報、セキュリティポリシーから回答 悪性通信を発生させている被疑端末は複数か 被疑の端末は1台 セグメントのトラフィック分析から特定 被疑端末は特定できるか 端末のIP、MACアドレスを特定できる 被疑端末が繋がっている物理機器から特定 被疑端末が接続している場所はどこか オフィスの某フロアである 被疑端末が繋がっている物理機器から特定 被疑端末から外部へのアクセスは継続しているか 初報時点から継続している トラフィック分析から特定 被疑端末からのトラフィックはあるか ダウンロード方向のトラフィックを発生させている トラフィック分析から特定 被疑端末の利用者は特定できるか 特定できない インベントリ情報の調査から回答 3: インシデント対応者は、得られた情報から 端末の封じ込め(ネットワークからの隔離)を行う判断 をし、情報収集・分析者に作業指示をしました。 4: 情報収集・分析者は、該当端末のMACアドレスをフィルタリングすることでネットワークから隔離しました。被疑端末の隔離後、悪性サイトへのトラフィックが停止したことを確認しています。 5: インシデント対応者は、詳細を把握するためオフィスにいる社員へ被疑端末とその利用者の特定を依頼しました。被疑端末の利用者が発見され、ヒヤリングにより被疑端末が社内管理のインベントリに未登録の端末であること、悪性通信と判断される暗号通信は個人の検証目的で発生させていたことが判明しました。 6: インシデント対応者は全ての情報から、今回は マルウェア感染や情報漏洩などのインシデントは発生していない と判断し、未登録の端末を利用していたことに対しては厳重注意することでシナリオをクローズとしました。 以上が演習の大まかな流れになります。今回の被疑端末はシャドーIT的な利用を想定しました。シナリオの中では封じ込めの判断、対処方法などが判断ポイントとなるよう作成していましたが、適切な判断と対処指示がなされたと思います。 以下は、事前に作成した演習のタイムテーブルになります。 演習からの課題 演習終了後の参加者で意見交換を行い、いくつかの意見、課題が挙げられました。 演習の作成においては、シナリオのレビュー、事前準備の重要性があげられました。特に実環境での演習においては、想定したシナリオどおりにアラートが検出できないことなども発生したため、事前のシミュレーション、確認作業が重要になります。 また、オンラインを前提としたインシデントハンドリング、対応時のルールの不備が課題に挙げられました。複数の対応者がいる場合、オンライン上で誰がどの対応をしている状況かなどの状況も見えにくかったため、インシデント対応時のコミュニケーションツールの使い方、ルールなどの取り決めが必要になります。 改善すべき点として、セキュリティ検知、対策機能などのドキュメント不足があがりました。特に、インシデント担当者がスムーズに判断、指示できるよう、最新化したドキュメントを事前に共有しておく必要があります。 まとめ 今回、自作のシナリオによるインシデントハンドリング演習を企画、実施しました。インシデント(恐れ)発生時の連絡体制やインシデントハンドリング時の検知、対策機能の課題や改善点を洗い出すことができ、当初の目的は達せられたと思います。 今後は、今回の演習で課題となった点の改善をすすめます。次回の演習としては、インシデントを突発的に発生させることを実施したいと考えています。また、新たに発生したインシデント(恐れ)を擬似したシナリオを作成することにより、演習の最新化も行っていく予定です。
アバター
はじめての方、はじめまして。久しぶりの方、お久しぶりです。 イノベーションセンターの何縫ねの。( @nenoMake )です。 普段の業務ではソフトウェアエンジニアとして Node-AI という WEB アプリケーションの開発をしています。 パブリックな活動としては、好きな言語である C# 関係の OSS 開発や 技術ブログ の投稿、 登壇 などをしています。 ですが、今回は C# ではなくフロントエンドのお話をします...! この記事では今まで Vue.js 2.x で開発されていた Node-AI の WEB フロントを 完全に捨て去り 、 React にリプレイス したお話をつらつらとしていきます。 まずは前編ということで、リプレイスプロジェクト発足時の課題感からはじめ、プロジェクトの進め方や選定技術などについてお話しします。 後編には内部の設計などのより技術的なお話をしたいと思います。では前編スタート...! Node-AI とは 今までのフロントエンドの課題 リプレイスプロジェクトの進め方 フェーズ1 フェーズ2 バックエンドにも手を入れる事を躊躇わない 選定技術 リプレイスを通して得たもの まとめ 後編予告 Node-AI とは Node-AI はノーコードでAIモデルを作成できる WEB アプリケーションです。以下の図のようにカードを直感的につなげるだけで時系列データの前処理からAIモデルの学習・評価までの一連のパイプラインを作成・実行できるようなものとなっています。 各データ処理(例えば正規化やデータ分割など)がそれぞれカードとして表現されており、それを繋げてパイプラインを作成します。 視覚的に処理の流れを追いやすく、データ分析者の(往々にしてカオスな)コードを解読する行為から解放されるため、業務が捗るでしょう。 また複数人での同時作業にも対応しているため、コラボレーションが活性化し、ステークホルダーを巻き込んだ効率的なデータ分析やAIモデル開発ができるようになるはずです。 現在 β 版 として公開しているので、気になる方は是非使ってみてください。 今までのフロントエンドの課題 すこし歴史的経緯から。 私は新卒2年目なのですが、その入社より遥か以前、Node-AI の開発プロジェクトが爆誕したのは機械学習エンジニアたちがいろいろ案件を回していく中での課題感からだったそうです。 なのでいざ Node-AI というアプリケーションを開発するぞ!となった時、発案者たちである機械学習エンジニア達がアサインされるのは言うに及ばずなのですが、さてアプリケーションエンジニアないし WEB 系エンジニアはどう調達するか。 課題感が発生したチームには、そのような人材はいなかったそうです。機械学習専門のチームだからそれはそうという感じ。 このような場合、社内から適切な人間を引っ張ってきてどうにか解決するのがベストなわけですが、残念ながらそうはいかなかったそうです。 ではどうするか。そう、外注です。 そんなこんなでプロジェクト発足当初は Node-AI のフロントエンドは完全に外注していたそうです。 発注元にコード書ける人間がいない中で外注するとどうなるかは火を見るよりも明らかで、以下のような状態に陥ってしまいました。 発注側にコードの品質を管理できる人間がいないため、コードが徐々にカオスへ 指示された機能さえ出来てればいい、の積み重ね コードがカオスになるにつれ、少しの修正に多くの時間と金がかかるように このような状態が続いたわけですが、とあるタイミングで「全部内製開発するぞ!」という事になり、弊チームの人間がフロントエンドの開発をするようにもなったそうです。 内製開発に倒したはとても良い事だと思うのですが、結局今までのカオスの上に増改築をするような状況となるので、フロントエンドの機能開発に時間がかかるのなんの。 この時、フロントエンドが抱えていた技術的な課題は以下のようなものでした。 問題ある DOM 構造や CSS 手を加えると意図しない箇所の描画が壊れたりする砂上の楼閣 問題あるコンポーネント設計 単一責務になっていなかった 結果として生まれる神コンポーネント 具体的には 3000 行を超える SFC (.vue ファイル) が存在していた むやみに複雑な props と emit のスパゲッティ 厳しい開発体験 Vue.js 2.x の低い TypeScript ビリティ 型が分からず、動かしてみないとデータ構造が分からないケース多数 にも関わらず、デバッガが使えない VSCode の intellisense や Find All References 等の機能が効かない 迫る Vue.js 2.x の EoL この技術的な課題の結果として、度々ユーザからリクエストを受けるフロントエンドマターな機能が実装できないという問題や、デザイナーと開発者との連携、例えば Figma で提示された CSS が使えない等の問題も生じていました。 という事で、 これらすべての問題 を解消するため、フロントエンドをリプレイスするプロジェクトが動きました。リファクタリングじゃなくてリプレイスですからね、すべての解消を狙って然るべきでしょう...! そしてただのリプレイスじゃねぇぞ、ド級のリプレイスだ...! という事で、度々ユーザからリクエストを受けていた機能もこれを機会に実装しちゃうぞ!という形で進める事となりました。 GUI アプリケーションの開発を組んだ事ある開発者の方はいろいろ分かると思いますが、最初から考慮していないと厳しいものはいろいろありますよね。 後から入れるとコストが大爆発するやつ。 リプレイスプロジェクトの進め方 まず前提として、 現在の Node-AI はスクラムを用いたアジャイル開発をしていて、開発チームはフロントエンドチーム、バックエンドチーム、インフラチームといったような技術領域での分割を していません 。 フロントエンドはできるがバックエンドは全くできない、あるいはバックエンドはできるがフロントエンドは全く出来ない、みたいなエンジニアは 現在では 弊チームに存在しません(採用を頑張っている事が伺えますね)。 まぁ、もちろん得手不得手はありますし、専門領域も異なるのですけどね。 そしてこのプロジェクトは主に2つのフェーズが存在しました。 それぞれどのような感じであったかを書いていきます。 予め断っておくと、いわゆる設計工程と開発工程とは異なったものです。 フェーズ1 期間としては 2022年6月~10月 です。 この期間は開発チームから私含めた4人を切り出し、主に以下のような事を行っていました。主には技術的な下地を作っていたといえるでしょう。 既存機能の整理 技術選定のためのサーベイ 不確実性の高い箇所についての設計やプロトタイプ実装 各既存機能の再実装にかかるコストの見積もり 技術選定の内容としては Vue.js 3.x/Nuxt.js, React/Next.js のどちらで行く?から始まり、UI ライブラリは?グラフライブラリは?とかとか。選定技術については後述します。 また技術的に不確実性が高い箇所については、実実装に入る前のこのフェーズで実際に手を動かしていろいろ試していました。 たとえば Node-AI のキャンバス画面 (カードを配置する画面) は素朴に DOM をくみ上げればいいというわけでもないので、その描画をどのように実現するか、具体的には html の <canvas> で行くのか <svg> で行くのかとか、フルスクラッチするかライブラリに乗っかるか等です。 他にも今までのフィードバックから需要が高い事は分かっているが今まで実装できなかった undo/redo や 複数人でのリアルタイム共同編集機能といった、さまざまな要求を実現するための技術的な不確実性を解消していました。 一個人のエンジニアとしては、とりあえず実装してみてそれをベースに開発メンバで頭突き合わせてあーだこーだと議論して、不確実性の解消し、完成度を高めていくというこのフェーズの活動はめちゃくちゃ楽しかったです。 そしてこれらの活動を通じて実装のおおよその感覚をつかみ、フェーズ2にて実装する全ての機能それぞれに実装コストの見積もりました。 とはいえ見積もり自体は大味ですが。 フェーズ2 期間としては 2022年11月~2023年12月 です。 まずはフェーズ1と同じ4人のエンジニアで実装をすすめ、2023年6月ごろから徐々に開発者の人数を増やし、12月にリプレイス完了!といった形です。 このフェーズの開発は Vue.js 2.x の EoL が 2023年12月であったことからも、とにかく開発速度が求められていました。 EoL までには何としてもリリースしたい。 そこでこのプロジェクトでは、これまで行っていた通常のスクラムとは一部異なる進め方をする事にしました。 これまでの進め方では、優先順位の高いプロダクトバックログアイテム(機能など)から順番に、複数の開発者で協力して開発してきました。 この進め方は必然的にチームの中で多くのコミュニケーションが発生するため、それが結果的に「コードをみんなのもの」にし、チームとしてのレジリエンスを高める事に寄与してくれていました。 しかし裏を返せば、コミュニケーションコストがそれなりにかかっているということですから、開発速度を最優先事項に据えた場合、最適ではなくなります。 そこでリプレイスプロジェクトでの開発においては「一人一殺」という標語の下に、特定の機能は特定の人が一気通貫で作るというスタイルで開発を進め、開発速度を高めていきました。 とはいえ当然レビューは行うので、実装者とレビュアーの間でのコードの共有はなされていましたし、誰かが悩んだりした際には随時メンバー間で相談や壁打ちは行っていたため(心理的安全性が確保されていると言えますね...!)、完全に一人しか知らないコード、というのはほぼないと思われます。 なお、インクリメントという名のアウトプットをステークホルダーにお見せしフィードバック貰ってプランニングして...、といったスクラム一般の一連の所作は今まで通りやっていました。 ところで一人一殺という進め方、技術的な視点で見ると、そのやり方で進めると実装取っ散らばらないか?と思ったりもするのではないでしょうか。 それについてはフェーズ1にて一定のレールを敷くことに成功し、基本的にはそれらのレールに沿って実装したため問題になりませんでした。 特に量産が必要なところ、例えばキャンバス上に配置されるカードなどのオブジェクトの操作や、各カード毎(=データ処理や機械学習に必要な処理毎)に対して作る必要があるカード詳細画面などは、それがよく機能していたと感じるところです。 また前述のとおり、2023年6月ごろから追加の開発者がこのプロジェクトに投入されたのですが、投入されたメンバーはいままで Vue.js で開発をしていたため、React には不慣れでした。 しかしながらメンバーそれぞれの React に対するモチベが高く優秀であった事に加え、コード上に一定のレールを敷くことが出来ていたため、スムーズにキャッチアップでき、最終的なゴールまで加速できたのではと思います。 その結果として2023年12月末、Vue.js 2.x の EoL というタイムリミットの前になんとかリリースできました、という感じです。 いやはやよかったよかった。 バックエンドにも手を入れる事を躊躇わない フロントエンドのリプレイスは既存のフロントエンドの負債を解消する事と、今まで実現できなかった機能を実装する事を主だった目的としていました。 しかしそもそも、なぜ負債の解消をするのでしょうか?それは今後の継続的な機能開発を加速可能な状態にするためです。 せっかくリプレイスしても新機能の追加が大変なものが出来上がったのでは、コストを支払った意味がありません。 そういった視点で考えたとき、既存のフロントエンドが利用しているエンドポイントをそのまま利用する事がそれに寄与するのか?というのはリプレイスプロジェクトを進める上で当然議題にのります。 フロントエンドの実装を進める上でぶつかった既存のエンドポイントに関する課題は以下のようなものでした。 複数のエンドポイントのレスポンスが闇鍋 いくつかのエンドポイントはレスポンスが極めて動的 エンドポイント単位で型を与えるのが困難 これは今後も新たに機能を追加する際、都度闇鍋 JSON に新機能由来のデータが追加され、それをデシリアライズした後に解釈するためのコードを加筆し続ける必要があるという事です。 これは継続的な開発及びバグ防止の観点から避けたいです。 そこでこの課題を解決するべく、バックエンド実装に対して以下の方策をとりました。 新規に実装してもたいしたコストがかからないものについては新規実装 新規実装にコストがかかりそうなものについても新規エンドポイント実装 ただし内部では BFF のような仕事をするレイヤを作成するだけに留め、ロジック自体は既存実装を使いまわす これによりレスポンスを比較的シンプル化 & 強く型付け もともとフロントエンドのリプレイスプロジェクトですから、コストをあまりかけないようにしました。 このようにバックエンドの実装も修正しながら進められた事は、フロントエンドだけでなくバックエンドも一定以上に書けるエンジニアでプロジェクトを進める事が出来た利点でしょう。 また上記の課題とは別軸に、以下に対応するためにもバックエンド実装は必ず通る道でした。 リプレイスで生まれる新機能向けバックエンド実装 リアルタイム通信系機能 ストレージ節約マイクロサービス リアルタイム通信に纏わる機能は既存の実装にはほぼ無いものでしたから、必然的に新規実装する事になりました。 また Node-AI のキャンバス上に配置されたカードのデータ処理や機械学習の結果にまつわる生成物がバックエンド上では伴うのですが、フロントの新機能としてキャンバス内操作の undo/redo を実現すると、それらを即座に削除する訳にもいかなくなりました。 つまり定期的に不要になったそれらを片付けるマイクロサービスなどが必要でした。 このようなものもフロントエンドのリプレイスプロジェクトだからといって躊躇わずに実装しました。 選定技術 選定した技術はおおよそ以下のような感じです。 TypeScript React/Next.js Redux Mantine ECharts SignalR Tailwind CSS Mock Service Worker Storybook React Testing Library Playwright もともと Vue.js 2.x を用いていた事から、Vue.js 3.x/Nuxt.js と React/Next.js のどちらを使うのかはプロジェクト発足時、当然議題にあがりました。 結果としては React/Next.js を選んでいるのですが、理由としては以下の通り。 TypeScript との親和性 世界的な潮流 Vue.js 3.x が JSX を取り込んだことからも分かる通り。 メンバーのモチベ 個人的には React の「GUI は純粋関数として表現できる」という思想及び単方向データフローである点は極めて有益であると感じ、関数型コンポーネント + hooks 登場以降の React は大好きです。 もちろん実装上は全てのコンポーネントが純粋関数とはいかないのですが、Node-AI の実装では純粋なコンポーネントとそうでないところは徹底して分離する事で、読みやすさと保守性の向上に努めています。 またグラフライブラリには ECharts を利用しています。 Node-AI は時系列データを取り扱うアプリケーションなので、そこそこ大きいデータも問題なく描画できるグラフライブラリを選択する必要があります。 そこで10個弱のグラフライブラリでそれなりのサイズのデータを描画し、パフォーマンスバトルを行いつつ、GUI としての操作感や今後実現したいグラフが描画できるか等を検討しました。 結果的にパフォーマンス的にもグラフ表現の幅も広かった、ECharts を採用しました。 リプレイスを通して得たもの 整理整頓された DOM 構造や CSS 綺麗になったコンポーネント達 TypeScript による徹底した静的な型付け Storybook による UI カタログ 統一された開発環境 もともと課題になっていた、いわゆる汚いコードというやつは当然ながら全て払拭しました。 上記で「綺麗になったコンポーネント達」というふんわりした事を書いているのですが、ここでは以下のような事を徹底しました、という事です。 単一責務 container と presenter の分離 message と service の分離 イベントハンドラ等の関数名による明示的な意味づけ 上2つについては特にいう事はないでしょう。 多くの人が頭で理解はしていても、なんやかんやで徹底されず、多くのコードではそうなっていないというだけで。 3つめの message と service の分離については、要はデータと処理の分離です。 データ指向プログラミングとも言いますね。 リプレイスされた TypeScript のコードの多くは純粋関数で出来ているため、これは自然と守られます。 とはいえそれが全てではなく、当然 class も使っています。 その場合でも、それらのインスタンスを「状態を持って振る舞うオブジェクト」として用いるのではなく、あくまで「immutable な message と service」といった形で分離し利用する事で、これを徹底してます。 そして最後のイベントハンドラ等の関数名による明示的な意味づけについてですが、これはたとえば useEffect の第一引数に処理をべた書きした無名関数を渡すのではなく、 コンポーネントの外で名前が与えられた関数を定義し、それを useEffect の引数内で用いるといったコードの書き方をしたという事です。 もう少し具体例をだすと onChange のような props があった時、そこに onChangeHandler みたいな情報量ゼロな関数オブジェクトを渡すのではなく、たとえば validateXxx のような何をする事を意図しているのか瞬時に判別できる名前のついた関数オブジェクトを渡すようにする、とかです。 こういった命名を積み重ねていくことで、初見でも渡されている関数が何を意図しているのかがすぐに分かります。 また同時に名前がついていることから、別の処理を追加しようとした際に心理的な抵抗感が生まれるため、1つのメソッドにさまざまな処理が追加され、結果的に単一責務からかけ離れた多重責務になってしまうといった状況が発生する事を防げます。 ラムダをべた書きしたり、情報量ゼロの名前を関数につけてしまった場合に発生しがちな複数の責務が押し寄せてくる事象も、小さな命名の積み重ねで防げると私は考えています。 そしてもう1つ、地味に大事な収穫の1つとして、統一された開発環境を提供できるようになりました。 現代の TypeScript によるフロントエンド開発する上で VSCode 上での開発体験は極めて重要です。 IntelliSense によるコード補間、Find All References や Go to Definition といったシンボルでコードを飛び回る機能、そしてデバッガ。 これらは生産性にダイレクトに響いてきます。せっかくゼロベースでやるのであれば、そのあたりは整備して全開発者にばら撒いてしまった方がなにかと良いです。 各々で開発環境をカスタムするのは止めませんが、標準的な開発環境は揃えた方が何かと幸せ。 という事で dev container で必要な設定や拡張が一式揃った開発環境を提供しています。 今までは標準的にはこれ使ってね、みたいのも無く、VSCode の便利機能を活用しきれていないケースが多々あったのですが、これにより全ての開発者はコストゼロで生産性の高い環境を手に入れられるようになりました。 まとめ Node-AI のフロントエンドは Vue.js 2.x を捨て、React/Next.js に移行を果たしました。 この記事では主にプロジェクトの進め方や技術選定、結果として得られたものについてお話しました。 私個人としては入社してから殆どこのプロジェクトに付きっ切りでしたので、いろいろやり切った感があります。 頑張った偉い。 とはいえ React にリプレイスされた Node-AI のフロントエンドはこれで終わりではなく、むしろこれからの機能追加がドシドシ行われるフェーズこそが本番であり、設計したものの真価が問われるので、気が引き締まりますね。 そして EoL を迎えた Vue.js 2.x を捨てなければならない案件は各所で発生している問題かと思いますので、この記事が読者の皆さまの役に立てば幸いです。 後編予告 前編であるこの記事では、主にプロジェクトの進め方等について書いていきました。後編ではもうちょい技術よりのお話をする予定です。今のところ、以下の内容の設計だったり開発フロー等についてを予定しています。それではまた後編で会いましょう...! ライブラリ依存無しでキャンバスを SVG で表現している話 キャンバスのリアルタイム共同編集機能の話
アバター
この記事では TypeScript ver4.x にて実験的な機能である decorator を使い、ログ出力コードを削減・コードの可読性を上げた経験を紹介します。 はじめに 背景 decorator とは decorator を使ったログ出力方法の検討 decorator を使ったログ出力の実装 実装時にハマったこと等 関数定義方法の変更 非同期・同期両方に対応 クラス名の取得 ログメッセージの統一 その他考慮した点 ライブラリの利用 実践結果 良かった点 悪かった点(苦労した点) まとめ 参考文献 はじめに こんにちは、NeWork 開発チームの加藤です。普段はオンラインワークスペースサービス NeWork の開発エンジニアをしています。 今回は TypeScript ver4.x にて実験的な機能である decorator を使った事例紹介をします。我々開発チームではログ出力のためのロジックの記述がコード全体の可読性を下げているという課題があり、decorator を活用することでこの課題を解決しました。その経験をもとに、良かった点・悪かった点(苦労した点)含めて紹介したいと思います。 背景 NeWork 開発チームでは、TypeScript を用いて開発しています。その中で開発中のコードの挙動を確認したり、エラー発生の監視その後の原因特定のために、ログ出力を行っています。 ログ出力は router, service, gateway などの各レイヤーで行っており、それぞれのレイヤーでログ出力を行うために以下のようなコードを書いていました。(※コードはサンプルです) const async getUser = (userId:string): Promise<MyUser> => { // 呼び出しログ表示ロジック Logger.getInstance().info( `getUser start: userId ${userId}`, // ログメッセージ LOG_POSITION.SERVICE, // ログ出力レイヤー(レイヤーごとに定数を用意しています) LOG_PADDING.START, // 開始/終了のログを判別するための定数 ); const outEndLog = () => // 終了ログ表示ロジック Logger.getInstance().info( 'getUser end', LOG_POSITION.SERVICE, LOG_PADDING.END, ); // 処理 const user = await MyGateway.getUserData(userId).catch(() => { outEndLog(); // 終了ログ表示ロジックの呼び出し throw new MyError(); }); outEndLog(); // 終了ログ表示ロジックの呼び出し return user; } このコードでは以下のような問題がありました。 エラーが発生するタイミングや、early return するタイミングでログ出力をしなければならないため、記述忘れが発生しやすい。 簡単な関数であっても、ログ出力のための記述が多くなり、可読性が下がっている。 開発者がログ出力のためのコードを書くのが面倒。 関数を作成するたびにログ出力を記述するので、人によってログメッセージの記述がバラついてしまうことがあった。(get user start と getUser start など) エラー発生時のログ出力漏れの対策としては、try-finally を書くことがあげられますが、結局のところ毎回関数を記載するたびに try-finally を書くのは大変であり、他の問題にもアプローチ可能な decorator を使ってログ出力を試してみました。 decorator とは TypeScript ver4.x の decorator は関数などに対して処理を追加する記述方法で、以下の 5 種類があります。 Class Decorators Method Decorators Accessor Decorators Property Decorators Parameter Decorators それぞれ、クラス・メソッド・アクセサ・プロパティ・パラメータに対して処理を追加可能です。 クラス・メソッド等の定義時に、decorator を @hogehoge という形式で記述することで、その decorator が適用されます。 decorator を利用することで、対象のクラスやメソッドに対して共通の処理を追加できます。 例えば method decorator の場合以下のように定義・利用します。 // decorator の定義 function logging(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) { const originalMethod = descriptor.value; // メソッドの処理を上書き descriptor.value = function (...args: unknown[]) { console.log('処理開始'); // 元のメソッドを呼び出す originalMethod.apply(this, args); console.log('処理終了'); } } class MyClass { // loggingというdecoratorをhelloメソッドに適用 @logging hello() { console.log('hello'); } // loggingというdecoratorをbyeメソッドに適用 @logging bye() { console.log('bye'); } } これにより、hello メソッドや bye メソッドの実行時には必ず 処理開始 と 処理終了 が出力されるようになります。 他の decorator の利用方法や具体例等は、 公式 に提示されていますので興味があればご覧ください。 今回は、メソッドに対して処理を追加するための Method Decorators を利用しました。 decorator を使ったログ出力方法の検討 Method Decorators にてログ出力を行うにあたり、以下の要件をもとに実装しました。 decorator を適用したメソッドの開始・終了時には必ずログ出力が行われる。 ログメッセージの形式を統一する。 非同期関数に対しても適用できるようにする。 ログ出力の際には、必ずクラス名・メソッド名が出力されるようにする。 decorator を使ったログ出力の実装 NeWork の実際の実装では、以下の serviceLogging , gatewayLogging という decorator を新規作成しました。 /** * @description ログ出力デコレーターファクトリーの共通処理部分,外部から呼び出す際はserviceLogging関数等を呼び出すこと * @param position ログ出力位置 * @returns デコレーター */ function logging(position: string): MethodDecorator { return ( target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor ) => { const originalMethod = descriptor.value; // ログ出力するクラス名を取得 // static関数の場合はtype of targetがfunctionに、それ以外はobjectになる const isStatic = typeof target === "function"; const className = isStatic ? target.name : target.constructor.name; // 関数呼び出し時のログ表示ロジック const startLog = () => Logger.getInstance().info( `${className}.${String(propertyKey)} start.`, position, Constants.LOG_PADDING.START ); // 関数終了時のログ表示ロジック const endLog = () => Logger.getInstance().info( `${className}.${String(propertyKey)} end.`, position, Constants.LOG_PADDING.END ); // async functionの場合、ログ出力前にawaitする const isAsync = descriptor.value.constructor.name === "AsyncFunction"; if (isAsync) { descriptor.value = async function (...args: unknown[]) { startLog(); // 仮引数の値もログ出力。ただし、オブジェクトの場合はログが煩雑になるので出力しない const argString = args .map((arg) => (typeof arg !== "object" ? util.format(arg) : "object")) .join(`, `); Logger.getInstance().debug(`args: ${argString}`); try { return await originalMethod.apply(this, args); } finally { endLog(); } }; return; } descriptor.value = function (...args: unknown[]) { startLog(); // 仮引数の値もログ出力。ただし、オブジェクトの場合はログが煩雑になるので出力しない const argString = args .map((arg) => (typeof arg !== "object" ? util.format(arg) : "object")) .join(`, `); Logger.getInstance().debug(`args: ${argString}`); try { return originalMethod.apply(this, args); } finally { endLog(); } }; }; } /** * @description サービスクラスのログ出力デコレーター * @param target クラス * @param propertyKey メソッド名 * @param descriptor ディスクリプター * @returns なし */ export const serviceLogging = ( target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor ): void => { // ログ出力位置をサービス用に指定して呼び出す logging(Constants.LOG_POSITION.SERVICES)(target, propertyKey, descriptor); }; /** * @description ゲートウェイクラスのログ出力デコレーター * @param target クラス * @param propertyKey メソッド名 * @param descriptor ディスクリプター * @returns なし */ export const gatewayLogging = ( target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor ): void => { // ログ出力位置をゲートウェイ用に指定して呼び出す logging(Constants.LOG_POSITION.GATEWAYS)(target, propertyKey, descriptor); }; 上記で定義した decorator を使った実装例は以下です。ここでは背景の項目で記載した getUser 関数を例に書き換えています。 class MyService { @serviceLogging static async getUser(userId: string): Promise<MyUser> { const user = await MyGateway.getUserData(userId).catch(() => { throw new MyError(); }); return user; } @serviceLogging static async setUser(user: MyUser): Promise<void> { ・・・中略・・・ } } このように記述することで getUser 関数の開始・終了時には必ずログが出力されるようになり、同じ定義を用いて各関数でログを出力できます。 実装時にハマったこと等 実装する際に困ったことや、想定外だったことを紹介します。 関数定義方法の変更 従来我々はアロー関数を利用し関数定義していたのですが、method decorator はアロー関数に対しては適用できず、関数定義を function で行うことで対応しました。 // 修正前 const async getUser = (userId:string): Promise<MyUser> => { ・・・中略・・・ } // 修正後 async function getUser(userId:string): Promise<MyUser> { ・・・中略・・・ } 非同期・同期両方に対応 非同期関数かどうかによって、元の関数に対して await を行うかどうかや、descriptor.value に代入する関数を非同期にするかどうかを判定する必要がありました。 // async functionの場合、ログ出力前にawaitする const isAsync = descriptor.value.constructor.name === "AsyncFunction"; if (isAsync) { descriptor.value = async function (...args: unknown[]) { ・・・中略・・・ try { return await originalMethod.apply(this, args); } ・・・中略・・・ }; return; } descriptor.value = function (...args: unknown[]) { ・・・中略・・・ try { return originalMethod.apply(this, args); } ・・・中略・・・ }; descriptor.value.constructor.name で関数の種類を判定しています。非同期関数の場合は AsyncFunction となります。 クラス名の取得 ログのメッセージにどのファイルの関数なのかを含めるために、関数のクラス化とクラス名を取得処理を追加しました。 各ファイルで定義していた関数を class でまとめ、default export するように修正し、既存の関数は class の static 関数として定義しました。 // 修正前 const async getUser = (userId:string): Promise<MyUser> => { ・・・中略・・・ } // 修正後 class MyService { static async getUser(userId:string): Promise<MyUser> { ・・・中略・・・ } } クラス名は static 関数の場合は target.name 、それ以外の場合は target.constructor.name から取得できます。 // ログ出力するクラス名を取得 // static関数の場合はtype of targetがfunctionに、それ以外はobjectになる const isStatic = typeof target === "function"; const className = isStatic ? target.name : target.constructor.name; ログメッセージの統一 ログメッセージについては、クラス名・メソッド名を必ず含めるようにしました。メソッド名は、propertyKey から取得できます。 Logger.getInstance().info( // クラス名.メソッド名 start. `${className}.${String(propertyKey)} start.`, position, Constants.LOG_PADDING.START ); また開始ログ出力後に、引数の値を出力するようにしました。 ただし引数がオブジェクトの場合は出力されるログが煩雑になるため、出力しないようにしました。もしログが必要な場合は decorator ではなく、関数内で個別にログ出力するなどの代替案で対応することとしました。 // 仮引数の値もログ出力。ただし、オブジェクトの場合はログが煩雑になるので出力しない const argString = args .map((arg) => (typeof arg !== "object" ? util.format(arg) : "object")) .join(`, `); Logger.getInstance().debug(`args: ${argString}`); 出来れば仮引数名も出力したいところですが、仮引数名を取得する方法が見つからなかったため、今回は実装を見送りました。 その他考慮した点 ライブラリの利用 decorator を直接利用するのではなく、logger-decorator というライブラリを利用することも検討しましたが、今回は我々独自のログ出力を行いたいため、ライブラリは利用しませんでした。 実践結果 実際に decorator を利用した結果、我々にとっての良かった点・悪かった点(苦労した点)は以下のようになりました。 良かった点 今回 decorator を適用したことで、元々の課題は解決できました。 関数のエラー発生時や、early return するタイミングでログ出力を意識する必要がなくなった。 関数の定義がシンプルになり、可読性が上がった。 開発者がログ出力のためのコードを書く必要がなくなった。 ログメッセージの記述が統一された。 それだけではなく、副次的に以下のようなメリットもありました。 ログの形式に、必ずクラス名が入るように修正したため、実際にログを見るときの可読性が上がった。 大きな破壊的変更をせずに適用できる方式であったため、開発速度を落とさずに無理のない範囲から順に適用できた。 コード量が多いことから、順次適用が可能だったのは特に大きなメリットでした。 悪かった点(苦労した点) 以下のような苦労点もありました。 アロー関数では method decorator が適用できない。 今回は関数定義方法を function に変更しましたが、既存のコードを大量に修正する必要がありました。この作業は単純ですが非常に作業時間がかかってしまいました。 ログ出力の完全な自動化はできていない。 関数の引数がオブジェクトの場合に中身を表示しないようにしましたが、一部、オブジェクトの内容をログに含めたい場合には結局ログ出力のためにコードを書く必要があります。 decorator を利用すると仮引数名が表示不可となりログを見た時に arg の意味が分かりづらい。 (現時点において我々には)仮引数名を取得する方法が見つけられていないことから、仮引数名をログに含めることができませんでした。 これらの問題はありましたが全体としては、decorator を利用したログ出力の実装は上手くいったと言えます。 まとめ 今回 NeWork 開発チームの課題であったログ出力コードに関して、decorator を利用したログ出力の実装について紹介しました。 我々のチームでは TypeScript v4 で実験的な decorator を利用したログ出力を実装し、コードの可読性向上に貢献できました。 一方で decorator とアロー関数の相性の悪さといったような苦労した点もありました。 方式に関して、TypeScript v5 では実験的ではなく正式に decorator を利用できるようになっています。 またログ出力には log-decorator というライブラリや、何かしらのフレームワークを導入するという手段もあると思います。 この記事が、皆さんのログ出力の実装についての 1 つの参考になれば幸いです。 NeWork チームでは、今後も開発の中で課題となっていることを解決するために、さまざまな技術を試していきたいと考えています。今回紹介した内容についても、今後も改善を続けていきます。 また、 NeWork はどなたでも無料でお試しできますので、もしプロダクトや使われている技術に興味を持っていただけたらぜひ触ってみてください。 最後に、2024 年 2 月現在、NeWork では一緒に開発を進めてくれる仲間を募集しています。詳細は以下のリンクをご覧ください。皆さまのご応募を心からお待ちしています! hrmos.co 参考文献 https://www.TypeScriptlang.org/docs/handbook/decorators.html https://bobbyhadz.com/blog/javascript-check-if-function-is-async
アバター
はじめに こんにちは、イノベーションセンターでノーコード分析ツール「Node-AI」開発チームの林です。 業務としては Node-AI のフロントエンドやバックエンド開発、最近では監視/可視化のプラットフォーム開発に携わっています。(興味ある方は こちら の記事もご覧ください。) 本記事では、2023 年 12 月 18 日に開催した NTT ドコモ・NTT コミュニケーションズ・NTT コムウェアからなるドコモグループ(以下、DCC グループ)内の Google Cloud のユーザーコミュニティ「GINGER」 の第 6 回目のイベントをご紹介します。 はじめに GINGER 紹介 オープニング 運営メンバー紹介 LT1:Google Cloud 生成AI Updates, Gemini 紹介 LT2:Google Cloud Next Tokyo'23 の 1 日目に行ってみた LT3:Google Cloud Next Tokyo'23 に行ってみた LT4:C&N部のデータ収集・可視化基盤開発およびデータ活用部の取り組み クロージング ↓ ↓ 過去イベントの開催報告はこちら ↓ ↓ DCC グループの Google Cloud ユーザーコミュニティイベント報告【GINGER Event#5】 GINGER 紹介 GINGER は Google Cloud Community In NTT Group Enterprise の頭文字をとって命名しました。経緯の詳細は こちらの記事 に掲載しています。 活動の中でも 特にイベントでのオフラインのつながりを重要視 しています。Google Cloud に関するノウハウ共有を実施しつつ、 このコミュニティに参加したからこそ得られる業務を超えたつながりを価値 として感じてほしいと思っています! では、本題である GINGER Event#6 の開催報告に入りたいと思います! オープニング Event#6 では下記のアジェンダで開催しました! 今回は 11 月 15 - 16 日で開催された「Google Cloud Next Tokyo ‘23」に行ってみた感想や面白いセッションの共有にフォーカスした LT 大会となりました。 トップバッターは グーグル・クラウド・ジャパン合同会社様のカスタマーエンジニアである仲根さん による 「生成 AI Updates & Gemini 紹介」 をお話しいただきました。仲根さんにはドコモ時代からお世話になっており、 本コミュニティ「GINGER」 の立ち上げを全面的に支援いただいており、感謝が尽きません。 次にコミュニティメンバー枠として 2 本の LT をしていただきました。1 本目は 2 回目の登壇となる NTT ドコモ データプラットフォーム部(以下、ドコモ DP 部)三浦さん から 「Google Cloud Next Tokyo ‘23 1 日目に行ってみた」 、2 本目は初参加で初登壇の NTT コミュニケーションズ イノベーションセンター 會澤さん から 「Google Cloud Next Tokyo ‘23 に行ってみた + 生成 AI 試してみた」 となっており有益な情報を共有していただきました。 最後にニューメンバー枠として NTT コミュニケーションズ クラウド&ネットワークサービス部(以下、C&N部) 渡邉さんと櫻田さん から 「C&N部のデータ収集・可視化基盤開発およびデータ活用部の取り組み」 ということで普段の業務と Google Cloud を絡めた内容を発表いただきました。 年内最後のイベントでもあったため LT 4 本の盛りだくさんなイベントとなりました!また、オフラインでの現地参加者数は過去最多の 18 名となっておりコミュニティの成長も感じられました。 アジェンダを見ただけでもワクワクするような LT 4 本立てとなっていて、振り返ってもとても濃密な時間となっていました! (執筆者 NTTコミュニケーションズ/林 知範) 運営メンバー紹介 今回の運営メンバーの紹介になります!前回同様にコミュニティメンバーへの呼びかけに応じてくれた森さんと中村さんの 2 名です。コミュニティ経験豊富なメンバーだったのでイベント運営が今まで以上に円滑でした。 —-------------------------------- NTT ドコモ サービスデザイン部(以下、ドコモ SD 部)の森と申します。元々ドコモ CCoE として Google Cloud の組織管理を担当し、当初よりグーグル・クラウド・ジャパン合同会社様とも密に連携をしておりました。また、Google Cloud の社内事例共有会を開催するなど、Google Cloud 利用者とも繋がりがあり、GINGER でも主要メンバーとして毎回参加しています。現在は別業務を担当していますが、Gemini の発表など Google 技術の変化は大変興味深く、同じモチベーションをもっているメンバーと交流できる GINGER は楽しみの1つとなっています。 本活動を支援いただいている全ての方々に、お礼申し上げるとともに、GINGER が皆さまに好影響を与えるコミュニティであり続けることを願っております。 —-------------------------------- (執筆者 NTTドコモ/森 健史) LT1:Google Cloud 生成AI Updates, Gemini 紹介 LTのトップバッターであり Googler 枠として登壇いただいたのは グーグル・クラウド・ジャパン合同会社様のカスタマーエンジニアである仲根さん になります。 「Google Cloud 生成AI Updates, Geminiご紹介」 のタイトルで発表いただきました。 はじめに、既存の生成 AI の Update として PaLM2 に chat-bison-002 と Unicorn のモデルが登場したこと、PaLM から Vertex AI Search を グラウンディング(モデルの出力を特定のデータに紐づける根拠付け)可能になったこと 、画像生成モデルの Imagen に Imagen2 が登場したことなどを説明いただきました。下図では Imagen よりも Imagen2 の方が生成される画像の精度が高いことが分かります。 続いて、2023年12月に発表された Gemini について説明いただきました。Ultra, Pro, Nano の 3 つのサイズが用意されており、 Gemini Pro については Google の会話型生成 AI サービスである Bard(英語版) や Google Cloud の Vertex AI で利用できるとのことです。 発表の中では Gemini のマルチモーダル機能について多くの説明がありました。2色の毛糸の画像を入力して「ここから何を作るべきか」の Gemini からのアイデア提案を受けたり、手のひらでコインを隠すマジックを複数の画像として入力して Gemini に説明・推論させたりといったものです。加えて Gemini Pro in Vertex AI のデモとして、Gemini が「ハイコンテキストな画像をどのように解釈するか」、「図形の意味をどこまで理解できるのか」の2つを実演いただきました。 図形の読み解きについてはシーケンス図とプロンプト(問題文)を入力としてGeminiが各問題に正しく回答する様子を実際に見せていただきました。 最後に、Sales Update として 2023 年 11 月に東京ビッグサイトで開催された Google Cloud Next Tokyo'23 参加の御礼と、ラスベガスで開催される Google Cloud Next'24 の案内で発表が締め括られました。 【感想】 Gemini の提供形態やマルチモーダル機能についてデモを交えてご説明いただき、とても分かりやすく参考になりました。MMLU(Massive Multitask Language Understanding) のベンチマークとして高いスコアを出していることを踏まえ、グラフ画像を含むレポートや文章の読み解き・生成にも利用できるといったところは今後試してみたいと思います。 (執筆者 NTTコミュニケーションズ/櫻田 真士) LT2:Google Cloud Next Tokyo'23 の 1 日目に行ってみた 次の LT は、 NTT ドコモ DP部の三浦さん です。Google Cloud Next Tokyo'23 の 1 日目に行ってみた感想を発表していただきました。 本人は大規模なイベントには初参加で、東京ビッグサイトで開催していることで「イベントやっている」感があり、楽しく参加できたとのことでした。 セッションは 業務で利用しているCI/CD周りを中心に聴講してきた とのことです。 1 つ目の参加セッションは、製造業での Cloud Run 周りの事例セッションです。 Cloud Run については知見がある中での参加とのことでしたが、小さなことでも知らなかった学びがあったり、セミナーの構成がとてもきれいであったという学びがあったようです。 ( Cloud Run を中心とした、製造業でのシステム開発コラボレーション事例 ) 2 つ目は、Organization を利用したガバナンスとセキュリティの事例セッションです。 あまり知見のない領域での参加とのことでしたが、役に立ちそうと前向きなコメントをしてくださっていました。Organization 機能は単一プロジェクトを利用しているだけでは意識することはないと思いますが、 Google Cloud のリソース管理体系は階層構造になっている点を理解して利用してもらえると、今後効果的な複数プロジェクト運用ができることがあるかも しれませんね。 ( 新米管理者の奮闘記のその後 〜 Organization の秩序を維持する試み 〜 ) 3 つ目は Google Cloud の CI/CD を利用したソフトウェアデリバリーについて、Google Cloud の方が講師を務めるセッションです。ここで触れられた各サービスについては三浦さん本人の業務でも利用しており、 「訳あってCI/CDをCloud BuildからGitHub Actionsに変えてみた」というタイトルで ドコモ開発者ブログ にもなっているため、皆さんも是非見てみてください!( 最新 Google Cloud CI/CD を利用したソフトウェア デリバリー ) (画像中のサービス群の引用元: Software Delivery Shield のコンポーネント ) 最後に全体を通して、「今回は業務で利用している領域中心だったけど、次はあえて自分が知らない領域も聞きたい」と前向きなコメントを残してくださいました! 【感想】 Google Cloud Next Tokyo には今回初参加ということで、色々刺激を受けたことが伝わってくる発表でした。実際に参加すると元々業務で利用している領域だけでなく、知らなかった領域への興味も湧いてきますね。全体的に前向きな姿勢を感じる発表で、聞いている側の私も刺激になりました。素晴らしい LT ありがとうございました! (執筆者 NTTドコモ/森 健史) LT3:Google Cloud Next Tokyo'23 に行ってみた LT 発表者は NTT コミュニケーションズ イノベーションセンター の會澤さん です。 今回 Google Cloud Next Tokyo'23 に行ってみた感想を発表していただきました。2 日間基調講演に参加しており、紹介しきれないのですが今回の Google Cloud Next Tokyo'23 の見どころであった生成AI部分を中心に紹介させていただきます。 會澤さんは NTT コミュニケーションズで Qmonus Value Stream という DevOps プラットフォームを開発 しています。 會澤さんには基調講演で聞いた 「生成AIによるアシスト Vertex AI」 を実際に自分のプロダクトのドキュメントで利用した様子をデモしていただきました。 ここで利用されていたのは 「 Vertex AI Search and Conversation 」というGoogle Cloudのプロダクト でした。本プロダクトには大きく分けて 「Vertex AI Search」「Vertex AI Conversation」 の 2 機能があります。 その中で會澤さんは 「Vertex AI Search」 を利用されていました。これは LLM(Large Language Model) がドキュメントを読み込み、利用者の質問に対して回答を生成するものです。 実際に Qmonus Value Stream のドキュメントを Vertex AI に学習させ、対話で内容を理解できる 様子をデモしていただきました。 デモの結果は上記の通り、無事に学習した内容を参照して対話形式で必要とする情報を取り出せていました。 最新技術をまずは自分のプロダクトで試してみることで、その技術の適用範囲を理解することができたとのことです! 【感想】 ドキュメント管理の問題は開発をしているとよくぶつかる問題です。 最新仕様のドキュメントはどれなのか、そもそも知りたい仕様はどこにあるのか、プロダクトが大きくなるにつれ膨大な量のドキュメントから探さなければなりません。 今回デモしていただいたように、知りたい情報をチャットボットで回答させるという方法は、この問題を解決する方法の 1 つと感じました。 「私もさっそく自分のプロダクトのドキュメントで活用したい」と感じさせる、ワクワクする LT でした! (執筆者 NTTコミュニケーションズ/渡邉 佑典) LT4:C&N部のデータ収集・可視化基盤開発およびデータ活用部の取り組み 最後の LT は、 NTT コミュニケーションズの渡邉さん、櫻田さん です。C&N 部のデータ収集・可視化基盤開発およびデータ活用部の取り組みについて発表していただきました。 まずは渡邉さんから NTT コミュニケーションズのクラウド・ネットワークサービス向けデータ収集・可視化基盤における、Google Cloud を利用したソフトウェアデリバリーについて話してもらいました。 渡邉さんも Google Cloud Next Tokyo'23 に参加し、自分たちのシステムの CI/CD をどう進化させられるかという観点で 「最新GoogleCloud CI/CD を利用したソフトウェアデリバリー」 セッションを聴講したとのことです。 そこで以下2点について見直しを行ったとのことでした。 CD にはデリバリーとデプロイの 2 種類がある セキュリティとCIを率先して実施すべき すると、 本番環境までの自動デプロイは実現できていない点、セキュリティについてはコンテナの脆弱性スキャン機能を使えていない点について気づいた とのことです。 「まだまだ改善すべきこと、やりたいことが たくさんあります」と締め括っていただきました。クラウドサービスやベストプラクティスは進化スピードが早いため、常に情報更新して適用していく姿勢が大事ですね。 続いて、櫻田さんからC&N部『データ活用部』 の取り組み事例について発表していただきました。 C&N部の『データ活用部』は、有志が公募制で参加し、データ利活用スキルを学び、教え合い、本業に活かしていく社内活動(部活) です。データドリブン化に向けた課題設定、解決に向けた活動だけではなくデータ利活用人材のキャリア形成サポートも行っているとのことです。 今の世の中、キャリア形成が大事なのでこのようなサポートはエンジニア一個人としてありがたいですよね。 また、取り組み事例として、 Google Cloud の Vertex AI を利用して、機械学習モデルを構築し、トラフィックデータの将来予測・可視化ワークフローを自動化する試みについて 話してもらいました。 最後に今後について、グーグル・クラウド・ジャパン合同会社様とさらなるコミュニケーションを活性化させて、Duet AI、BigQuery での PaLM 活用、BigQuery DataFrames、Vertex AI Search 等の新機能についても検証したいと語ってくれました。 【感想】 今回、LT2 の三浦さんも CI/CD 周りが中心でしたが、皆さん開発初期段階からしっかり CI/CD まで考えて構築されてるんだなぁと感心しました(CICD を考えてないプロジェクトも結構あるという認識でした)。セキュリティに関しては Artifact Registry の脆弱性スキャンなどまだまだ新サービスも出てきている状況なので、一度構築したらおしまいではなく、継続的に情報更新して適用していく姿勢が大事ですね。 また、データ活用に関しては私自身あまり知見のない領域ですが、LT1 の仲根さんもAI周りが中心で、今後 Vertex AI 周りも詳しくならないとなぁと感じ、発表を聞いているだけでも勉強になりました。 お二人とも素晴らしい LT ありがとうございました! (執筆者 NTTドコモ/森 健史) クロージング これにて LT パート終了となりました。 生成系 AI のホットな情報から Google Cloud Next Tokyo の有益なセッション共有、社内での利用事例といったバラエティに富んだイベントとなり非常に満足度が高いもの でした! また、冒頭でも記載しましたが徐々にオフラインでの現地参加者が増えており、業務だけでは出会えない DCC グループ内のメンバーとの交流の輪が広がっていることも肌で感じられて嬉しく思っています。 次回のイベント開催報告にもご期待ください! (執筆者 NTTコミュニケーションズ/林 知範)
アバター
こんにちは、NTT Com イノベーションセンターのNetwork Analytics for Security(NA4Sec)プロジェクトです。Team NA4Secでは2024年1月25日・26日に開催されたセキュリティカンファレンスJSAC2024に参加しました。この記事では、聴講した中で特に印象深かった講演について紹介します。 また、Team NA4Secでは2件の講演についても登壇しており、その内容は セキュリティカンファレンス「JSAC2024」に参加してきた話(登壇編) で紹介しています。今回参加したJSACとTeam NA4Secの概要についても 登壇編 の冒頭に記載がありますので興味のある方は合わせてご確認いただければと思います。 JSAC2024に参加してみて JSAC2024において印象深かった講演 A Study on Long-Term Trends about Amadey C2 Infrastructure Unveiling TeleBoyi: Chinese APT Group Targeting Critical Infrastructure Worldwide Workshop: Infrastructure Tracking With Mihari Workshop: Investigation Techniques and Practice on External Attack Surface おわりに JSAC2024に参加してみて 今回のJSAC2024も多くの参加者で賑わっており会場は活気に満ち溢れていました。セキュリティ業界で活躍する著名な方を見かけることも度々あり、改めてこのJSACが業界において重要なカンファレンスであることを認識しました。また、JSACは多くのアナリストが現地交流できる場ともなっているようで、特に登壇後の講演者の周りには多くの参加者が集まり情報交換がされていました。 講演・ワークショップではいずれも多数の聴講者が参加しており、新しい情報の数々を食い入るように聞いていました。特に一部のワークショップでは開始前から参加希望者が行列を作っており、開催されるワークショップの期待度の高さが伺えました。 このように数多くの興味深く、貴重な講演・ワークショップが実施されましたが今回はその中から一部を紹介したいと思います。 JSAC2024において印象深かった講演 A Study on Long-Term Trends about Amadey C2 Infrastructure (BlackBerry Japan, Masaki Kasuya氏) 本講演はAmadeyというマルウェアの長期観測(50ヶ月の観測)により得られた知見に関する発表でした。 活性化までに4年ほどかかったこと、Amadey上で使われた各種マルウェアがGitHubやDiscordなどのよく使われるサービス上に設置されていたこと、さらにAmadeyのボットネット上で100種類以上のマルウェアファミリーが拡散されており、一度感染すると複数のマルウェアに同時感染するリスクがある点などが紹介されており、マルウェアの挙動を長期視点で理解できる良い講演でした。特にAmadeyとRedlineが協調して動いている分析は興味深い発表と感じます(資料のp.30前後を参照)。 詳細は、こちらに資料がありますのでご参照ください。 https://jsac.jpcert.or.jp/archive/2024/pdf/JSAC2024_1_1_kasuya_en.pdf Unveiling TeleBoyi: Chinese APT Group Targeting Critical Infrastructure Worldwide (TeamT5, Yi-Chin Chuang氏およびYu-Tung Chang氏) JSAC常連の台湾のセキュリティベンダーTeamT5からは中国のAPTグループTeleBoyiに関する調査内容が共有されました。 TeleBoyiは発足当初、APAC(Asia-Pacific)に標的を絞っていました。発表者によると2023年には日本国内企業に関心を窺わせる攻撃インフラが確認されたとのことです。また、業界で見ると主に通信事業を主とした重要インフラを攻撃しており、一昨年あたりからエネルギー業界にも手を出し始めていることは注目に値します。 攻撃者の使うテクニックには目新しい印象はなく、マルウェアも中国系アクターの利用が多いPlugXなど多岐に渡っているとのことです。TeleBoyiも漏れなく他の中国系APTとの関連について講演で言及されていましたが、一方でTeleBoyiの特徴としてKCPプロトコルを使うユニークなマルウェアの使用も取り挙げられました。 台湾へのAPTの時期や対象は日本へのAPTと共通するケースがあります。台湾のベンダーの調査は日本の有事の際に正確なアトリビューションを行うための貴重なインプットとなりました。 詳細は、こちらに資料がありますのでご参照ください。 https://jsac.jpcert.or.jp/archive/2024/pdf/JSAC2024_1_8_yi-chin_yu-tung_en.pdf Workshop: Infrastructure Tracking With Mihari (Manabu Niseki氏) 本ワークショップは、shodanやCensysなどを利用したモニタリングツールである Mihari の作者である二関氏によるものです。 Mihariのコンセプトや利用方法、Mihariを使った実際のトラッキングの手法について学習することができました。 ワークショップ用のRepositoryが用意されており、参加者はドキュメントを参照しながらMihariのコンセプトを学んだり、実際にMihariを使ったトラッキングを実践することができました。 Shodan/Censysを利用した情報収集、 Nuclei と連携した調査など、ツールの使い方に留まらない充実したコンテンツが用意されていました。 本ワークショップの内容はVSCodeのDev Containersを利用して容易に環境を構築できるようになっているため、誰でも簡単に実習に取り組めます。興味がある方は下記の資料よりぜひ試してみてください。 こちらが当日の資料ですのでご参照ください。 https://ninoseki.github.io/jsac_mihari_workshop/ Workshop: Investigation Techniques and Practice on External Attack Surface (MACNICA, Inc., Kenzo Masamoto氏およびTakeya Yamazaki氏, Yutaka Sejiyama氏, Takeshi Teshigawara氏) 株式会社マクニカからEASM(External Attack Surface Management)についての解説と、実践ワークショップが開催されました。 EASMとはネットワーク機器や公開サーバ等の外部から攻撃される可能性がある領域(Attack Surface)を把握・対処するための取り組みであり、Attack Surfaceを起点としたインシデントの発生が確認されている昨今において、EASMが重要であることとその具体的な手法について解説されました。特に製品別にそのOSのバージョンを推測する方法については興味深く、貴重な情報であると感じました。 また本ワークショップでは、参加者が複数のツール・サービスを実際に使用して、社内の外部公開資産の調査およびリスク評価を実践するパートがあり、特にここでは重要なスキルを習得できたと考えています。それに加えて、外部から特定組織への調査が可能であることを再認識することでEASMの重要性を骨身にしみて理解できたという点においても、本ワークショップは貴重な経験となりました。 おわりに 以上より、この記事ではJSAC2024における特に印象深い講演・ワークショップを紹介しました。 今回のJSAC2024への参加を通して、セキュリティ業界の最前線で活躍するセキュリティアナリストから最新のアクターの動向や重要な解析結果など、参加した今となれば必聴とも思える貴重な情報をインプットできました。 今回は聴講という形での参加となりましたが、次回以降の開催では登壇することを目標としてコミュニティへの還元とセキュリティ業界への貢献ができればと考えています。
アバター
こんにちは、NTT Com イノベーションセンターのNetwork Analytics for Security(NA4Sec)プロジェクトです。Team NA4Secでは2024年1月25日・26日に開催されたセキュリティカンファレンスJSAC2024に参加しました。この記事では、聴講した中で特に印象深かった講演について紹介します。 また、Team NA4Secでは2件の講演についても登壇しており、その内容は セキュリティカンファレンス「JSAC2024」に参加してきた話(登壇編) で紹介しています。今回参加したJSACとTeam NA4Secの概要についても 登壇編 の冒頭に記載がありますので興味のある方は合わせてご確認いただければと思います。 JSAC2024に参加してみて JSAC2024において印象深かった講演 A Study on Long-Term Trends about Amadey C2 Infrastructure Unveiling TeleBoyi: Chinese APT Group Targeting Critical Infrastructure Worldwide Workshop: Infrastructure Tracking With Mihari Workshop: Investigation Techniques and Practice on External Attack Surface おわりに JSAC2024に参加してみて 今回のJSAC2024も多くの参加者で賑わっており会場は活気に満ち溢れていました。セキュリティ業界で活躍する著名な方を見かけることも度々あり、改めてこのJSACが業界において重要なカンファレンスであることを認識しました。また、JSACは多くのアナリストが現地交流できる場ともなっているようで、特に登壇後の講演者の周りには多くの参加者が集まり情報交換がされていました。 講演・ワークショップではいずれも多数の聴講者が参加しており、新しい情報の数々を食い入るように聞いていました。特に一部のワークショップでは開始前から参加希望者が行列を作っており、開催されるワークショップの期待度の高さが伺えました。 このように数多くの興味深く、貴重な講演・ワークショップが実施されましたが今回はその中から一部を紹介したいと思います。 JSAC2024において印象深かった講演 A Study on Long-Term Trends about Amadey C2 Infrastructure (BlackBerry Japan, Masaki Kasuya氏) 本講演はAmadeyというマルウェアの長期観測(50ヶ月の観測)により得られた知見に関する発表でした。 活性化までに4年ほどかかったこと、Amadey上で使われた各種マルウェアがGitHubやDiscordなどのよく使われるサービス上に設置されていたこと、さらにAmadeyのボットネット上で100種類以上のマルウェアファミリーが拡散されており、一度感染すると複数のマルウェアに同時感染するリスクがある点などが紹介されており、マルウェアの挙動を長期視点で理解できる良い講演でした。特にAmadeyとRedlineが協調して動いている分析は興味深い発表と感じます(資料のp.30前後を参照)。 詳細は、こちらに資料がありますのでご参照ください。 https://jsac.jpcert.or.jp/archive/2024/pdf/JSAC2024_1_1_kasuya_en.pdf Unveiling TeleBoyi: Chinese APT Group Targeting Critical Infrastructure Worldwide (TeamT5, Yi-Chin Chuang氏およびYu-Tung Chang氏) JSAC常連の台湾のセキュリティベンダーTeamT5からは中国のAPTグループTeleBoyiに関する調査内容が共有されました。 TeleBoyiは発足当初、APAC(Asia-Pacific)に標的を絞っていました。発表者によると2023年には日本国内企業に関心を窺わせる攻撃インフラが確認されたとのことです。また、業界で見ると主に通信事業を主とした重要インフラを攻撃しており、一昨年あたりからエネルギー業界にも手を出し始めていることは注目に値します。 攻撃者の使うテクニックには目新しい印象はなく、マルウェアも中国系アクターの利用が多いPlugXなど多岐に渡っているとのことです。TeleBoyiも漏れなく他の中国系APTとの関連について講演で言及されていましたが、一方でTeleBoyiの特徴としてKCPプロトコルを使うユニークなマルウェアの使用も取り挙げられました。 台湾へのAPTの時期や対象は日本へのAPTと共通するケースがあります。台湾のベンダーの調査は日本の有事の際に正確なアトリビューションを行うための貴重なインプットとなりました。 詳細は、こちらに資料がありますのでご参照ください。 https://jsac.jpcert.or.jp/archive/2024/pdf/JSAC2024_1_8_yi-chin_yu-tung_en.pdf Workshop: Infrastructure Tracking With Mihari (Manabu Niseki氏) 本ワークショップは、shodanやCensysなどを利用したモニタリングツールである Mihari の作者である二関氏によるものです。 Mihariのコンセプトや利用方法、Mihariを使った実際のトラッキングの手法について学習することができました。 ワークショップ用のRepositoryが用意されており、参加者はドキュメントを参照しながらMihariのコンセプトを学んだり、実際にMihariを使ったトラッキングを実践することができました。 Shodan/Censysを利用した情報収集、 Nuclei と連携した調査など、ツールの使い方に留まらない充実したコンテンツが用意されていました。 本ワークショップの内容はVSCodeのDev Containersを利用して容易に環境を構築できるようになっているため、誰でも簡単に実習に取り組めます。興味がある方は下記の資料よりぜひ試してみてください。 こちらが当日の資料ですのでご参照ください。 https://ninoseki.github.io/jsac_mihari_workshop/ Workshop: Investigation Techniques and Practice on External Attack Surface (MACNICA, Inc., Kenzo Masamoto氏およびTakeya Yamazaki氏, Yutaka Sejiyama氏, Takeshi Teshigawara氏) 株式会社マクニカからEASM(External Attack Surface Management)についての解説と、実践ワークショップが開催されました。 EASMとはネットワーク機器や公開サーバ等の外部から攻撃される可能性がある領域(Attack Surface)を把握・対処するための取り組みであり、Attack Surfaceを起点としたインシデントの発生が確認されている昨今において、EASMが重要であることとその具体的な手法について解説されました。特に製品別にそのOSのバージョンを推測する方法については興味深く、貴重な情報であると感じました。 また本ワークショップでは、参加者が複数のツール・サービスを実際に使用して、社内の外部公開資産の調査およびリスク評価を実践するパートがあり、特にここでは重要なスキルを習得できたと考えています。それに加えて、外部から特定組織への調査が可能であることを再認識することでEASMの重要性を骨身にしみて理解できたという点においても、本ワークショップは貴重な経験となりました。 おわりに 以上より、この記事ではJSAC2024における特に印象深い講演・ワークショップを紹介しました。 今回のJSAC2024への参加を通して、セキュリティ業界の最前線で活躍するセキュリティアナリストから最新のアクターの動向や重要な解析結果など、参加した今となれば必聴とも思える貴重な情報をインプットできました。 今回は聴講という形での参加となりましたが、次回以降の開催では登壇することを目標としてコミュニティへの還元とセキュリティ業界への貢献ができればと考えています。
アバター
こんにちは、NTT Com イノベーションセンターのNetwork Analytics for Security(NA4Sec)プロジェクトです。 この記事では、2024年1月25日・26日に開催されたセキュリティカンファレンス JSAC2024 にTeam NA4Secから登壇した2件の講演について紹介します。 Operation So-seki: You Are a Threat Actor. As Yet You Have No Name. Analysis of Activities and Tools of Phishing Actors Targeting Japan JSACとは Team NA4Secとは Team NA4SecによるJSAC2024講演 講演1: Operation So-seki: You Are a Threat Actor. As Yet You Have No Name. 講演2: Analysis of Activities and Tools of Phishing Actors Targeting Japan おわりに 興味を持たれた方へ 出張講演承ります 脅威情報を配信しています 仲間を募集しています JSACとは JSACはJPCERT/CCが主催するセキュリティカンファレンスで、 現場のセキュリティアナリストが集い、高度化するサイバー攻撃に対抗するための情報を共有すること を目的に開催されています。 毎年300-450名の定員が事前に埋まって参加申し込みが締め切られるほど関心を集めているイベントで、今年は7回目の開催でした。 本日、予定通り開催です。みなさまのご来場お待ちしております。 #JSAC2024 pic.twitter.com/0KNBqKv2ed — Analysis Center (@jpcert_ac) 2024年1月24日 もともとはJapan Security Analyst Conferenceの略称としてJSAC(ジェイサック)と呼称していましたが、日本に閉じず国際会議としての位置付けを目指すためにJSAC2023からはJSACを正式名称としています。 実際に毎年、海外からも応募・登壇があり、今年も海外から複数のスピーカーが登壇されていました。 特にAPAC(Asia-Pacific)に関係するセキュリティ脅威について他では得られない深い知見の集まるイベントの1つと言えます。 なお、過去開催の様子は JPCERT/CCのブログ でも紹介されています。 一部非公開のものもありますが、各回のWebサイトでは講演資料が公開されており、 JPCERT/CCのYoutube公式チャンネル には講演動画も公開されています。 Team NA4Secとは NA4Secプロジェクトは「NTTはインターネットを安心、安全にする社会的責務がある」を理念として、攻撃インフラの解明、撲滅を目指すプロジェクトです *1 。 NTT Com イノベーションセンターを中心としてNTTセキュリティ・ジャパンやエヌ・エフ・ラボラトリーズ(以下、NFLabs.)からもメンバーが参画し、日夜攻撃インフラを追跡しています。 今回、JSAC2024においてTeam NA4Secが追跡してきた脅威アクターに関する講演が2件採択され、登壇してきました。 なお、NTT ComのJSAC採択は今回が初で、いきなり合計5名での登壇となりました。 / イベント登壇情報✨ \ ​ 国内有数のセキュリティカンファレンス #JSAC2024 にて、 NTT Com、NFLabs.の社員が2つのセッションに登壇✨ ​ ハクティビスト、フィッシング被害について 調査で得られた知見を来場者限定で公開します! ​ 詳細はこちら⬇ https://t.co/zGuh2fOImO pic.twitter.com/6Iz3ta9BSH — NTTドコモビジネス (@NTTCom_online) 2024年1月23日 Team NA4SecによるJSAC2024講演 講演1: Operation So-seki: You Are a Threat Actor. As Yet You Have No Name. 1件目の講演は、親ロシア派ハクティビストを長期追跡した内容でした。 DDoS攻撃を用いるハクティビストという非常にセンシティブな話題を扱うため、多くの情報を参加者限定としましたが、選考委員や運営の方々にもご理解いただき、発表の機会を得ることができました。 昨年来、DDoS攻撃による被害は日本でもたびたびメディアに取り上げられるなど、関心が高まっていたこともあってか、うなずきながら話に耳を傾けてくださる参加者が何人も壇上から見えました。 「複数の観点からの分析や考察がとてもわかりやすく解説されていて非常に良かった」といった声を得ることもでき、このタイミングでこの話を持って来られてよかったです。 講演の中では昨今アクティブサイバーディフェンスの議論などでも注目を集めているフロー情報の活用についても触れ、その有効性や限界についてセキュリティ実務者の視点から共有しました。 前述の理由からほとんどの情報は伏せられていますが、JSAC2024の公式サイトに講演資料( 日本語版 ・ 英語版 )が掲載されていますので、気になる方はダウンロードしてみてください。 講演1登壇者の皆川(左: @strinsert1Na )、 神田(中央: @ashy0x41 )、 鮫嶋(右: @islairand ) 講演2: Analysis of Activities and Tools of Phishing Actors Targeting Japan 2件目の講演は、日本を狙ったフィッシングに関して、フィッシングアクター同士が交流する「フィッシングコミュニティ」やフィッシングに使われるツール(フィッシングキット)を調査した内容でした。 日本を狙ったフィッシングを取り巻くコミュニティがどのように形成され分業化されているのか、その実態を明らかにするとともに、フィッシングキットの挙動について実例を挙げて紹介しました。 参加者からは「フィッシングコミュニティやフィッシングアクターの活動状況についての話は大変興味深い」「フィッシングキットの分析内容の共有やIoCの活用例についても解りやすく説明されていた」「IoCの活用方法としてそういうツールがあるのか」などポジティブな反応を得ることができました。 講演内で取り上げたフィッシングキットに関するIoCについては講演資料( 日本語版 ・ 英語版 )内のAppendixにも記載していますので、もし参加ができなかった方は是非ダウンロードしてみてください。 講演2登壇者の益本(左: @masaomi346 )、 坪井(右: @ytsuboi0322 ) おわりに 多くの優秀なセキュリティアナリストが発表するカンファレンスに登壇し、コミュニティに貢献する機会を得たことは、登壇したメンバー各人だけでなくチームにとっても大きな出来事でした。 実を言えば昨年JSAC2023が開催されていた頃はプロジェクトの本務メンバーが1名しかいない状態でした。 そこから縁にも恵まれ、チームの活動を拡大・加速させることができ、今回の結果につながりました。 実際、今回の登壇者5名のうち3名はこの1年で新たにチームに加わったメンバーです(もっと言えば1名は今年度入社の新卒社員です)。 この短期間で一定の成果を上げられたことは、チームビルディングや環境・風土作りの方向性がチームメンバーや業務の性質にマッチしている表れと考えています。 今後も引き続き、セキュリティアナリストのスキルの底上げに貢献し、セキュリティ業界を盛り上げていければと考えています。 興味を持たれた方へ 出張講演承ります 今回の講演(特に1件目のハクティビスト)は、情報の性質上、攻撃者の詳細に関わる情報は公開していません *2 。 他方、サイバー攻撃に係る情報を(非公開に)共有することは今後の被害の未然防止や被害低減につながる価値があると考えています *3 。 出張講演なども前向きに検討しますので、興味のある方はNA4Secプロジェクトまでお気軽にご相談ください。 脅威情報を配信しています NA4Secプロジェクトでは兄弟プロジェクトであるMetemcyber *4 と連携してマルウェアやフィッシングに関する脅威情報を配信しています( @Metemcyber ) *5 。 情報配信に関する経緯や思いはブログ記事を公開していますので、興味のある方はそちらもぜひご覧ください。 サイバー脅威インテリジェンス(CTI)配信はじめました 日本を狙ったフィッシングサイトの情報配信はじめました 仲間を募集しています NA4Sec/Metemcyberプロジェクトではそれぞれ一緒に働く仲間を募集しています。 「脅威インテリジェンス」をキーワードに活躍の場を探している方、プロジェクトの理念に共感していただける方のご応募をお待ちしています。 Threat Intelligence Analyst / 脅威インテリジェンスアナリスト (NA4Sec) Threat Intelligence Engineer / 脅威インテリジェンスエンジニア (Metemcyber) NFLabs. ではセキュリティエンジニア/セキュリティインストラクター/マネージャーを募集中です。 Xやエンジニアブログでも情報を発信していますのでこちらも合わせてご覧ください。 NFLabs. RECRUIT NFLabs. 公式Xアカウント(@NFLaboratories) NFLabs. エンジニアブログ *1 : 社内では親しみを込めて「NA4Sec(なよせ)」と呼んでいます *2 : DDoS攻撃に関する情報共有の問題については、JPCERT/CCのブログ記事「 注意喚起や情報共有活動における受信者側の「コスト」の問題について ー情報発信がアリバイや成果目的の自己目的化した行為にならないためにー 」がおすすめです。 *3 : このあたりはNISCから公開されている「 サイバー攻撃被害に係る情報の共有・公表ガイダンス 」にて論点が整理されています。 *4 : 最近のMetemcyberの活動については、「 ソフトウェア開発におけるサプライチェーンセキュリティの実践 」をご覧ください。 *5 : 最近では TweetFeed にもデータソースとして取り込まれるようになったので、以前よりも扱いやすくなりました。
アバター