TECH PLAY

電通総研

電通総研 の技術ブログ

832

こんにちは、ISID デジタルビジネス推進室の浦本です。好きな食べ物は生八ツ橋です。 本記事は 電通国際情報サービス Advent Calendar 2021 の24日目の記事です。 はじめに 皆さんは、npmでインストールした依存パッケージを定期的に更新されていますか? 「面倒だから更新していない。。。」 「フロントエンドはそのままでも大丈夫でしょ?」 と思って放置されている方もいらっしゃるかもしれません。 しかーし!! 更新せずに放置していると、古い依存パッケージの 脆弱性 を突かれてしまったり、アプリのコード体系が古くなり開発に支障が出たりします。 そこで本日は、面倒になりがちな依存パッケージのバージョン更新を円滑に行うための戦略を書きたいと思います。 【用語について】 本記事では、依存パッケージを利用する開発プロジェクトを単に「アプリ」と呼称します。 戦略 以下より詳細をご説明します。 dependencies と devDependencies の違いを意識する お悩み:「色々とパッケージを追加したけれど、どれが重要か分からなくなってきた。」 package. json 内の dependencies にはプロダクション・コードに影響する依存パッケージ名を列挙し、 devDependencies にはプロダクション・コードに影響しない依存パッケージ名(ビルドツールなど)を列挙します。 【例】 { " name ": " my-app ", " version ": " 1.0.0 ", " private ": true , " dependencies ": { " hogehoge ": " ^2.1.0 ", " fugafuga ": " ^3.4.2 " } , " devDependencies ": { " piyopiyo ": " ^6.7.0 " } } 依存パッケージ名を両者に振り分けておくことで、更新作業の際に、どのパッケージがより重要であるか容易に把握できます。 また、 脆弱性 情報の有無を確認するための npm audit コマンドでは --production オプションを指定することで dependencies のみを調査対象とすることもできます。 【振り分け方法】 npm install <パッケージ名> コマンドにて依存パッケージを追加する際に、下記のオプションで指定します。 ## dependenciesに追加 (オプション指定不要) $ npm intall hogehoge ## devDependenciesに追加 (--devまたは-Dオプションを付与) $ npm install --dev hogehoge 既に依存パッケージを追加済みである場合は、package. json を手動で編集して対象パッケージ名の行を移動した後に、引数なしの npm install コマンドを実行すれば大丈夫です。 更新サイクルをチーム内で明確に決める お悩み:「依存パッケージ、最後に更新したのはいつだろう(遠い目)。」 フロントエンドの依存パッケージは非常に速いペースで機能拡張されていきますので、定期的に更新するという意識を持たないと、ついつい利用バージョンが古いままになってしまいます。 そこで下記のように、いつ(どのような頻度で)更新を行うかを明確化することが大切です。 臨時のセキュリティ更新 週に1回など短い間隔で依存パッケージの 脆弱性 の有無をチェックし、 脆弱性 があればピンポイントで更新する。これによりアプリをセキュアに保つ。 npm audit --production コマンドにて dependencies の依存パッケージに対し既知の 脆弱性 がないかチェックし、影響度に応じてパッケージを更新する。または、 GitHub Dependabot などの自動チェックサービスを用いる。 定期的な一括更新 3カ月に1回など具体的な頻度を決めて、依存パッケージを可能な範囲で全て更新する。これによりコードの陳腐化を防ぐ。 npm outdated コマンドにて新しいバージョンの存在チェックを一括で行い、影響調査・更新を実施する。 動作に影響を与える可能性が高い依存パッケージを把握する お悩み:「package.json内の記載順にパッケージ更新可否を調査し始めたが、何だか効率が悪い。」 以下に属する依存パッケージは芋づる式で他のパッケージの動作に影響を与えるため、優先的に更新の検討を行う事をオススメします。 TypeScript 最近はTypeScriptの型定義を提供するライブラリが多くありますが、型定義よりもTypeScriptのバージョンの方が古いと コンパイル エラーになる場合があるため、真っ先に更新可否を調査したいところです。 webpackなどのモジュール・バンドラ、および プラグイン 例えばwebpackの場合、基本的に複数のloader系 プラグイン を導入して使うことになるため、webpackと プラグイン 間のバージョン相性が悪いとビルドに失敗します。当然、各loader系 プラグイン の作者はバラバラなので、最適なバージョンの組み合わせは自分で探る必要が出てきます。まさにパズルであり、場合によっては更新を断念する事もあります。こちらも優先的に調査したいところです。 VueやReactなどの フレームワーク 、および プラグイン こちらは説明不要ですね! フレームワーク の更新内容はアプリの実装コード全体に影響してしまうので、早めに調査しましょう。 まとめると、以下の優先順位で影響を調査していけば、手戻りを防ぐことが出来ます。 npm audit --production コマンドにて 脆弱性 が表示されたパッケージ 本節で触れた、動作に影響を与える可能性が高い依存パッケージ 残りの dependencies 残りの devDependencies 【Tips】 プラグイン 系パッケージが想定している基幹パッケージ(例えば wepack-hogehoge-plugin の作者が想定している webpack)のバージョンを知りたいときは、 GitHub リポジトリ のリリースノートの確認に加えて、対象パッケージ直下にあるpackage. json 内の devDependencies と peerDependencies に書いてある基幹パッケージのバージョンをチェックしましょう。 peerDependencies の方は馴染みがないかもしれませんが、ここには、 プラグイン 側がアプリの dependencies または devDependencies に要求する基幹パッケージのバージョンが記載されています。 ただし、緩い範囲(例えばメジャーバージョンの指定のみ)でバージョン指定されていることもあるので、あくまで指標として捉えてください。 ビルド結果の差分を確認する お悩み:「従来まで取得できていた値がundefinedになっちゃった!」 TypeScriptなどのトランスパイラや、webpackなどのモジュール・バンドラのバージョンを更新すると、生成される JavaScript コードに差分が出ることがあります。 それが僅かな差分であっても、アプリの一部が機能しなくなる可能性があります。 生成されたコードの差分を確認するためには、以下の手順を踏んでください。 旧環境と新環境において、モジュール・バンドラのコード圧縮をOFFにしてそれぞれビルドを行う。 ※圧縮したままだと比較が困難であるため JavaScript コードの差分をdiffツールで確認する。明らかに影響がなければここで終了。 影響が有りそうな差分を発見した場合、その周辺のキーワードを元に、TypeScriptやwebpackの GitHub ソースコード を確認し、コードを生成している箇所を突き止める。その上で差分の意味を理解し、自分のアプリに影響があるかを判断する。 なお、開発環境のNode.jsをメジャーバージョンアップしたときも、念のため、同様の手順で確認しておいた方が良いでしょう。 バージョン選定の理由や注意点を表にまとめる お悩み:「何らかの理由でこのバージョンに固定したんだけど、思い出せない。」 依存パッケージの定期的な一括更新作業を行うとき、前回の実施時から日が空いてしまうと、前回採用したバージョンの選定理由を忘れてしまう事があります。 それを防ぐために、バージョン選定の理由や注意点を表にまとめておきましょう。未来の自分・自チームへの助けになります。 下表に例を示します。 No. 分類 パッケージ名 バージョン 選定理由や注意点 1 dependencies hogehoge 2.1.0 動作確認済みであるv2系の最新版を利用。v3系はアイコンの見た目が変わるので利用不可。 2 dependencies fugafuga 3.4.2 IE11向けのpolyfillなのでバージョンアップ不要。IE11のサポートを切ったら消す。 ... 70 devDependencies piyopiyo 6.7.0 極力最新版を利用するが、あくまでTypeScriptのバージョンに依存。 このような情報さえまとめておけば、更新作業担当者が変わっても差し支えないため、柔軟な作業 アサイ ンも可能となります。 コマンド一発で実行可能な 単体テスト を用意しておく お悩み:「影響範囲の確認が終わらないよ~!」 依存パッケージの更新時は、アプリの動作に影響がない事を確認する必要があります。 このテスト作業の負荷を少しでも減らすために、フロントエンドの各種実装コードに対して、普段からコマンド一発で実行可能な 単体テスト を書いておく事が非常に重要です。 最近ではVueやReactなどの普及によりUI コンポーネント を主眼に置いた開発が浸透してきているため、コードの部品化が促進され、比較的テストが作りやすい状況にあると言えます。 ご利用の フレームワーク で推奨されているテストライブラリを用い、UI コンポーネント やクラスの 単体テスト を実装しておきましょう。何千というテストケースが一気に通る様を眺めるのは爽快ですよ! 【テスト実装方法の参考リンク】 Vue.js公式ドキュメント - Testing React公式ドキュメント - Testing Overview おわりに いかがでしたでしょうか。 本記事の内容が、少しでも読者の方のお役に立つことができたなら幸いです。 最後に戦略図を再掲します。 電通国際情報サービス Advent Calendar 2021 の他の記事もぜひ、お楽しみください。 執筆: @uramoto.kazuhiro 、レビュー: @sato.taichi ( Shodo で執筆されました )
アバター
こんにちは、ISID デジタルビジネス推進室の浦本です。好きな食べ物は生八ツ橋です。 本記事は 電通国際情報サービス Advent Calendar 2021 の24日目の記事です。 はじめに 皆さんは、npmでインストールした依存パッケージを定期的に更新されていますか? 「面倒だから更新していない。。。」 「フロントエンドはそのままでも大丈夫でしょ?」 と思って放置されている方もいらっしゃるかもしれません。 しかーし!! 更新せずに放置していると、古い依存パッケージの 脆弱性 を突かれてしまったり、アプリのコード体系が古くなり開発に支障が出たりします。 そこで本日は、面倒になりがちな依存パッケージのバージョン更新を円滑に行うための戦略を書きたいと思います。 【用語について】 本記事では、依存パッケージを利用する開発プロジェクトを単に「アプリ」と呼称します。 戦略 以下より詳細をご説明します。 dependencies と devDependencies の違いを意識する お悩み:「色々とパッケージを追加したけれど、どれが重要か分からなくなってきた。」 package. json 内の dependencies にはプロダクション・コードに影響する依存パッケージ名を列挙し、 devDependencies にはプロダクション・コードに影響しない依存パッケージ名(ビルドツールなど)を列挙します。 【例】 { " name ": " my-app ", " version ": " 1.0.0 ", " private ": true , " dependencies ": { " hogehoge ": " ^2.1.0 ", " fugafuga ": " ^3.4.2 " } , " devDependencies ": { " piyopiyo ": " ^6.7.0 " } } 依存パッケージ名を両者に振り分けておくことで、更新作業の際に、どのパッケージがより重要であるか容易に把握できます。 また、 脆弱性 情報の有無を確認するための npm audit コマンドでは --production オプションを指定することで dependencies のみを調査対象とすることもできます。 【振り分け方法】 npm install <パッケージ名> コマンドにて依存パッケージを追加する際に、下記のオプションで指定します。 ## dependenciesに追加 (オプション指定不要) $ npm intall hogehoge ## devDependenciesに追加 (--devまたは-Dオプションを付与) $ npm install --dev hogehoge 既に依存パッケージを追加済みである場合は、package. json を手動で編集して対象パッケージ名の行を移動した後に、引数なしの npm install コマンドを実行すれば大丈夫です。 更新サイクルをチーム内で明確に決める お悩み:「依存パッケージ、最後に更新したのはいつだろう(遠い目)。」 フロントエンドの依存パッケージは非常に速いペースで機能拡張されていきますので、定期的に更新するという意識を持たないと、ついつい利用バージョンが古いままになってしまいます。 そこで下記のように、いつ(どのような頻度で)更新を行うかを明確化することが大切です。 臨時のセキュリティ更新 週に1回など短い間隔で依存パッケージの 脆弱性 の有無をチェックし、 脆弱性 があればピンポイントで更新する。これによりアプリをセキュアに保つ。 npm audit --production コマンドにて dependencies の依存パッケージに対し既知の 脆弱性 がないかチェックし、影響度に応じてパッケージを更新する。または、 GitHub Dependabot などの自動チェックサービスを用いる。 定期的な一括更新 3カ月に1回など具体的な頻度を決めて、依存パッケージを可能な範囲で全て更新する。これによりコードの陳腐化を防ぐ。 npm outdated コマンドにて新しいバージョンの存在チェックを一括で行い、影響調査・更新を実施する。 動作に影響を与える可能性が高い依存パッケージを把握する お悩み:「package.json内の記載順にパッケージ更新可否を調査し始めたが、何だか効率が悪い。」 以下に属する依存パッケージは芋づる式で他のパッケージの動作に影響を与えるため、優先的に更新の検討を行う事をオススメします。 TypeScript 最近はTypeScriptの型定義を提供するライブラリが多くありますが、型定義よりもTypeScriptのバージョンの方が古いと コンパイル エラーになる場合があるため、真っ先に更新可否を調査したいところです。 webpackなどのモジュール・バンドラ、および プラグイン 例えばwebpackの場合、基本的に複数のloader系 プラグイン を導入して使うことになるため、webpackと プラグイン 間のバージョン相性が悪いとビルドに失敗します。当然、各loader系 プラグイン の作者はバラバラなので、最適なバージョンの組み合わせは自分で探る必要が出てきます。まさにパズルであり、場合によっては更新を断念する事もあります。こちらも優先的に調査したいところです。 VueやReactなどの フレームワーク 、および プラグイン こちらは説明不要ですね! フレームワーク の更新内容はアプリの実装コード全体に影響してしまうので、早めに調査しましょう。 まとめると、以下の優先順位で影響を調査していけば、手戻りを防ぐことが出来ます。 npm audit --production コマンドにて 脆弱性 が表示されたパッケージ 本節で触れた、動作に影響を与える可能性が高い依存パッケージ 残りの dependencies 残りの devDependencies 【Tips】 プラグイン 系パッケージが想定している基幹パッケージ(例えば wepack-hogehoge-plugin の作者が想定している webpack)のバージョンを知りたいときは、 GitHub リポジトリ のリリースノートの確認に加えて、対象パッケージ直下にあるpackage. json 内の devDependencies と peerDependencies に書いてある基幹パッケージのバージョンをチェックしましょう。 peerDependencies の方は馴染みがないかもしれませんが、ここには、 プラグイン 側がアプリの dependencies または devDependencies に要求する基幹パッケージのバージョンが記載されています。 ただし、緩い範囲(例えばメジャーバージョンの指定のみ)でバージョン指定されていることもあるので、あくまで指標として捉えてください。 ビルド結果の差分を確認する お悩み:「従来まで取得できていた値がundefinedになっちゃった!」 TypeScriptなどのトランスパイラや、webpackなどのモジュール・バンドラのバージョンを更新すると、生成される JavaScript コードに差分が出ることがあります。 それが僅かな差分であっても、アプリの一部が機能しなくなる可能性があります。 生成されたコードの差分を確認するためには、以下の手順を踏んでください。 旧環境と新環境において、モジュール・バンドラのコード圧縮をOFFにしてそれぞれビルドを行う。 ※圧縮したままだと比較が困難であるため JavaScript コードの差分をdiffツールで確認する。明らかに影響がなければここで終了。 影響が有りそうな差分を発見した場合、その周辺のキーワードを元に、TypeScriptやwebpackの GitHub ソースコード を確認し、コードを生成している箇所を突き止める。その上で差分の意味を理解し、自分のアプリに影響があるかを判断する。 なお、開発環境のNode.jsをメジャーバージョンアップしたときも、念のため、同様の手順で確認しておいた方が良いでしょう。 バージョン選定の理由や注意点を表にまとめる お悩み:「何らかの理由でこのバージョンに固定したんだけど、思い出せない。」 依存パッケージの定期的な一括更新作業を行うとき、前回の実施時から日が空いてしまうと、前回採用したバージョンの選定理由を忘れてしまう事があります。 それを防ぐために、バージョン選定の理由や注意点を表にまとめておきましょう。未来の自分・自チームへの助けになります。 下表に例を示します。 No. 分類 パッケージ名 バージョン 選定理由や注意点 1 dependencies hogehoge 2.1.0 動作確認済みであるv2系の最新版を利用。v3系はアイコンの見た目が変わるので利用不可。 2 dependencies fugafuga 3.4.2 IE11向けのpolyfillなのでバージョンアップ不要。IE11のサポートを切ったら消す。 ... 70 devDependencies piyopiyo 6.7.0 極力最新版を利用するが、あくまでTypeScriptのバージョンに依存。 このような情報さえまとめておけば、更新作業担当者が変わっても差し支えないため、柔軟な作業 アサイ ンも可能となります。 コマンド一発で実行可能な 単体テスト を用意しておく お悩み:「影響範囲の確認が終わらないよ~!」 依存パッケージの更新時は、アプリの動作に影響がない事を確認する必要があります。 このテスト作業の負荷を少しでも減らすために、フロントエンドの各種実装コードに対して、普段からコマンド一発で実行可能な 単体テスト を書いておく事が非常に重要です。 最近ではVueやReactなどの普及によりUI コンポーネント を主眼に置いた開発が浸透してきているため、コードの部品化が促進され、比較的テストが作りやすい状況にあると言えます。 ご利用の フレームワーク で推奨されているテストライブラリを用い、UI コンポーネント やクラスの 単体テスト を実装しておきましょう。何千というテストケースが一気に通る様を眺めるのは爽快ですよ! 【テスト実装方法の参考リンク】 Vue.js公式ドキュメント - Testing React公式ドキュメント - Testing Overview おわりに いかがでしたでしょうか。 本記事の内容が、少しでも読者の方のお役に立つことができたなら幸いです。 最後に戦略図を再掲します。 電通国際情報サービス Advent Calendar 2021 の他の記事もぜひ、お楽しみください。 執筆: @uramoto.kazuhiro 、レビュー: @sato.taichi ( Shodo で執筆されました )
アバター
本記事は、 電通国際情報サービス Advent Calendar 2021 の23日目の記事です。 担当は、 エンタープライズ IT事業部 データマネジメント コンサルティング 部 宮城です。 データはDX推進における要であり、データを司る「環境」の重要性というのは昨今ますます高まってきています。 先日、ISIDは、 データクラウド"Snowflake"の販売代理店契約を締結しました。 本日は、この” Snowflake ”について特に私が感銘を受けている特徴を2つ紹介します。 特徴その①:独自の アーキテクチャ <ストレージとコンピュート> 一般的なコンピューターを構成する重要な要素はCPUとメモリとストレージです。" Snowflake "では、そのうちCPUとメモリだけを分離したものをコンピュートという概念で扱います。 ストレージは1つ。利用用途ごとに、さまざまなスペックのコンピュートを立てることができます。 各コンピュートはお互い影響せず、独立したパフォーマンスを実現できます。 このコンピュートを「ウェアハウス」と呼びます。ウェアハウスのスペックは「サイズ」と呼ばれ、XS⇒S⇒M⇒L⇒・・・とTシャツのサイズと同じように表現されます。 たとえば、下記のようなウェアハウスの使い方ができます。 データ加工専用ウェアハウス:   大量のデータを処理するため、大きいサイズのウェアハウスを1台 BI参照専用ウェアハウス:   複数のユーザーが同時にアクセスするため、小~中程度のウェアハウスを複数台 この「ウェアハウス」について、ポイントを2つご紹介します。 完全時間課金 大きいサイズのウェアハウスは高速なぶん高価なわけですが、上記の使い方でデータ連携が1時間内に終われば、データ連携用のウェアハウスは1時間分しか課金されません。データ連携処理が必要とする処理性能に合わせて、全体の性能を上げる必要はないのです。利用用途単位で処理性能を決めれば良いのです。用途によって求められる性能は違いますので、このような考え方は非常に効率的といえます。 ウェアハウスの運用が容易 たとえば、新しい部門がDWHを新たに使いたいと言い出したとします。このとき、その部門用に新たにウェアハウスを作成して提供してあげるだけです。既存のユーザーが使っているウェハアウスには、パフォーマンスを含めてなんの影響を与えません。 また、運用の中でウェアハウスのサイズや数を変えたい場合、Web画面から簡単に操作できるのも魅力的です。 特徴その②:「データ・シェアリング」機能 特徴①の アーキテクチャ の派生ともいえるのが、「データ・シェアリング」の機能です。 自社のアカウントのストレージにあるデータを、別アカウントに共有できます。共有した側を「データ・プロバイダー」、データを共有される側を「データ・コンシューマー」と呼びます。 このとき、ストレージは「データ・プロバイダー」が管理し、ウェアハウスは「データ・コンシューマー」が管理します。データの”保持”とデータの”利用”を、分離して考えることができます。 こちらも、ポイントを2つご紹介します。 データ連携処理が不要 たとえば、自社のデータを他社や他組織に共有しようとした場合、従来であれば、共有用のデータを出力する⇒そのデータを取り込んでもらうという処理フローを作ることになります。 データの構造が変わったり、共有したいデータが増えたりするたび、また追加で開発をしなければならないという保守性の問題が発生します。データに障害が発生した場合の リカバリ も大変ですね。 また、ガバナンスの観点からも、データをばらまきたくないという考えもあります。 データ連携処理を作らなくてもデータを共有できるわけなので、このような課題がクリアになる、というわけです。 データ共有で広がる世界 自社で 保有 しているデータに加えて、他組織や外部のデータを利用することで分析の幅が広がります。これは共有される側のメリットです。 一方、共有する側にもメリットがあります。たとえば、製品メーカーが各工場・各製品の販売・在庫・生産などのデータを Snowflake に一元管理し、販売代理店各社にデータ共有するというストーリーが考えられます。販売代理店は提供された情報をもとに高精度な販売見込データを立てることができ、販売見込販売機会の拡大や見込の精度向上に繋がります。販売代理店のパフォーマンスが向上することで、結果として製品メーカー側にもメリットが生まれます。 データを共有したり共有されたりすることにより、さらに可能性が拡がっていく。その考えを実現するのが、" Snowflake "の「データ・シェアリング」です。 まとめ 本記事は、データ クラウド " Snowflake "の特徴についてご紹介しました。 さらに詳しく知りたい方は、 30日無料トライアル で" Snowflake "を体験してみてください。 電通国際情報サービス Advent Calendar 2021 も残りわずかです。引き続きお楽しみください。 執筆: @miyagi.reiko 、レビュー: @sato.taichi ( Shodo で執筆されました )
アバター
本記事は、 電通国際情報サービス Advent Calendar 2021 の23日目の記事です。 担当は、 エンタープライズ IT事業部 データマネジメント コンサルティング 部 宮城です。 データはDX推進における要であり、データを司る「環境」の重要性というのは昨今ますます高まってきています。 先日、ISIDは、 データクラウド"Snowflake"の販売代理店契約を締結しました。 本日は、この” Snowflake ”について特に私が感銘を受けている特徴を2つ紹介します。 特徴その①:独自の アーキテクチャ <ストレージとコンピュート> 一般的なコンピューターを構成する重要な要素はCPUとメモリとストレージです。" Snowflake "では、そのうちCPUとメモリだけを分離したものをコンピュートという概念で扱います。 ストレージは1つ。利用用途ごとに、さまざまなスペックのコンピュートを立てることができます。 各コンピュートはお互い影響せず、独立したパフォーマンスを実現できます。 このコンピュートを「ウェアハウス」と呼びます。ウェアハウスのスペックは「サイズ」と呼ばれ、XS⇒S⇒M⇒L⇒・・・とTシャツのサイズと同じように表現されます。 たとえば、下記のようなウェアハウスの使い方ができます。 データ加工専用ウェアハウス:   大量のデータを処理するため、大きいサイズのウェアハウスを1台 BI参照専用ウェアハウス:   複数のユーザーが同時にアクセスするため、小~中程度のウェアハウスを複数台 この「ウェアハウス」について、ポイントを2つご紹介します。 完全時間課金 大きいサイズのウェアハウスは高速なぶん高価なわけですが、上記の使い方でデータ連携が1時間内に終われば、データ連携用のウェアハウスは1時間分しか課金されません。データ連携処理が必要とする処理性能に合わせて、全体の性能を上げる必要はないのです。利用用途単位で処理性能を決めれば良いのです。用途によって求められる性能は違いますので、このような考え方は非常に効率的といえます。 ウェアハウスの運用が容易 たとえば、新しい部門がDWHを新たに使いたいと言い出したとします。このとき、その部門用に新たにウェアハウスを作成して提供してあげるだけです。既存のユーザーが使っているウェハアウスには、パフォーマンスを含めてなんの影響を与えません。 また、運用の中でウェアハウスのサイズや数を変えたい場合、Web画面から簡単に操作できるのも魅力的です。 特徴その②:「データ・シェアリング」機能 特徴①の アーキテクチャ の派生ともいえるのが、「データ・シェアリング」の機能です。 自社のアカウントのストレージにあるデータを、別アカウントに共有できます。共有した側を「データ・プロバイダー」、データを共有される側を「データ・コンシューマー」と呼びます。 このとき、ストレージは「データ・プロバイダー」が管理し、ウェアハウスは「データ・コンシューマー」が管理します。データの”保持”とデータの”利用”を、分離して考えることができます。 こちらも、ポイントを2つご紹介します。 データ連携処理が不要 たとえば、自社のデータを他社や他組織に共有しようとした場合、従来であれば、共有用のデータを出力する⇒そのデータを取り込んでもらうという処理フローを作ることになります。 データの構造が変わったり、共有したいデータが増えたりするたび、また追加で開発をしなければならないという保守性の問題が発生します。データに障害が発生した場合の リカバリ も大変ですね。 また、ガバナンスの観点からも、データをばらまきたくないという考えもあります。 データ連携処理を作らなくてもデータを共有できるわけなので、このような課題がクリアになる、というわけです。 データ共有で広がる世界 自社で 保有 しているデータに加えて、他組織や外部のデータを利用することで分析の幅が広がります。これは共有される側のメリットです。 一方、共有する側にもメリットがあります。たとえば、製品メーカーが各工場・各製品の販売・在庫・生産などのデータを Snowflake に一元管理し、販売代理店各社にデータ共有するというストーリーが考えられます。販売代理店は提供された情報をもとに高精度な販売見込データを立てることができ、販売見込販売機会の拡大や見込の精度向上に繋がります。販売代理店のパフォーマンスが向上することで、結果として製品メーカー側にもメリットが生まれます。 データを共有したり共有されたりすることにより、さらに可能性が拡がっていく。その考えを実現するのが、" Snowflake "の「データ・シェアリング」です。 まとめ 本記事は、データ クラウド " Snowflake "の特徴についてご紹介しました。 さらに詳しく知りたい方は、 30日無料トライアル で" Snowflake "を体験してみてください。 電通国際情報サービス Advent Calendar 2021 も残りわずかです。引き続きお楽しみください。 執筆: @miyagi.reiko 、レビュー: @sato.taichi ( Shodo で執筆されました )
アバター
これは 電通国際情報サービス アドベントカレンダー の22日目の記事です。 こんにちは。 電通国際情報サービス (ISID) X(クロス) イノベーション 本部ソフトウェアデザインセンター セキュリティグループの富田です。 本記事はISIDで20年継続している全社的な施策のセキュリティレビューをご紹介し、その活動を振り返ってみたいと思います。 背景 現在の システム開発 を取り巻くセキュリティ概況は、顧客情報の漏えい、機密情報の窃取、 ランサムウェア による脅迫など被害報告が後を絶たず、攻撃は高度化・巧妙化していると言えます。そのため、セキュリティ確保の要求は日々高まっています。そのような状況の中、 システム開発 に目を向けると、開発チームが脅威とその対策方法を個別に調査するのには限界があると考えています。そこで必要になるのがセキュリティ専門チームによる調査・検証で得た知見の蓄積と展開です。 知見の展開では、全社的に進めることが欠かせません。ISIDではセキュリティ専門チームによる部門横断のセキュリティレビューを行っています。 セキュリティレビューの開始は、1990年代にさかのぼります。 1998年に、当時はチャレンジングだった Java 技術を適用したインターネットバンキング構築を行いました。その経験から、早期からWebアプリケーションのセキュリティに関心を持っていました。 2001年頃にWebならではの新たな脅威が発生します。 クロスサイトスクリプティング 等の新たな脅威が現れました。これを機に、2001年に組織的な対応を検討し、セキュリティレビューのプロセスを策定しました。そして、2002年にISIDのセキュリティレビューが開始されました。 2008年には、要件定義/設計時のセキュリティレビューに加え、構築システムのアプリケーション部分(及びインフラの一部)のセキュリティチェックを目的に、 脆弱性 検査(静的検査と動的検査)を開始しました。 その後、継続して改善と強化を行っています。 ISIDのセキュリティレビューについて セキュリティレビューの目的、受託開発やISIDの製品/サービス開発のプロジェクトにおけるセキュリティリスクを低減することです。レビューは、プロジェクトのフェーズに応じて段階的に実施し、設計面のセキュリティにおいて一般的な 脆弱性 検査より踏み込んだレビューによりセキュリティを確保します。 提案時のセキュリティレビュー RFP 、要求仕様書、提案書を元に ヒアリ ング形式でリスクの洗い出しを行います。 設計時のセキュリティレビュー 非機能要件定義書/基本設計書の内容を元に、チェックシートを使って対策のレビューを行います。 脆弱性 検査(静的検査、動的検査) 構築システムのアプリケーション部分およびインフラの一部に対して、検査ツールを使用して 脆弱性 検査を行います。 レビュー体制は、セキュリティ分野の 有識者 で構成された10名ほどの専門チームです。具体的には、セキュリティ専門グループのメンバーだけでなく、開発技術と クラウド アーキテクチャ の専門グループのメンバーも参画しています。 この20年で変わっているものは 2008年に 脆弱性 検査が追加され、その時点でレビュープロセスとしては概ねできあがっていますが、その後はプロセスに従って形式的にレビューを実施してきたのでしょうか? そうではありません。 それは、レビューの題材が変わるからです。以下の要素が変化し、絡み合ってきます。 脅威 対策方法 システム アーキテクチャ クラウド サービス 要素技術 開発手法 セキュリティ関連の法制度、 ガイドライン など幅広い分野の調査、知見の蓄積が必要になります。 その他の変化には、セキュリティレビューで使用するチェックシートがあります。 設計時のセキュリティレビューに利用するセキュリティ対策チェックシートも変わっていきます。例えば、以下のような分野別のチェックシートを新規に作成してきました。 2010年  クラウド 環境シートを作成 2011年 モバイルアプリシートを作成 2016年 認証と認可 プロトコル のシートを作成 2018年 IoTシステムのシートを作成 これらは、プロジェクトでの適用可能性が出てきたタイミングで作成しています。 その他にも、セキュリティ対策チェックシート本体を含めたチェックシートを定期的(半期に1回程度)に見直しています。 これらのチェックシートは、セキュリティ専門チームの調査・検証の成果をもとに、新しい脅威への対策やセキュリティ対策のベストプ ラク ティスなどをタ イムリ ーに反映(育てているイメージ)したものです。特長としては、何のための対策かが分かるようにしている点です。 大事にしてきたポリシー セキュリティレビューを進めるときに大事にしてきたことは、当事者意識を持って、「問題の指摘と対応案をセットで伝える」ということです。プロジェクトの開発チームとは別の第 三者 的なチームとしてセキュリティレビューを行いますが、最終的なゴールは同じです。良いシステムを作り、顧客の要求にこたえることです。 今後について セキュリティ確保の要求が強まっている状況において、最新の脅威や クラウド サービスの進化などに追随すべく、セキュリティ専門チームによるより広く深い知見の蓄積と展開が必要だと考えています。ISIDでは、従来のやり方にとらわれない、開発手法などのトレンドに応じたセキュリティレビューの仕組みを作っていってくための体制強化を行っています。 執筆: @tomita 、レビュー: @sato.taichi ( Shodo で執筆されました )
アバター
これは 電通国際情報サービス アドベントカレンダー の22日目の記事です。 こんにちは。 電通国際情報サービス (ISID) X(クロス) イノベーション 本部ソフトウェアデザインセンター セキュリティグループの富田です。 本記事はISIDで20年継続している全社的な施策のセキュリティレビューをご紹介し、その活動を振り返ってみたいと思います。 背景 現在の システム開発 を取り巻くセキュリティ概況は、顧客情報の漏えい、機密情報の窃取、 ランサムウェア による脅迫など被害報告が後を絶たず、攻撃は高度化・巧妙化していると言えます。そのため、セキュリティ確保の要求は日々高まっています。そのような状況の中、 システム開発 に目を向けると、開発チームが脅威とその対策方法を個別に調査するのには限界があると考えています。そこで必要になるのがセキュリティ専門チームによる調査・検証で得た知見の蓄積と展開です。 知見の展開では、全社的に進めることが欠かせません。ISIDではセキュリティ専門チームによる部門横断のセキュリティレビューを行っています。 セキュリティレビューの開始は、1990年代にさかのぼります。 1998年に、当時はチャレンジングだった Java 技術を適用したインターネットバンキング構築を行いました。その経験から、早期からWebアプリケーションのセキュリティに関心を持っていました。 2001年頃にWebならではの新たな脅威が発生します。 クロスサイトスクリプティング 等の新たな脅威が現れました。これを機に、2001年に組織的な対応を検討し、セキュリティレビューのプロセスを策定しました。そして、2002年にISIDのセキュリティレビューが開始されました。 2008年には、要件定義/設計時のセキュリティレビューに加え、構築システムのアプリケーション部分(及びインフラの一部)のセキュリティチェックを目的に、 脆弱性 検査(静的検査と動的検査)を開始しました。 その後、継続して改善と強化を行っています。 ISIDのセキュリティレビューについて セキュリティレビューの目的、受託開発やISIDの製品/サービス開発のプロジェクトにおけるセキュリティリスクを低減することです。レビューは、プロジェクトのフェーズに応じて段階的に実施し、設計面のセキュリティにおいて一般的な 脆弱性 検査より踏み込んだレビューによりセキュリティを確保します。 提案時のセキュリティレビュー RFP 、要求仕様書、提案書を元に ヒアリ ング形式でリスクの洗い出しを行います。 設計時のセキュリティレビュー 非機能要件定義書/基本設計書の内容を元に、チェックシートを使って対策のレビューを行います。 脆弱性 検査(静的検査、動的検査) 構築システムのアプリケーション部分およびインフラの一部に対して、検査ツールを使用して 脆弱性 検査を行います。 レビュー体制は、セキュリティ分野の 有識者 で構成された10名ほどの専門チームです。具体的には、セキュリティ専門グループのメンバーだけでなく、開発技術と クラウド アーキテクチャ の専門グループのメンバーも参画しています。 この20年で変わっているものは 2008年に 脆弱性 検査が追加され、その時点でレビュープロセスとしては概ねできあがっていますが、その後はプロセスに従って形式的にレビューを実施してきたのでしょうか? そうではありません。 それは、レビューの題材が変わるからです。以下の要素が変化し、絡み合ってきます。 脅威 対策方法 システム アーキテクチャ クラウド サービス 要素技術 開発手法 セキュリティ関連の法制度、 ガイドライン など幅広い分野の調査、知見の蓄積が必要になります。 その他の変化には、セキュリティレビューで使用するチェックシートがあります。 設計時のセキュリティレビューに利用するセキュリティ対策チェックシートも変わっていきます。例えば、以下のような分野別のチェックシートを新規に作成してきました。 2010年  クラウド 環境シートを作成 2011年 モバイルアプリシートを作成 2016年 認証と認可 プロトコル のシートを作成 2018年 IoTシステムのシートを作成 これらは、プロジェクトでの適用可能性が出てきたタイミングで作成しています。 その他にも、セキュリティ対策チェックシート本体を含めたチェックシートを定期的(半期に1回程度)に見直しています。 これらのチェックシートは、セキュリティ専門チームの調査・検証の成果をもとに、新しい脅威への対策やセキュリティ対策のベストプ ラク ティスなどをタ イムリ ーに反映(育てているイメージ)したものです。特長としては、何のための対策かが分かるようにしている点です。 大事にしてきたポリシー セキュリティレビューを進めるときに大事にしてきたことは、当事者意識を持って、「問題の指摘と対応案をセットで伝える」ということです。プロジェクトの開発チームとは別の第 三者 的なチームとしてセキュリティレビューを行いますが、最終的なゴールは同じです。良いシステムを作り、顧客の要求にこたえることです。 今後について セキュリティ確保の要求が強まっている状況において、最新の脅威や クラウド サービスの進化などに追随すべく、セキュリティ専門チームによるより広く深い知見の蓄積と展開が必要だと考えています。ISIDでは、従来のやり方にとらわれない、開発手法などのトレンドに応じたセキュリティレビューの仕組みを作っていってくための体制強化を行っています。 執筆: @tomita 、レビュー: @sato.taichi ( Shodo で執筆されました )
アバター
こんにちは。ISID CIT事業部の熊倉です。 Salesforce 開発者の皆様、Lightning Web Components(以下、LWC)活用されてますでしょうか? LWCを活用することでHTML/ CSS /JSを使用したリッチなフロントエンドを Salesforce で構築できるようになりましたが、その反面、 Salesforce の強みである「オブジェクトの スキーマ を定義した段階でフロントエンドが作成される」といった強みを活かすことができなくなりました。 ただ、反対に考えてみれば通常のWeb開発のフローと変わりがなくなったとも言え、Web開発では当たり前となっているプロトタイプや モックアップ の作成が有用になったのではないかと思います。 今回の記事は非デザイナーである自分が Salesforce から提供されているSketchの プラグイン を使用しデザイン( モックアップ )を制作してみた、いわゆる「やってみた」系記事となります。 1. Sketchとは 2. Salesforce プラグインについて 2.1. プラグインのインストール方法 2.1.1 (インストールしていない人は)Sketchのインストール 2.1.2 Salesforce プラグインをダウンロード 2.1.3 (オプション)Salesforce Sansをインストール 2.1.4 (オプション)Assistantsをインストール 2.2 プラグインの利用方法 2.2.1 Sketchのメニューから「Plugins」>「Lightning Design System Plugin」を選択(または⌘+Jを押下)し、プラグインを開く 2.2.2 使用したいコンポーネントを選択し、Sketchのキャンバスにドラッグ&ドロップ 3. デザインを制作してみた 3.1 Tips コンポーネントで複数の状態を使用する テンプレートの中の文字を修正する 4. 感想 1. Sketchとは (既にご存知の方もたくさん居るかと思いますので簡単に紹介します) SketchとはUIデザインツールと呼ばれる製品の一つで、フロントエンドのデザイン制作に特化したソフトウェアです。 今では Adobe XDや Figma など各社から色々なUIデザインツールが提供されておりますが、その分野の先駆けとなった製品でもあります。 日本では最近 Adobe XDや Figma の方がSketchより人気のようですが、Sketchにも先駆者としても強みがあり、例えば日本語のドキュメントが豊富だったり サードパーティ の プラグイン が豊富だったりします。 (ちなみに最近、 uxtools.coが発表した統計 によると世界的には Figma がかなりのシェアを占めてました) 今回は Salesforce が公式で プラグイン を提供しているSketchを利用し、デザイン制作を行ってみました。 なお、Sketchはデザイン制作を行えるネイティブアプリの提供が Mac に限定されておりますのでご注意ください。 2. Salesforce プラグイン について 皆様はLWCを使用した開発をする際、 CSS をどのように作成していますか? 人によってはBulmaといった CSS フレームワーク を利用しているケースもあるかと思いますが、 多くの方が Salesforce Lightning Design System (以下、SLDS) を使用して作成しているかと思います。 Salesforce が提供しているSketchの プラグイン はSLDSを使用したUIの作成をサポートしてくれるものとなります。 2.1. プラグイン のインストール方法 インストール方法や使用方法を学ぶには、まず SLDSのサイト に公開されている動画を見ていただくのが一番わかりやすいかと思います。 https://youtu.be/bm1ZhGoNIG4 ご視聴いただいた上で簡単に Salesforce プラグイン の使い方について説明していきたいと思います。 2.1.1 (インストールしていない人は)Sketchのインストール Sketchをインストールされてない方は、 Sketchの公式サイト の「 Sign Up for Free」からフォームに情報を入力し、アプリのインストールをしてください。 30日間限定ではありますが、無料で全ての機能を使用できます。 2.1.2 Salesforce プラグイン をダウンロード SLDSのサイト から Salesforce プラグイン をダウンロードしてください。 ZIP形式でファイルがダウンロードされますので解凍していただき、生成されたファイル design-system-sketch.sketchplugin をダブルクリックすることでSketchがインストールされて入れば自動で プラグイン がインストールされます。 2.1.3 (オプション) Salesforce Sansをインストール (2021/12/16 時点) Salesforce ではフォントとして Salesforce Sans という独自のフォントを使用してきた歴史がありますが、Summer '21のアップデートでネイティブのsans-serif系フォントを使用するように変更が加えられました。 https://help.salesforce.com/s/articleView?id=release-notes.rn_lex_default_font.htm&type=5&release=232 しかし、Sketchの Salesforce プラグイン では現在も Salesforce Sans が利用されているので、 プラグイン を使用する前にフォントをPCへインストールしておくことをお勧めします。 前述のように最新(2021/12/16 時点 Winter'21)のサイトからはフォントをダウンロードできませんので、 Salesforce Sans が使用されていたSpring'21の アーカイブ からファイルをダウンロードしてください。 https://spring-21.lightningdesignsystem.com/resources/downloads/ Mac にフォントを追加する方法は以下のドキュメントを参考にしていただければと思います。 https://support.apple.com/ja-jp/HT201749 2.1.4 (オプション)Assistantsをインストール Sketchには Assistants と呼ばれる特定のルールに則ってデザインファイル内をLintしてくれる機能があります。(便利!) Salesforce もSLDSに準拠したAsistantsを提供しておりますので、Sketchにインストールしておくことをお勧めします。 https://add-sketch-assistant.now.sh/api/main?pkg=lightning-design-system-linter 上記、URLをクリックすることでSketchに対してAssistantsをインストールできます。 Sketch内では「View」> 「Show Assistants」からLintされた内容を確認できます。 (後述しているデモのデザインを制作した後にAssistantsを有効にしたので、すごい怒られていました...笑) 2.2 プラグイン の利用方法 2.2.1 Sketchのメニューから「Plugins」>「Lightning Design System Plugin」を選択(または⌘+Jを押下)し、 プラグイン を開く Sketchで「Plugins」>「Lightning Design System Plugin」を選択するか、⌘+J を押下することで、 Salesforce プラグイン のウィンドウが開きます。 初回に起動した場合、以下のようなライブラリを選択する画面が表示されます。 ライブラリの右側のチェックを有効にすることで、ライブラリが使用できます(基本的に全て有効で良いと思います) ちなみに、各ライブラリの意味は以下のようになります( FAQ の内容を引用) - Components: Web - Sketch equivalents of component blueprints and tokens as seen on the SLDS website - Components: Mobile - Sketch collection of native mobile patterns and mobile web coded components - Icons - A file of design system icons which is automatically generated from design system code - Builder - Builder design guideline customized component symbols - User Engagement - User engagement design guideline customized component symbols - Chart - Chart design guideline customized component symbols - Rules, Filters, and Logic - Rules, Filters, Logic design guideline customized component symbols - Standard Artboards - Based on user data, Sketch artboards are sized to the common viewport dimensions used - Spec - A collection of symbols to use when documenting dimensions and details of designs for engineers - Wireframes - Grey box stencils of common Lightning interfaces 2.2.2 使用したい コンポーネント を選択し、Sketchのキャンバスに ドラッグ&ドロップ ライブラリを選択した後、 コンポーネント を選択できるウィンドウが開きます。 プラグイン の構成は次のようになっています。 検索し、 コンポーネント を絞り込むことができます。 (日本語では検索できません) 『ライブラリの選択』『FAQの参照』『 プラグイン のフィードバック』を行えます。2.2.1で選択したライブラリを無効化・有効化し直したい場合はこちらから再設定できます。 表示するライブラリを切り替えることができます。 『All Libraries』『Components: Web』ライブラリを選択している場合、上部の Show LWCs Only を有効化することで、 LWC コンポーネント のみ表示できます。 コンポーネント が一覧で表示されます。 プラグイン の使用方法自体は至って簡単で、表示されている コンポーネント をSketchのキャンバスに ドラッグ&ドロップ するだけです! 3. デザインを制作してみた 実際にデモとして次のようなデザインを制作してみました。 商品の登録画面 商品の一覧画面 Customer 360的な顧客の一元ビュー 3.1 Tips デモのデザインを制作した際に自分が感じたTipsを以下に記載します。 (Sketchそのものの機能も多分に紹介してますが、初めてSketchを触った人目線として記載しております) コンポーネント で複数の状態を使用する ボタンのように複数の状態(Brand , Success , Destructive , Inverse 等々)があるものはリストのプルダウンボタンを押すことで、それぞれの状態の コンポーネント が参照できます。(複数の状態が用意されているものは n Variants と表示されます) コンポーネント をキャンバスに配置してからでも状態を切り替えることが可能で、右のインスペクターからSYMBOLを選択することで切り替えることができます。 テンプレートの中の文字を修正する コンポーネント にはデフォルトでサンプルの文が入力されているものもあります。 サンプルの文より具体的な言葉に入れ替えたい場合、右のインスペクターにあるOverridesから文字を修正できます。 4. 感想 実はSketchを触る前に Salesforce がUI Kitを提供しているFrammerも試したことがあったのですが、比べると以下の部分で利点を感じました。 プラグイン の形で提供されており、検索機能も使用できるので使用したい コンポーネント を見つけやすい プラグイン の他にAssistantsといった便利機能も提供されているので、デザイン制作の統一を計ることができる 他の プラグイン に比べると Salesforce が力を入れているだけありドキュメントの種類も多い Sketchネイティブアプリの提供が Mac に限定されているのでソフト自体の利用のハードルはちょっと高いかもしれませんが、 LWC(やAura , VisualForceといったカスタマイズされたフロントエンド)の開発が多い方は是非試してみてはいかがでしょうか? 最後までお読みいただきありがとうございました。 執筆: @kumakura.koki.isid 、レビュー: @sato.taichi ( Shodo で執筆されました )
アバター
こんにちは。ISID CIT事業部の熊倉です。 Salesforce 開発者の皆様、Lightning Web Components(以下、LWC)活用されてますでしょうか? LWCを活用することでHTML/ CSS /JSを使用したリッチなフロントエンドを Salesforce で構築できるようになりましたが、その反面、 Salesforce の強みである「オブジェクトの スキーマ を定義した段階でフロントエンドが作成される」といった強みを活かすことができなくなりました。 ただ、反対に考えてみれば通常のWeb開発のフローと変わりがなくなったとも言え、Web開発では当たり前となっているプロトタイプや モックアップ の作成が有用になったのではないかと思います。 今回の記事は非デザイナーである自分が Salesforce から提供されているSketchの プラグイン を使用しデザイン( モックアップ )を制作してみた、いわゆる「やってみた」系記事となります。 1. Sketchとは 2. Salesforce プラグインについて 2.1. プラグインのインストール方法 2.1.1 (インストールしていない人は)Sketchのインストール 2.1.2 Salesforce プラグインをダウンロード 2.1.3 (オプション)Salesforce Sansをインストール 2.1.4 (オプション)Assistantsをインストール 2.2 プラグインの利用方法 2.2.1 Sketchのメニューから「Plugins」>「Lightning Design System Plugin」を選択(または⌘+Jを押下)し、プラグインを開く 2.2.2 使用したいコンポーネントを選択し、Sketchのキャンバスにドラッグ&ドロップ 3. デザインを制作してみた 3.1 Tips コンポーネントで複数の状態を使用する テンプレートの中の文字を修正する 4. 感想 1. Sketchとは (既にご存知の方もたくさん居るかと思いますので簡単に紹介します) SketchとはUIデザインツールと呼ばれる製品の一つで、フロントエンドのデザイン制作に特化したソフトウェアです。 今では Adobe XDや Figma など各社から色々なUIデザインツールが提供されておりますが、その分野の先駆けとなった製品でもあります。 日本では最近 Adobe XDや Figma の方がSketchより人気のようですが、Sketchにも先駆者としても強みがあり、例えば日本語のドキュメントが豊富だったり サードパーティ の プラグイン が豊富だったりします。 (ちなみに最近、 uxtools.coが発表した統計 によると世界的には Figma がかなりのシェアを占めてました) 今回は Salesforce が公式で プラグイン を提供しているSketchを利用し、デザイン制作を行ってみました。 なお、Sketchはデザイン制作を行えるネイティブアプリの提供が Mac に限定されておりますのでご注意ください。 2. Salesforce プラグイン について 皆様はLWCを使用した開発をする際、 CSS をどのように作成していますか? 人によってはBulmaといった CSS フレームワーク を利用しているケースもあるかと思いますが、 多くの方が Salesforce Lightning Design System (以下、SLDS) を使用して作成しているかと思います。 Salesforce が提供しているSketchの プラグイン はSLDSを使用したUIの作成をサポートしてくれるものとなります。 2.1. プラグイン のインストール方法 インストール方法や使用方法を学ぶには、まず SLDSのサイト に公開されている動画を見ていただくのが一番わかりやすいかと思います。 https://youtu.be/bm1ZhGoNIG4 ご視聴いただいた上で簡単に Salesforce プラグイン の使い方について説明していきたいと思います。 2.1.1 (インストールしていない人は)Sketchのインストール Sketchをインストールされてない方は、 Sketchの公式サイト の「 Sign Up for Free」からフォームに情報を入力し、アプリのインストールをしてください。 30日間限定ではありますが、無料で全ての機能を使用できます。 2.1.2 Salesforce プラグイン をダウンロード SLDSのサイト から Salesforce プラグイン をダウンロードしてください。 ZIP形式でファイルがダウンロードされますので解凍していただき、生成されたファイル design-system-sketch.sketchplugin をダブルクリックすることでSketchがインストールされて入れば自動で プラグイン がインストールされます。 2.1.3 (オプション) Salesforce Sansをインストール (2021/12/16 時点) Salesforce ではフォントとして Salesforce Sans という独自のフォントを使用してきた歴史がありますが、Summer '21のアップデートでネイティブのsans-serif系フォントを使用するように変更が加えられました。 https://help.salesforce.com/s/articleView?id=release-notes.rn_lex_default_font.htm&type=5&release=232 しかし、Sketchの Salesforce プラグイン では現在も Salesforce Sans が利用されているので、 プラグイン を使用する前にフォントをPCへインストールしておくことをお勧めします。 前述のように最新(2021/12/16 時点 Winter'21)のサイトからはフォントをダウンロードできませんので、 Salesforce Sans が使用されていたSpring'21の アーカイブ からファイルをダウンロードしてください。 https://spring-21.lightningdesignsystem.com/resources/downloads/ Mac にフォントを追加する方法は以下のドキュメントを参考にしていただければと思います。 https://support.apple.com/ja-jp/HT201749 2.1.4 (オプション)Assistantsをインストール Sketchには Assistants と呼ばれる特定のルールに則ってデザインファイル内をLintしてくれる機能があります。(便利!) Salesforce もSLDSに準拠したAsistantsを提供しておりますので、Sketchにインストールしておくことをお勧めします。 https://add-sketch-assistant.now.sh/api/main?pkg=lightning-design-system-linter 上記、URLをクリックすることでSketchに対してAssistantsをインストールできます。 Sketch内では「View」> 「Show Assistants」からLintされた内容を確認できます。 (後述しているデモのデザインを制作した後にAssistantsを有効にしたので、すごい怒られていました...笑) 2.2 プラグイン の利用方法 2.2.1 Sketchのメニューから「Plugins」>「Lightning Design System Plugin」を選択(または⌘+Jを押下)し、 プラグイン を開く Sketchで「Plugins」>「Lightning Design System Plugin」を選択するか、⌘+J を押下することで、 Salesforce プラグイン のウィンドウが開きます。 初回に起動した場合、以下のようなライブラリを選択する画面が表示されます。 ライブラリの右側のチェックを有効にすることで、ライブラリが使用できます(基本的に全て有効で良いと思います) ちなみに、各ライブラリの意味は以下のようになります( FAQ の内容を引用) - Components: Web - Sketch equivalents of component blueprints and tokens as seen on the SLDS website - Components: Mobile - Sketch collection of native mobile patterns and mobile web coded components - Icons - A file of design system icons which is automatically generated from design system code - Builder - Builder design guideline customized component symbols - User Engagement - User engagement design guideline customized component symbols - Chart - Chart design guideline customized component symbols - Rules, Filters, and Logic - Rules, Filters, Logic design guideline customized component symbols - Standard Artboards - Based on user data, Sketch artboards are sized to the common viewport dimensions used - Spec - A collection of symbols to use when documenting dimensions and details of designs for engineers - Wireframes - Grey box stencils of common Lightning interfaces 2.2.2 使用したい コンポーネント を選択し、Sketchのキャンバスに ドラッグ&ドロップ ライブラリを選択した後、 コンポーネント を選択できるウィンドウが開きます。 プラグイン の構成は次のようになっています。 検索し、 コンポーネント を絞り込むことができます。 (日本語では検索できません) 『ライブラリの選択』『FAQの参照』『 プラグイン のフィードバック』を行えます。2.2.1で選択したライブラリを無効化・有効化し直したい場合はこちらから再設定できます。 表示するライブラリを切り替えることができます。 『All Libraries』『Components: Web』ライブラリを選択している場合、上部の Show LWCs Only を有効化することで、 LWC コンポーネント のみ表示できます。 コンポーネント が一覧で表示されます。 プラグイン の使用方法自体は至って簡単で、表示されている コンポーネント をSketchのキャンバスに ドラッグ&ドロップ するだけです! 3. デザインを制作してみた 実際にデモとして次のようなデザインを制作してみました。 商品の登録画面 商品の一覧画面 Customer 360的な顧客の一元ビュー 3.1 Tips デモのデザインを制作した際に自分が感じたTipsを以下に記載します。 (Sketchそのものの機能も多分に紹介してますが、初めてSketchを触った人目線として記載しております) コンポーネント で複数の状態を使用する ボタンのように複数の状態(Brand , Success , Destructive , Inverse 等々)があるものはリストのプルダウンボタンを押すことで、それぞれの状態の コンポーネント が参照できます。(複数の状態が用意されているものは n Variants と表示されます) コンポーネント をキャンバスに配置してからでも状態を切り替えることが可能で、右のインスペクターからSYMBOLを選択することで切り替えることができます。 テンプレートの中の文字を修正する コンポーネント にはデフォルトでサンプルの文が入力されているものもあります。 サンプルの文より具体的な言葉に入れ替えたい場合、右のインスペクターにあるOverridesから文字を修正できます。 4. 感想 実はSketchを触る前に Salesforce がUI Kitを提供しているFrammerも試したことがあったのですが、比べると以下の部分で利点を感じました。 プラグイン の形で提供されており、検索機能も使用できるので使用したい コンポーネント を見つけやすい プラグイン の他にAssistantsといった便利機能も提供されているので、デザイン制作の統一を計ることができる 他の プラグイン に比べると Salesforce が力を入れているだけありドキュメントの種類も多い Sketchネイティブアプリの提供が Mac に限定されているのでソフト自体の利用のハードルはちょっと高いかもしれませんが、 LWC(やAura , VisualForceといったカスタマイズされたフロントエンド)の開発が多い方は是非試してみてはいかがでしょうか? 最後までお読みいただきありがとうございました。 執筆: @kumakura.koki.isid 、レビュー: @sato.taichi ( Shodo で執筆されました )
アバター
この記事は 電通国際情報サービス Advent Calendar 2021 21日目の記事です。 はじめに 学生時代の私とスパゲッティコード 脱!スパゲッティコード! コピー&ペーストしない!とことん処理の共通化 前処理・主処理・後処理を意識した構造化プログラミングの実施 まとめ 最後に はじめに こんにちは、ISID 金融ソリューション事業部の星野将吾と申します。2年目の ひよっこ エンジニアです。 アドベントカレンダー に参加したい!と思ったものの、 ひよっこ であるのもあり詳細な技術に踏み込んだことは書けないので、今回は「 "脱 スパゲッティコード " してプロダクトコードを書くスタートに立つまで」というタイトルでお話していこうと思います。 今まで大学の課題や研究において個人開発でしかコードを書いてこなかった私が、プロダクトコードを書く上で解決しなければならなかった課題をここに書きます。 これからプロダクトコードを書く新社会人や学生の皆様の一助になればと思います。 この手の技術記事は初めて書くので、読者の皆様お手柔らかにどうぞ… 学生時代の私と スパゲッティコード まず本タイトルにある「 スパゲッティコード 」とは何かという話ですが 「実行順序や構造が複雑に入り組んでいて整理されていないプログラム」 を指します。 コードを スパゲッティコード たらしめている要因を挙げてみると以下のようなものがあります。 同じ処理・似たような処理が複数箇所に書かれている。 処理構造化が適切に階層化されていない。 学生時代は自分しかそのコードに触れないため、 スパゲッティコード であっても自分さえ理解できていれば問題はありません。 しかしながら、プロダクトコードを書く上で スパゲッティコード は許されません。 なぜなら、 自分以外の人がそのコードを触る ことになるからです。他の人にとって読みにくいコードは、コードの保守性が著しく低下します。 次の章では スパゲッティコード を防ぐに当たって気をつけるべき観点について説明します。 脱! スパゲッティコード ! 脱 スパゲッティコード するための観点は以下です。 コピー&ペーストしない!とことん処理を共 通化 前処理・主処理・後処理を意識した構造化プログラミングの実施 コピー&ペーストしない!とことん処理の共 通化 個人で開発していると、共 通化 を考えるのが面倒で、自分や先輩、同僚が書いた既存コードベースからついつい コピー&ペースト してしまいませんか? 私はかなりやってました。 このコピー&ペーストをやってしまうと、1か所で済んだはずのコード修正が、3, 4箇所にも及んでしまい 修正コストが増加 しています。 ひとりなら3, 4箇所くらいなんとかなるかもしれません。 しかし、他の人が修正するにあたっては、どこにコピー&ペーストがされているか探す必要も出るのでプロダクトコードでは大きな問題になります。 コピー&ペーストをしたい部分を見つけたら、その部分を 共通関数 として切り出して使いたいところで呼びだすことができないか考えてみましょう。 もちろんコピー&ペーストをしていなくても、同じ処理を書いてしまうこともあります。まずは、コピー&ペーストを止めるところから共 通化 を行う意識を高めていけるとよいでしょう。 コピー&ペースト厳禁!みたいな話をしましたが、共通関数として切り出すことができなかったり、無理やり共 通化 するのが不適切なケースも多くあります。 しかし、この判断は個々のプロダクトにおける設計と関係する話になってくるので、本記事での説明は割愛します。 ただ、「共 通化 できないか?」と考える姿勢は スパゲッティコード 化を防ぐ上で大変重要です。 前処理・主処理・後処理を意識した構造化プログラミングの実施 構造化プログラミングとは、簡単に言ってしまえば 「処理を階層化すること」 です。 まず階層化されていないコードの例を以下に示します。 言語は大学のプログラミング演習等の講義でよく扱われるであろう、 C言語 で書いてみます。 内容は二つの数字の加減算を行う簡単なプログラムです。 #include <stdio.h> int main(void){ // 前処理 printf("加減算へようこそ。\n"); // 主処理 while(1) { int a, b, op, result, ctrl; char op_char; printf("1つ目の数字を入力してください\n"); scanf("%d",&a); printf("2つ目の数字を入力してください\n"); scanf("%d",&b); printf("加算なら0, 減算ならそれ以外を入力してください\n"); scanf("%d", &op); if (op == 0) { result = a + b; op_char = '+'; }else{ result = a - b; op_char = '-'; } printf("計算結果:%d %c %d = %d\n", a, op_char, b, result); printf("他の計算をしたい場合、1を入力してください\n"); scanf("%d", &ctrl); if( ctrl != 1 ){ break; } } // 後処理 printf("お疲れ様でした。\n"); return 0; } これは短いコードなので、一つの関数に書いても大きな問題はありません。 しかし、これ以上に長いコードや、if文やfor文などがされるコードは読みにくくなります。 読みにくいコード = 理解が困難なコード であるため、コードの保守性の悪化を招くこととなります。 このコードを構造化してみると以下のようになります。 #include <stdio.h> void input(int *ptr_a, int *ptr_b, int *ptr_op){ printf("1つ目の数字を入力してください\n"); scanf("%d", ptr_a); printf("2つ目の数字を入力してください\n"); scanf("%d", ptr_b); printf("加算なら0, 減算ならそれ以外を入力してください\n"); scanf("%d", ptr_op); } int calc(int a, int b, int op){ int result = 0; if (op == 0) { result = a + b; } else { result = a - b; } return result; } void output(int a, int b, int result, int op){ char op_char; if (op == 0) { op_char = '+'; } else { op_char = '-'; } printf("計算結果:%d %c %d = %d\n", a, op_char, b, result); } int scan_continue_ctrl(void){ int ctrl = 0; printf("他の計算をしたい場合、1を入力してください\n"); scanf("%d", &ctrl); return ctrl; } void exec(void){ while (1) { int a, b, op, result, ctrl = 0; // 前処理 input(&a, &b, &op); // 主処理 result = calc(a, b, op); // 後処理1 output(a, b, result, op); // 後処理2 ctrl = scan_continue_ctrl(); if ( ctrl != 1 ) { break; } } } int main(void){ // 前処理 printf("加減算へようこそ。\n"); // 主処理 exec(); // 後処理 printf("お疲れ様でした。\n"); return 0; } コード中のコメント文にあるように、多くのケースで 前処理・主処理・後処理 というパターンで構造化すると上手く構造化できます。 例えば、ファイルに対する書き込み処理という仕様のコードでも、 前処理:ファイルのオープン 主処理:ファイルへの書き込み 後処理:ファイルのクローズ のように構造化できます。 また、例のコードの exec関数 に着目してみてください。exec関数はmain関数の主処理として切り出されたものですが、その中でさらに 前処理・主処理・後処理 と分けることができています。 ただ後処理はあえて一つにまとめませんでした。というのも、output関数とscan_continue関数をまとめたときに与える関数名がpost_processくらいしか思いつかなかったためです。 該当行周辺における関数のまとめ方次第でこの判断の是非は分かれると思います。 今回例えばpost_process関数という関数を用意して後処理をまとめてしまうと、input関数とcalc関数より 抽象度が高い 関数名になってしまいます。抽象度がばらつくとそれだけで ソースコード 理解の難易度は上昇します。 また、今回に限った話ですが、 input関数 の存在は output関数 の存在を期待しています。ただ入力を受け付けるだけのプログラムならいいのですが、今回は結果を表示するまでが必要とされています。よって、output関数がないと、ぱっと見で「え?どこで出力するの?」となってしまいます。 このように、必ずしも 前処理・主処理・後処理 の3つにキレイに分かれるとは限りません。しかしながら、慣れないうちはこの分け方を意識すると、構造化の方針が見えやすいので非常におすすめです。 まとめ 今回この記事では、ただ動きさえすればいい スパゲッティコード を改善するための、2つの観点をお話しました。 1つ目は 「共 通化 」 、2つ目は 「構造化」 です。 この2点に気をつけるだけでぐっとコードの保守性はあがると思います。 もちろん最初は気をつけてもなかなかうまくいかないものです。私もまだ完璧にはできていません。 たくさんコードを書いてたくさんレビューをしてもらう。これをくじけずに継続することで着実に身についていくと思います。 私も引き続きくじけずに頑張ります… ただこの "脱 スパゲッティコード " を成し遂げたらプロダクトコードとして完璧かと言われればそうではありません。 他にも変数・関数の 命名 の仕方、変数のスコープなど、気をつける点は多くあります。 今後、今回触れていない内容についても、投稿できればなとは思っています。(今回は上手くまとめられず…) 最後に 今回この記事が書けるようになるレベルまでマンツーマンのご指導をしていただいた、12/1執筆者の太一さん( 記事 )と12/17執筆者の水野さん( 記事 )には大変感謝しております。 さて、明日12/22の アドベントカレンダー は、山口さんによるセキュリティ周りの記事が投稿される予定です。 是非他の記事もお楽しみください! 執筆: @hoshino.shogo 、レビュー: @sato.taichi ( Shodo で執筆されました )
アバター
この記事は 電通国際情報サービス Advent Calendar 2021 21日目の記事です。 はじめに 学生時代の私とスパゲッティコード 脱!スパゲッティコード! コピー&ペーストしない!とことん処理の共通化 前処理・主処理・後処理を意識した構造化プログラミングの実施 まとめ 最後に はじめに こんにちは、ISID 金融ソリューション事業部の星野将吾と申します。2年目の ひよっこ エンジニアです。 アドベントカレンダー に参加したい!と思ったものの、 ひよっこ であるのもあり詳細な技術に踏み込んだことは書けないので、今回は「 "脱 スパゲッティコード " してプロダクトコードを書くスタートに立つまで」というタイトルでお話していこうと思います。 今まで大学の課題や研究において個人開発でしかコードを書いてこなかった私が、プロダクトコードを書く上で解決しなければならなかった課題をここに書きます。 これからプロダクトコードを書く新社会人や学生の皆様の一助になればと思います。 この手の技術記事は初めて書くので、読者の皆様お手柔らかにどうぞ… 学生時代の私と スパゲッティコード まず本タイトルにある「 スパゲッティコード 」とは何かという話ですが 「実行順序や構造が複雑に入り組んでいて整理されていないプログラム」 を指します。 コードを スパゲッティコード たらしめている要因を挙げてみると以下のようなものがあります。 同じ処理・似たような処理が複数箇所に書かれている。 処理構造化が適切に階層化されていない。 学生時代は自分しかそのコードに触れないため、 スパゲッティコード であっても自分さえ理解できていれば問題はありません。 しかしながら、プロダクトコードを書く上で スパゲッティコード は許されません。 なぜなら、 自分以外の人がそのコードを触る ことになるからです。他の人にとって読みにくいコードは、コードの保守性が著しく低下します。 次の章では スパゲッティコード を防ぐに当たって気をつけるべき観点について説明します。 脱! スパゲッティコード ! 脱 スパゲッティコード するための観点は以下です。 コピー&ペーストしない!とことん処理を共 通化 前処理・主処理・後処理を意識した構造化プログラミングの実施 コピー&ペーストしない!とことん処理の共 通化 個人で開発していると、共 通化 を考えるのが面倒で、自分や先輩、同僚が書いた既存コードベースからついつい コピー&ペースト してしまいませんか? 私はかなりやってました。 このコピー&ペーストをやってしまうと、1か所で済んだはずのコード修正が、3, 4箇所にも及んでしまい 修正コストが増加 しています。 ひとりなら3, 4箇所くらいなんとかなるかもしれません。 しかし、他の人が修正するにあたっては、どこにコピー&ペーストがされているか探す必要も出るのでプロダクトコードでは大きな問題になります。 コピー&ペーストをしたい部分を見つけたら、その部分を 共通関数 として切り出して使いたいところで呼びだすことができないか考えてみましょう。 もちろんコピー&ペーストをしていなくても、同じ処理を書いてしまうこともあります。まずは、コピー&ペーストを止めるところから共 通化 を行う意識を高めていけるとよいでしょう。 コピー&ペースト厳禁!みたいな話をしましたが、共通関数として切り出すことができなかったり、無理やり共 通化 するのが不適切なケースも多くあります。 しかし、この判断は個々のプロダクトにおける設計と関係する話になってくるので、本記事での説明は割愛します。 ただ、「共 通化 できないか?」と考える姿勢は スパゲッティコード 化を防ぐ上で大変重要です。 前処理・主処理・後処理を意識した構造化プログラミングの実施 構造化プログラミングとは、簡単に言ってしまえば 「処理を階層化すること」 です。 まず階層化されていないコードの例を以下に示します。 言語は大学のプログラミング演習等の講義でよく扱われるであろう、 C言語 で書いてみます。 内容は二つの数字の加減算を行う簡単なプログラムです。 #include <stdio.h> int main(void){ // 前処理 printf("加減算へようこそ。\n"); // 主処理 while(1) { int a, b, op, result, ctrl; char op_char; printf("1つ目の数字を入力してください\n"); scanf("%d",&a); printf("2つ目の数字を入力してください\n"); scanf("%d",&b); printf("加算なら0, 減算ならそれ以外を入力してください\n"); scanf("%d", &op); if (op == 0) { result = a + b; op_char = '+'; }else{ result = a - b; op_char = '-'; } printf("計算結果:%d %c %d = %d\n", a, op_char, b, result); printf("他の計算をしたい場合、1を入力してください\n"); scanf("%d", &ctrl); if( ctrl != 1 ){ break; } } // 後処理 printf("お疲れ様でした。\n"); return 0; } これは短いコードなので、一つの関数に書いても大きな問題はありません。 しかし、これ以上に長いコードや、if文やfor文などがされるコードは読みにくくなります。 読みにくいコード = 理解が困難なコード であるため、コードの保守性の悪化を招くこととなります。 このコードを構造化してみると以下のようになります。 #include <stdio.h> void input(int *ptr_a, int *ptr_b, int *ptr_op){ printf("1つ目の数字を入力してください\n"); scanf("%d", ptr_a); printf("2つ目の数字を入力してください\n"); scanf("%d", ptr_b); printf("加算なら0, 減算ならそれ以外を入力してください\n"); scanf("%d", ptr_op); } int calc(int a, int b, int op){ int result = 0; if (op == 0) { result = a + b; } else { result = a - b; } return result; } void output(int a, int b, int result, int op){ char op_char; if (op == 0) { op_char = '+'; } else { op_char = '-'; } printf("計算結果:%d %c %d = %d\n", a, op_char, b, result); } int scan_continue_ctrl(void){ int ctrl = 0; printf("他の計算をしたい場合、1を入力してください\n"); scanf("%d", &ctrl); return ctrl; } void exec(void){ while (1) { int a, b, op, result, ctrl = 0; // 前処理 input(&a, &b, &op); // 主処理 result = calc(a, b, op); // 後処理1 output(a, b, result, op); // 後処理2 ctrl = scan_continue_ctrl(); if ( ctrl != 1 ) { break; } } } int main(void){ // 前処理 printf("加減算へようこそ。\n"); // 主処理 exec(); // 後処理 printf("お疲れ様でした。\n"); return 0; } コード中のコメント文にあるように、多くのケースで 前処理・主処理・後処理 というパターンで構造化すると上手く構造化できます。 例えば、ファイルに対する書き込み処理という仕様のコードでも、 前処理:ファイルのオープン 主処理:ファイルへの書き込み 後処理:ファイルのクローズ のように構造化できます。 また、例のコードの exec関数 に着目してみてください。exec関数はmain関数の主処理として切り出されたものですが、その中でさらに 前処理・主処理・後処理 と分けることができています。 ただ後処理はあえて一つにまとめませんでした。というのも、output関数とscan_continue関数をまとめたときに与える関数名がpost_processくらいしか思いつかなかったためです。 該当行周辺における関数のまとめ方次第でこの判断の是非は分かれると思います。 今回例えばpost_process関数という関数を用意して後処理をまとめてしまうと、input関数とcalc関数より 抽象度が高い 関数名になってしまいます。抽象度がばらつくとそれだけで ソースコード 理解の難易度は上昇します。 また、今回に限った話ですが、 input関数 の存在は output関数 の存在を期待しています。ただ入力を受け付けるだけのプログラムならいいのですが、今回は結果を表示するまでが必要とされています。よって、output関数がないと、ぱっと見で「え?どこで出力するの?」となってしまいます。 このように、必ずしも 前処理・主処理・後処理 の3つにキレイに分かれるとは限りません。しかしながら、慣れないうちはこの分け方を意識すると、構造化の方針が見えやすいので非常におすすめです。 まとめ 今回この記事では、ただ動きさえすればいい スパゲッティコード を改善するための、2つの観点をお話しました。 1つ目は 「共 通化 」 、2つ目は 「構造化」 です。 この2点に気をつけるだけでぐっとコードの保守性はあがると思います。 もちろん最初は気をつけてもなかなかうまくいかないものです。私もまだ完璧にはできていません。 たくさんコードを書いてたくさんレビューをしてもらう。これをくじけずに継続することで着実に身についていくと思います。 私も引き続きくじけずに頑張ります… ただこの "脱 スパゲッティコード " を成し遂げたらプロダクトコードとして完璧かと言われればそうではありません。 他にも変数・関数の 命名 の仕方、変数のスコープなど、気をつける点は多くあります。 今後、今回触れていない内容についても、投稿できればなとは思っています。(今回は上手くまとめられず…) 最後に 今回この記事が書けるようになるレベルまでマンツーマンのご指導をしていただいた、12/1執筆者の太一さん( 記事 )と12/17執筆者の水野さん( 記事 )には大変感謝しております。 さて、明日12/22の アドベントカレンダー は、山口さんによるセキュリティ周りの記事が投稿される予定です。 是非他の記事もお楽しみください! 執筆: @hoshino.shogo 、レビュー: @sato.taichi ( Shodo で執筆されました )
アバター
これは 電通国際情報サービス アドベントカレンダー の 20日 目の記事です。 こんにちは、 電通国際情報サービス (ISID)の上羽優貴です。 ISIDは今年に新しくスマートシティや 自治 体DX、脱炭素化などの社会課題対応型ビジネスの推進を目的とした スマートソサエティセンター という新組織を立ち上げました。私はここに所属し、スマートシティ関連のビジネスを推進しています。本記事では、スマートシティを実現するための基盤ソフトウェアであるFIWARE(ファイウェア)について解説します。 スマートシティと都市OS 近年、日本におけるスマートシティへの取り組みが盛んになっています。 トヨタ が推進する ウーブンシティ は有名ですね。スマートシティを実現するうえで欠かせないのがICTやデータの活用です。その活用の分野は防災や安全、モビリティ、教育・医療など多岐にわたります。今現在も様々な都市においてICTやデータを活用した住民サービスの提供がなされています。 しかし、日本でのスマートシティの実現に向けては、これまで大きく3つの課題がありました。 1. サービスの再利用・横展開 分野や組織ごとに個別にシステムを構築することが多く、他の地域での再利用や横展開が困難 2. 分野間データ利活用 分野や組織ごとにデータが独立し、分野や組織を横断してデータを活用することが困難 3. 拡張性の低さ 個別にシステムが構築されるため独自の仕様を持ち、機能拡張にかかるコストが大きく 、サービスを拡張させることが困難 そこで、近年注目を集めているのが都市OSというソフトウェア基盤です。都市OSは以下のような特徴を持ち、これまで課題だったサービスの再利用や、分野間のデータ利活用を促進する効果を期待されています。 1. 相互運用(つながる) 共通の機能や標準的なインタフェース( API )を具備して外部に公開する仕組みを持ち、分野や組織をまたがるサービス連携や横展開を可能にします。 2. データ流通(ながれる) スマートシティに利用するデータを仲介する機能を持ち、分野や組織を超えたデータ活用を可能にします。 3. 拡張容易(つづけられる) 機能間の 疎結合 なシステム構成を持ち、システムの拡張を容易にします。 都市OSを構築するためのソフトウェアの1つとして、この記事で紹介するFIWAREが挙げられます。 ※ スマートシティガイドブック(本文)第2章1 p.33より引用 FIWAREとは FIWARE とはFI(Future Internet)WARE(SOFTWARE)の略で、 自治 体や企業などの業種を超えたデータ利活用やサービス連携を促すために開発されたソフトウェア群です。ソフトウェア群と表現した通り、FIWAREは1つのソフトウェアのことではなく、いくつかのソフトウェアの総称です。 OSS として GitHub に公開されています。 FIWAREは欧州のFI-PPPという官民連携プログラムで開発されました(FI-PPPについては こちら を参照ください)。その後、FIWAREを民間主導で推進するための FIWARE Foundation が設立されました。現在はTelefonica( GitHubリポジトリ でFIWAREの コンポーネント を公開)や NEC ( 加古川市 や 高松市 にFIWAREを導入)などが中心メンバーとなって推進しています。 FIWAREは都市OSを構築するために利用されます。都市OSとして利用されるのは、前述の都市OSの特徴を持つためです。具体的には以下のとおりです。 1. 相互運用(つながる) NGSI(Next Generation Service Interfaces)と呼ばれる API 標準規格を採用しています。標準規格の API により、分野や組織間のサービス連携やデータの利活用を可能にします。NGSIについては後述します。 2. データ流通(ながれる) FIWAREのコア コンポーネント である FIWARE Orion がデータを分散管理したり、データを中継したり機能を持ちます。 3. 拡張容易(つづけられる) 下図の通り、FIWAREを構成する コンポーネント はそれぞれが独立して動作する「マイクロサービス アーキテクチャ 」を採用しています。必要な機能を持つ コンポーネント を取捨選択することにより、システムの拡張を容易にします。 ※ GitHubより引用 FIWAREの コンポーネント FIWAREは多くの コンポーネント を持ち、それぞれを組み合わせて利用します。FIWAREを構成する コンポーネント はGeneric Enablers(GE)と呼ばれます。ここではGEのうち、代表的なものを挙げて簡単に説明します。 FIWARE Orion FIWAREのコア(必須)となる コンポーネント です。コンテキストブローカーとしてデータを保管・管理するための機能を持ち、NGSIでデータを公開できます。MongoDBがデータストアとして利用されます。Orionに保管されるデータのライフサイクルは基本的に短く、最新のデータにより上書き更新されます。例えばビルの電力データをOrionで管理することを考えたときに、Orionに保管されるのは現在のビルの電力のみで、その履歴は保管されません。 FIWARE Cygnus (Cygnus) Orionに登録されたデータを蓄積するための コンポーネント です。データストアとして PostgreSQL 、ElasticSearch、 AWS のDynamoDBなど幅広く対応しています。 Orionに登録されたデータの変更をNGSIで受け取り、その変更履歴をデータストアに登録します。 IoT Agent For Json (IoT Agent) 名前の通り、IoTのデータ収集にかかわるコンポ―ネントです。RabbitMQなどのMQTTブローカーに集められたデータを収集してNGSIに変換し、Orionに登録する機能を持ちます。 WireCloud データを可視化するための コンポーネント です。OrionからNGSIでデータを受け取り、地図やグラフなどを活用した ダッシュ ボードを通じてデータを閲覧できます。 開発ツール Dockerイメージ や Helmチャート が公開されています。 AWS やAzureといった パブリッククラウド のコンテナプラットフォームを利用してFIWAREをホストすることが可能になります。 実際にFIWAREを使ってみる ここからは実際にFIWAREを使ったデータ登録、データ取得といった手順を試してみます。この手順で利用するFIWAREの コンポーネント はOrionのみです。Orionを利用するにあたり、事前にNGSIの説明します。 NGSIとは NGSIは、 NEC を中心にOMA(Open Mobile Alliance)によって標準化された API の規格です。アップデートが継続的に行われ、NGSI-LD(Linked Data)と呼ばれる規格が最新です。ただし、FIWAREに実装されているNGSIのバージョンはNGSIv2(NGSI-LDの以前のバージョン)であり、 NGSI-LDは開発中 になります。そのため、ここではNGSIv2に関して説明します。 まずはNGSIv2のデータモデルについて、以下の json を例に説明します。これはNGSIv2の規格に則り表現された json です。 { " id ":" urn:ngsi-ld:Vehicle:A4567 ", " type ":" Vehicle ", " brandName ": { " type ":" Property ", " value ":" Mercedes " } , " isParked ": { " type ":" Relationship ", " value ":" urn:ngsi-ld:OffStreetParking:Downtown1 ", " metadata ": { " observedAt ": { " value ":" 2017-07-29T12:00:04 ", " type ":" DateTime " } , " providedBy ": { " type ":" Relationship ", " value ":" urn:ngsi-ld:Person:Bob " } } } } この json は Vehicle という車のオブジェクトを表しています。NGSIv2において、このオブジェクトのことをエンティティ(Entity)と呼びます。このEntityは、どのブランドであるかを示す brandName と、どこに駐車されているかを示す isParked という属性を持ちます。これら属性のことを、 アトリビュート (Attribute)と呼びます。さらに isParked 属性は metadata と呼ばれるその属性に付随する情報を持ちます。 observedAt というそのデータが変更された時間や、 providedBy というそのデータが誰によって変更された、といったような情報です。この情報のことを メタデータ (Metadata) このようにNGSIv2でのデータモデルはEntity・Attribute・Metadataの3つにより構成される下図のようなモデルです。 ※ こちらより引用 NGSIでは API Specification も定められています。 Orionでのデータ管理を試す こちら で公開されている手順を参考に、Orionでのデータ管理を試してみます。実行にあたり、 Docker 、 Docker Compose が必要になりますので事前にインストールお願いします。なお、コマンドの実行環境は bash になります。 まずは チュートリアル 用の リポジトリ からファイルを取得し、 環境変数 を設定してます。 環境変数 を設定後、コンテナを起動します。 # リポジトリのクローン git clone https://github.com/FIWARE/tutorials.Getting-Started.git cd tutorials.Getting-Started git checkout NGSI-v2 # 環境変数の設定 export $( cat .env | grep " # " -v ) # コンテナを起動 docker compose -p fiware up -d docker-compose.yml の中を確認すると、Orionのコンテナと、MongoDBのコンテナを起動することが確認できます。前述の通り、MongoDBはOrionのデータストアとして利用されるためです。これがFIWAREを始めるにあたっての最小構成となります。 次に、起動したOrionへ以下のリク エス トを投げてみてください。 curl ではなくても、Postmanなどの GUI ソフトウェアを利用しても構いません。 curl -iX POST \ ' http://localhost:1026/v2/entities ' \ -H ' Content-Type: application/json ' \ -d ' { "id": "urn:ngsi-ld:Store:001", "type": "Store", "address": { "type": "PostalAddress", "value": { "streetAddress": "Bornholmer Straße 65", "addressRegion": "Berlin", "addressLocality": "Prenzlauer Berg", "postalCode": "10439" }, "metadata": { "verified": { "value": true, "type": "Boolean" } } }, "location": { "type": "geo:json", "value": { "type": "Point", "coordinates": [13.3986, 52.5547] } }, "name": { "type": "Text", "value": "Bösebrücke Einkauf" } } ' NGSIv2のEntityを作成する API ( /v2/entities )に対してリク エス トを送信していることがわかります。このリク エス トにより、Orionには Store Entityが作成されます。 次に登録したEntityを取得する API を実行してみます。以下のコマンドを実行してください。 curl -G -X GET \ ' http://localhost:1026/v2/entities/urn:ngsi-ld:Store:001 ' \ -d ' options=keyValues ' NGSIv2のEntityを取得する API ( /v2entities/<Entity ID> )に対してリク エス トを送信していることがわかります。このリク エス トにより、Orionに登録されたEntityを取得します。なお、 options=keyValues というクエリが指定されていますが、これはAttributeの type と metadata を省略した形でレスポンスを得るためのオプションです。レスポンスとして、登録したEntityを取得できていることが確認できます。 { " id ": " urn:ngsi-ld:Store:001 ", " type ": " Store ", " address ": { " streetAddress ": " Bornholmer Straße 65 ", " addressRegion ": " Berlin ", " addressLocality ": " Prenzlauer Berg ", " postalCode ": " 10439 " } , " location ": { " type ": " Point ", " coordinates ": [ 13.3986 , 52.5547 ] } , " name ": " Bösebrücke Einkauf " } このように基本的な CRUD 操作のほか、都市OSの特徴である「データ流通(ながれる)」を実現するための機能を持ちます。Orionのデータが変更されたときにPush型で情報を通知する Subscription と呼ばれる機能や、外部のデータを仲介する Registration と呼ばれる機能などがそれに該当します。本記事では割愛しますが、リンク先で手順が公開されていますのでぜひ試してください。 おわりに 本記事ではスマートシティを実現する都市OSについて、また都市OSを構築するためのFIWAREについて紹介しました。 日本におけるFIWAREの状況として、 NEC 中心にコミュニティが形成され、日本語の記事も増えてきています。またいくつかの 自治 体にも導入され、今後ますます認知度も高まり、発展していくことが予想されます。そんな中、ISIDとしても個人としても、日本のスマートシティの分野に貢献できるよう情報発信を続けていきたいなと考えています。 最後までお読みいただきありがとうございました。 参考文献 スマートシティガイドブック スマートシティリファレンスアーキテクチャ FIWARE FIWARE GitHubリポジトリ Let's FIWARE https://www.slideshare.net/fisuda/fiware-context-information-management https://www.slideshare.net/fisuda/orioncontextbroker-ngsiv2-overview-for-developers-that-already-know-ngsiv1-20180615 執筆: @ueba.yuki 、レビュー: @sato.taichi ( Shodo で執筆されました )
アバター
これは 電通国際情報サービス アドベントカレンダー の 20日 目の記事です。 こんにちは、 電通国際情報サービス (ISID)の上羽優貴です。 ISIDは今年に新しくスマートシティや 自治 体DX、脱炭素化などの社会課題対応型ビジネスの推進を目的とした スマートソサエティセンター という新組織を立ち上げました。私はここに所属し、スマートシティ関連のビジネスを推進しています。本記事では、スマートシティを実現するための基盤ソフトウェアであるFIWARE(ファイウェア)について解説します。 スマートシティと都市OS 近年、日本におけるスマートシティへの取り組みが盛んになっています。 トヨタ が推進する ウーブンシティ は有名ですね。スマートシティを実現するうえで欠かせないのがICTやデータの活用です。その活用の分野は防災や安全、モビリティ、教育・医療など多岐にわたります。今現在も様々な都市においてICTやデータを活用した住民サービスの提供がなされています。 しかし、日本でのスマートシティの実現に向けては、これまで大きく3つの課題がありました。 1. サービスの再利用・横展開 分野や組織ごとに個別にシステムを構築することが多く、他の地域での再利用や横展開が困難 2. 分野間データ利活用 分野や組織ごとにデータが独立し、分野や組織を横断してデータを活用することが困難 3. 拡張性の低さ 個別にシステムが構築されるため独自の仕様を持ち、機能拡張にかかるコストが大きく 、サービスを拡張させることが困難 そこで、近年注目を集めているのが都市OSというソフトウェア基盤です。都市OSは以下のような特徴を持ち、これまで課題だったサービスの再利用や、分野間のデータ利活用を促進する効果を期待されています。 1. 相互運用(つながる) 共通の機能や標準的なインタフェース( API )を具備して外部に公開する仕組みを持ち、分野や組織をまたがるサービス連携や横展開を可能にします。 2. データ流通(ながれる) スマートシティに利用するデータを仲介する機能を持ち、分野や組織を超えたデータ活用を可能にします。 3. 拡張容易(つづけられる) 機能間の 疎結合 なシステム構成を持ち、システムの拡張を容易にします。 都市OSを構築するためのソフトウェアの1つとして、この記事で紹介するFIWAREが挙げられます。 ※ スマートシティガイドブック(本文)第2章1 p.33より引用 FIWAREとは FIWARE とはFI(Future Internet)WARE(SOFTWARE)の略で、 自治 体や企業などの業種を超えたデータ利活用やサービス連携を促すために開発されたソフトウェア群です。ソフトウェア群と表現した通り、FIWAREは1つのソフトウェアのことではなく、いくつかのソフトウェアの総称です。 OSS として GitHub に公開されています。 FIWAREは欧州のFI-PPPという官民連携プログラムで開発されました(FI-PPPについては こちら を参照ください)。その後、FIWAREを民間主導で推進するための FIWARE Foundation が設立されました。現在はTelefonica( GitHubリポジトリ でFIWAREの コンポーネント を公開)や NEC ( 加古川市 や 高松市 にFIWAREを導入)などが中心メンバーとなって推進しています。 FIWAREは都市OSを構築するために利用されます。都市OSとして利用されるのは、前述の都市OSの特徴を持つためです。具体的には以下のとおりです。 1. 相互運用(つながる) NGSI(Next Generation Service Interfaces)と呼ばれる API 標準規格を採用しています。標準規格の API により、分野や組織間のサービス連携やデータの利活用を可能にします。NGSIについては後述します。 2. データ流通(ながれる) FIWAREのコア コンポーネント である FIWARE Orion がデータを分散管理したり、データを中継したり機能を持ちます。 3. 拡張容易(つづけられる) 下図の通り、FIWAREを構成する コンポーネント はそれぞれが独立して動作する「マイクロサービス アーキテクチャ 」を採用しています。必要な機能を持つ コンポーネント を取捨選択することにより、システムの拡張を容易にします。 ※ GitHubより引用 FIWAREの コンポーネント FIWAREは多くの コンポーネント を持ち、それぞれを組み合わせて利用します。FIWAREを構成する コンポーネント はGeneric Enablers(GE)と呼ばれます。ここではGEのうち、代表的なものを挙げて簡単に説明します。 FIWARE Orion FIWAREのコア(必須)となる コンポーネント です。コンテキストブローカーとしてデータを保管・管理するための機能を持ち、NGSIでデータを公開できます。MongoDBがデータストアとして利用されます。Orionに保管されるデータのライフサイクルは基本的に短く、最新のデータにより上書き更新されます。例えばビルの電力データをOrionで管理することを考えたときに、Orionに保管されるのは現在のビルの電力のみで、その履歴は保管されません。 FIWARE Cygnus (Cygnus) Orionに登録されたデータを蓄積するための コンポーネント です。データストアとして PostgreSQL 、ElasticSearch、 AWS のDynamoDBなど幅広く対応しています。 Orionに登録されたデータの変更をNGSIで受け取り、その変更履歴をデータストアに登録します。 IoT Agent For Json (IoT Agent) 名前の通り、IoTのデータ収集にかかわるコンポ―ネントです。RabbitMQなどのMQTTブローカーに集められたデータを収集してNGSIに変換し、Orionに登録する機能を持ちます。 WireCloud データを可視化するための コンポーネント です。OrionからNGSIでデータを受け取り、地図やグラフなどを活用した ダッシュ ボードを通じてデータを閲覧できます。 開発ツール Dockerイメージ や Helmチャート が公開されています。 AWS やAzureといった パブリッククラウド のコンテナプラットフォームを利用してFIWAREをホストすることが可能になります。 実際にFIWAREを使ってみる ここからは実際にFIWAREを使ったデータ登録、データ取得といった手順を試してみます。この手順で利用するFIWAREの コンポーネント はOrionのみです。Orionを利用するにあたり、事前にNGSIの説明します。 NGSIとは NGSIは、 NEC を中心にOMA(Open Mobile Alliance)によって標準化された API の規格です。アップデートが継続的に行われ、NGSI-LD(Linked Data)と呼ばれる規格が最新です。ただし、FIWAREに実装されているNGSIのバージョンはNGSIv2(NGSI-LDの以前のバージョン)であり、 NGSI-LDは開発中 になります。そのため、ここではNGSIv2に関して説明します。 まずはNGSIv2のデータモデルについて、以下の json を例に説明します。これはNGSIv2の規格に則り表現された json です。 { " id ":" urn:ngsi-ld:Vehicle:A4567 ", " type ":" Vehicle ", " brandName ": { " type ":" Property ", " value ":" Mercedes " } , " isParked ": { " type ":" Relationship ", " value ":" urn:ngsi-ld:OffStreetParking:Downtown1 ", " metadata ": { " observedAt ": { " value ":" 2017-07-29T12:00:04 ", " type ":" DateTime " } , " providedBy ": { " type ":" Relationship ", " value ":" urn:ngsi-ld:Person:Bob " } } } } この json は Vehicle という車のオブジェクトを表しています。NGSIv2において、このオブジェクトのことをエンティティ(Entity)と呼びます。このEntityは、どのブランドであるかを示す brandName と、どこに駐車されているかを示す isParked という属性を持ちます。これら属性のことを、 アトリビュート (Attribute)と呼びます。さらに isParked 属性は metadata と呼ばれるその属性に付随する情報を持ちます。 observedAt というそのデータが変更された時間や、 providedBy というそのデータが誰によって変更された、といったような情報です。この情報のことを メタデータ (Metadata) このようにNGSIv2でのデータモデルはEntity・Attribute・Metadataの3つにより構成される下図のようなモデルです。 ※ こちらより引用 NGSIでは API Specification も定められています。 Orionでのデータ管理を試す こちら で公開されている手順を参考に、Orionでのデータ管理を試してみます。実行にあたり、 Docker 、 Docker Compose が必要になりますので事前にインストールお願いします。なお、コマンドの実行環境は bash になります。 まずは チュートリアル 用の リポジトリ からファイルを取得し、 環境変数 を設定してます。 環境変数 を設定後、コンテナを起動します。 # リポジトリのクローン git clone https://github.com/FIWARE/tutorials.Getting-Started.git cd tutorials.Getting-Started git checkout NGSI-v2 # 環境変数の設定 export $( cat .env | grep " # " -v ) # コンテナを起動 docker compose -p fiware up -d docker-compose.yml の中を確認すると、Orionのコンテナと、MongoDBのコンテナを起動することが確認できます。前述の通り、MongoDBはOrionのデータストアとして利用されるためです。これがFIWAREを始めるにあたっての最小構成となります。 次に、起動したOrionへ以下のリク エス トを投げてみてください。 curl ではなくても、Postmanなどの GUI ソフトウェアを利用しても構いません。 curl -iX POST \ ' http://localhost:1026/v2/entities ' \ -H ' Content-Type: application/json ' \ -d ' { "id": "urn:ngsi-ld:Store:001", "type": "Store", "address": { "type": "PostalAddress", "value": { "streetAddress": "Bornholmer Straße 65", "addressRegion": "Berlin", "addressLocality": "Prenzlauer Berg", "postalCode": "10439" }, "metadata": { "verified": { "value": true, "type": "Boolean" } } }, "location": { "type": "geo:json", "value": { "type": "Point", "coordinates": [13.3986, 52.5547] } }, "name": { "type": "Text", "value": "Bösebrücke Einkauf" } } ' NGSIv2のEntityを作成する API ( /v2/entities )に対してリク エス トを送信していることがわかります。このリク エス トにより、Orionには Store Entityが作成されます。 次に登録したEntityを取得する API を実行してみます。以下のコマンドを実行してください。 curl -G -X GET \ ' http://localhost:1026/v2/entities/urn:ngsi-ld:Store:001 ' \ -d ' options=keyValues ' NGSIv2のEntityを取得する API ( /v2entities/<Entity ID> )に対してリク エス トを送信していることがわかります。このリク エス トにより、Orionに登録されたEntityを取得します。なお、 options=keyValues というクエリが指定されていますが、これはAttributeの type と metadata を省略した形でレスポンスを得るためのオプションです。レスポンスとして、登録したEntityを取得できていることが確認できます。 { " id ": " urn:ngsi-ld:Store:001 ", " type ": " Store ", " address ": { " streetAddress ": " Bornholmer Straße 65 ", " addressRegion ": " Berlin ", " addressLocality ": " Prenzlauer Berg ", " postalCode ": " 10439 " } , " location ": { " type ": " Point ", " coordinates ": [ 13.3986 , 52.5547 ] } , " name ": " Bösebrücke Einkauf " } このように基本的な CRUD 操作のほか、都市OSの特徴である「データ流通(ながれる)」を実現するための機能を持ちます。Orionのデータが変更されたときにPush型で情報を通知する Subscription と呼ばれる機能や、外部のデータを仲介する Registration と呼ばれる機能などがそれに該当します。本記事では割愛しますが、リンク先で手順が公開されていますのでぜひ試してください。 おわりに 本記事ではスマートシティを実現する都市OSについて、また都市OSを構築するためのFIWAREについて紹介しました。 日本におけるFIWAREの状況として、 NEC 中心にコミュニティが形成され、日本語の記事も増えてきています。またいくつかの 自治 体にも導入され、今後ますます認知度も高まり、発展していくことが予想されます。そんな中、ISIDとしても個人としても、日本のスマートシティの分野に貢献できるよう情報発信を続けていきたいなと考えています。 最後までお読みいただきありがとうございました。 参考文献 スマートシティガイドブック スマートシティリファレンスアーキテクチャ FIWARE FIWARE GitHubリポジトリ Let's FIWARE https://www.slideshare.net/fisuda/fiware-context-information-management https://www.slideshare.net/fisuda/orioncontextbroker-ngsiv2-overview-for-developers-that-already-know-ngsiv1-20180615 執筆: @ueba.yuki 、レビュー: @sato.taichi ( Shodo で執筆されました )
アバター
ISID X(クロス) イノベーション 本部 の三浦です。本記事は 電通国際情報サービス Advent Calendar 2021 の19日目のポストです。 本記事では、Azure Web Appsでは簡単にモダンな開発ができることをキャプチャーを多めで説明します。 GUI からポチポチ設定でここまで簡単にできるということをお伝えするのが目的です。 (あまりインフラに詳しくない アプリ開発 者でも簡単にインフラ構築、運用ができるかもしれないといった内容です) 触れる技術要素 今回の模擬システムの説明 今回の環境でできること OpenID Connectによる認証(Office 365のユーザーでお手軽認証) の構築 webappsのディプロイスロットによる、ブルーグリーンディプロイ GitHub Actionによる継続的デリバリー まとめ 触れる技術要素 Azure Web Apps OpenID Connectによる認証(Office 365のユーザーでお手軽Single Sign On) ディプロイスロットによるブルーグリーンディプロイ GitHub ActionによるContinuous Delivery 今回の模擬システムの説明 Azure Web Apps + cognitive searchのシンプルなシステムです。 Azure Web Appsの機能で、 OpenID ConnectでSingle Sign Onし、 GitHub から、ステージング環境へ GitHub Actionで継続的デリバリーし、 GUI 上の操作で簡易にブルーグリーンディプロイをします。また、app insightsによる APM 監視、および、log analytics によるログ管理をしています。 今回のエントリでは用いてる技術のうち「 OpenID Connectによる認証」「ディプロイスロットによるブルーグリーンディプロイ」「 GitHub Actionによる継続的デリバリー」を紹介します。 今回の環境でできること Azure Web Apps の OpenID Connect認証による簡単な Office 365ユーザーで Single Sign On(AzureAD) ブルーグリーンディプロイによる停止時間の短縮、障害時の高速切り戻し GitHub acitionによる継続的デリバリー OpenID Connectによる認証(Office 365のユーザーでお手軽認証) の構築 下記のように GUI 操作していくだけで、簡易にOffice 365のユーザーで認証が可能となります。 ここの設定を間違えると、認証してないユーザー、全世界のAzureADのユーザーにこのシステムが公開されてしまうので注意です。 このように設定すると、webapp側にRelying Party としての設定が完了、AzureAD側に OpenID Provider としてのリソースが作成されています。 では、AzureADに遷移し、 OpenID Providerとしての追加設定をします。 まず、プロパティを開き下記の項目を設定します。 デフォルトの「いいえ」の場合、そのテナントの全てのユーザーがwebapps にアクセス可能となります。「はい」の場合は後述の手順により、webapps単位でアクセスするユーザーを制限できます。 例えば、マルチテナント的に複数の顧客をゲストユーザーとして登録しているテナントで、「いいえ」で設定してしまうと、他社向けのシステムが見えてしまうといったことが起こります。 次に、このアプリケーションへのアクセス権を与えるユーザーを追加してます。 ここでポイントなのは、AzureADのゲストユーザーも追加可能であるということです。これは、他社のOffice 365ユーザーに対して、他社の管理者の作業なしにSingle Sign Onが可能だということです。顧客が普段使ってるOffice 365のユーザーでのSingle Sign Onが数分で構築できる強力な機能です。 また、社内向けシステムを検討する際にも、煩雑な情シスへのIDP関連の申請を省略して普段使っているOffice 365のID、MFAを用いたシステムが提供可能となります。 Single Sign Onの設定は開発者、ID管理側、双方に一定の知識が必要でトラブリやすい作業です。しかし、Azure Web Apps + azureADのゲストユーザーを用いることでこの作業を大幅に簡易化できます。 webappsのディプロイスロットによる、ブルーグリーンディプロイ では、次に、ブルーグリーンディプロイを設定します。Azure Web Apps には、ブルーグリーンディプロイを実現するための ディプロイスロット という仕組みがあります。 これを作成します。 「スロットの追加」を選択し、「次から設定を複製」で元のスロットを選ぶだけで、アプリケーション設定がコピーされます( 環境変数 、 java バージョン、 tomcat バージョンなど)。 また、待機スロット用のURL、サーバが作成されます。 できあがったディプロイスロットを入れ替えるには スワップ するだけです。 これにより、待機スロットで Java や Tomcat をバージョンアップし、動作確認が取れたら スワップ するといったことも可能になります。 スワップ 時には、下記のように変更差分をわかりやすく表示してくれます。 また、待機スロットに GitHub Actionから継続的デリバリーし、動作確認してから スワップ で本番環境にアプリケーションを展開することもできます。 なお、今回の手順で待機スロットを使うためには、『 OpenID Connectによる認証』の再作成が必要です。スロットの設定を複製するときに認証設定も複製されているのですが、この認証設定はURLと結びついているためこのままでは動作しません。再作成で、待機スロット用の認証を構成しましょう。 GitHub Actionによる継続的デリバリー ここまでの作業で認証付きの待機スロットが準備でき、安全にアプリケーションをディプロイできる環境が整いました。では、 GitHub Actionによる継続的デリバリーを設定します。 継続的デリバリーは待機スロットにし、待機スロットでディプロイ後アプリケーションの動作確認して、 スワップ で運用スロットに展開するといったながれとなります。 「ディ プロイセン ター」で、 GitHub を選択し、レポジトリ、ブランチ情報を入力します。 そうすると、mvnを前提とした GitHub acitonの設定ファイルが自動的に GitHub にコミットされます。 が、本プロジェクトではgraldeを使用していたので、適宜修正をします。 これだけで継続的デリバリーが構成されます。 まとめ Azureでは、このように、 GUI によりポチポチするだけでこのような環境を作成できます。 とある案件では、今回の手順をキャプチャーベースでDevのメンバーに展開することにより 「Devで簡単に巻き取れそうなので横展開は今後Devでやっていきます」 というありがたいお言葉をいただくことができました。 Azureをうまく使うことにより、 Ops の関与を非常に減らした運用ができるのではないか?と思います。 Ops に負担をかけずに運用したいDevの方、構築・リリース作業で手一杯になっている Ops の方は、Azure Web Appsを使った環境構築を試してみてはいかがでしょうか 執筆: @miura.toshihiko 、レビュー: @sato.taichi ( Shodo で執筆されました )
アバター
ISID X(クロス) イノベーション 本部 の三浦です。本記事は 電通国際情報サービス Advent Calendar 2021 の19日目のポストです。 本記事では、Azure Web Appsでは簡単にモダンな開発ができることをキャプチャーを多めで説明します。 GUI からポチポチ設定でここまで簡単にできるということをお伝えするのが目的です。 (あまりインフラに詳しくない アプリ開発 者でも簡単にインフラ構築、運用ができるかもしれないといった内容です) 触れる技術要素 今回の模擬システムの説明 今回の環境でできること OpenID Connectによる認証(Office 365のユーザーでお手軽認証) の構築 webappsのディプロイスロットによる、ブルーグリーンディプロイ GitHub Actionによる継続的デリバリー まとめ 触れる技術要素 Azure Web Apps OpenID Connectによる認証(Office 365のユーザーでお手軽Single Sign On) ディプロイスロットによるブルーグリーンディプロイ GitHub ActionによるContinuous Delivery 今回の模擬システムの説明 Azure Web Apps + cognitive searchのシンプルなシステムです。 Azure Web Appsの機能で、 OpenID ConnectでSingle Sign Onし、 GitHub から、ステージング環境へ GitHub Actionで継続的デリバリーし、 GUI 上の操作で簡易にブルーグリーンディプロイをします。また、app insightsによる APM 監視、および、log analytics によるログ管理をしています。 今回のエントリでは用いてる技術のうち「 OpenID Connectによる認証」「ディプロイスロットによるブルーグリーンディプロイ」「 GitHub Actionによる継続的デリバリー」を紹介します。 今回の環境でできること Azure Web Apps の OpenID Connect認証による簡単な Office 365ユーザーで Single Sign On(AzureAD) ブルーグリーンディプロイによる停止時間の短縮、障害時の高速切り戻し GitHub acitionによる継続的デリバリー OpenID Connectによる認証(Office 365のユーザーでお手軽認証) の構築 下記のように GUI 操作していくだけで、簡易にOffice 365のユーザーで認証が可能となります。 ここの設定を間違えると、認証してないユーザー、全世界のAzureADのユーザーにこのシステムが公開されてしまうので注意です。 このように設定すると、webapp側にRelying Party としての設定が完了、AzureAD側に OpenID Provider としてのリソースが作成されています。 では、AzureADに遷移し、 OpenID Providerとしての追加設定をします。 まず、プロパティを開き下記の項目を設定します。 デフォルトの「いいえ」の場合、そのテナントの全てのユーザーがwebapps にアクセス可能となります。「はい」の場合は後述の手順により、webapps単位でアクセスするユーザーを制限できます。 例えば、マルチテナント的に複数の顧客をゲストユーザーとして登録しているテナントで、「いいえ」で設定してしまうと、他社向けのシステムが見えてしまうといったことが起こります。 次に、このアプリケーションへのアクセス権を与えるユーザーを追加してます。 ここでポイントなのは、AzureADのゲストユーザーも追加可能であるということです。これは、他社のOffice 365ユーザーに対して、他社の管理者の作業なしにSingle Sign Onが可能だということです。顧客が普段使ってるOffice 365のユーザーでのSingle Sign Onが数分で構築できる強力な機能です。 また、社内向けシステムを検討する際にも、煩雑な情シスへのIDP関連の申請を省略して普段使っているOffice 365のID、MFAを用いたシステムが提供可能となります。 Single Sign Onの設定は開発者、ID管理側、双方に一定の知識が必要でトラブリやすい作業です。しかし、Azure Web Apps + azureADのゲストユーザーを用いることでこの作業を大幅に簡易化できます。 webappsのディプロイスロットによる、ブルーグリーンディプロイ では、次に、ブルーグリーンディプロイを設定します。Azure Web Apps には、ブルーグリーンディプロイを実現するための ディプロイスロット という仕組みがあります。 これを作成します。 「スロットの追加」を選択し、「次から設定を複製」で元のスロットを選ぶだけで、アプリケーション設定がコピーされます( 環境変数 、 java バージョン、 tomcat バージョンなど)。 また、待機スロット用のURL、サーバが作成されます。 できあがったディプロイスロットを入れ替えるには スワップ するだけです。 これにより、待機スロットで Java や Tomcat をバージョンアップし、動作確認が取れたら スワップ するといったことも可能になります。 スワップ 時には、下記のように変更差分をわかりやすく表示してくれます。 また、待機スロットに GitHub Actionから継続的デリバリーし、動作確認してから スワップ で本番環境にアプリケーションを展開することもできます。 なお、今回の手順で待機スロットを使うためには、『 OpenID Connectによる認証』の再作成が必要です。スロットの設定を複製するときに認証設定も複製されているのですが、この認証設定はURLと結びついているためこのままでは動作しません。再作成で、待機スロット用の認証を構成しましょう。 GitHub Actionによる継続的デリバリー ここまでの作業で認証付きの待機スロットが準備でき、安全にアプリケーションをディプロイできる環境が整いました。では、 GitHub Actionによる継続的デリバリーを設定します。 継続的デリバリーは待機スロットにし、待機スロットでディプロイ後アプリケーションの動作確認して、 スワップ で運用スロットに展開するといったながれとなります。 「ディ プロイセン ター」で、 GitHub を選択し、レポジトリ、ブランチ情報を入力します。 そうすると、mvnを前提とした GitHub acitonの設定ファイルが自動的に GitHub にコミットされます。 が、本プロジェクトではgraldeを使用していたので、適宜修正をします。 これだけで継続的デリバリーが構成されます。 まとめ Azureでは、このように、 GUI によりポチポチするだけでこのような環境を作成できます。 とある案件では、今回の手順をキャプチャーベースでDevのメンバーに展開することにより 「Devで簡単に巻き取れそうなので横展開は今後Devでやっていきます」 というありがたいお言葉をいただくことができました。 Azureをうまく使うことにより、 Ops の関与を非常に減らした運用ができるのではないか?と思います。 Ops に負担をかけずに運用したいDevの方、構築・リリース作業で手一杯になっている Ops の方は、Azure Web Appsを使った環境構築を試してみてはいかがでしょうか 執筆: @miura.toshihiko 、レビュー: @sato.taichi ( Shodo で執筆されました )
アバター
本記事は 電通国際情報サービス Advent Calendar 2021 の18日目のポストです。 (本記事の太字部分は、 GitHub Copilotで補完された箇所です。その仕組みや感想などは記事の後半で説明します。) こんにちは。ISID X イノベーション 本部の半田です。普段は 社内向けの構成管理サービスの運用 をやっています。 今年の6月末、 GitHub は「関数名とコメントから、関数の ソースコード を補完する」機能、 GitHub Copilot のテクニカルプレビューを開始しました。 このCopilot、私もここ2ヶ月くらい使用しているのですが、最近 ソースコード だけではなく日本語も補完してくれることに気づきました。 そこで今日は、この GitHub Copilotにブログの記事を書いてみてもらおう と思います。 Copilotで使われている技術などの内容はありませんが、気休め程度にお付き合いください。 ※なお、以下のパラグラフでは GitHub Copilotによる補完をそのまま掲載します。以下の文章には事実関係の誤りや、日本語の揺れがあることをご容赦 ください。 GitHub Copilotに日本語を書いてもらった その1 まずは GitHub Copilotに、 GitHub Copilot自身の説明をしてもらいましょう。あくまで補完のためのツールなので、テーマや書き出しの文は私から与える必要があります。 はじめまして。今日は、 GitHub Copilotに日本語を書いてもらったのです。 GitHub Copilotは、 GitHub の補完機能を日本語で使えるようにしたものです。 みなさんは、 GitHub Copilotを使っているのですか?私は、 GitHub の補完機能を使っているのですが、その補完機能は日本語を使えるようになったのです。 ところで、 GitHub Copilotは、 GitHub の補完機能を使っているのですが、その補完機能は日本語を使えるようになったのです。 ということで、 GitHub Copilotに日本語を書いてもらったのです。 ありがとうございます。 GitHub Copilotによる補完部分は、以下の太字の部分でした。 はじめ まして。 今日は 、 GitHub Copilotに日本語を書いてもらったのです。 G itHub Copilotは、 GitHub の補完機能を日本語で使えるようにしたものです。 みなさん は、 GitHub Copilotを使っているのですか? 私は 、 GitHub の補完機能を使っているのですが、その補完機能は日本語を使えるようになったのです。 ところで 、 GitHub Copilotは、 GitHub の補完機能を使っているのですが、その補完機能は日本語を使えるようになったのです。 という ことで、 GitHub Copilotに日本語を書いてもらったのです。 あ りがとうございます。 私が与えた文章はとても少ないですが、なんだかそれっぽい日本語が生成されてきました。ただ、内容はとても薄いですし、なんだか日本語の補完ツールだという説明になっていますね。この記事の前段から学習したことを、ほとんどそのまま言っているようです。 一方で、文章のつながりはとても自然で驚きました。接続詞は私が与えていますが、例えば「ところで」に続くセンテンスとして「○○ですが、」という言葉がきていますね。ほかにも、「という(ことで)」に続くセンテンスとして要点を簡潔に 表現しているのです。 ちなみに補完はこのように表示されます。 その2 さすがに接続詞だけだと、文章の中身としてはほとんど空っぽですね。 次はもう少し意図を持って文章を与えてみましょう。普段書いている プログラミング言語 を紹介したいと思います。 こんにちは。 みなさんは、普段どのような プログラミング言語 を使っていますか? 私は、 Python とTypeScriptを使っています。主にWebアプリケーションを作っています。 ほかにも、 JavaScript や PHP なども使っています。 普段の仕事を便利にするための自動化もしています。 例えば、 GitHub の監査ログを収集して、 Google BigQueryに保存しています。 この収集では、RxJSを使っています。RxJSは、 JavaScript のPromiseをラップして、非同期処理を楽にするためのライブラリです。 ほかにも、社内システムから出力される 工数 の実績データを Google Sheetsに保存して、 Google Data Studioで統計を表示しています。 メンバーがどのような業務をしているのかを知りたいときなどに使います。 このような簡単な処理を自動化するのに、 Python は非常に便利です。 こちらも答え合わせです。 こんにちは。 みなさんは、普段どのような プログラミング言語 を使っていますか? 私は Python とType Scriptを使っています。 主にWeb アプリケーションを作っています。 ほかにも、 JavaScript や PHP なども使っています。 普段の仕事を便利にするための自動化 もしています。 例えば、 GitHub の監査ログを収集して、 Google B igQueryに保存しています。 この収集では、R xJSを使っています。 R xJSは、 JavaScript のPromiseをラップして、非同期処理を楽にするためのライブラリです。 ほかにも、社内システムから出力される 工数 の実績データを Google Sheetsに保存して、 Google D ata Studioで統計を表示しています。 メンバーがどのような 業務をしているのかを知りたいときなどに使います。 このような簡単な処理を自動化するのに、 Python は 非常に便利です。 いかがでしょうか。私は PHP をあまり書きませんし、RxJSを「Promiseをラップして、非同期処理を楽にするためのライブラリ」と説明するのは多少危険な気がします。それでもずいぶん正確に文章を構成できていますね。 例えば「自動化も しています 」という部分では、まるで前半の文章に情報を並立していることを理解しているかのように「も」という助詞を使用していますね。 GitHub Copilotに日本語を書いてもらって感じたこと GitHub Copilotの「クセ」 最初は「へえ、日本語も補完するんだ」という驚きをモチベーションに記事を書き始めましたが、ここまで書いてみて GitHub Copilotにはいくつかの癖があるように感じました。少しまとめます。 ファイル内の文章も学習する ソースコード もファイル内のコンテンツを学習しているそうですが、日本語も同じように学習しているようですね。文章の前半より後半の方が、補完の精度は高くなっていきます。 試しに新しいファイルを開いて同じ文章を入力してみましたが、得られる結果は異なるものでした。 文章内にあるキーワードや自分やチームが持っている書き方の「クセ」を、ちゃんと学習してくれているようです。 一文を短く終わらせる傾向にある どの文章も、表示される補完は一文が短く終わっているなと感じました。主語と述語を簡潔に結んでいるような印象です。 「傾向にある」と書いたのは、まれにとてつもなく長い補完を表示したり、同じ文章が何度もループして表示されたりする事があったためです。 私は一文を長く書いてしまう傾向にあるので、この補完を見て「そろそろ文章を終わらせなきゃ」と焦ることもしばしばありました。 与えられた接続詞に対して、適切な助詞を補ったセンテンスを補完している…? これは驚きましたね。接続詞にどのような文章を続けるかというのは、時に人間であっても難しいことがあります。 もちろん完全に正しいセンテンスが表示されるわけではないのですが、どうやって意味の通る文章を生成しているのかはとても興味深いですね。AIってすごいです。 どう付き合っていくか? 今回は日本語の補完を題材にしましたが、 ソースコード の補完であっても、今回の補完に感じた違和感や誤りと同じようなものがあると思われます。 言わずもがなではありますが、 GitHub Copilotによる補完は意味的に正しいものを確実に補完してくれるわけではないことを理解する必要があります。 日本語であればパッと見てその意味があっているかどうかを確認できることも多いですが、例えば ソースコード で条件分岐の式を書くときなど、正しく補完されているかを意識して確認した方が良さそうです。 また、補完は基本的に過去のコードを学習して、それらしきものを表示してくれるものです。同じようなコードを書くような状況と、まったく新しいコードを書くような状況では、精度も異なるはずです。 これらのことから、基本的には「stackoverflowやQiitaなどの ソースコード をコピー&ペースト」する時と同じように扱うと良いのかなと考えています。 そのコードは正常に コンパイル できるのか、ランタイムエラーはでないのか、要件は満たせているのかなどを丁寧に確認できるようであれば、 GitHub Copilotの補完は強力な相棒になってくれるでしょう。 日本語の補完に使うときは、文末を補完してもらうのが良いかなと思います。 文頭からの補完でセンテンスの意味的な整合性を確保するのは難しいですが、文末を少し補完してもらえるだけでも結構便利です。文末につける言葉のバリエーションに悩んだときも、ア イデア をもらえてありがたいですよ。 あるときは驚くような高い精度の補完を、またあるときはクスッと笑えるような補完を提示してくれる GitHub Copilotですが、引き続き Microsoft Office の「イルカ」のようにかわいがってみようかなと思いました。 あとがき 記事を書いている途中、 GitHub Copilotからは 「そうですね、日本語も補完するのは面倒だ」という苦痛を感じました。 という補完を出してくれました。タイミングが良すぎて笑っちゃいました。 公式ドキュメント では、日本語を学習しているとは明記されていません。もし万が一にも GitHub Copilotで日本語を書きたい時は、どうぞ自己責任でお願いします。 執筆: @handa.kenta 、レビュー: @sato.taichi ( Shodo で執筆されました )
アバター
本記事は 電通国際情報サービス Advent Calendar 2021 の18日目のポストです。 (本記事の太字部分は、 GitHub Copilotで補完された箇所です。その仕組みや感想などは記事の後半で説明します。) こんにちは。ISID X イノベーション 本部の半田です。普段は 社内向けの構成管理サービスの運用 をやっています。 今年の6月末、 GitHub は「関数名とコメントから、関数の ソースコード を補完する」機能、 GitHub Copilot のテクニカルプレビューを開始しました。 このCopilot、私もここ2ヶ月くらい使用しているのですが、最近 ソースコード だけではなく日本語も補完してくれることに気づきました。 そこで今日は、この GitHub Copilotにブログの記事を書いてみてもらおう と思います。 Copilotで使われている技術などの内容はありませんが、気休め程度にお付き合いください。 ※なお、以下のパラグラフでは GitHub Copilotによる補完をそのまま掲載します。以下の文章には事実関係の誤りや、日本語の揺れがあることをご容赦 ください。 GitHub Copilotに日本語を書いてもらった その1 まずは GitHub Copilotに、 GitHub Copilot自身の説明をしてもらいましょう。あくまで補完のためのツールなので、テーマや書き出しの文は私から与える必要があります。 はじめまして。今日は、 GitHub Copilotに日本語を書いてもらったのです。 GitHub Copilotは、 GitHub の補完機能を日本語で使えるようにしたものです。 みなさんは、 GitHub Copilotを使っているのですか?私は、 GitHub の補完機能を使っているのですが、その補完機能は日本語を使えるようになったのです。 ところで、 GitHub Copilotは、 GitHub の補完機能を使っているのですが、その補完機能は日本語を使えるようになったのです。 ということで、 GitHub Copilotに日本語を書いてもらったのです。 ありがとうございます。 GitHub Copilotによる補完部分は、以下の太字の部分でした。 はじめ まして。 今日は 、 GitHub Copilotに日本語を書いてもらったのです。 G itHub Copilotは、 GitHub の補完機能を日本語で使えるようにしたものです。 みなさん は、 GitHub Copilotを使っているのですか? 私は 、 GitHub の補完機能を使っているのですが、その補完機能は日本語を使えるようになったのです。 ところで 、 GitHub Copilotは、 GitHub の補完機能を使っているのですが、その補完機能は日本語を使えるようになったのです。 という ことで、 GitHub Copilotに日本語を書いてもらったのです。 あ りがとうございます。 私が与えた文章はとても少ないですが、なんだかそれっぽい日本語が生成されてきました。ただ、内容はとても薄いですし、なんだか日本語の補完ツールだという説明になっていますね。この記事の前段から学習したことを、ほとんどそのまま言っているようです。 一方で、文章のつながりはとても自然で驚きました。接続詞は私が与えていますが、例えば「ところで」に続くセンテンスとして「○○ですが、」という言葉がきていますね。ほかにも、「という(ことで)」に続くセンテンスとして要点を簡潔に 表現しているのです。 ちなみに補完はこのように表示されます。 その2 さすがに接続詞だけだと、文章の中身としてはほとんど空っぽですね。 次はもう少し意図を持って文章を与えてみましょう。普段書いている プログラミング言語 を紹介したいと思います。 こんにちは。 みなさんは、普段どのような プログラミング言語 を使っていますか? 私は、 Python とTypeScriptを使っています。主にWebアプリケーションを作っています。 ほかにも、 JavaScript や PHP なども使っています。 普段の仕事を便利にするための自動化もしています。 例えば、 GitHub の監査ログを収集して、 Google BigQueryに保存しています。 この収集では、RxJSを使っています。RxJSは、 JavaScript のPromiseをラップして、非同期処理を楽にするためのライブラリです。 ほかにも、社内システムから出力される 工数 の実績データを Google Sheetsに保存して、 Google Data Studioで統計を表示しています。 メンバーがどのような業務をしているのかを知りたいときなどに使います。 このような簡単な処理を自動化するのに、 Python は非常に便利です。 こちらも答え合わせです。 こんにちは。 みなさんは、普段どのような プログラミング言語 を使っていますか? 私は Python とType Scriptを使っています。 主にWeb アプリケーションを作っています。 ほかにも、 JavaScript や PHP なども使っています。 普段の仕事を便利にするための自動化 もしています。 例えば、 GitHub の監査ログを収集して、 Google B igQueryに保存しています。 この収集では、R xJSを使っています。 R xJSは、 JavaScript のPromiseをラップして、非同期処理を楽にするためのライブラリです。 ほかにも、社内システムから出力される 工数 の実績データを Google Sheetsに保存して、 Google D ata Studioで統計を表示しています。 メンバーがどのような 業務をしているのかを知りたいときなどに使います。 このような簡単な処理を自動化するのに、 Python は 非常に便利です。 いかがでしょうか。私は PHP をあまり書きませんし、RxJSを「Promiseをラップして、非同期処理を楽にするためのライブラリ」と説明するのは多少危険な気がします。それでもずいぶん正確に文章を構成できていますね。 例えば「自動化も しています 」という部分では、まるで前半の文章に情報を並立していることを理解しているかのように「も」という助詞を使用していますね。 GitHub Copilotに日本語を書いてもらって感じたこと GitHub Copilotの「クセ」 最初は「へえ、日本語も補完するんだ」という驚きをモチベーションに記事を書き始めましたが、ここまで書いてみて GitHub Copilotにはいくつかの癖があるように感じました。少しまとめます。 ファイル内の文章も学習する ソースコード もファイル内のコンテンツを学習しているそうですが、日本語も同じように学習しているようですね。文章の前半より後半の方が、補完の精度は高くなっていきます。 試しに新しいファイルを開いて同じ文章を入力してみましたが、得られる結果は異なるものでした。 文章内にあるキーワードや自分やチームが持っている書き方の「クセ」を、ちゃんと学習してくれているようです。 一文を短く終わらせる傾向にある どの文章も、表示される補完は一文が短く終わっているなと感じました。主語と述語を簡潔に結んでいるような印象です。 「傾向にある」と書いたのは、まれにとてつもなく長い補完を表示したり、同じ文章が何度もループして表示されたりする事があったためです。 私は一文を長く書いてしまう傾向にあるので、この補完を見て「そろそろ文章を終わらせなきゃ」と焦ることもしばしばありました。 与えられた接続詞に対して、適切な助詞を補ったセンテンスを補完している…? これは驚きましたね。接続詞にどのような文章を続けるかというのは、時に人間であっても難しいことがあります。 もちろん完全に正しいセンテンスが表示されるわけではないのですが、どうやって意味の通る文章を生成しているのかはとても興味深いですね。AIってすごいです。 どう付き合っていくか? 今回は日本語の補完を題材にしましたが、 ソースコード の補完であっても、今回の補完に感じた違和感や誤りと同じようなものがあると思われます。 言わずもがなではありますが、 GitHub Copilotによる補完は意味的に正しいものを確実に補完してくれるわけではないことを理解する必要があります。 日本語であればパッと見てその意味があっているかどうかを確認できることも多いですが、例えば ソースコード で条件分岐の式を書くときなど、正しく補完されているかを意識して確認した方が良さそうです。 また、補完は基本的に過去のコードを学習して、それらしきものを表示してくれるものです。同じようなコードを書くような状況と、まったく新しいコードを書くような状況では、精度も異なるはずです。 これらのことから、基本的には「stackoverflowやQiitaなどの ソースコード をコピー&ペースト」する時と同じように扱うと良いのかなと考えています。 そのコードは正常に コンパイル できるのか、ランタイムエラーはでないのか、要件は満たせているのかなどを丁寧に確認できるようであれば、 GitHub Copilotの補完は強力な相棒になってくれるでしょう。 日本語の補完に使うときは、文末を補完してもらうのが良いかなと思います。 文頭からの補完でセンテンスの意味的な整合性を確保するのは難しいですが、文末を少し補完してもらえるだけでも結構便利です。文末につける言葉のバリエーションに悩んだときも、ア イデア をもらえてありがたいですよ。 あるときは驚くような高い精度の補完を、またあるときはクスッと笑えるような補完を提示してくれる GitHub Copilotですが、引き続き Microsoft Office の「イルカ」のようにかわいがってみようかなと思いました。 あとがき 記事を書いている途中、 GitHub Copilotからは 「そうですね、日本語も補完するのは面倒だ」という苦痛を感じました。 という補完を出してくれました。タイミングが良すぎて笑っちゃいました。 公式ドキュメント では、日本語を学習しているとは明記されていません。もし万が一にも GitHub Copilotで日本語を書きたい時は、どうぞ自己責任でお願いします。 執筆: @handa.kenta 、レビュー: @sato.taichi ( Shodo で執筆されました )
アバター
これは 電通国際情報サービス アドベントカレンダー の17日目の記事です。 はじめに 開発環境 ValueObject(値オブジェクト)とは? 実装方針のアプローチ 構造体として実装し、フィールドに値を保持し、必要な機能をメソッドで外部公開する defined typeとして実装し、必要な機能をメソッドで外部公開する 両アプローチの考察 データベースへの永続化 Value関数 Scan関数 実際にRDBに永続化してみる 値オブジェクトの実装 DB永続化処理 終わりに はじめに みなさんこんにちは。 電通国際情報サービス (ISID) 金融ソリューション事業部の水野です。 今回は、値オブジェクトをgo言語でどのように実装したかをご紹介します。 値の生成から振る舞いの実装、データベースへの永続化の際に如何に透過的に扱うかまでを見ていきます。 開発環境 Visual Studio Code 1.62.2 go 1.17 Docker Desktop 4.2.0 (内包されているDocker CLI を利用) 1 ValueObject(値オブジェクト)とは? Martin Fowlerさんの エンタープライズ アプリケーションアーキテクチャパターン で紹介されたのが最初だと理解しています。 「値オブジェクトとは何か」についての深堀りも非常に興味深いテーマですが、今回は以下と定義します。 イミュータブルである 不変条件が定義されており、条件を満たさない値では生成できない 特定の属性で等価性が定義される 値だけでなく、自身に属する機能を公開する 実装方針のアプローチ 以下の2つのアプローチを検討しました。 構造体 として実装し、フィールドに値を保持し、必要な機能をメソッドで外部公開する defined type で実装し、必要な機能をメソッドで外部公開する 上記どちらのアプローチでも、共通する戦略は以下です。 生成時にバリデーションを行い、エラー時は値を生成せずにerrorを返す 真偽値を返す等価性判定関数を実装する 自身が保持する値を使った何らかの操作を、メソッドで外部公開する イミュータブルに実装する方法は、構造体の場合はフィールドをエクスポートせず、値取得用のメソッドを設けて実現します。 defined typeとして実装する場合、基底にする型がイミュータブルかどうかに依存します。 構造体の場合、ボイラープレートとして値取得メソッドが毎回必要になるため、割り切ってフィールドをエクスポートしても良いと考えます。 その他の違いとしては、構造体だと複数の値を保持しやすいですが、defined typeだと単一の値の取り扱いが基本になります。 defined typeでも別の変数を保持することは可能ですが、やはりstringのような型として扱いたくなるでしょう。 例として、算術演算や税率算出などの機能を持つ「価格」という値オブジェクトを1.と2.で考えてみます。 構造体として実装し、フィールドに値を保持し、必要な機能をメソッドで外部公開する type Price struct { value int64 } func NewPrice(v int64 ) (Price, error ) { if err := isValidPrice(v); err != nil { ・・・エラーの場合の処理 } func isValidPrice(v int64 ) error { ...値の範囲チェックなど } func (price Price) Equal(other Price) bool { return price.value == other.value } func (price Price) CalcTax(rate uint ) Tax { ...省略} func (price Price) calcInternal(rate uint ) Tax { ...省略} // 内部処理用 value という構造体のフィールドに値を格納します。 defined typeとして実装し、必要な機能をメソッドで外部公開する type Price int64 func NewPrice(v int64 ) (Price, error ) { if err := isValidPrice(v); err != nil { ・・・エラーの場合の処理 } func isValidPrice(v int64 ) error { ...値の範囲チェックなど } func (price Price) Equal(other Price) bool { return int64 (price) == int64 (other) } func (price Price) CalcTax(rate uint ) Tax { ...省略} func (price Price) calcInternal(rate uint ) Tax { ...省略} // 内部処理用 両アプローチの考察 構造体による実装だと、Entityのような他の構造体のフィールドとして使用すると、構造体がネストすることになります。 今回は、 RDB への永続化時のシンプルさや、 JSON フィールドとして用いる際の取りまわしやすさから、defined typeで実装し必要な機能をメソッドで外部公開する方式を選択しました。 また、ValueObjectとして等価判定メソッドを実装する上では、以下のようなインタフェースを導入しても良いでしょう。 type ValueObject interface { Equal(other interface {}) bool } go 1.17の時点では ジェネリクス が未導入のため、上記のインタフェースでは毎回キャストする必要があります。 func (price Price) Equal(other interface {}) bool { val, ok := other.(Price) return ok && int64 (price) == int64 (val) } 余談ですが、レシーバの変数名は https://github.com/golang/go/wiki/CodeReviewComments#receiver-names では「It can be very short」と、非常に短い略称が理由と共に推奨されています。 ですが、レシーバ変数は関数内のローカル変数のスコープとしては最も広いものとなります。 また、ループカウンタの i や j と重複して意図せぬ シャドウイング を誘発したりと、短い変数名がゆえの弊害もあります。 そのため、レシーバの変数名には1, 2文字の略称ではなく、意味のある名称を割り当てています。 データベースへの永続化 defined type として実装する場合、基底型によっては意図した永続化が出来ず、動作をカスタムしたくなるケースがあります。 その場合、 Valuer インタフェースと Scanner インタフェースを実装します。 Valuerインタフェースの Value 関数は、ドライバから呼び出され、DBカラム型に対応する型に変換する役割を担います。 ScannerインタフェースのScan関数は、DBから取得したカラムの値を自身型に変換するための関数で、定められた特定の型から、ValueObject型への変換を実装します。 では、具体的に見ていきましょう。 Value 関数 シグニチャ は Value() (Value, error) と、非常にシンプルです。 前出のPrice型で実装するなら以下となります。 func (price Price) Value() (driver.Value, error ) { val := int64 (price) if val == - 1 { return NaNPrice, エラーオブジェクト } return int64 (price), nil } 上述のような実装にする必要はありませんが、int64のようなビルトイン型ではなく、固定小数10進表現を利用するケースなども考えられるため、例として無効な値が入っていた場合に無効値とerrorを返す疑似コードにしています。 Scan関数 Scan関数は若干特殊な仕組みで、ポインタを介して値をやり取りします。 そのため、ポインタレシーバとして実装する必要があります。 func (price *Price) Scan(value interface {}) error { switch v := value.( type ) { case int64 : if p, err := NewPrice(v); err == nil { *price = p return nil } else { return err } default : return errInvalidPrice } } 実際に RDB に永続化してみる RDB はPostgresSQLを使います。 今回は、Docker Desktopに内包されているDocker CLI で、最新の公式イメージでホストしつつ、デフォルトのpostgres スキーマ を使いました。 実際の開発では、アプリケーション用の スキーマ を別途用意する方が良いでしょう。 詳細は割愛しますが、 docker pull でイメージをダウンロードした後、 docker run するだけですぐに使えます。 PostgreSQL に接続し、非常にシンプルな以下の単価テーブルを作成します。 CREATE TABLE unit_price ( id serial PRIMARY KEY , lower_price bigint NOT NULL , upper_price bigint NOT NULL ); これで準備が整いました。サンプルなので、テーブル物理設計の妥当性は無視します。 PostgresSQLに永続化するにあたって、ドライバには pgx を利用します。 他のドライバに lib/pq がありますが、現在メンテナンスモードに入っており、公式ドキュメントではアクティブにメンテナンスされているpgxの利用が推奨( 2 )されています。 PostgreSQL を使うなら、今はpgxを使うのが良いでしょう。 実装した値オブジェクト Price を永続化するコードサンプルです。 税の算出などの機能を持たせていますが、紙面の都合上 RateやTaxの実装は省略しています。 値オブジェクトの実装 const ( minPrice, maxPrice = 0 , 9999999999999 NaNPrice = Price(- 1 ) ) type Price int64 func NewPrice(v int64 ) (Price, error ) { if err := isValidPrice(v); err != nil { return NaNPrice, err } return Price(v), nil } var ( errOutOfRangePrice = errors.New( "Price is out of range" ) errInvalidPrice = errors.New( "invalid Price" ) ) func isValidPrice(v int64 ) error { if v < minPrice && maxPrice < v { return fmt.Errorf( "Price must be between %d and %d, but [%d]: %w" , minPrice, maxPrice, v, errOutOfRangePrice) } return nil } func (price Price) Equal(other Price) bool { return int64 (price) == int64 (other) } func (price Price) String() string { return strconv.FormatInt( int64 (price), 10 ) } func (price Price) CalcTax(rate Rate) Tax { tax := float64 (price) * rate.AsPercentage() return NewTax(math.Floor(tax)) } func (price Price) Value() (driver.Value, error ) { if err := isValidPrice( int64 (price)); err != nil { return NaNPrice, err } return int64 (price), nil } func (price *Price) Scan(value interface {}) error { switch v := value.( type ) { case int64 : if p, err := NewPrice(v); err == nil { *price = p return nil } else { return fmt.Errorf( "invalid value [%v]: %w" , v, errOutOfRangePrice) } default : return errInvalidPrice } } func (price Price) EncodeBinary(ci *pgtype.ConnInfo, buf [] byte ) ([] byte , error ) { var numeric pgtype.Int8 if err := numeric.Set( int64 (price)); err != nil { return nil , err } return numeric.EncodeBinary(ci, buf) } Equal、String、CalcTaxというメソッドを定義しているのが分かりますね。 以下、実装におけるポイントを記します。 CalcTaxが ドメイン 固有処理 Value 、Scanはデータベースアクセスのために必要なメソッド pgx でカスタムされた型を使用するにはEncodeBinaryが必要 ( 3 参考) なため実装している pgxドライバを使うために、 github .com/jackc/pgx/v4と github .com/jackc/pgtypeを go getしている DB永続化処理 値オブジェクトを PostgreSQL に永続化する実装です。(エラー処理は意図的に省略しています) func main() { ctx := context.TODO() conn, _ := Connect(ctx, "postgres://postgres:testpass1@localhost:5432/postgres" ) defer func () { conn.Close(ctx) }() argLower, _ := value.NewPrice( 1000 ) argUpper, _ := value.NewPrice( 2500 ) conn.Exec(ctx, "INSERT INTO unit_price (lower_price, upper_price) VALUES ($1, $2)" , argLower, argUpper) // (1)挿入 rows, _ := conn.Query(ctx, "SELECT lower_price, upper_price from unit_price" ) // (2)選択 defer func () { rows.Close() }() for rows.Next() { var lower, upper value.Price rows.Scan(&lower, &upper) // (3)変数へ読み込み fmt.Printf( "lowerPrice=[%s], upperPrice=[%s]" , lower.String(), upper.String()) } } func Connect(ctx context.Context, connString string ) (*pgx.Conn, error ) { if conn, err := pgx.Connect(ctx, connString); err != nil { return nil , err } else { return conn, nil } } コード中の(1)で、値オブジェクトを引数にデータベースにINSERT文を発行しています。 デバッグ すると、以下のようにEncodeBinaryメソッドが呼び出されることが分かります。 (2)では、データベースから値を取得し、(3)でPrice値オブジェクトに読み込んでいます。 ここでは、Scanメソッドがドライバから呼び出されます。 構造体と結果セットを マッピング するライブラリを使えば、Entity構造体として以下のような実装も可能になります。 type UnitPrice struct { Id string `db:"id"` LowerPrice value.Price `db:"lower_price"` UpperPrice value.Price `db:"upper_price"` } 終わりに go言語で値オブジェクトを実装するための、一つの方法を紹介させていただきました。 全てstring, intなどのbuiltin型でいく戦略もあるので、これが正解と言うものではありません。 これからも試行錯誤しつつ、goでいろいろなアプリケーションを実装していきたいと思います。 最後までご覧になっていただき、誠にありがとうございました。 執筆: @mizuno.kazuhiro 、レビュー: @sato.taichi ( Shodo で執筆されました ) 個人利用は問題ありませんが、条件によっては2022年2月1日以降、有料になります。 https://www.docker.com/blog/updating-product-subscriptions/ ↩ https://github.com/lib/pq/blob/master/README.md#status ↩ https://pkg.go.dev/github.com/jackc/pgtype#example-package-CustomCompositeTypes ↩
アバター
これは 電通国際情報サービス アドベントカレンダー の17日目の記事です。 はじめに 開発環境 ValueObject(値オブジェクト)とは? 実装方針のアプローチ 構造体として実装し、フィールドに値を保持し、必要な機能をメソッドで外部公開する defined typeとして実装し、必要な機能をメソッドで外部公開する 両アプローチの考察 データベースへの永続化 Value関数 Scan関数 実際にRDBに永続化してみる 値オブジェクトの実装 DB永続化処理 終わりに はじめに みなさんこんにちは。 電通国際情報サービス (ISID) 金融ソリューション事業部の水野です。 今回は、値オブジェクトをgo言語でどのように実装したかをご紹介します。 値の生成から振る舞いの実装、データベースへの永続化の際に如何に透過的に扱うかまでを見ていきます。 開発環境 Visual Studio Code 1.62.2 go 1.17 Docker Desktop 4.2.0 (内包されているDocker CLI を利用) 1 ValueObject(値オブジェクト)とは? Martin Fowlerさんの エンタープライズ アプリケーションアーキテクチャパターン で紹介されたのが最初だと理解しています。 「値オブジェクトとは何か」についての深堀りも非常に興味深いテーマですが、今回は以下と定義します。 イミュータブルである 不変条件が定義されており、条件を満たさない値では生成できない 特定の属性で等価性が定義される 値だけでなく、自身に属する機能を公開する 実装方針のアプローチ 以下の2つのアプローチを検討しました。 構造体 として実装し、フィールドに値を保持し、必要な機能をメソッドで外部公開する defined type で実装し、必要な機能をメソッドで外部公開する 上記どちらのアプローチでも、共通する戦略は以下です。 生成時にバリデーションを行い、エラー時は値を生成せずにerrorを返す 真偽値を返す等価性判定関数を実装する 自身が保持する値を使った何らかの操作を、メソッドで外部公開する イミュータブルに実装する方法は、構造体の場合はフィールドをエクスポートせず、値取得用のメソッドを設けて実現します。 defined typeとして実装する場合、基底にする型がイミュータブルかどうかに依存します。 構造体の場合、ボイラープレートとして値取得メソッドが毎回必要になるため、割り切ってフィールドをエクスポートしても良いと考えます。 その他の違いとしては、構造体だと複数の値を保持しやすいですが、defined typeだと単一の値の取り扱いが基本になります。 defined typeでも別の変数を保持することは可能ですが、やはりstringのような型として扱いたくなるでしょう。 例として、算術演算や税率算出などの機能を持つ「価格」という値オブジェクトを1.と2.で考えてみます。 構造体として実装し、フィールドに値を保持し、必要な機能をメソッドで外部公開する type Price struct { value int64 } func NewPrice(v int64 ) (Price, error ) { if err := isValidPrice(v); err != nil { ・・・エラーの場合の処理 } func isValidPrice(v int64 ) error { ...値の範囲チェックなど } func (price Price) Equal(other Price) bool { return price.value == other.value } func (price Price) CalcTax(rate uint ) Tax { ...省略} func (price Price) calcInternal(rate uint ) Tax { ...省略} // 内部処理用 value という構造体のフィールドに値を格納します。 defined typeとして実装し、必要な機能をメソッドで外部公開する type Price int64 func NewPrice(v int64 ) (Price, error ) { if err := isValidPrice(v); err != nil { ・・・エラーの場合の処理 } func isValidPrice(v int64 ) error { ...値の範囲チェックなど } func (price Price) Equal(other Price) bool { return int64 (price) == int64 (other) } func (price Price) CalcTax(rate uint ) Tax { ...省略} func (price Price) calcInternal(rate uint ) Tax { ...省略} // 内部処理用 両アプローチの考察 構造体による実装だと、Entityのような他の構造体のフィールドとして使用すると、構造体がネストすることになります。 今回は、 RDB への永続化時のシンプルさや、 JSON フィールドとして用いる際の取りまわしやすさから、defined typeで実装し必要な機能をメソッドで外部公開する方式を選択しました。 また、ValueObjectとして等価判定メソッドを実装する上では、以下のようなインタフェースを導入しても良いでしょう。 type ValueObject interface { Equal(other interface {}) bool } go 1.17の時点では ジェネリクス が未導入のため、上記のインタフェースでは毎回キャストする必要があります。 func (price Price) Equal(other interface {}) bool { val, ok := other.(Price) return ok && int64 (price) == int64 (val) } 余談ですが、レシーバの変数名は https://github.com/golang/go/wiki/CodeReviewComments#receiver-names では「It can be very short」と、非常に短い略称が理由と共に推奨されています。 ですが、レシーバ変数は関数内のローカル変数のスコープとしては最も広いものとなります。 また、ループカウンタの i や j と重複して意図せぬ シャドウイング を誘発したりと、短い変数名がゆえの弊害もあります。 そのため、レシーバの変数名には1, 2文字の略称ではなく、意味のある名称を割り当てています。 データベースへの永続化 defined type として実装する場合、基底型によっては意図した永続化が出来ず、動作をカスタムしたくなるケースがあります。 その場合、 Valuer インタフェースと Scanner インタフェースを実装します。 Valuerインタフェースの Value 関数は、ドライバから呼び出され、DBカラム型に対応する型に変換する役割を担います。 ScannerインタフェースのScan関数は、DBから取得したカラムの値を自身型に変換するための関数で、定められた特定の型から、ValueObject型への変換を実装します。 では、具体的に見ていきましょう。 Value 関数 シグニチャ は Value() (Value, error) と、非常にシンプルです。 前出のPrice型で実装するなら以下となります。 func (price Price) Value() (driver.Value, error ) { val := int64 (price) if val == - 1 { return NaNPrice, エラーオブジェクト } return int64 (price), nil } 上述のような実装にする必要はありませんが、int64のようなビルトイン型ではなく、固定小数10進表現を利用するケースなども考えられるため、例として無効な値が入っていた場合に無効値とerrorを返す疑似コードにしています。 Scan関数 Scan関数は若干特殊な仕組みで、ポインタを介して値をやり取りします。 そのため、ポインタレシーバとして実装する必要があります。 func (price *Price) Scan(value interface {}) error { switch v := value.( type ) { case int64 : if p, err := NewPrice(v); err == nil { *price = p return nil } else { return err } default : return errInvalidPrice } } 実際に RDB に永続化してみる RDB はPostgresSQLを使います。 今回は、Docker Desktopに内包されているDocker CLI で、最新の公式イメージでホストしつつ、デフォルトのpostgres スキーマ を使いました。 実際の開発では、アプリケーション用の スキーマ を別途用意する方が良いでしょう。 詳細は割愛しますが、 docker pull でイメージをダウンロードした後、 docker run するだけですぐに使えます。 PostgreSQL に接続し、非常にシンプルな以下の単価テーブルを作成します。 CREATE TABLE unit_price ( id serial PRIMARY KEY , lower_price bigint NOT NULL , upper_price bigint NOT NULL ); これで準備が整いました。サンプルなので、テーブル物理設計の妥当性は無視します。 PostgresSQLに永続化するにあたって、ドライバには pgx を利用します。 他のドライバに lib/pq がありますが、現在メンテナンスモードに入っており、公式ドキュメントではアクティブにメンテナンスされているpgxの利用が推奨( 2 )されています。 PostgreSQL を使うなら、今はpgxを使うのが良いでしょう。 実装した値オブジェクト Price を永続化するコードサンプルです。 税の算出などの機能を持たせていますが、紙面の都合上 RateやTaxの実装は省略しています。 値オブジェクトの実装 const ( minPrice, maxPrice = 0 , 9999999999999 NaNPrice = Price(- 1 ) ) type Price int64 func NewPrice(v int64 ) (Price, error ) { if err := isValidPrice(v); err != nil { return NaNPrice, err } return Price(v), nil } var ( errOutOfRangePrice = errors.New( "Price is out of range" ) errInvalidPrice = errors.New( "invalid Price" ) ) func isValidPrice(v int64 ) error { if v < minPrice && maxPrice < v { return fmt.Errorf( "Price must be between %d and %d, but [%d]: %w" , minPrice, maxPrice, v, errOutOfRangePrice) } return nil } func (price Price) Equal(other Price) bool { return int64 (price) == int64 (other) } func (price Price) String() string { return strconv.FormatInt( int64 (price), 10 ) } func (price Price) CalcTax(rate Rate) Tax { tax := float64 (price) * rate.AsPercentage() return NewTax(math.Floor(tax)) } func (price Price) Value() (driver.Value, error ) { if err := isValidPrice( int64 (price)); err != nil { return NaNPrice, err } return int64 (price), nil } func (price *Price) Scan(value interface {}) error { switch v := value.( type ) { case int64 : if p, err := NewPrice(v); err == nil { *price = p return nil } else { return fmt.Errorf( "invalid value [%v]: %w" , v, errOutOfRangePrice) } default : return errInvalidPrice } } func (price Price) EncodeBinary(ci *pgtype.ConnInfo, buf [] byte ) ([] byte , error ) { var numeric pgtype.Int8 if err := numeric.Set( int64 (price)); err != nil { return nil , err } return numeric.EncodeBinary(ci, buf) } Equal、String、CalcTaxというメソッドを定義しているのが分かりますね。 以下、実装におけるポイントを記します。 CalcTaxが ドメイン 固有処理 Value 、Scanはデータベースアクセスのために必要なメソッド pgx でカスタムされた型を使用するにはEncodeBinaryが必要 ( 3 参考) なため実装している pgxドライバを使うために、 github .com/jackc/pgx/v4と github .com/jackc/pgtypeを go getしている DB永続化処理 値オブジェクトを PostgreSQL に永続化する実装です。(エラー処理は意図的に省略しています) func main() { ctx := context.TODO() conn, _ := Connect(ctx, "postgres://postgres:testpass1@localhost:5432/postgres" ) defer func () { conn.Close(ctx) }() argLower, _ := value.NewPrice( 1000 ) argUpper, _ := value.NewPrice( 2500 ) conn.Exec(ctx, "INSERT INTO unit_price (lower_price, upper_price) VALUES ($1, $2)" , argLower, argUpper) // (1)挿入 rows, _ := conn.Query(ctx, "SELECT lower_price, upper_price from unit_price" ) // (2)選択 defer func () { rows.Close() }() for rows.Next() { var lower, upper value.Price rows.Scan(&lower, &upper) // (3)変数へ読み込み fmt.Printf( "lowerPrice=[%s], upperPrice=[%s]" , lower.String(), upper.String()) } } func Connect(ctx context.Context, connString string ) (*pgx.Conn, error ) { if conn, err := pgx.Connect(ctx, connString); err != nil { return nil , err } else { return conn, nil } } コード中の(1)で、値オブジェクトを引数にデータベースにINSERT文を発行しています。 デバッグ すると、以下のようにEncodeBinaryメソッドが呼び出されることが分かります。 (2)では、データベースから値を取得し、(3)でPrice値オブジェクトに読み込んでいます。 ここでは、Scanメソッドがドライバから呼び出されます。 構造体と結果セットを マッピング するライブラリを使えば、Entity構造体として以下のような実装も可能になります。 type UnitPrice struct { Id string `db:"id"` LowerPrice value.Price `db:"lower_price"` UpperPrice value.Price `db:"upper_price"` } 終わりに go言語で値オブジェクトを実装するための、一つの方法を紹介させていただきました。 全てstring, intなどのbuiltin型でいく戦略もあるので、これが正解と言うものではありません。 これからも試行錯誤しつつ、goでいろいろなアプリケーションを実装していきたいと思います。 最後までご覧になっていただき、誠にありがとうございました。 執筆: @mizuno.kazuhiro 、レビュー: @sato.taichi ( Shodo で執筆されました ) 個人利用は問題ありませんが、条件によっては2022年2月1日以降、有料になります。 https://www.docker.com/blog/updating-product-subscriptions/ ↩ https://github.com/lib/pq/blob/master/README.md#status ↩ https://pkg.go.dev/github.com/jackc/pgtype#example-package-CustomCompositeTypes ↩
アバター
こんにちは、 電通国際情報サービス デジタル イノベーション 部の加世です。 昨今は、コンテナアプリケーション開発が主流であり、コンテナ オーケストレーション を理解することは非常に重要であると考えています。 そこで、コンテナ オーケストレーション ツールである「 Kubernetes 」をマネージド・サービス化した「 Amazon EKS」を題材として、 Amazon EKSの クラスタ ー認証・認可について理解します。 Kubernetes は、カスタマイズ性の高いコンテナ オーケストレーション ツールです。 正しく設計すれば「マイクロサービス化」「リソース最適化」「リリース最適化」「耐障害性に関わる制御の最適化」などを1つの統合された仕組みで実現できます。 これは、非常に魅力的です。 また、アプリケーション開発者が主体となって、サービス構成変更・運用を進められる点も素晴らしいです。 下記のガートナープレスリリースのとおり、コンテナー化の増加とともにコンテナー管理の需要が高まると考えています。 Kubernetes のようなコンテナ オーケストレーション ツールを始めるなら「今」です。 ■ガートナー プレスリリース https://www.gartner.com/en/newsroom/press-releases/2020-06-25-gartner-forecasts-strong-revenue-growth-for-global-co https://www.gartner.co.jp/ja/newsroom/press-releases/pr-20211118 はじめに Amazon EKSのクラスター認証・認可の概要について 認証 認可 検証環境の準備 Cognito構築 CloudShellの事前準備 EKS構築 「ClusterRoleBinding」によるRBAC認可の設定 OIDC認証で取得したトークンを利用したAPI操作 まとめ はじめに Amazon EKS クラスタ ー認証には「IAMによる認証(本記事では便宜上この方式を aws -auth 方式と呼びます)」「OIDCプロバイダーによる認証」の2つの方式があります。 本記事は、このうち以下の内容を記載します。 Amazon EKSの クラスタ ー認証・認可の概要を説明します。 Amazon EKSの「 OpenID Connect(OIDC)」認証の検証環境を構築します。 「OIDC」認証後に Kubernetes の API 操作ができることを確認します。 Amazon EKSの クラスタ ー認証・認可の概要について Amazon EKSの クラスタ ー認証・認可の概要を説明します。 Kubernetes コンポーネント と認証・認可の基礎は、下記リンク先を参照してください。 ■ Kubernetes の コンポーネント https://kubernetes.io/ja/docs/concepts/overview/components/ ■認証 https://kubernetes.io/ja/docs/reference/access-authn-authz/authentication ■RBAC認可を使用する https://kubernetes.io/ja/docs/reference/access-authn-authz/rbac 認証 Amazon EKS クラスタ ー認証は、「 aws -auth」「OIDC」の2つの方式があります。 IAMによる認証( aws -auth) ■ クラスタ ーのユーザーまたは IAM ロールの管理 https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/add-user-role.html Amazon EKSは、デフォルト設定でIAMユーザー/IAMロールに基づく認証機能が組み込まれています。 機能仕様は、 aws eks get-token コマンドで取得した トーク ンを「kube-apiserver」に渡して認証します。 ※Auditログを確認した限りでは、 ブラックボックス 化されたコン トロール プレーン内の「 kubernetes - aws -authenticator」プロセスが トーク ンを検証しているものと推察しています。なお、 AWS マニュアルに詳細な仕様は公開されていません。 OIDCプロバイダーによる認証 ■ OpenID Connect ID プロバイダーから クラスタ ーのユーザーを認証する https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/authenticate-oidc-identity-provider.html OIDCプロバイダーを用意して、「kube-apiserver」自体のOIDC認証機能(標準機能)を利用します。 複数 AWS アカウントで Amazon EKSを含めたサービスを運用する場合は、一元的なID統制・管理を目指すことによるメリットが大きくなるためこちらを検討します。 ※ Kubernetes 専用のOIDCプロバイダーになってしまう場合は、今後のID統合方針や運用コストなどを考慮して採用を検討します。 認可 認証が完了したら、「kube-apiserver」は次に Kubernetes の API 操作を許可するかをRBACで判断します。 その際に使用されるのが「Role/ClusterRole」「RoleBinding/ClusterRoleBinding」です。 なお、 Amazon EKSの認可は「 Kubernetes の認可」と同様です。 そのため、本記事では説明を省きます。 検証環境の準備 では、ここからOIDCを利用した Amazon EKS クラスタ ー認証を実際に試してみたいと思います。 検証環境は、下記の AWS Blogを参考に構築します。 なお、 AWS サービス(東京リージョン内)のみで検証を完了できるように構成しています。 ■ AWS Blog https://aws.amazon.com/jp/blogs/containers/introducing-oidc-identity-provider-authentication-amazon-eks 検証環境の構成 ※最低限の コンポーネント のみを示しています。 AWS サービス Amazon VPC 事前に、任意の VPC ネットワークを作成した状態を前提とします。 AWS IAM 事前に、EKSを初期作成するためのユーザー作成と権限付与をした状態を前提とします。 Amazon Cognito (User Pool) 補足情報を後述します。 Amazon EKS (ver 1.21) 補足情報を後述します。 ※ワーカーノードは不要です。 CloudShell (EKS API 操作用) 補足情報を後述します。 ※最近 AWS 管理コンソールのホーム画面のインタフェースアップデートがあり、ホーム画面の右上のアイコンからすぐに起動できます。 Cognito構築 AWS のマネジメントコンソールから、OIDCプロバイダーとなるCognitoユーザープールを作成します。 ※「Cognitoフェデレーティッド IDプール」の整備は不要です。 サインインエクス ペリエ ンスを設定 「Cognito ユーザープールのサインインオプション」は「Eメール」のみを指定します。 セキュリティ要件を設定 検証のため、「パスワードポリシー」「多要素認証」は任意設定で問題ありません。 検証のため、「ユーザーアカウントの復旧」は、デフォルト設定で問題ありません。 サインアップエクス ペリエ ンスを設定 検証のため、「自己登録」は無効化します。 検証のため「Cognito が検証と確認のためにメッセージを自動的に送信することを許可」の設定は無効化します。 必須の属性は自動的に「email」が設定されるため、追加の必須属性・カスタム属性は設定不要です。 メッセージ配信を設定 「Cognito で E メールを送信」を設定して、デフォルト設定で問題ありません。 アプリケーションを統合 「ユーザープール名」は、任意設定で問題ありません。 「ホストされた認証ページ」は、「Cognito のホストされた UI を使用」「Cognito ドメイン を使用する」を有効化しつつ、任意の ドメイン 名を登録します。 「最初のアプリケーションクライアント」は、検証のため「パブリッククライアント(クライアントシークレットなし)」を設定します。 ※「秘密クライアント(クライアントシークレットあり)」を選択した場合は、OIDC認証時にクライアントシークレット情報が必要となり、後述する手順では情報不足になりますが本記事では割愛します。 「アプリケーションクライアント名」は、任意設定で問題ありません。 「許可されているコールバックURL」は、検証のため「 http://localhost 」を設定します。 「高度なアプリケーションクライアントの設定」は、検証のため以下の「認証フロー」「 OpenID 接続スコープ」を設定します。 認証フロー ALLOW_REFRESH_TOKEN_AUTH(自動設定) ALLOW_ADMIN_USER_PASSWORD_AUTH ALLOW_USER_PASSWORD_AUTH OpenID 接続スコープ E メール(email) OpenID ( openid ) プロファイル(profile) ※それ以外は、検証のためデフォルト設定で問題ありません。 Cognito管理コンソールから作成された「ユーザープールID」「クライアントID」を控えます。 txt プールID : ap-northeast-1_XXXXXXXXX クライアントID : 1abc7efgh6xxxxxxxxxxx11ab1 CognitoユーザープールのOpen IDプロバイダー設定情報( OpenID Provider Configuration Information)を確認します。 ※本記事ではCognitoの「issuer」の情報のみ利用しますが、すぐに特定できるため確認はスキップ可能です。 ※Cognito以外のOpen IDプロバイダーを利用する場合は、Open IDプロバイダー設定情報を確認することが多いです。 txt https://cognito-idp.ap-northeast-1.amazonaws.com/<ユーザープールID>/.well-known/openid-configuration issuer txt https://cognito-idp.ap-northeast-1.amazonaws.com/<ユーザープールID>/ Cognitoグループ Cognito管理コンソールから「admin」グループを作成します。 ※cognitoグループに対して、IAMロールの設定は不要です。 Cognitoユーザ Eメールを受信可能なメールアドレスを利用して、ユーザーを登録します。 その際に、「E メールで招待を送信」を選択した場合は、登録したEメールにメッセージが送信されます。 Cognitoグループにユーザーを追加 [4.]の手順で作成したCognitoグループに[5.]で作成したユーザーを追加します。 Cognito管理コンソール上から「アプリケーションクライアント」の設定を表示し、「ホストされた UI」から「ホストされた UIを表示」ボタンを押下してCognito専用のログイン画面を表示します。 Cognito専用ログイン画面が表示されるため、作成したCognitoユーザーでログインして初期パスワードを変更します。 認証後はCallBack URLで指定した「locahost」のURLが表示され、「Not Found」になります。 検証はこの結果で問題なく、パスワード変更と認証完了を確認したことになります。 CloudShellの事前準備 CloudShellは、 Amazon Linux2ベースのクライアントとして利用可能です。 いくつか利用上の注意点はあります。 最低限の条件 IAMユーザー(または、スイッチ先のIAMロール)にcloudshellの操作権限が必要です。 セッション数に制限はありますが、無料です。 「/home/<ユーザ>」配下が永続データ領域となり、1GB制限があります。 必要なモジュールのインストール ■kubectl https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/install-kubectl.html こちらのマニュアルを参照して「/home/<ユーザ>」配下にkubectlを導入します。 ※ AWS CLI 含めて、いくつか必要なモジュールはデフォルトで使用可能です。 AWS CLI 経由でCognitoのユーザー認証& トーク ン取得 OIDCプロバイダーとなるCognitoで認証しつつ、リフレッシュ トーク ン・ID トーク ンを取得します。 この トーク ンは、 Kubernetes の「kube-apiserver」に連携するものです。 また、ID トーク ン(ヘッダー、 ペイロード 、署名が Base64 化されたもの)の ペイロード からユーザーの属性情報を確認することがポイントです。 特に、本記事では所属グループとなるcognito:groupsの「admin」に属していることを確認します。 OIDCに関する情報 sh ACCOUNT_ID="123456789123" REGION="ap-northeast-1" USERPOOL_ID="ap-northeast-1_XXXXXXXXX" ISSUER_URL="https://cognito-idp.${REGION}.amazonaws.com/${USERPOOL_ID}" CLIENT_ID="5abc7ufem9hpagvidrafo11ce1" USERNAME="kase.teruyoshi@isid.co.jp" PASSWORD="InitPassword" OIDC認証でリフレッシュ トーク ン、ID トーク ンを取得 ``sh tokenInfo= aws cognito-idp --region ${REGION} admin-initiate-auth --auth-flow ADMIN_USER_PASSWORD_AUTH --client-id ${CLIENT_ID} --user-pool-id ${USERPOOL_ID} --auth-parameters USERNAME=${USERNAME},PASSWORD=${PASSWORD} --query 'AuthenticationResult.{RefreshToken:RefreshToken, IdToken:IdToken}' refreshToken= echo ${tokenInfo} | jq -r .RefreshToken idToken= echo ${tokenInfo} | jq -r .IdToken` echo $refreshToken echo $idToken ``` ID トーク ンから ペイロード を確認 コマンド ``sh idTokenHeader= echo $idToken | cut -f 1 -d. | base64 --decode idTokenPayload= echo $idToken | cut -f 2 -d. | base64 --decode` echo $idTokenHeader | jq echo $idTokenPayload | jq ``` 実行結果 ``` [cloudshell-user@ip-10-0-107-185 ~]$ echo $idTokenHeader | jq { "kid": "lxZZOgtZffh16NGpS8a6IM9J5zu3KmkcbLnkDQ9/MCY=", "alg": "RS256" } [cloudshell-user@ip-10-0-107-185 ~]$ echo $idTokenPayload | jq { "sub": "abc4d541-e6f1-45g0-h6c1-184b36f52cf6", "cognito:groups": [ "admin" ], "email_verified": true, " iss ": " https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_XXXXXXXXX ", "cognito:username": "abc4d541-e6f1-45g0-h6c1-184b36f52cf6", "origin_jti": "5abc2d90-e3f4-455g-94h8-6cd7909f2059", "aud": "5abc7ufem9hpagvidrafo11ce1", "event_id": "8765f9f9-999c-10e5-8a13-c44a68c8ed33", "token_use": "id", "auth_time": 1637655335, "name": "kase.teruyoshi@isid.co.jp", "exp": 1637658935, "iat": 1637655335, "jti": "568d2c50-544c-4fa8-92d0-9dc9cac2d2cb", "email": "kase.teruyoshi@isid.co.jp" } ``` EKS構築 EKS クラスタ ー「poc-eks-cluster-dev」を作成します。 検証環境のため、パブリック API エンドポイントは作成します。 Cloudshellを使用する都合で、パブリック API エンドポイントに対するアクセス元の制限はしません。 EKSを作成したIAMユーザー(またはIAMロール)で「 aws -auth」認証が登録されます。 今まで得た情報を元にOIDCプロバイダーを Amazon EKSの クラスタ ーに関連付けます。 ■ AWS Blog https://aws.amazon.com/jp/blogs/containers/introducing-oidc-identity-provider-authentication-amazon-eks こちらを参考に設定します。 なお、追加設定で20~40分程度かかることと、変更は再作成となるためおよそ2倍の時間が必要になります。 これにより、 Amazon EKS内の「kube-apiserver」にOIDCプロバイダー情報が登録されます。 これで、「kube-apiserver」側で トーク ン検証できる準備が整います。 「ClusterRoleBinding」によるRBAC認可の設定 CloudShell上でkubectlコマンドを実行して、ClusterRoleBinding「admin-role-binding」を作成します。 この段階では、「 aws -auth」認証を使用します。 AWS Blogでは「secret-reader」に対応するClusterRoleを作成しています。 本記事は、簡略化のため既にデフォルトで作成されているClusterRole「cluster-admin」を利用します。 ※「cluster-admin」は、操作権限の範囲が大きいため運用時は注意してください。 また、subjectセクションは、Cognitoユーザーが属するグループ「admin」を設定します。 この際、「kube-apiserver」にOIDCプロバイダーを登録したGroup Prefix「 gid :」を考慮して「 gid :admin」とします。 --- apiVersion : rbac.authorization.k8s.io/v1 kind : ClusterRoleBinding metadata : name : admin-role-binding namespace : default roleRef : apiGroup : rbac.authorization.k8s.io kind : ClusterRole name : cluster-admin subjects : - apiGroup : rbac.authorization.k8s.io kind : Group name : "gid:admin" OIDC認証で取得した トーク ンを利用した API 操作 「CloudShellの事前準備」の章の「OIDC認証でリフレッシュ トーク ン、ID トーク ンを取得」を実施して、再度 トーク ンを取得します。 その後、以下のとおりkubectl側で「kube-apiserver」に トーク ンを渡す準備をしたあと、自由にkubectlコマンドを実行してみてください。 ※今回、RBAC認可に使用した「cluster-admin」は強力な権限のため、ほとんどの操作ができます。 kube-config初期設定 sh aws eks --region ap-northeast-1 update-kubeconfig --name poc-eks-cluster-dev kubectl config get-contexts kubectl トーク ン設定 credentials設定 sh kubectl config set-credentials cognito-user --auth-provider=oidc --auth-provider-arg=idp-issuer-url=${ISSUER_URL} --auth-provider-arg=client-id=${CLIENT_ID} --auth-provider-arg=refresh-token=${refreshToken} --auth-provider-arg=id-token=${idToken} context設定 sh kubectl config set-context cognito-user-login --cluster arn:aws:eks:ap-northeast-1:${ACCOUNT_ID}:cluster/poc-eks-cluster-dev --user cognito-user context切替 sh kubectl config use-context cognito-user-login kubectl config get-contexts kubectlコマンドで API 実行結果 Amazon EKSにデフォルトで設定されている「ConfigMap」の情報を API で取得します。 sh [cloudshell-user@ip-10-0-107-185 ~]$ kubectl get configmap -n kube-system NAME DATA AGE aws-auth 1 6d6h   まとめ 本記事では、 Amazon EKSのOIDC認証を AWS サービスのみで検証しました。 OIDCプロバイダーは、一般的には SaaS サービス( Google 、Azure AD、Okta...etc)でID統合することになります。 本記事では触れていませんが、様々なクライアントツールを活用してログイン認証画面(本記事では「Cognito のホストされた UI 」)を経由して認証をさせることもできます。 また、本日使用した「cluster-admin」はデフォルトのClusterRoleであり、 API 操作の許可範囲が大きいものになります。 そのため、操作可能な 名前空間 ・リソース・アクションなどを正しく設計して、ID管理されたユーザー(または、ユーザー属性情報)に対して適切に付与することが重要になります。 執筆: @kase.teruyoshi 、レビュー: @shibata.takao ( Shodo で執筆されました )
アバター
こんにちは、 電通国際情報サービス デジタル イノベーション 部の加世です。 昨今は、コンテナアプリケーション開発が主流であり、コンテナ オーケストレーション を理解することは非常に重要であると考えています。 そこで、コンテナ オーケストレーション ツールである「 Kubernetes 」をマネージド・サービス化した「 Amazon EKS」を題材として、 Amazon EKSの クラスタ ー認証・認可について理解します。 Kubernetes は、カスタマイズ性の高いコンテナ オーケストレーション ツールです。 正しく設計すれば「マイクロサービス化」「リソース最適化」「リリース最適化」「耐障害性に関わる制御の最適化」などを1つの統合された仕組みで実現できます。 これは、非常に魅力的です。 また、アプリケーション開発者が主体となって、サービス構成変更・運用を進められる点も素晴らしいです。 下記のガートナープレスリリースのとおり、コンテナー化の増加とともにコンテナー管理の需要が高まると考えています。 Kubernetes のようなコンテナ オーケストレーション ツールを始めるなら「今」です。 ■ガートナー プレスリリース https://www.gartner.com/en/newsroom/press-releases/2020-06-25-gartner-forecasts-strong-revenue-growth-for-global-co https://www.gartner.co.jp/ja/newsroom/press-releases/pr-20211118 はじめに Amazon EKSのクラスター認証・認可の概要について 認証 認可 検証環境の準備 Cognito構築 CloudShellの事前準備 EKS構築 「ClusterRoleBinding」によるRBAC認可の設定 OIDC認証で取得したトークンを利用したAPI操作 まとめ はじめに Amazon EKS クラスタ ー認証には「IAMによる認証(本記事では便宜上この方式を aws -auth 方式と呼びます)」「OIDCプロバイダーによる認証」の2つの方式があります。 本記事は、このうち以下の内容を記載します。 Amazon EKSの クラスタ ー認証・認可の概要を説明します。 Amazon EKSの「 OpenID Connect(OIDC)」認証の検証環境を構築します。 「OIDC」認証後に Kubernetes の API 操作ができることを確認します。 Amazon EKSの クラスタ ー認証・認可の概要について Amazon EKSの クラスタ ー認証・認可の概要を説明します。 Kubernetes コンポーネント と認証・認可の基礎は、下記リンク先を参照してください。 ■ Kubernetes の コンポーネント https://kubernetes.io/ja/docs/concepts/overview/components/ ■認証 https://kubernetes.io/ja/docs/reference/access-authn-authz/authentication ■RBAC認可を使用する https://kubernetes.io/ja/docs/reference/access-authn-authz/rbac 認証 Amazon EKS クラスタ ー認証は、「 aws -auth」「OIDC」の2つの方式があります。 IAMによる認証( aws -auth) ■ クラスタ ーのユーザーまたは IAM ロールの管理 https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/add-user-role.html Amazon EKSは、デフォルト設定でIAMユーザー/IAMロールに基づく認証機能が組み込まれています。 機能仕様は、 aws eks get-token コマンドで取得した トーク ンを「kube-apiserver」に渡して認証します。 ※Auditログを確認した限りでは、 ブラックボックス 化されたコン トロール プレーン内の「 kubernetes - aws -authenticator」プロセスが トーク ンを検証しているものと推察しています。なお、 AWS マニュアルに詳細な仕様は公開されていません。 OIDCプロバイダーによる認証 ■ OpenID Connect ID プロバイダーから クラスタ ーのユーザーを認証する https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/authenticate-oidc-identity-provider.html OIDCプロバイダーを用意して、「kube-apiserver」自体のOIDC認証機能(標準機能)を利用します。 複数 AWS アカウントで Amazon EKSを含めたサービスを運用する場合は、一元的なID統制・管理を目指すことによるメリットが大きくなるためこちらを検討します。 ※ Kubernetes 専用のOIDCプロバイダーになってしまう場合は、今後のID統合方針や運用コストなどを考慮して採用を検討します。 認可 認証が完了したら、「kube-apiserver」は次に Kubernetes の API 操作を許可するかをRBACで判断します。 その際に使用されるのが「Role/ClusterRole」「RoleBinding/ClusterRoleBinding」です。 なお、 Amazon EKSの認可は「 Kubernetes の認可」と同様です。 そのため、本記事では説明を省きます。 検証環境の準備 では、ここからOIDCを利用した Amazon EKS クラスタ ー認証を実際に試してみたいと思います。 検証環境は、下記の AWS Blogを参考に構築します。 なお、 AWS サービス(東京リージョン内)のみで検証を完了できるように構成しています。 ■ AWS Blog https://aws.amazon.com/jp/blogs/containers/introducing-oidc-identity-provider-authentication-amazon-eks 検証環境の構成 ※最低限の コンポーネント のみを示しています。 AWS サービス Amazon VPC 事前に、任意の VPC ネットワークを作成した状態を前提とします。 AWS IAM 事前に、EKSを初期作成するためのユーザー作成と権限付与をした状態を前提とします。 Amazon Cognito (User Pool) 補足情報を後述します。 Amazon EKS (ver 1.21) 補足情報を後述します。 ※ワーカーノードは不要です。 CloudShell (EKS API 操作用) 補足情報を後述します。 ※最近 AWS 管理コンソールのホーム画面のインタフェースアップデートがあり、ホーム画面の右上のアイコンからすぐに起動できます。 Cognito構築 AWS のマネジメントコンソールから、OIDCプロバイダーとなるCognitoユーザープールを作成します。 ※「Cognitoフェデレーティッド IDプール」の整備は不要です。 サインインエクス ペリエ ンスを設定 「Cognito ユーザープールのサインインオプション」は「Eメール」のみを指定します。 セキュリティ要件を設定 検証のため、「パスワードポリシー」「多要素認証」は任意設定で問題ありません。 検証のため、「ユーザーアカウントの復旧」は、デフォルト設定で問題ありません。 サインアップエクス ペリエ ンスを設定 検証のため、「自己登録」は無効化します。 検証のため「Cognito が検証と確認のためにメッセージを自動的に送信することを許可」の設定は無効化します。 必須の属性は自動的に「email」が設定されるため、追加の必須属性・カスタム属性は設定不要です。 メッセージ配信を設定 「Cognito で E メールを送信」を設定して、デフォルト設定で問題ありません。 アプリケーションを統合 「ユーザープール名」は、任意設定で問題ありません。 「ホストされた認証ページ」は、「Cognito のホストされた UI を使用」「Cognito ドメイン を使用する」を有効化しつつ、任意の ドメイン 名を登録します。 「最初のアプリケーションクライアント」は、検証のため「パブリッククライアント(クライアントシークレットなし)」を設定します。 ※「秘密クライアント(クライアントシークレットあり)」を選択した場合は、OIDC認証時にクライアントシークレット情報が必要となり、後述する手順では情報不足になりますが本記事では割愛します。 「アプリケーションクライアント名」は、任意設定で問題ありません。 「許可されているコールバックURL」は、検証のため「 http://localhost 」を設定します。 「高度なアプリケーションクライアントの設定」は、検証のため以下の「認証フロー」「 OpenID 接続スコープ」を設定します。 認証フロー ALLOW_REFRESH_TOKEN_AUTH(自動設定) ALLOW_ADMIN_USER_PASSWORD_AUTH ALLOW_USER_PASSWORD_AUTH OpenID 接続スコープ E メール(email) OpenID ( openid ) プロファイル(profile) ※それ以外は、検証のためデフォルト設定で問題ありません。 Cognito管理コンソールから作成された「ユーザープールID」「クライアントID」を控えます。 txt プールID : ap-northeast-1_XXXXXXXXX クライアントID : 1abc7efgh6xxxxxxxxxxx11ab1 CognitoユーザープールのOpen IDプロバイダー設定情報( OpenID Provider Configuration Information)を確認します。 ※本記事ではCognitoの「issuer」の情報のみ利用しますが、すぐに特定できるため確認はスキップ可能です。 ※Cognito以外のOpen IDプロバイダーを利用する場合は、Open IDプロバイダー設定情報を確認することが多いです。 txt https://cognito-idp.ap-northeast-1.amazonaws.com/<ユーザープールID>/.well-known/openid-configuration issuer txt https://cognito-idp.ap-northeast-1.amazonaws.com/<ユーザープールID>/ Cognitoグループ Cognito管理コンソールから「admin」グループを作成します。 ※cognitoグループに対して、IAMロールの設定は不要です。 Cognitoユーザ Eメールを受信可能なメールアドレスを利用して、ユーザーを登録します。 その際に、「E メールで招待を送信」を選択した場合は、登録したEメールにメッセージが送信されます。 Cognitoグループにユーザーを追加 [4.]の手順で作成したCognitoグループに[5.]で作成したユーザーを追加します。 Cognito管理コンソール上から「アプリケーションクライアント」の設定を表示し、「ホストされた UI」から「ホストされた UIを表示」ボタンを押下してCognito専用のログイン画面を表示します。 Cognito専用ログイン画面が表示されるため、作成したCognitoユーザーでログインして初期パスワードを変更します。 認証後はCallBack URLで指定した「locahost」のURLが表示され、「Not Found」になります。 検証はこの結果で問題なく、パスワード変更と認証完了を確認したことになります。 CloudShellの事前準備 CloudShellは、 Amazon Linux2ベースのクライアントとして利用可能です。 いくつか利用上の注意点はあります。 最低限の条件 IAMユーザー(または、スイッチ先のIAMロール)にcloudshellの操作権限が必要です。 セッション数に制限はありますが、無料です。 「/home/<ユーザ>」配下が永続データ領域となり、1GB制限があります。 必要なモジュールのインストール ■kubectl https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/install-kubectl.html こちらのマニュアルを参照して「/home/<ユーザ>」配下にkubectlを導入します。 ※ AWS CLI 含めて、いくつか必要なモジュールはデフォルトで使用可能です。 AWS CLI 経由でCognitoのユーザー認証& トーク ン取得 OIDCプロバイダーとなるCognitoで認証しつつ、リフレッシュ トーク ン・ID トーク ンを取得します。 この トーク ンは、 Kubernetes の「kube-apiserver」に連携するものです。 また、ID トーク ン(ヘッダー、 ペイロード 、署名が Base64 化されたもの)の ペイロード からユーザーの属性情報を確認することがポイントです。 特に、本記事では所属グループとなるcognito:groupsの「admin」に属していることを確認します。 OIDCに関する情報 sh ACCOUNT_ID="123456789123" REGION="ap-northeast-1" USERPOOL_ID="ap-northeast-1_XXXXXXXXX" ISSUER_URL="https://cognito-idp.${REGION}.amazonaws.com/${USERPOOL_ID}" CLIENT_ID="5abc7ufem9hpagvidrafo11ce1" USERNAME="kase.teruyoshi@isid.co.jp" PASSWORD="InitPassword" OIDC認証でリフレッシュ トーク ン、ID トーク ンを取得 ``sh tokenInfo= aws cognito-idp --region ${REGION} admin-initiate-auth --auth-flow ADMIN_USER_PASSWORD_AUTH --client-id ${CLIENT_ID} --user-pool-id ${USERPOOL_ID} --auth-parameters USERNAME=${USERNAME},PASSWORD=${PASSWORD} --query 'AuthenticationResult.{RefreshToken:RefreshToken, IdToken:IdToken}' refreshToken= echo ${tokenInfo} | jq -r .RefreshToken idToken= echo ${tokenInfo} | jq -r .IdToken` echo $refreshToken echo $idToken ``` ID トーク ンから ペイロード を確認 コマンド ``sh idTokenHeader= echo $idToken | cut -f 1 -d. | base64 --decode idTokenPayload= echo $idToken | cut -f 2 -d. | base64 --decode` echo $idTokenHeader | jq echo $idTokenPayload | jq ``` 実行結果 ``` [cloudshell-user@ip-10-0-107-185 ~]$ echo $idTokenHeader | jq { "kid": "lxZZOgtZffh16NGpS8a6IM9J5zu3KmkcbLnkDQ9/MCY=", "alg": "RS256" } [cloudshell-user@ip-10-0-107-185 ~]$ echo $idTokenPayload | jq { "sub": "abc4d541-e6f1-45g0-h6c1-184b36f52cf6", "cognito:groups": [ "admin" ], "email_verified": true, " iss ": " https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_XXXXXXXXX ", "cognito:username": "abc4d541-e6f1-45g0-h6c1-184b36f52cf6", "origin_jti": "5abc2d90-e3f4-455g-94h8-6cd7909f2059", "aud": "5abc7ufem9hpagvidrafo11ce1", "event_id": "8765f9f9-999c-10e5-8a13-c44a68c8ed33", "token_use": "id", "auth_time": 1637655335, "name": "kase.teruyoshi@isid.co.jp", "exp": 1637658935, "iat": 1637655335, "jti": "568d2c50-544c-4fa8-92d0-9dc9cac2d2cb", "email": "kase.teruyoshi@isid.co.jp" } ``` EKS構築 EKS クラスタ ー「poc-eks-cluster-dev」を作成します。 検証環境のため、パブリック API エンドポイントは作成します。 Cloudshellを使用する都合で、パブリック API エンドポイントに対するアクセス元の制限はしません。 EKSを作成したIAMユーザー(またはIAMロール)で「 aws -auth」認証が登録されます。 今まで得た情報を元にOIDCプロバイダーを Amazon EKSの クラスタ ーに関連付けます。 ■ AWS Blog https://aws.amazon.com/jp/blogs/containers/introducing-oidc-identity-provider-authentication-amazon-eks こちらを参考に設定します。 なお、追加設定で20~40分程度かかることと、変更は再作成となるためおよそ2倍の時間が必要になります。 これにより、 Amazon EKS内の「kube-apiserver」にOIDCプロバイダー情報が登録されます。 これで、「kube-apiserver」側で トーク ン検証できる準備が整います。 「ClusterRoleBinding」によるRBAC認可の設定 CloudShell上でkubectlコマンドを実行して、ClusterRoleBinding「admin-role-binding」を作成します。 この段階では、「 aws -auth」認証を使用します。 AWS Blogでは「secret-reader」に対応するClusterRoleを作成しています。 本記事は、簡略化のため既にデフォルトで作成されているClusterRole「cluster-admin」を利用します。 ※「cluster-admin」は、操作権限の範囲が大きいため運用時は注意してください。 また、subjectセクションは、Cognitoユーザーが属するグループ「admin」を設定します。 この際、「kube-apiserver」にOIDCプロバイダーを登録したGroup Prefix「 gid :」を考慮して「 gid :admin」とします。 --- apiVersion : rbac.authorization.k8s.io/v1 kind : ClusterRoleBinding metadata : name : admin-role-binding namespace : default roleRef : apiGroup : rbac.authorization.k8s.io kind : ClusterRole name : cluster-admin subjects : - apiGroup : rbac.authorization.k8s.io kind : Group name : "gid:admin" OIDC認証で取得した トーク ンを利用した API 操作 「CloudShellの事前準備」の章の「OIDC認証でリフレッシュ トーク ン、ID トーク ンを取得」を実施して、再度 トーク ンを取得します。 その後、以下のとおりkubectl側で「kube-apiserver」に トーク ンを渡す準備をしたあと、自由にkubectlコマンドを実行してみてください。 ※今回、RBAC認可に使用した「cluster-admin」は強力な権限のため、ほとんどの操作ができます。 kube-config初期設定 sh aws eks --region ap-northeast-1 update-kubeconfig --name poc-eks-cluster-dev kubectl config get-contexts kubectl トーク ン設定 credentials設定 sh kubectl config set-credentials cognito-user --auth-provider=oidc --auth-provider-arg=idp-issuer-url=${ISSUER_URL} --auth-provider-arg=client-id=${CLIENT_ID} --auth-provider-arg=refresh-token=${refreshToken} --auth-provider-arg=id-token=${idToken} context設定 sh kubectl config set-context cognito-user-login --cluster arn:aws:eks:ap-northeast-1:${ACCOUNT_ID}:cluster/poc-eks-cluster-dev --user cognito-user context切替 sh kubectl config use-context cognito-user-login kubectl config get-contexts kubectlコマンドで API 実行結果 Amazon EKSにデフォルトで設定されている「ConfigMap」の情報を API で取得します。 sh [cloudshell-user@ip-10-0-107-185 ~]$ kubectl get configmap -n kube-system NAME DATA AGE aws-auth 1 6d6h   まとめ 本記事では、 Amazon EKSのOIDC認証を AWS サービスのみで検証しました。 OIDCプロバイダーは、一般的には SaaS サービス( Google 、Azure AD、Okta...etc)でID統合することになります。 本記事では触れていませんが、様々なクライアントツールを活用してログイン認証画面(本記事では「Cognito のホストされた UI 」)を経由して認証をさせることもできます。 また、本日使用した「cluster-admin」はデフォルトのClusterRoleであり、 API 操作の許可範囲が大きいものになります。 そのため、操作可能な 名前空間 ・リソース・アクションなどを正しく設計して、ID管理されたユーザー(または、ユーザー属性情報)に対して適切に付与することが重要になります。 執筆: @kase.teruyoshi 、レビュー: @shibata.takao ( Shodo で執筆されました )
アバター