APC 技術ブログ

株式会社エーピーコミュニケーションズの技術ブログです。

株式会社 エーピーコミュニケーションズの技術ブログです。

Bicepで新しい関数 deployer() が追加されました

みなさんこんにちは。ACS事業部の亀崎です。

2024年12月に公開されたAzure Bicep v0.32で、便利な関数がひとつ追加されました。それが deployer() です。

learn.microsoft.com

通常BicepでAzure Resourceをデプロイする際は、作成・更新権限を持っていると思います。このためリソースオーナーなどの指定は必要ないことが多いです。しかし、それらのリソースの中のデータ(たとえばBlob Storageに配置するデータそのものの参照・更新権や、Keyvaultのシークレットそのものへのアクセス権)に対しては権限が付与されていません。このため、明示的に権限を付与するなどを行う必要があります。これまではそのために自身のObject Idなどを調べて明示的に設定していました。

こういった場合に活躍するのが deployer() 関数です。この関数はそのBicepを実行しているユーザーやサービスプリンシパルの情報を取得するものです。deployer()の実行結果は次のようなものになります。

{
  "objectId": "principal-object-id",
  "tenantId": "prncipal-tenant-id"
}

これを活用して、KeyVaultやBlob Storageなどのデータアクセス権を自分自身に付与することが簡単になります。 たとえば次のように利用します。

var dataOwnerObjectId = deployer().objectId

Azure Resourceは作成したけど、データアクセス権の付与を忘れ、あとからAzure Portalなどで追加で付与するといったことを頻繁にしていた自分にとって、この機能はとても助かります。

ぜひみなさんも最新のBicepをご利用いただき、この機能を活用してください。

# Bicepのバージョン確認方法
az bicep version

# Bicepのアップデート
az bicep update

ネットワークセキュリティ境界でAzure PaaSのインターネットアクセスを制御しよう

こんにちは、ACS事業部の吉川です。

本記事は エーピーコミュニケーションズ Advent Calendar 2024 の14日目の記事です。

先月開催されたMicrosoft Igniteに合わせ ネットワークセキュリティ境界(Network Security Perimeter) なるサービスのパブリックプレビューが始まりました。
どんなサービスなのか、手を動かしながら確認してみましょう。

概要

サービスの概要を掴むために、まずは公式ドキュメントに目を通すのがよいでしょう。

learn.microsoft.com

こちらのドキュメントにある以下の図から、

  • 複数のPaaSを束ねてグループ化して
  • Internetや他サービスへのInbound/Outboundを制御する

というサービスだというのが見て取れます。

ざっくりと、従来は各サービスの設定にあったアクセス制限のルールをまとめて設定できるもの、と考えてよさそうです。

検証環境

以下のような検証環境を準備してみました。

VNetにサブネットを2つ作り、片方にVMを配置、もう片方にSQL DatabaseのPrivate Endpointを作成した構成です。 SQL Databaseを閉域接続するケースでは一般的な構成でしょう。

以下のコマンドで作成しています。

RG_NAME="rg-sample"
LOCATION="japaneast"
VNET_NAME="vnet-sample"
VM_SNET_NAME="snet-VM"
SQL_SNET_NAME="snet-SQL"
VM_NAME="sample-vm"
SQL_SERVER_NAME="sample-sql-server-hoge"
SQL_DB_NAME="sample-sql-db"

# リソースグループの作成
az group create -n $RG_NAME -l $LOCATION

# ネットワークの作成
az network vnet create -n $VNET_NAME -g $RG_NAME -l $LOCATION \
  --address-prefixes 192.168.0.0/16
az network vnet subnet create -n $VM_SNET_NAME \
  --vnet-name $VNET_NAME -g $RG_NAME \
  --address-prefixes 192.168.0.0/24
az network vnet subnet create -n $SQL_SNET_NAME \
  --vnet-name $VNET_NAME -g $RG_NAME \
  --address-prefixes 192.168.1.0/24

# VMの作成
az vm create -n $VM_NAME -g $RG_NAME --image Ubuntu2204 \
  --vnet-name $VNET_NAME --subnet $VM_SNET_NAME --public-ip-address "pip-sample" \
  --nsg "nsg-sample" --nsg-rule SSH 

# SQL Databaseの作成
az sql server create -n $SQL_SERVER_NAME -g $RG_NAME -u myadminuser -p myAdminpassword123

az sql db create -n $SQL_DB_NAME -g $RG_NAME --server $SQL_SERVER_NAME \
  --sample-name AdventureWorksLT --edition GeneralPurpose \
    --compute-model Serverless --family Gen5 --capacity 2

# Private EndpointとPrivate DNS Zoneの作成
ID=$(az sql server show -n $SQL_SERVER_NAME -g $RG_NAME --query id -o tsv)

az network private-endpoint create --connection-name connection-1 \
  -n private-endpoint -g $RG_NAME --private-connection-resource-id $ID \
  --vnet-name $VNET_NAME --subnet $SQL_SNET_NAME --group-ids sqlServer

az network private-dns zone create \
  -n "privatelink.database.windows.net" -g $RG_NAME

az network private-dns link vnet create \
  -n DNSLink -g $RG_NAME -v $VNET_NAME \
  -z "privatelink.database.windows.net" \
  --registration-enabled false

az network private-endpoint dns-zone-group create \
  -n MyZoneGroup -g $RG_NAME \
  --endpoint-name private-endpoint \
  --private-dns-zone "privatelink.database.windows.net" \
  --zone-name sql

このSQL Databaseに対し、ネットワークセキュリティ境界を設定していきます。
ネットワークセキュリティ境界はプレビュー扱いのサービスのため、有効化設定が必要です。 以下のコマンドで有効化します。

# ネットワークセキュリティ境界の有効化
az feature register --name AllowNSPInPublicPreview --namespace Microsoft.Network

# 有効化状態の確認。RegisteredになればOK。
az feature show --name AllowNSPInPublicPreview --namespace Microsoft.Network --output table

# 有効化を反映するためにMicrosoft.Networkプロバイダーを再登録
az provider register --namespace Microsoft.Network

有効化が完了したら、ネットワークセキュリティ境界のリソースを作成していきます。

NSP_NAME="nsp-sample"
PROFILE_NAME="npp-sample"

az network perimeter create -n $NSP_NAME -g $RG_NAME

az network perimeter profile create \
  -n $PROFILE_NAME -g $RG_NAME --perimeter-name $NSP_NAME 

上記のコマンドで、nsp-sample というネットワークセキュリティ境界 リソースと、npp-sample というポリシー定義が作成されます。

ここまでで環境の準備ができました。
続いて設定項目と挙動を見ていきましょう。

ネットワークセキュリティ境界 の設定

ネットワークセキュリティ境界は、作成したポリシーに対象となるPaaSリソースと受信/送信規則を登録して使用します。
受信・送信それぞれの設定を見ていきましょう。

受信規則の設定

前項で作成したSQL Databaseは、インターネットからのアクセスは許可されておらずPrivate Endpointからのみアクセス可能な状態です。
実際にインターネット越しにアクセスしてみると

Cannot open server 'sample-sql-server-hoge' requested by the login. Client with IP address '###.###.###.###' is not allowed to access the server. To enable access, use the Azure Management Portal or run sp_set_firewall_rule on the master database to create a firewall rule for this IP address or address range. It may take up to five minutes for this change to take effect.

といったエラーが表示されます。

このSQL Databaseをポリシーに追加してみましょう。
ポリシーの設定メニューの 関連するリソース から、リソースの関連付け ボタンでリソースを追加します。

リソースを追加すると、最初は Learning モードとして設定されます。

これは、ネットワークセキュリティ境界の通信規則を実際には適用せず、通信状態のモニタリングのみを行うモードです。WAFにおける検出モードのようなものですね。

このモードを Enforced に変更してみましょう。同画面の アクセスモードの変更 から変更できます。

現状は通信規則を一つも追加していない状態です。この状態でインターネット越しにSQL Databaseへのログインを試みると、以下のようにエラーメッセージが変わっていることが確認できます。

Login failed because the network security perimeter denied inbound access.

なお、この状態でも Private Endpoint経由の通信は問題なく行えます。ネットワークセキュリティ境界が制御するのは、パブリックIP経由のアクセスのみのようです。

では、受信アクセス規則を許可してみましょう。 受信アクセス規則 の画面から自宅のパブリックIPを登録してみます。

登録後、正常にログインできるようになりました。
この状態でSQL Databaseのネットワーク設定を見ても、ファイアウォール設定に変更がないことが見て取れます。

ネットワークセキュリティ境界を設定すると、PaaS側のファイアウォール設定に入っている設定に関係なく、ネットワークセキュリティ境界のポリシーの設定内容に従って制御されるようです。 ネットワークセキュリティ境界への移行を検討する際には注意が必要なポイントですね。

送信規則の設定

送信側の設定についても確認してみましょう。

SQL Databaseには外部のエンドポイントを参照する機能 があるので、これを利用して確認します。 Azureサービスのドメインしか許可されていないので、この辺りを参考にApp Serviceで適当にサンプルサイトを準備して確認します。

送信規則を設定する前に確認すると、以下のようにネットワークセキュリティ境界にてブロックされている旨が表示されます。

送信規則はFQDNでアクセス許可する先を指定します。送信アクセス規則の追加 メニューからFQDNを追加します。

また、ネットワークセキュリティ境界での送信規則制御にはマネージドIDの有効化が必須なようです。SQL Database側でシステム割り当てマネージドIDを有効化しておきましょう。

規則の追加・マネージドIDの有効化の双方が完了した後に再度確認すると、正常にAPIエンドポイントに接続できたことが見て取れます。

おわりに

PaaSのインターネットアクセスを制御できる新サービスの紹介でした。
今回は単一のリソースのみを登録して確認しましたが、複数のPaaSをまとめて設定できるのは有用なシーンが多そうです。 一方、既存の各PaaSのネットワーク設定と競合する部分なので、実際の運用面では設定の確認で混乱しそうな予感もあります。そのあたりが今後クリアされることに期待しつつ、GAを待ちたいと思います。

本記事の投稿者: 吉川 俊甫
Advent Calendar投稿間に合いませんでした… Microsoft MVP (Microsoft Azure)
Shunsuke Yoshikawa - Credly

New RelicのAlertのStreaming Methodでハマった話(Event flowとEvent timerの違い)

こちらは

qiita.com

qiita.com

の6日目です。

Azureを始めとしたクラウドでインフラをTerraformなどを活用しながら構築・運用しているエンジニアですが、今年に入ってからNew Relicに入門しました。
直近はAzure Monitorを使っていて、そちらではKQLというクエリ言語でグラフやアラートを書いていたんですが、
NRQLが大枠ではKQLと近いようなクエリ言語だったので特に違和感なくNew Relicを使い始められました。

APMやSynthetic MonitoringといったNew Relicならではの機能を始め、豊富なメニューから様々な情報が得られてグラフやダッシュボード、SLI/SLO、そしてアラートに利用できるのがとても良い感じです。

アラートについては色々カスタマイズ性できるのですが・・・カスタマイズ性の高さ故にキチンと要件に合わせて設定しないと「思った通りに動かない!」ということに繋がったので共有したいと思います。

TL;DR

  • Alert ConditionのStreaming Methodのデフォルト(推奨)はEvent flow
  • Event flowは常にデータが流れてくるモノ向けで、デイリーバッチのように散発的で実行頻度が低いデータには向かない
  • バッチをアラートにする場合はEvent timerないしCadenceを設定すべし

何があったのか?

WebシステムをAKS(Azure Kubernetes Service)で構築しており、その中に1日1回動くデイリーバッチをCronJobとして実装しているのですが、対抗システムの仕様変更によってデイリーバッチが何日かに一回程度エラーが発生するようになってしまいました。
バッチのエラーの監視については

  1. KubernetesのJobステータスによる監視
  2. エージェントで転送したログのエラー監視

の2つを行っており、1.のアラートの発報によって気づきました。
対抗システムの想定外の変更ということもあって、バッチの処理内容を変更するまで度々アラートが発生してしまうのでアラートを無効化しました。
その後も度々バッチはコケていて、まあ既知の問題だしアラートは無効化しているから問題ないか…と思い過ごしそうになりましたが、
なんでエラーログは出ているはずなのに無効化していない2.のログ監視のアラートが出てないんだ???となり、調査を開始しました。

調査

調査と言ってもどこが怪しいかの検討がついていなかったので、見えるところから見ていくスタイルで調査していきました。

ログの確認

ログのエラー監視は特定のentity.nameのログでログレベルがErrorのものがあったらアラートを発報する、というよくあるログ監視にしている認識でした。
New RelicのログテーブルでNRQLを叩いたりAKSのPodの生ログを見ても、数日に一回程度のペースでErrorレベルのログが出力していました。
Errorログはしっかり出ているのに何故アラートがならないのか…?と疑問が深まる限りでした。

他のエラーログとの比較

(良いことではないですが)都合よく度々エラーログ検知のアラートが上がっているアプリがあったので、設定を見比べてみることにしました。

NRQLは概ね同じものだったんですが、Signal behaviorのところを見比べてみると

アラートが出ていた方のSignal behavior

アラートが出てない方のSignal behavior

Timer/Delayという表記の違いもありましたが、Streaming MethodがEvent timerとEvent flowと違うものが設定されているのが一番の違いでは?と考え、New Relicの設定の意味を調べました。

Streaming Method - Event flowとEvent timerの違い

Event timerやEvent flowといった具体的なキーワードで調べてみると色々情報が出てきました。

ちなみにNew Relicを使い始めた頃に一通りの説明をしてもらっていたのですが、まさに「難しくてよく分からないな…?」となっていた部分でした。

docs.newrelic.com

newrelic.com

newrelic.com

これらの記事でもしっかり書かれていたのでお恥ずかしいことですが、まとめると、
Azureなど各種プラットフォームのメトリクスや常にある程度のアクセスがあるWebページのログのように、常にデータが流れ続けるものにはEvent flow(New Relicアラートのデフォルト)は向いていますが、
デイリーバッチのログのように発生間隔が大きいデータには向かず、
Event timerもしくはCadenceにするべきとのことでした。

完全に理解した!というわけではないですが私の理解では、
Event flowでは、Window durationの期間が終わってDelayの時間が経過後にさらに後続のデータを受信したタイミングで集計・評価が行われて、しきい値を超えていたらアラートを発報するという形のようです。
上記の公式ドキュメント等に図などもあるのでご確認ください。

上記の例ですと、バッチは深夜1時に動くので、1:00-1:01が評価期間になります。より厳密にはバッチが走って最初のログが出力され、それがNew Relicに取り込めたタイミングから1分間、というほうが正確なようですが一旦理解しやすいように1:00-1:01にします。
そして2分間のDelayがあって1:03以降に何かしらのログが流れればそのタイミングがアラートを発報する、ということになります。
しかしこのバッチは概ね1:00-1:01の一分間のうちに処理が終わってしまい、次にログが出るのは24時間後になるので、Event flowの仕様によって後続データを65分以上受信しない場合は未集計データとして破棄されてしまったようです。
つまりWindow Duration期間内に処理が完了してしまうバッチではEvent flowでは基本的にアラートが発報しない!ということだと思います。
1時間間隔のバッチであれば65分後の破棄より前にギリギリアラートは発報するわけですが、処理から1時間後にアラート発報なのでやはり不適切ですね…

一方、Event timerの場合は、後続データの有無に関わらずDelayの時間が終わった瞬間にアラートが発報するので、今回のケースでもキチンとアラートは発報することを検証環境で確認できました。

ちなみにCadenceは従来の一般的なアラート方式で、データが流入したタイミングなどは考慮せずにNew RelicのシステムクロックでWindow Durationの間のデータを集計してDelayの後に発報するという形式で、
私達が期待していた挙動はこちらに近かったと思います。

まとめ

今回は、 - ログ以外の方法でもアラートを設定していてエラーに気づけた - 他にきちんと機能している同等のアラート設定があって比較することができた

以上のような都合のよい状況だったので大きな問題にはなりませんでしたが、これらがなかったらエラーを見逃していたと思うと中々ゾッとしますね…

個人的には、Event flowがデフォルト・推奨として設定されている理由として記載されていた、

ほとんどの場合、この集計方法の方が、遅延によるデータの取りこぼしが少なく、検出までの時間が短縮されると考えられるためです。

という文言が未だに腹落ちしていなかったりするので、もう少しNew Relicへの理解を深めたいと思っています。

VS Code でも Mermaid で Azure アイコンを使ったアーキテクチャを書き隊

はじめに

こんにちは、ACS 事業部の田中(脩)です。

ダイアグラムを作成するツールは draw.io が有名です。
私自身も利用していますが、図形の前面/背面の把握が面倒だったり アイコンを1つ動かすと複数の図形が動いたりと、
スマートに作図できずヤキモキすることが多々あります。
コードベースで作図できればと思っていたところ、下記の記事に出会い Mermaid を試すことにしました。

www.kentsu.website

こちらの記事ではブログ上で Azure のアイコンを表示するための手順が紹介されていますが、
業務での利用を考え、Visual Studio Code で プレビューできる方法を模索しました。
本記事ではその設定方法をご紹介します。

設定方法

手順1. 拡張機能をインストールする

Visual Studio Code に拡張機能 Markdown Preview Enhanced をインストールします。
こちらの拡張機能をインストールすれば、Mermaid で記述したダイアグラムがプレビューされるようになります。

marketplace.visualstudio.com

手順2. 拡張機能の設定を編集する

前述の拡張機能をインストールしただけでは Mermaid の標準のアイコンしかプレビューされません。
Azure のアイコンもプレビューされるように、Mermaid の初期設定を編集します。

github.com

  1. VS Code でコマンドパレットを表示する。(F1 キー)
  2. コマンドパレットで Markdown Preview Enhanced: Customize Preview Html Head を入力・選択して、head.html ファイルを開く。
  3. head.html ファイルを下記のように編集する。

編集前

<!-- The content below will be included at the end of the <head> element. -->
<script type="text/javascript">
  document.addEventListener("DOMContentLoaded", function () {
    // your code here
  });
</script>

編集後

<!-- The content below will be included at the end of the <head> element. -->
<script type="text/javascript">
  const configureMermaidIconPacks = () => {
    window["mermaid"].registerIconPacks([
      {
        name: "azure",
        loader: () =>
          fetch("https://unpkg.com/azureiconkento@1.1.1/azureicons/allicons.json").then(
            (res) => res.json()
          ),
      },
    ]);
  };

  if (document.readyState !== 'loading') {
    configureMermaidIconPacks();
  } else {
    document.addEventListener("DOMContentLoaded", () => {
      configureMermaidIconPacks();
    });
  }
</script>

テスト

任意の Markdown ファイルに下記コード(参考記事と同じもの)を記述して、プレビューします。

architecture-beta
    
group rg1(azure:resource-groups)[Resource Group]

    group vnet1(azure:virtual-networks)[Virtual Network] in rg1
        group subnet1(azure:subnet)[Subnet] in vnet1
        service server(azure:virtual-machine)[Server] in subnet1

    service storage(azure:storage-accounts)[Storage] in rg1
    service nsg1(azure:network-security-groups)[NSG] in rg1
    service database(azure:sql-database)[Database] in rg1

    nsg1:L --> R:server{group}

プレビューは下図のように表示され、Azure アイコンが使用できていることが確認できました。

おわりに

本記事は Azure のアイコンを使用したアーキテクチャ図を Mermaid で書き、VS Code でプレビューするための設定方法をご紹介しました。
業務で利用できるレベルのアーキテクチャ図を Mermaid で書けるかどうかは、別途検証していきます。

ACS事業部のご紹介

私達ACS事業部はAzure・AKSなどのクラウドネイティブ技術を活用した内製化のご支援をしております。
ご相談等ありましたらぜひご連絡ください。

www.ap-com.co.jp

また、一緒に働いていただける仲間も募集中です!
今年もまだまだ組織規模拡大中なので、ご興味持っていただけましたらぜひお声がけください。

www.ap-com.co.jp

本記事の投稿者: 田中 脩平

【Microsoft Ignite 2024速報】コンテナ系アップデートまとめ

はじめに

こんばんは、ACS事業部の吉川です。
Microsoftの年次イベント Microsoft Ignite が今年も始まりました!

ignite.microsoft.com

今回も多くのアップデートが Book of News のサイトにまとまっています。

news.microsoft.com

…が、今回はコチラにあまりPaaSの更新情報は載っていないようです。
ですがご安心ください。Microsoft公式のTech Community Blogでは、各サービスの更新情報がモリモリ投稿されております。

techcommunity.microsoft.com

本記事では私の所属するACS事業部の注力領域であるコンテナ系サービスのアップデート情報をピックアップしてお届けします。

Azure Kubernetes Service のアップデート

techcommunity.microsoft.com

Azure Kubernetes Service(AKS) については、先日ソルトレイクシティで開催された Azure Day with Kubernetes で多くのアップデートが公開されており、その情報が上記のブログにまとまっているようです。

AKS Automatic の機能向上

今年5月のMicrosoft Buildで公開されたAKSの自動管理オプション、AKS Automatic の機能向上が発表されています。
AKS Automaticについては過去 コチラの記事 で取り上げていますので合わせてご覧ください。

ノードのSKU管理やアップグレード時の挙動の変更によって、より信頼性を上げていっているようです。
その他にも、来年1月からApplication Insightsの自動インストルメンテーション機能のプレビューが始まるようです。
基盤を意識するポイントを減らしてくれる、地味ながら良いアップデートですね。

セキュリティ観点の機能向上

セキュリティに関するアップデートとして、以下の2点が挙げられています。

  • トラステッド起動のサポート(GA)
  • AKSセキュリティダッシュボードの提供(パブリックプレビュー)

トラステッド起動はAzure VMでSecure Bootを利用可能とする機能です。
Gen2と呼ばれるVMの世代で利用可能な機能ですが、これがAKSのワーカーノードでも利用可能になりました。

AKSセキュリティダッシュボードは、Microsoft Defender for Cloudから該当のAKSクラスターにまつわる情報を切り出して表示する機能のようです。
Microsoft Defender for CloudはAzure上でセキュリティの対策状況を確認するのに便利なサービスですが、その情報をAKSの画面から参照できるようになるというアップデートです。
AKSクラスターの管理者からすると、ポータルのいろんなところを見なくてよくなるという点で便利ではないでしょうか。

Azure Kubernetes Fleet Manager の機能向上

複数のAKSクラスターをまとめて管理する Fleet Managerについても以下の機能のアップデートが紹介されています。

  • マルチクラスターの自動アップグレード
  • リソース状況によるインテリジェント配置

自動アップグレードは、Azure側で新しいKubernetes・ノードバージョンが利用可能となったときの更新処理を支援する機能です。 予め設定した更新チャネルやスケジュールに従い、複数のAKSクラスターのバージョンアップを行います。
AKSを利用する上では基盤のバージョン管理は切っても切れない作業となるため、このような機能を使ってうまく自動化していくのがよいでしょう。

learn.microsoft.com

もう一つのインテリジェント配置は、PodなどのワークロードをどのAKSクラスターに配置するかを決定する際に利用できるパラメータが増えたというものです。
従来は配置されたリージョンなどの静的な情報ベースでしか配置先を選択できませんでしたが、インテリジェント配置を利用するとノード数やCPU/メモリの空き状況といった動的なメトリックベースで配置先を指定できるようになります。

Fleet Managerは複数AKSクラスターを運用している環境でないとメリットの出にくいサービスですが、規模が大きくなった際にうまく使いこなせると管理負担が減らすのに有用なサービスです。こういったアップデートは嬉しいですね。

Azure Container Apps のアップデート

techcommunity.microsoft.com

AKSよりお手軽にコンテナを扱える Azure Container Apps(ACA) も、いくつかのアップデート情報が出ています。

Serverless GPUs (パブリックプレビュー)

techcommunity.microsoft.com

従来ACAでGPUを使いたい場合、GPU付きのホストをデプロイし占有して利用する必要がありました。
その場合、アプリが動いているかどうかに関わらず課金されてしまっていましたが、今回登場したサーバーレスプランにより、GPUを必要とするアプリケーションも0スケールでコストを抑えることができます。
特にジョブ型のアプリケーションでGPUを使う場合、有効な選択肢になりそうです。

Dynamic Sessions (GA)

techcommunity.microsoft.com

サンドボックス環境で安全にコードを実行できるDynamic SessionsがGAとなりました。
主な利用用途としてはLLMが生成したコードを実行し結果を得る、というものでしょう。 上記のブログによると、実際にMicrosoft Copilotの中でDynamic Sessionsが大規模に稼働しているそうです。実績としては十分でしょう。
ネイティブでのPython実行とコンテナーを準備して任意の言語を実行する機能がGA、新たにネイティブでのJavaScript対応がパブリックプレビューとなっています。

Private Endpoint対応(パブリックプレビュー)

techcommunity.microsoft.com

ACAに対しPrivate Endpoint経由でアクセスできるようになります。
主な利用シーンとしてはFront Doorと組み合わせるときにFront Door - ACA間をPrivate Link接続するというものでしょう。
私も以前に以下のブログでムリヤリPrivate Linkを設定したことがありましたが、公式に対応する方向で進めているようです。

techblog.ap-com.co.jp

計画メンテナンス(パブリックプレビュー)

learn.microsoft.com

ACAのアップグレードが適用されるタイミングについて、メンテナンスウインドウを指定することができるようになります。
AKSでは以前から対応している機能なので、ACAでも同様に設定できるのは嬉しいアップデートです。

パスベースルーティング(早期アクセス)

github.com

同一のContainer Apps環境に配置されたアプリに対し、パスベースルーティングができるようになります。
従来は同一のContainer Apps環境に配置されていても、アプリごとに個別のドメインでアクセスする必要がありました。 パスベースルーティングを設定できるとドメインの設計をより柔軟にできます。 特にAKSからACAに置き換えするような際、KubernetesのIngressでは当たり前にパスベースルーティングができていたので、ここがネックになることが多々あります。
個人的に最も嬉しいアップデートです。GAが待ち遠しいですね。

おわりに

コンテナ系サービスのアップデートをピックアップしてお届けしました。
今回のIgniteのキーノートはAI・Microsoft 365・ハードウェアの話が中心でしたが、Azureの各サービスも堅実にアップデートを重ねています。お時間がある方はぜひIgniteのセッション動画も視聴してみてください。

本記事の投稿者: 吉川 俊甫
Igniteに合わせ夜型生活です。Microsoft MVP (Microsoft Azure)
Shunsuke Yoshikawa - Credly

Bicep のMicrosoft Graphの指定方法が変更されます

皆さんこんにちは。ACS事業部 亀崎です。

今年の初夏にMicrosoft Graph Bicepが利用可能になったことをご紹介したのを覚えていますでしょうか。

techblog.ap-com.co.jp

まだExperimentalではありますが、2024年5月から利用可能になっていました。

当初は

provider microsoftGraph

@description('Application name, unique globally. Can not change after create it')
param appName string
@description('Applicaton displayname, default value is same as appName')
param displayName string = appName

resource app 'Microsoft.Graph/applications@v1.0' = {
  displayName: displayName
  uniqueName: appName
}

resource sp 'Microsoft.Graph/servicePrincipals@v1.0' = {
  appId: app.appId
}

と、 provider microsoftGraph という組み込み型を指定することで利用できました。 じつはこのあと providerの部分が extension という指定に変更され、 extension microsoftGraph と指定する方式になりました。

そしてこの度指定方法がさらに変更となります。

learn.microsoft.com

これまでは「組み込み型」で定義するものでしたが、それが「動的な型」に変更され、従来の「組み込み型」は2025年1月24日に廃止となります。

ということで今回は変更方法についてご紹介したいと思います。

Microsoft Graphの動的な型指定方法

変更するのは以下の2点です。

変更点1 bicepconfig.json へ指定追加

bicepconfig.jsonに'extension' 部の指定を追加します。

microsoftGraphV1_0の部分はMicrosoft アーティファクト レジストリ内のパッケージ バージョンを参照するためのユーザー定義のフレンドリ拡張名です。

mcr.microsoft.com/bicep/extensions/microsoftgraph の部分がアーティファクトレジストリで <version> はレジストリで公開されているバージョンです。

バージョンは https://github.com/microsoftgraph/msgraph-bicep-types/tags で公開されているタグの先頭のvを除いたものを指定します(v0.1.8-previewの場合は 0.1.8-preview と記載します)。

{  
    "experimentalFeaturesEnabled": {  
        "extensibility": true  
    },
    "extensions": {  
        "microsoftGraphV1_0": "br:mcr.microsoft.com/bicep/extensions/microsoftgraph/v1.0:<version>"  
    }  
}

変更点2 bicepでの指定

続いて実際にMicrosoft Graphを利用しているBicepでの指定です。 先程の例で provider microsoftGraph または extension microsoftGraph となっている部分を extension microsoftGraphV1_0 と置き換えます。 microsoftGraphV1_0 の部分は bicepconfig.json のextensionsのところで定義した名称になります。

extension microsoftGraphV1_0

@description('Application name, unique globally. Can not change after create it')
param appName string

...

これで終了です。

ステータスがexperimentalであったこともあり何度か変更が実施されましたが、今回の指定で概ね方向は固まったのではないかなと思います。

ということで、今回はMicrosoft Graph Bicep利用時の変更方法についてお知らせしました。

Microsoft Graph Bicepのステータスがexperimentalから脱するのも間近かもしれません。早くGAとなることを期待します。

Azure Deployment EnvironmentsとPlatform Engineeringの親和性を考える

本記事はAP Tech Blog Week Vol.5の企画(の期間を1週間ほどオーバーランしました…)です。

はじめに

こんにちは、ACS事業部の吉川です。
「自動化」というキーワードで思い浮かべる要素は様々かと思いますが、個人的には「セルフサービス」という観点が重要だと考えています。
Azureにおけるリソースの作成をセルフサービス化するための機能として Azure Deployment Environments というサービスがあります。
プレビュー開始時に本ブログでも紹介していましたが、現在とは少し異なる部分もあるため、改めてご紹介します。

techblog.ap-com.co.jp

techblog.ap-com.co.jp

Azure Deployment Environmentsの概要

Azure Deployment Environmentsの概念を説明するのにちょうどいい図が公式ドキュメントにありますので、引用しつつ見ていきましょう。

Azure Deployment Environmentsを端的に言うと、
『プラットフォームチームが事前定義した構成を、開発者がセルフサービスでプロビジョニングできる』
というサービスです。

上図の左側にある『Dev Infra Teams』は、昨今のPlatform Engineeringの文脈で言うプラットフォームチームと読み替えて差し支えないでしょう。 このチームは、あらかじめAzureリソースの構成をテンプレート化してリポジトリに格納し、開発チーム向けにサービスカタログとして公開します。
テンプレートは標準でARMテンプレートとBicepに対応しており、プロビジョニング実行用にコンテナイメージを別途作成することでTerraformとPulumiもサポートされています。

learn.microsoft.com

上図中央の『Developers』は、開発工程において必要になったタイミングで、プラットフォームチームが公開したサービスカタログから必要な構成を選んでAzureリソースを作成します。

ここで重要なポイントとしては、DevelopersはAzureリソースを作成する権限を持つ必要なく、定められた構成のみ作成可能なように統制が取れる という点です。

セルフサービスにおける権限どうする問題

プラットフォームチームとしては、開発チームからの依頼ベースでリソースを作成すると工数が膨らむ、とはいえガバナンスの観点から開発チームが好き勝手にリソースを作れてしまうのは困る… といった悩みがあると思います。
Azure Deployment Environmentsを利用することで、開発者に不要な権限を渡すことなくセルフサービスでの環境払い出しが実現できます。

仕組みとしてはシンプルで、Azureのリソース作成はAzure Deployment EnvironmentsのマネージドID(厳密に言うとDev CenterリソースのマネージドID)が行います。 また、Azure Deployment Environmentsは開発者のユーザープリンシパルに対し、作成したリソースの管理者権限を別途割り振ることもできます。 カタログからしかリソースを作成させないことで制限をかけつつ、作成したリソースに対して強い権限を割り振ることで開発者に自由を与える という、良いとこ取りな機能を簡単に実現可能です。

Azure Deployment Environments の作成

Azure Deployment Environmentsは複数のAzureリソースの組み合わせで構成されています。 公式ドキュメント にある下図を見てもわかるように、Dev CenterやProject、Catalogなど、多様なリソースが組み合わさっています。

実際に試そうとすると複数のリソースを順番に作らねばならずかなり面倒なので、Azure CLIを用いた構成用のコマンド例を以下に示します。 Dev CenterリソースのマネージドIDにサブスクリプションの「共同作成者」「ユーザーアクセス管理者」という強めの権限を与える都合上、このコマンドを実行するユーザーはサブスクリプションの管理者権限を持っている必要があります。

# リソース名/リージョンの定義
RG_NAME="rg-devcenter"
DC_NAME="devcenter-sample"
CATALOG_NAME="catalog-sample"
PROJECT_NAME="project-sample"
LOCATION="japaneast"
SUBSCRIPTION_ID=$(az account show --query id -o tsv)

# リソースグループ作成
az group create --location $LOCATION --name $RG_NAME

# Dev Centerの作成
az devcenter admin devcenter create --name $DC_NAME \
  --resource-group $RG_NAME --location $LOCATION \
  --identity-type SystemAssigned


# Dev CenterのマネージドIDに対する権限割り当て
MANAGED_ID=$(az devcenter admin devcenter show --name $DC_NAME \
  --resource-group $RG_NAME --query identity.principalId -o tsv)

az role assignment create --assignee $MANAGED_ID --role Contributor \
  --scope /subscriptions/$SUBSCRIPTION_ID
az role assignment create --assignee $MANAGED_ID --role "User Access Administrator" \
  --scope /subscriptions/$SUBSCRIPTION_ID

# カタログの作成(GitHubにあるサンプルを利用)
az devcenter admin catalog create --catalog-name $CATALOG_NAME \
  --dev-center $DC_NAME --resource-group $RG_NAME \
  --git-hub uri="https://github.com/microsoft/devcenter-catalog.git" branch="main" path="Environment-Definitions"


# 環境定義の作成
az devcenter admin environment-type create --dev-center $DC_NAME \
  --name "Dev" --resource-group $RG_NAME --tags Env="Dev"
az devcenter admin environment-type create --dev-center $DC_NAME \
  --name "Staging" --resource-group $RG_NAME --tags Env="Staging"
az devcenter admin environment-type create --dev-center $DC_NAME \
  --name "Prod" --resource-group $RG_NAME --tags Env="Prod"

# プロジェクトの作成
DC_ID=$(az devcenter admin devcenter show --name $DC_NAME \
  --resource-group $RG_NAME --query id -o tsv)
az devcenter admin project create --dev-center-id $DC_ID \
  --name $PROJECT_NAME --resource-group $RG_NAME

# プロジェクト環境の種類の作成
az devcenter admin project-environment-type create \
  --deployment-target-id /subscriptions/$SUBSCRIPTION_ID \
  --environment-type-name Dev \
  --identity-type SystemAssigned \
  --project $PROJECT_NAME \
  --resource-group $RG_NAME \
  --roles "{\"8e3af657-a8ff-443c-a75c-2fe8c4bcb635\":{}}" \
  --status Enabled

az devcenter admin project-environment-type create \
  --deployment-target-id /subscriptions/$SUBSCRIPTION_ID \
  --environment-type-name Staging \
  --identity-type SystemAssigned \
  --project $PROJECT_NAME \
  --resource-group $RG_NAME \
  --roles "{\"8e3af657-a8ff-443c-a75c-2fe8c4bcb635\":{}}" \
  --status Enabled

az devcenter admin project-environment-type create \
  --deployment-target-id /subscriptions/$SUBSCRIPTION_ID \
  --environment-type-name Prod \
  --identity-type SystemAssigned \
  --project $PROJECT_NAME \
  --resource-group $RG_NAME \
  --roles "{\"8e3af657-a8ff-443c-a75c-2fe8c4bcb635\":{}}" \
  --status Enabled

上記のコマンド例ですと、rg-devcenter というリソースグループ内に devcenter-sample というDev Centerリソースと、project-sample というProjectリソースの2つのリソースが作成されます。
開発者がカタログからリソースを作成するためには、Projectリソースに対しIAMロールの割り当てが必要です。
Azure Deployment Environmentsを利用する開発者のアカウントを、Projectリソースの Deployment Environments User に追加します。 下図では個別のユーザーを追加していますが、実際に利用する際にはグループを活用すると便利でしょう。

これでAzure Deployment Environmentsが利用可能になりました。

Azureリソースを作ってみる

それでは、実際にAzure Deployment Environmentsを利用してリソースを作成してみましょう。
作成したDev CenterリソースやProjectリソースには、以下のようにURIが表示されています。

利用するときはこのURIにアクセスして…と思いきや、このURIにはアクセスできません。
Azure Deployment Environmentsからリソースを作成するときは、https://devportal.microsoft.com にアクセスします。

左上の「+新しい環境」をクリックすると、以下のような入力画面が表示されます。

  • 名前
  • 種類
  • 定義

の項目を入力して環境を作成します。
「定義」が構成のカタログを示す部分ですが、今回は以下リポジトリにあるMicrosoftのサンプルを取り込んでいます。 自身でカタログを作成する場合にも、以下リポジトリ内のファイルを参考にするとよいでしょう。

github.com

「スケジュールされた削除を有効にします」のチェックボックスを有効化すると、作成した環境を削除する日時を設定できます。
一時的な検証目的で環境を作成する場合には有効に使える機能です。

作成が完了すると、以下のように新規のリソースグループが作成され、リソースが配置されているのが確認できます。

リソースグループのIAMを見ると、Azure Deployment Environmentsからリソースを作成したユーザーが、リソースグループの所有者として登録されていることが確認できます。

このように、

  • カタログからのセルフサービスでのリソース作成
  • 作成されたリソースに対する権限割り当て

というサービスを開発者に提供できるのがAzure Deployment Environmentsの特徴です。

おわりに

Azure Deployment Environmentsを使うことで、セルフサービスでのAzure環境払い出しを行うことができます。 期限を決めての環境自動削除も行えることから、開発環境の払い出しに向いたサービスであるといえます。

一方、実際に本番サービスを動かす環境を作るとなると、Azureリソースだけでは環境は完結せず、

  • Gitリポジトリ
  • CI/CDパイプライン
  • モニタリング/Observabilityツール

といったものも必要となります。
その点を意識するとBackstageのSoftware Template機能のほうが有力な選択肢となりうるでしょう。

techblog.ap-com.co.jp

一口にセルフサービス化といっても、どういった目的の環境を、どのような実装で提供するかは様々です。 用途にあったツールを選択していくことが重要ですね。

本記事の投稿者: 吉川 俊甫
BicepよりTerraform派。Microsoft MVP (Microsoft Azure)
Shunsuke Yoshikawa - Credly

GitHub ActionsでMicrosoft Graph APIを利用したEntra IDユーザー招待を試してみた

本記事はAP Tech Blog Week Vol.5のものになります。

はじめに

こんにちは、ACS事業部 CIチームの平井です。この記事では、GitHub Actionsを使ってOIDCを利用し、Microsoft Graph APIでEntra IDユーザーを招待する方法をご紹介します。 ユーザー招待システムを構築するためのヒントとして、参考にしていただけたらと思います。

背景

Azure ADへのユーザー招待を自動化するにあたり、当初はTerraformのazureadプロバイダーazuread_invitationリソースを使用する予定でした。しかし、実装する過程で以下のような課題に直面しました。

ユーザープロパティが設定できない 通常、招待時にユーザープロパティを設定したいところですが、azuread_invitationリソースだけではこれができません。設定するためには、次の複雑な手順を踏む必要がありました。

  1. azuread_invitationでユーザーを招待
  2. terraform importコマンドで招待したユーザーリソースをインポート
  3. azuread_userリソースでプロパティを更新

このように、シンプルに見えるユーザー招待も、Terraformでは複数のステップが必要となり、運用が煩雑化してしまいます。

そこで行きついたのがMicroSoft Graph APIをGitHub ActionsのOIDCで使用する方法でした。

Microsoft Graph APIとは

Microsoft Graph APIはMicrosoftのクラウドサービスに対するRESTful APIです。Entra IDを含むMicrosoft 365のサービスを統合的に操作することができます。azureadプロバイダーも内部的にはMicrosoft Graph APIを利用して動いています。

learn.microsoft.com

実装の流れ

では早速実装に入ります。今回は簡易的に招待の際、表示名、姓、名のプロパティを設定する実装になります。 流れとしては以下のように進んでいきます。

  1. Entra IDアプリケーションの設定
  2. GitHub Actionsワークフローの作成
  3. ユーザー招待処理の作成(Node.js)

Entra IDアプリケーションの設定

まずはEntra IDにアプリケーションを登録し、フェデレーションの設定をします。以下の記事を参考に進めていきましょう。 zenn.dev

アプリケーションの作成が完了したら、ユーザー招待を行う上で必要なAPIの権限を付与していきます。 必要な権限は以下の二つです。

  • Directory.ReadWrite.All
  • User.ReadWrite.All

このように付与できていればEntra IDアプリケーションの設定は終了です。

GitHub Actionsワークフローの作成

GitHub ActionsでOIDC認証を使用してMicrosoft Graph APIを呼び出すワークフローを作成します。

ファイル名:.github/workflows/invitation_workflow.yml

name: user invitation

on:
  workflow_dispatch:
    inputs:
      user_email:
        description: "Email of the user to invite"
        required: true
      display_name:
        description: "Display name of the user to invite"
        required: true
      first_name:
        description: "First name of the user to invite"
        required: true
      last_name:
        description: "Last name of the user to invite"
        required: true

permissions:
  id-token: write
  contents: read

jobs:
  invite_user:
    runs-on: ubuntu-latest
    environment:
      name: staging
    defaults:
      run:
        working-directory: ./invitation

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: "20"
          cache: "npm"
          cache-dependency-path: "invitation/package-lock.json"

      - name: Install dependencies
        run: npm ci

      - name: Login in to Azure
        uses: azure/login@v2
        with:
          client-id: ${{ secrets.AZURE_CLIENT_ID }}
          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

      - name: Invite user
        env:
          TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
          USER_EMAIL: ${{ github.event.inputs.user_email }}
          DISPLAY_NAME: ${{ github.event.inputs.display_name }}
          FIRST_NAME: ${{ github.event.inputs.first_name }}
          LAST_NAME: ${{ github.event.inputs.last_name }}
        run: npm start

なお、以下のGitHubシークレットの設定が必要です:

  • AZURE_CLIENT_ID: アプリケーションのクライアントID
  • AZURE_TENANT_ID: テナントID
  • AZURE_SUBSCRIPTION_ID: サブスクリプションID

ユーザー招待処理の作成(Node.js)

最後にユーザー招待処理の実装していきます。

# プロジェクトディレクトリの作成
mkdir user-invitation
cd user-invitation

# package.jsonの作成
npm init -y

# 必要なパッケージのインストール
npm install @azure/identity @microsoft/microsoft-graph-client isomorphic-fetch

package.jsonに以下の内容を追加

"scripts": {
  "start": "node userInvitaiton.js"
},
"type": "module",

ユーザー招待処理コードを追加します。 今回利用するAPIエンドポイントのリファレンスになります。

learn.microsoft.com

learn.microsoft.com

こちらをもとに作成していきます。

ファイル名:/invitation/userInvitaiton.js

import { DefaultAzureCredential } from "@azure/identity";
import { Client } from "@microsoft/microsoft-graph-client";
import { TokenCredentialAuthenticationProvider } from "@microsoft/microsoft-graph-client/authProviders/azureTokenCredentials/index.js";
import "isomorphic-fetch";

const credential = new DefaultAzureCredential();

// Microsoft Graph APIクライアントを初期化
const authProvider = new TokenCredentialAuthenticationProvider(credential, {
  scopes: ["https://graph.microsoft.com/.default"],
});

const client = Client.initWithMiddleware({ authProvider: authProvider });

// ユーザーの招待内容
const invitation = {
  invitedUserEmailAddress: process.env.USER_EMAIL,
  inviteRedirectUrl: `https://myapplications.microsoft.com/?tenantId=${process.env.TENANT_ID}`,
  sendInvitationMessage: true, // メール通知を送信する
};

// 招待ユーザーのプロパティ
const properties = {
  displayName: process.env.DISPLAY_NAME,
  givenName: process.env.FIRST_NAME,
  surname: process.env.LAST_NAME,
};

// ユーザーの招待とプロパティの設定
async function sendInvitation() {
  try {
    const invitationResponse = await client.api("/invitations").post(invitation);
    const userId = invitationResponse.invitedUser.id;
    console.log(
      `Invitation sent to ${process.env.USER_EMAIL} with id: ${userId}`
    );
    return userId;
  } catch (error) {
    console.error("Errer sending invitation:", error);
    throw error;
  }
}

async function updateProperties() {
  try {
    const userId = await sendInvitation();
    await client.api(`/users/${userId}`).patch(properties);
    console.log(`User ${userId} properties updated`);
  } catch (error) {
    console.error("Error updating user properties:", error);
    throw error;
  }
}

updateProperties().catch((error) => {
  console.error(error);
  process.exit(1);
});

これで準備は終わりました。コードをPushして、さっそくワークフローの動作確認をしていきます。

動作確認

リポジトリのActionsタブより、user invitationをworkflow_dispatchで動かします。

無事ワークフローが実行できました。

Azureポータルより招待ユーザーが実際に作成されたか確認してみます。

無事、招待ユーザーの表示名、姓、名のプロパティが設定されています。

おわりに

今回はGitHub Actionsを使ってOIDCを利用し、Microsoft Graph APIでユーザーを招待する方法をご紹介しました。今回は一つのユーザーのみの招待ですが、ワークフロー内でマトリックスを使用することで 単一のワークフローで複数のユーザーを並行して処理することも可能になります。この記事が皆さんの学びや実践に少しでも役立てば嬉しいです。

私達ACS事業部はAzure・AKSなどのクラウドネイティブ技術を活用した内製化のご支援をしております。

www.ap-com.co.jp

また、一緒に働いていただける仲間も募集中です!
今年もまだまだ組織規模拡大中なので、ご興味持っていただけましたらぜひお声がけください。

www.ap-com.co.jp

本記事の投稿者: <平井亨>

Azure LogicAppsを用いたVM起動停止

1_はじめに

本記事はAP Tech Blog Week Vol.5のものになります。

こんにちは、ACS事業部の本田です。

以前、ベンダーのリモート保守用VMの起動停止を、Azure AutomationのRunbookと、そのスケジュール機能で行っていました。
複数のベンダーが共有する環境でもあったため、不定期な起動停止が多くなり、管理が大変になってきたことがありました。 そのため、カレンダーを用いてスケジュールを可視化させて分かりやすくさせたことがありますので、 そちらを実施していきたいと思います。

2_目的

次の形で、作成を行いたいと思います。

  • カレンダーの件名に「Start」と入力するとVMを起動する
  • カレンダーの件名に「Stop」と入力するとVMを停止する

リソースグループの作成などは、省略いたします。

3_Azure Logicappsの作成

従量課金のLogcappsで作成します。

4_アプリの作成

アプリデザイナーで作成していきます。 コードビューでも作成可能ですが、今回はデザイナーで作成を行います。

4-1_トリガーを作成

  • 「Office 365 Outlook」の「予定しているイベントが間もなく開始されるとき」

  • Office 365 Outlookへ接続し、カレンダーと連携する
    今回は、簡略化して自身のカレンダーを利用していますが、 次に考慮してください。

    • アカウントは管理用アカウントを利用する
    • 共有カレンダーを作成し、権限を付与し利用する

4-2_分岐させる

上記で、カレンダーに予定がある場合には、実行されるようになります。 次に件名「Start」で起動、「Stop」で停止をさせるためのcaseを作成していきます。

Controlのアクションから、Switchを選択していきます。

「On」に件名を選択し、各Swich動作を記載していきます。

4-3_VMの起動停止

各アクションを構成していきます。

今回はVMの起動停止なので、それらを選択していきます。

各VMを起動停止を行う設定を行います。

利用するユーザや、ロール等を考慮してください。

起動や停止の設定を行っていきます。

5_動作

カレンダーに登録すると、トリガーが動きVMの起動や停止を行えます。

6_おわりに

ただVMの起動停止を行いたいだけだという場合、 簡単にできますので試してみてください。

私達ACS事業部はAzure・AKSなどのクラウドネイティブ技術を活用した内製化のご支援をしております。ご相談等ありましたらぜひご連絡ください。

www.ap-com.co.jp

また、一緒に働いていただける仲間も募集中です!
今年もまだまだ組織規模拡大中なので、ご興味持っていただけましたらぜひお声がけください。

www.ap-com.co.jp

本記事の投稿者: 本田 和也
社内SEやサーバ構築などを行って来ていました

Azure Backupの利用上の注意点とコントロール方法について

本記事はAP Tech Blog Week Vol.5のものになります。

始めに

こんにちは、株式会社エーピーコミュニケーションズ クラウド事業部の藤江です。Azure Backupの利用上の注意点と注意点を回避するためのAzure Backupのコントロール方法について記します。

Azure Backupの概要

AzureVMやオンプレミスサーバなどのバックアップを取得するサービスです。バックアップの周期実行の設定や手動実行によるオンデマンド実行を行うことが出来ます。簡単な設定で自動的にバックアップを取ることが出来るサービスですがいくつか注意点があります。

Azure Backup利用上の注意点

バックアップが失敗する場合がある

Azure Backupは実行すれば確実に成功するとは保障されていません。そのためバックアップが失敗した場合に備えて監視設定やエラー処理を自前で準備する必要があります。

バックアップは指定した時刻に開始するとは限らない

別ユーザのリソースの利用状況などでバックアップの開始が遅延することがあります。

バックアップは一定時間内に完了するとは限らならない

バックアップの開始時刻と同様にバックアップは一定時間内に完了するとは限りません。ただし仕様上、24時間未満に完了すると定義されています。

バックアップの方法によってはアプリケーションレベルでのデータの整合性が保証されない

Azure BackupはOSの起動やファイルの整合性は保証してくれますが、アプリケーションレベルでのデータの整合性は保証されません。アプリケーションがバックアップ中にディスクに書き込むデータについてはバックアップには含まれないためバックアップのタイミングによっては、データの整合性が取れない状態でバックアップがとられる可能性があります。

Azure Backupをコントロールする方法

先ほど記した注意点について何かしらの対応が必要な場合はAzure Backupをコントロールする必要があります。今回は2点コントロールする方法について紹介します。

事前、事後スクリプトによるコントロール

Linux OS限定の機能になりますが、Azure Backupでディスクのスナップショット取得開始、終了のタイミングでVM内に置いたスクリプトを実行する機能があります。この機能を使えはDBなどのBackup中は停止しておきたいプログラムを停止してバックアップ後に起動することや、開始、終了時刻を判定して何かしらの処理を実行することなどが実現できます。今回の例はナップショット取得開始時にpostgresqlを停止、取得完了時に実行させる設定例を記します。

設定方法

設定例の概要

今回は/root/binに事前スクリプト/pre-script.sh、事後スクリプトpost-script.shを設定する例をしまします。事前事後スクリプトの実行に係る設定ファイルは/etc/azure/VMSnapshotScriptPluginConfig.jsonに固定で設置することが決まっています。設定はすべて管理者権限が必要なため管理者権限があるユーザで設定します。

事前、事後スクリプトの設置

事前、事後スクリプトを設置します。 設置場所やファイル名は任意でよいです。 最初にスクリプトの置き場と空スクリプトファイルを作成します。 実行権限の設定を忘れずに実施してください。

# スクリプト保存用のディレクトリの作成
$ mkdir /root/bin

# 空のスクリプトファイルを作成する。
$ cd /root/bin
$ touch pre-script.sh
$ touch post-script.sh
$ chown root:root pre-script.sh
$ chmod 700 pre-script.sh
$ chown root:root post-script.sh
$ chmod 700 post-script.sh

スクリプトファイルをエディタで開き、実行する処理を記述します。
pre-script.shの内容は下記のとおりです。

#! /bin/bash
systemctl stop postgresql.service

post-script.shの内容は下記の通りです。

#! /bin/bash
systemctl start postgresql.service
設定ファイルの設置

設定ファイルを/etc/azureに設置します。/etc/azureが無ければ作成します。設定ファイル名はVMSnapshotScriptPluginConfig.jsonです。

mkdir -p /etc/azure
touch /etc/azure/VMSnapshotScriptPluginConfig.json
$ chown root:root /etc/azure/VMSnapshotScriptPluginConfig.json
$ chmod 600 /etc/azure/VMSnapshotScriptPluginConfig.json

設定内容は下記のページを参考にして設定します。
MicrosoftAzureBackup/VMSnapshotPluginConfig
今回の例に対応する設定ファイルの内容は下記のような内容です。設定内容の詳細については参考ページに記されているので確認してください。

{
    "pluginName" : "ScriptRunner",
    "preScriptLocation" : "/root/bin/pre-script.sh",
    "postScriptLocation" : "/root/bin/post-script.sh",
    "preScriptParams" : ["", ""],
    "postScriptParams" : ["", ""],
    "preScriptNoOfRetries" : 0,
    "postScriptNoOfRetries" : 0,
    "timeoutInSeconds" : 30,
    "continueBackupOnFailure" : true,
    "fsFreezeEnabled" : true
}

事前、事後スクリプトと設定ファイルを設置すると次回のAzure Backupから事前、事後スクリプトが動作するようになります。

注意事項
エラー処理の記述

Azure Backup側ではスクリプトがどの処理で失敗したのか判断できません。実際の運用ではエラー処理をスクリプトに記述してスクリプト実行時にエラーに対応する必要があります。今回の事前、事後スクリプトにはエラー処理は記載していませんが実際の運用ではエラー処理をスクリプトに記述してください。

スクリプトファイルおよび設定ファイルへの所有権及び、実行権限の設定

事前、事後スクリプト、設定ファイルの所有者と実行権限を間違えないように設定してください。事前、事後スクリプトファイルの所有者はrootを指定し、所有者のみ読み込み、書き込み、実行できるように設定します。設定ファイルの所有者はrootを指定し、所有者のみ書き込み、読み込みができるように設定してください。重要なポイントなため改めて設定方法を記します。

# 事前、事後スクリプトの所有者、実行権限の設定方法
$ chown root:root pre-script.sh
$ chmod 700 pre-script.sh
$ chown root:root post-script.sh
$ chmod 700 post-script.sh

# 設定ファイルの所有者、実行権限の設定方法
$ chown root:root /etc/azure/VMSnapshotScriptPluginConfig.json
$ chmod 600 /etc/azure/VMSnapshotScriptPluginConfig.json
事前、事後スクリプトの内容にかかわらず実行しただけでアプリケーション整合性のあるバックアップと判定される

スクリプトの内容がアプリケーションのコントロールと関係がない内容でも、スクリプトの実行に成功すればAzure Backup側はアプリケーションレベルで整合性が取れたバックアップの取得が成功したと判定されます。 そのため事前、事後スクリプトを設定してバックアップを取得した後にスクリプトの動作検証を行い、アプリケーションレベルでの整合性が取れたバックアップが取得できたのか検証する必要があります。

Azure CLI、Azure Powershellなどのスクリプトによるコントロール

事前、事後スクリプト機能がないWindows OSや事前、事後スクリプトだけでは実現できないより細かいコントロールが必要な場合は、Azure CLIやAzure Powershellを使用してオンデマンドバックアップを実行してバックアップを取得するのが良いです。VM内にAzure CLIやAzure Powershellをインストールしてバックアップを行う方法でもよいですが、VMにこれらをインストールできない場合はAzure Automationを使い、Azure CLIやAzure Powershellを実行することが出来ます。Azure BackupをスクリプトによってコントロールするにはAzure Backup Recovery Services コンテナーにアクセスできる権限が必要になります。アクセス権限はバックアップ オペレーターの権限が必要で、このロールをマネージドidやシステムidに割り当てればバックアップを取得することが出来ます。

まとめ

Azure Backupは簡単な設定で自動バックアップを取得することが出来ますが、細かい制約があり、自力でコントロールする必要がある場合は事前、事後スクリプトやAzure CLI、Azure Powershellを使ってAzure Backupをコントロールしてバックアップを取得するのが良いです。

参考

クラウドコンピューティングの主役:AzureとAWSの比較(Feat. Chat GPT)

AzureとAWSは、クラウドコンピューティング市場で最も広く使用されている2つのプラットフォームです。どちらも企業、開発者、スタートアップなど、さまざまなユーザーに強力なクラウドサービスを提供しており、それぞれ独自の利点と特徴を持っています。この記事では、AzureとAWSをいくつかの観点から比較し、各プラットフォームが提供するサービス、価格、セキュリティ、使いやすさなどについて説明します。

1. 市場シェアと歴史

AWS(Amazon Web Services)は2006年に設立された、最初の大規模なクラウドサービスプロバイダーであり、長年にわたり市場のリーダーとしての地位を保っています。2023年の時点でも、AWSは依然として最大の市場シェアを誇っています。

一方、Microsoft Azureは2010年にリリースされ、Microsoftの強力な企業顧客基盤とWindowsやその他のMicrosoft製品との高い互換性を活かして急速に成長しました。特に、AzureはMicrosoftの従来のソフトウェア製品と統合を希望する企業に人気があります。

2. 提供するサービスの範囲

AWSはIaaS(Infrastructure as a Service)、PaaS(Platform as a Service)、SaaS(Software as a Service)を含む200以上のサービスを提供しており、特にデータストレージ(S3)、コンピューティングパワー(EC2)、データベース(RDS、DynamoDB)などのサービスで強みを発揮します。AWSは、グローバルな拡張性に優れた、世界中に多くのデータセンターリージョンを持っています。

Azureも200以上のサービスを提供しており、特にWindowsベースのアプリケーションとMicrosoftソフトウェアスタック(例: Active Directory、Office 365、SQL Serverなど)との統合が優れています。Azureはハイブリッドクラウドソリューションで特に優れており、オンプレミスのデータセンターとクラウド環境を結びつけたハイブリッド環境の構築が容易です。

3. 価格

両プラットフォームとも、使用量に応じた価格体系を持っており、サービスの利用量に応じて料金が変動します。基本的には 従量課金(pay-as-you-go) 方式ですが、AWSは無料枠を提供しており、新規ユーザーが簡単に試せるようにしています。

AWSはリージョンごとに価格が異なり、Azureは同じサービスに対して若干安価に提供する傾向がありますが、これも地域や使用ケースによって異なります。価格比較は具体的なニーズやワークロードに依存するため、実際に使用するサービスに基づいた見積もり比較が必要です。

4. 対応言語とツール

AWSはPython、Java、.NET、Node.jsなど、さまざまなプログラミング言語に対応しており、AWS CLI、SDK、CloudFormationといったツールを通じて自動化やインフラ設定をサポートします。

Azureも.NET、Python、Java、Node.jsなどの複数の言語をサポートしていますが、特に .NET ベースのアプリケーション開発とデプロイメントに強みがあります。Visual Studioなどの開発ツールとの統合が優れており、Azure DevOpsを利用してCI/CDパイプラインを簡単に設定できます。

5. セキュリティとコンプライアンス

AWSとAzureの両方がクラウドセキュリティを非常に重視しており、データの暗号化、認証、ネットワーク保護など、多様なセキュリティ機能を提供しています。両プラットフォームとも、GDPR、HIPAA、SOC 2などのさまざまなコンプライアンス要件を満たしています。

AWSはセキュリティグループとネットワークACLによる階層的なセキュリティ管理を提供し、AzureはSecurity CenterやAzure Active Directoryを使用してセキュリティとコンプライアンス管理を統合的に行えます。特にAzureは、Microsoftのセキュリティフレームワークと密接に連携しており、Microsoft製品を多く使用している企業に適しています。

6. グローバルリージョンと可用性

AWSは30以上のリージョンと99以上のアベイラビリティゾーン(Availability Zone)を持っており、Azureは60以上のリージョンでサービスを提供しています。AWSは地域ごとにより多くの可用性を提供しており、地理的に分散したリージョンでデータを管理したい顧客に有利です。

Azureは特定の地域でより多くのリージョンを提供しており、特にアジアやヨーロッパで強い存在感を示しています。AzureのグローバルインフラはMicrosoftのデータセンターと密接に連携しており、地域ごとに多様な選択肢を提供します。

7. ユーザーエクスペリエンスと学習曲線

AWSは初めて使用するユーザーにとってはやや複雑かもしれませんが、充実したドキュメントやユーザーコミュニティ、認定プログラムを提供しています。AWSは開発者中心のインターフェースを持ち、クラウドリソースの直接制御と管理に優れた経験を提供します。

Azureは既存のMicrosoftユーザーにとってはより親しみやすいインターフェースとエクスペリエンスを提供します。特にAzureポータルは直感的なUIで知られており、Microsoftエコシステムとの統合がスムーズで、Windowsベースの環境で作業するユーザーにとっては簡単に適応できるでしょう。

結論

AWSはクラウド市場をリードしてきたプラットフォームであり、広範なグローバルインフラと多様なサービスを通じて、さまざまな顧客ニーズに対応します。一方、AzureはMicrosoft製品との統合に優れており、特にハイブリッドクラウドやエンタープライズ環境で強力な競争力を発揮します。

したがって、AWSとAzureのどちらを選択するかは、ユーザーの具体的なニーズ、既存のインフラ、予算、技術スタックに依存します。

Azure Kubernetes ServiceでのGitOps活用(Argo CDで試してみる)

本記事はAP Tech Blog Week Vol.5のものになります。

はじめに

こんにちは、ACS事業部の小原です。

Kubernetes環境の管理やデプロイメントは、手動操作が多く、エラーのリスクも高いと感じていませんか?
今回は、そんな悩みを解決する1つの手段として、GitOpsツールであるArgo CDを用いた自動化について取り上げます。
Azure Kubernetes Service (AKS)環境と連携させてみたいと思います。

Argo CDを活用することで、インフラをコードとして管理し、Gitリポジトリの履歴から変更を追跡できるようになります。

  • 一貫性と再現性のある環境構築
  • 手動操作によるヒューマンエラーの削減
  • 迅速かつ安全なデプロイ
  • 変更履歴の可視化とロールバックの容易さ

を実現できます。


本記事のゴール

以下の理解が進むことをゴールとします。

  • GitOps、Argo CDとは何か
  • Argo CDの導入方法
  • GitOpsを使うと何がうれしいのか


用語の説明

  • GitOps

    • バージョン管理システムであるGitを使いインフラ管理を一元的に管理する方法
    • DevOpsの手段のひとつ
  • Argo CD

    • GitOpsを実現するためのツールの1つ
    • Gitリポジトリ内のマニフェストと実際のクラスターの状態と比較し、差異があればクラスターへ反映する


構成

前提

すでにAKS環境が用意されアクセスできることを前提に進めます。


実践

Gitリポジトリを信頼できる情報源として、AKSクラスターの管理とデプロイを自動化していきたいと思います。


1. 事前準備(オプション)

asdfのインストール
私の環境では、バージョン管理ツールのasdfを準備することにします。
今後、異なるバージョンを使用したい場合に切り替えられるようにするためです。
こちらを参考にダウンロードとインストールを進めます。 asdf-vm.com

プラグインの追加
argocdプラグインをasdfに追加します。

$ asdf plugin add argocd


インストール
argocdの最新バージョンをインストールしてみます。

$ asdf install argocd latest

インストールしたバージョンを確認します。

$ asdf list argocd
 *2.12.4

今回はバージョン2.12.4を使っていきます。


グローバルの設定
利用したいバージョンを設定します。

$ asdf global argocd latest



2. Argo CDのインストール

公式ページの手順を参考に進めていきます。

argo-cd.readthedocs.io


ネームスペース作成
ネームスペースを作成することで、Kubernetesリソースを論理的に分離できます。

$ kubectl create namespace argocd


マニフェストファイルの適用
AKSクラスターにArgo CDをインストールします。
-fオプションで指定しているマニフェストファイルには、Argo CDのインストールに必要なリソースが定義されています。

$ kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.12.4/manifests/install.yaml


Argo CD API サーバーへのアクセス
今回はLoadBalancerサービスタイプを使います。
※ローカル環境で構築の場合は、ポートフォワーディングが分かりやすいと思います。

$ kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'


パスワードの取得
初期パスワードを取得します。 Argo CDの管理画面にログインする際に使用します。

$ argocd admin initial-password -n argocd


ログイン
argocd-serverのEXTERNAL-IPを確認します。

$ kubectl get svc -n argocd

Argo CDにログインします。確認したEXTERNAL-IPをloginの後に指定します。
--insecureオプションで証明書の検証をスキップします。

$ argocd login {IPアドレスまたはホスト名} --insecure


ブラウザからもアクセスしてみます。
ログイン情報を入力し管理画面に入ります。


3. Gitリポジトリからアプリケーション作成

リポジトリの用意
サンプルリポジトリををforkします。
https://github.com/argoproj/argocd-example-apps.git


アプリを作成
現在のネームスペースをargocd に設定します。

$ kubectl config set-context --current --namespace=argocd


サンプルのguestbookアプリケーションを作成します。

$ argocd app create guestbook --repo https://github.com/{fork先の指定に合わせる}/argocd-example-apps.git --path guestbook --dest-server https://kubernetes.default.svc --dest-namespace default


ブラウザの管理画面に戻ると、現時点ではステータスが以下のようになっています。


guestbookを選択すると以下の画面が開きます。
SYNCを選択します。


そのままSYNCHRONIZEを選択します。


以下のようにSyncが完了します。


先程のステータスも変わっていますね。


リソースの確認
リソースが作成されたことを確認します。

$ kubectl -n default get deploy,svc,rs,pod
NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/guestbook-ui   1/1     1            1           6m14s

NAME                   TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
service/guestbook-ui   ClusterIP   10.0.255.229   <none>        80/TCP    6m15s
service/kubernetes     ClusterIP   10.0.0.1       <none>        443/TCP   37m

NAME                                      DESIRED   CURRENT   READY   AGE
replicaset.apps/guestbook-ui-56c646849b   1         1         1       6m15s

NAME                                READY   STATUS    RESTARTS   AGE
pod/guestbook-ui-56c646849b-v4b8h   1/1     Running   0          6m15s


4. マニフェストの変更と反映

Syncの自動化
--sync-policy automatedの設定により、自動的に変更を検知することもできます。

$ argocd app set guestbook --sync-policy automated


マニフェスト編集
argocd-example-apps/guestbookにあるguestbook-ui-deployment.yamlを編集します。
replicasの値を1から2へ変更してみます。編集が終わったらcommitします。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: guestbook-ui
spec:
  replicas: 2  # ここを変更
  revisionHistoryLimit: 3
  selector:
(略)


変更が検出され、Podが2つになったことを確認できます。

CLIで確認してみます。

$ kubectl get po -n default
NAME                            READY   STATUS    RESTARTS   AGE
guestbook-ui-56c646849b-mgnxm   1/1     Running   0          11m
guestbook-ui-56c646849b-v4b8h   1/1     Running   0          25m

2つのPodがRunningステータスで動いていますね!

5. 片付け

  • Argo CD APIサーバーへのアクセスで、ポートフォワーディングを使用している場合は停止する
  • 必要に応じAKS環境を削除する


まとめ

何がうれしかったのか整理してみます。

  • インフラをコードとして管理することで、一貫性と再現性を確保できた
  • 手動操作を減らし、自動化されたプロセスでデプロイメントを行うため、エラーのリスクが低減した
  • Gitリポジトリの履歴から、インフラの変更履歴を簡単に追跡したり、ロールバックができる

GitOpsでKubernetesの運用を効率化することができました。
AKSとの連携もスムーズに行えました。
Argo CDはGUIが備わっているのも視覚的でいいですね。たこさん(?)も可愛いですね。

実際の環境では、変更が反映される前に承認プロセスを挟むなど、環境にあわせて制御があるとよさそうです。 今後もGitOpsについて深堀りしていきたいと思います。


その他参考

Azure Kubernetes Service向けGitOps learn.microsoft.com



ACS事業部のご紹介

私達ACS事業部はAzure・AKSなどのクラウドネイティブ技術を活用した内製化のご支援をしております。

www.ap-com.co.jp

また、一緒に働いていただける仲間も募集中です!
今年もまだまだ組織規模拡大中なので、ご興味持っていただけましたらぜひお声がけください。

www.ap-com.co.jp

本記事の投稿者: 小原 丈明
Azureをメインにインフラ系のご支援を担当しています。

Microsoft Defender for Cloud DevOps security の Microsoft Security DevOps GitHub Action を触ってみた

本記事はAP Tech Blog Week Vol.5のものになります。

はじめに

こんにちは。ACS事業部の青木です。
この記事では、Microsoft Defender for Cloud DevOps security の Microsoft Security DevOps GitHub Action の利用方法について解説したいと思います。

本記事の対象読者

この記事は、以下3点に該当する方を読者と想定しています。

  1. AzureでIaCを用いたインフラリソースの構築や、アプリケーションの開発を行っている
  2. コード管理にGitHubを使用している(プラン種別は問いません)
  3. ソースコード管理だけでなく、GitHub ActionsのようなCI/CDパイプラインも使用したDevOps的手法を用いて開発を行っている

開発プラットフォームにおけるセキュリティ対策の必要性

いわゆる、 "DevOps" 的な開発ライフサイクルを用いる場合、開発を行いつつセキュリティ的な脆弱性を担保する必要が求められます。
例えば以下のようなものです。

  • コンテナイメージやライブラリパッケージの脆弱性
  • IaCやアプリケーションコードなど、コード上に存在する脆弱性
  • パイプライン環境構成における脆弱性

これらを考慮しながら迅速な開発を進めていくのはとても骨の折れる作業です。
Microsoft Defender for Cloud DevOps security を利用することで、上記のような開発環境や作成した成果物に対するセキュリティの状態の可視化させたり、推奨される構成についての提案を受けたりすることができます。

様々な機能が存在しますが、今回はその中でもGitHub Actionsと連携してセキュリティスキャンを行ってくれる機能である「Microsoft Security DevOps GitHub Action」について深堀をしていきたいと思います。

Microsoft Defender for Cloud DevOps security について

そもそも Microsoft Defender for Cloud DevOps security とは?

Microsoft Defender for Cloud DevOps securityは、Microsoft Defender for Cloud の製品の中の一つで、DevOps プラットフォームのセキュリティ情報を統合プラットフォームで管理できるツールです。
現在、以下3つのプラットフォームに対応しており、事前に環境を接続しておくことで、セキュリティスキャンの結果などを Defender for Cloud DevOps security の画面に表示することができます。

  • Azure DevOps
  • GitHub
  • GitLab

learn.microsoft.com

DevOps security における GitHub プラットフォームの使用制限緩和について

実は、最近までは GitHub 環境を Defender for Cloud に接続するためには、GitHub Enterprise ライセンスが必須でした。
しかし、2024年07月にその制限がなくなり、GitHub のプランに関係なくこの機能が利用できるようになりました!

プレビュー: GitHub のセキュリティ評価で追加のライセンスが不要になりました learn.microsoft.com

Microsoft Security DevOps GitHub Actionとは?

Microsoft Security DevOps GitHub Action は、Microsoft Defender for Cloud DevOps security の中で GitHub 環境を利用する際に使用できるツールです。 Microsoft Defender for Cloud DevOps security に GitHub Organization を接続した後に利用できるセキュリティスキャンツールで、接続した GitHub Organization が管理している GitHub リポジトリ の GitHub Actions ワークフローにセキュリティスキャンのステップとして設定することで、リポジトリ上のコードや GitHub Actions 上でビルドしたイメージにセキュリティスキャンを行うことができます。
(セキュリティスキャンの結果は自動的にDefender for Cloud DevOps securityのスキャン結果画面に表示されます)

Microsoft Security DevOps GitHub Action ではスキャンエンジンとしてOSSのツールを採用しており、スキャン対象に応じて使用するツールを使い分けることができるようになっています。
採用されているツールは以下のようなものがあります。

learn.microsoft.com

Microsoft Security DevOps GitHub Action を使ってみる

GitHub Organization を Microsoft Defender for Cloud に接続する

Microsoft Security DevOps GitHub Action を利用するには、まず Microsoft Defender for Cloud に GitHub Organization を接続する必要があります。
接続用のリソースを作成することで、接続した Organization 配下のリポジトリを自動検出し、Defender for Cloud の画面で確認することができるようになります。
また、GitHub Organization側にも GitHub Apps の設定が必要となりますが、設定は簡単です。

以下の手順を参考に、接続作業を行ってください。

learn.microsoft.com

GitHub Actionsでセキュリティスキャン用ワークフローを作成する

環境を接続できたら、次にワークフローを作成しましょう。

ワークフロー設定時に参照するドキュメントについて

まずは公式サイトを見てみましょう。
以下のページを見ると、サンプルのワークフローを見ることができます。 learn.microsoft.com

しかし、自分の環境の都合に合わせて細かいカスタマイズを行いたい場合は、Microsoft Security DevOps GitHub Action のWikiを確認しましょう。

github.com

こちらのページで見ると、Microsoft Security DevOps GitHub Action 共通の設定項目と、スキャンツール別の設定項目があることが分かります。
また、パラメータの設定方法にも以下二通りありますので、状況に応じて好みの設定方法を採用しましょう。

  • *.gdnconfigファイルに設定する
  • ワークフローファイルの環境変数として設定する

(例)Microsoft 標準のセキュリティスキャンを行いたい場合

Microsoft Security DevOps GitHub Action はデフォルトで GitHub のセキュリティ標準でセキュリティスキャンツールを自動で選定し、動作しています。
しかし、以下のようにワークフローを設定することで、 Microsoft のセキュリティ標準 でセキュリティスキャンを行うことができます。

steps:
- name: Run Microsoft Security DevOps
   uses: microsoft/security-devops-action@latest
   with:
     policy: 'microsoft'

実行結果のログは以下の通りです。 bandit、checkov、credscan、iacfilescannerなどが動いていることが分かりますね。

(例)IaCカテゴリのセキュリティスキャンを行う場合

IaC カテゴリのセキュリティスキャンツールのみを動作させたい場合は、以下のように設定します。

steps:
- name: Run Microsoft Security DevOps
   uses: microsoft/security-devops-action@latest
   with:
     categories: 'IaC'

実行結果のログは以下の通りです。 checkovだけが動作しています。

実践例: コンテナイメージをビルドし、コンテナイメージのセキュリティスキャンを行う

では、より実践的な例を見てみましょう。

ここでは、「mainリポジトリにマージを行ったタイミングで処理を実行する」という想定で、以下のことを実施するワークフローを作成してみます。

  • GitHub Actionsでリポジトリ上にあるDockerfileを参照し、コンテナイメージをビルドする
  • Microsoft Security DevOps GitHub Action でセキュリティスキャンを行う
  • セキュリティスキャンの結果、脆弱性が発見されたら GitHub Actionsを異常終了させる。脆弱性が無ければ ACR にプッシュを行う

ワークフローを作成する

今回、リポジトリには以下のようなDockerfileを用意しました。
脆弱性が含まれるよう、あえて古いベースイメージを使用しています。

FROM centos:centos6

GitHub Actions のワークフロー例は以下の通りです。

name: Build image and deploy

# mainブランチにプッシュされたときにワークフローが実行される
on:
  push:
    branches: [ main ]
    
permissions:
  contents: read
  id-token: write
  actions: read

jobs: 
  build:
    runs-on: ubuntu-latest
    name: Build & Push
    steps:
      # チェックアウト
      - uses: actions/checkout@v3

      # Azureにログイン
      - name: Login to Azure Public Cloud
        uses: Azure/login@v1
        with:
          # 認証情報にリポジトリに登録しているSecretsを使用
          creds: ${{ secrets.AZURE_CREDENTIALS }}

      # コンテナイメージをビルドする
      - name: Container image build
        run: |
          # ACRにログイン
          az acr login -n ${{ vars.ACR_NAME }}
          # ACRにプッシュするためのタグでコンテナイメージをビルド
          docker build -t ${{ vars.ACR_NAME }}.azurecr.io/${{ vars.APP_NAME }}:latest .
 
     # Microsoft Security DevOps GitHub Actionを実行
      - name: Run Microsoft Security DevOps
        uses: microsoft/security-devops-action@latest
        with:
          # スキャンツールとしてTrivyを選択
          tools: 'trivy'
        env:
          # コンテナイメージをスキャン対象とする
          GDN_TRIVY_ACTION: image
          # イメージタグでセキュリティ対象のコンテナイメージを指定
          GDN_TRIVY_TARGET: ${{ vars.ACR_NAME }}.azurecr.io/${{ vars.APP_NAME }}:latest
          # HIGH, CRITICALの脆弱性のみ検知する
          GDN_TRIVY_SEVERITIES: HIGH,CRITICAL
          # 脆弱性が検知されたら異常終了する
          GDN_TRIVY_EXITCODE: 1

      # (脆弱性がなかったときのみ実施)コンテナイメージをACRにプッシュ
      - name: Push container image
        run: |
          docker push ${{ vars.ACR_NAME }}.azurecr.io/${{ vars.APP_NAME }}:latest

スキャン実行で使用したパラメータは、Trivy Environment Variablesを参照して設定しています。
これらのパラメータはTrivyのオプションをベースに用意されているため、各パラメータ自体の意味がよくわからない場合は Trivy docsTrivy Actionをまず参照し、Trivy自体の理解を深めると良いでしょう。

実行結果

このワークフローを記載した状態でワークフローを実行すると、以下のように脆弱性が検知され、処理が失敗します。

では、Defender for Cloud DevOps security の画面でスキャン結果を見てみましょう。
Azure Portal で "Microsoft Defender for Cloud" をクリックします。

"DevOps セキュリティ"→"DevOps ブック"とクリックします。

"コード"タブをクリックすることで、セキュリティスキャン結果を確認することができます。
使用するツールによってセキュリティ結果が出力されるタブは変わりますので、注意しましょう。

おわりに

いかがでしたか?
Azure を開発環境として使用されている方には、アプリケーションのセキュリティレベルを高めるためにMicrosoft Defender for Cloud DevOps securityを使用するのはとても有効な選択肢だと思います。
本ページでは GitHub を利用されている方向けの解説となりましたが、Azure DevOps や GitLab でも利用できるツールのため、ぜひ使ってみてください。

私達ACS事業部はAzure・AKSなどのクラウドネイティブ技術を活用した内製化のご支援をしております。ご相談等ありましたらぜひご連絡ください。

www.ap-com.co.jp

また、一緒に働いていただける仲間も募集中です!
今年もまだまだ組織規模拡大中なので、ご興味持っていただけましたらぜひお声がけください。

www.ap-com.co.jp

本記事の投稿者: 青木 平
ウィスキー好きな柔道初段のエンジニア

【AP Tech Blog Week】Azure × 自動化をテーマにしたブログ投稿週間を開催します

こんにちは、エンジニアリングメンター室(以降EM室)所属の山路です。

今回は、社内エンジニア向けのブログ投稿応援企画として、AP Tech Blog Weekというイベントを開催するので、その案内をさせていただきます。

なお今回のテーマと開催時期は以下の通りです。

テーマ: Azure × 自動化

開催時期: 2024年10月28日~11月1日

AP Tech Blog Weekとは

AP Tech Blog Weekは、弊社エンジニアが技術ブログをアウトプットする機会として開催する技術イベントの一つです。

本イベントでは毎回技術テーマを1つ設定し、テーマに沿った内容でブログを投稿していただきます。

なおBlog Weekというイベント名の通り、ブログ記事を投稿する週は指定しますが、誰がいつ投稿するかは特に指定しない、比較的ゆるいイベントとなります。

※過去のBlog Weekについてはこちらをご覧ください。

今回のテーマは?

今回のテーマは「Azure × 自動化」です。

弊社は数年前からACS事業部を中心にAzureに力を入れており、マイクロソフト様のパートナー認定や各種支援サービスの提供、Azureに関する技術情報発信を継続して実施しております。

www.ap-com.co.jp

techblog.ap-com.co.jp

現在ではACS事業部以外もAzureを扱うプロジェクトが増加しており、企業全体でAzureに関する支援をサポートできる体制が出来つつあります。

今回は弊社の中心事業となったAzureを取り上げつつ、その中でも要望が多い「自動化」をキーワードとしました。本記事投稿時点ではどのような記事が投稿されるか把握できておりませんが、Azureにおける自動化について、幅広いテーマの記事が投稿されるのではと期待しています。

イベント時期・投稿記事

今回のAP Tech Blog Weekの開催時期は「2024年10月28日~11月1日」となります。

また、このイベントへの参加者数ですが、本記事投稿時点で6名が参加予定となっています。

さいごに

APCではAzureに強い・興味のあるエンジニアを積極的に採用しております。ご興味のある方は以下のページから、お気軽にご連絡ください。

hrmos.co

Azure AppService / Container AppsでManaged Identityを利用する

こんにちは。ACS事業部亀崎です。

最近取り組んでいたBackstage RBAC Policy対応のため、Open Policy Agentopa-serverをAzure Container Appsで利用するための設定をする機会がありました。

Backstage RBAC Policyの対応についてはぜひ以下の投稿をご覧ください。

techblog.ap-com.co.jp

opa-serverはPolicyという設定情報の置き場としてAzure Blob Storageを利用することができるのですが、アクセスの際の認証方法としてmanaged identityが利用できるように記載されていました。そのドキュメントに従って指定するのですが、どうしてもアクセスができませんでした。

そこで、Azureプロフェッショナル集団でもある私達のチームメンバーにも確認したところ、Azure VMとAzure Container Appsではmanaged identityの利用方法が違う、ということを教えてもらいました(ちょっと質問したらすぐに「それはこうだよ」と応えてくれるチームメンバー、本当に頼もしいです

ではどうやればできるのか。その調査結果とその後の対応について今回はお伝えしたいと思います。

Azure Managed Identityとは

Blob Storageなど、Azureリソースにアクセスする際にはアクセストークンが必要になります。外部からアクセスする際にはあらかじめ発行した資格情報(セキュリティトークン)を利用します。しかし、できればそうした資格情報はアプリケーション側に持たせたくないものです。そうしたときに利用するのがAzure Managed Identityです。 Managed Identityを利用することでアプリケーション側には資格情報をもたせる必要なく自動的に認証をサポートするAzure内の仕組みです。

learn.microsoft.com

Azure内で動かすサービスならば積極的に活用したいものの1つではないでしょうか。

アプリケーションでの利用方法

Azure VM上のアプリケーションで利用する場合

Azure VM上でmanaged identityを利用してAzure Access Tokenを取得するには、Azure Instance Metadata Service(IMDS)というサービスを利用します。

learn.microsoft.com

実際には http://169.254.169.254/metadata/identity/oauth2/token エンドポイントに対し、resource(scope)やapi-versionを指定し、さらにHTTP Headerに Metadata: true という値を設定してリクエストします。

(request)

$ curl 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/' -H Metadata:true

すると以下のような応答が返ってきます。

response

{
  "access_token":"eyJ0eXAiOi...",
  "refresh_token":"",
  "expires_in":"3599",
  "expires_on":"1504130527",
  "not_before":"1504126627",
  "resource":"https://management.azure.com",
  "token_type":"Bearer"
}

ここで返されるaccess_tokenをAzure Resourceにアクセスする際のTokenとして利用します。

learn.microsoft.com

Azure AppService / Azure Container Appsの場合

Azure AppService(Azure Functions)やContainer Appsの場合、上記のIMDSエンドポイントにアクセスすることができません。 実はこれらの環境では別の方法が提供されています。

learn.microsoft.com

Azure Container AppsやApp Serviceでmanaged identityを有効にすると以下の2つの環境変数が設定されます。

IDENTITY_ENDPOINT="http://localhost:42356/msi/token"
IDENTITY_HEADER="853b9a84-5bfa-4b22-a3f3-0b9a43d9ad8a"

これらの値をエンドポイント、およびHTTP Headerで利用してアクセストークンを取得します。

request

curl `${IDENTITY_ENDPOINT}?resource=https://vault.azure.net&api-version=2019-08-01 -H x-identity-header:${IDENTITY_HEADER}

response

{
    "access_token": "eyJ0eXAi…",
    "expires_on": "1586984735",
    "resource": "https://vault.azure.net",
    "token_type": "Bearer",
    "client_id": "5E29463D-71DA-4FE0-8E69-999B57DB23B0"
}

SDKではどう扱っている?

すでにアプリケーションを開発されている方で、SDKをご利用の方は「こんなエンドポイントとか意識したことないよ」と思われるかもしれません。

実はその通りです。SDKは、環境変数など様々な情報を利用して環境を特定し、適切な方式を自動的に選択しています。

例えば、Go言語の場合は次のところで判定しています。

   c := managedIdentityClient{id: options.ID, endpoint: imdsEndpoint, msiType: msiTypeIMDS}
    env := "IMDS"
    if endpoint, ok := os.LookupEnv(identityEndpoint); ok {
        if _, ok := os.LookupEnv(identityHeader); ok {
            if _, ok := os.LookupEnv(identityServerThumbprint); ok {
                if options.ID != nil {
                    return nil, errors.New("the Service Fabric API doesn't support specifying a user-assigned managed identity at runtime")
                }
                env = "Service Fabric"
                c.endpoint = endpoint
                c.msiType = msiTypeServiceFabric
            } else {
                env = "App Service"
                c.endpoint = endpoint
                c.msiType = msiTypeAppService
            }
        } else if _, ok := os.LookupEnv(arcIMDSEndpoint); ok {
            if options.ID != nil {
                return nil, errors.New("the Azure Arc API doesn't support specifying a user-assigned managed identity at runtime")
            }
            env = "Azure Arc"
            c.endpoint = endpoint
            c.msiType = msiTypeAzureArc
        }
    } else if endpoint, ok := os.LookupEnv(msiEndpoint); ok {
        c.endpoint = endpoint
        if _, ok := os.LookupEnv(msiSecret); ok {
            if options.ID != nil && options.ID.idKind() != miClientID {
                return nil, errors.New("the Azure ML API supports specifying a user-assigned managed identity by client ID only")
            }
            env = "Azure ML"
            c.msiType = msiTypeAzureML
        } else {
            if options.ID != nil {
                return nil, errors.New("the Cloud Shell API doesn't support user-assigned managed identities")
            }
            env = "Cloud Shell"
            c.msiType = msiTypeCloudShell
        }
    } else {
        c.probeIMDS = options.dac
        setIMDSRetryOptionDefaults(&cp.Retry)
    }

    client, err := azcore.NewClient(module, version, azruntime.PipelineOptions{
        Tracing: azruntime.TracingOptions{
            Namespace: traceNamespace,
        },
    }, &cp)

github.com

JavaScriptの場合はいくつかのファイルに分かれて判定ロジックが記述されていますが、IDENTITY_ENDPOINTについては次のコードでチェックしています。

github.com

これらのロジックのお陰で意識することなく最適な方式で実現されています。

独自実装の例(opa-serverのその後)

では、どういった場合に今回の情報が必要になるのか。

それが私が遭遇した opa-server の例です。 opa-server のBlob StorageアクセスのロジックはSDKは利用せずに、独自でHTTP Requestを記述しています。私が調べ始めた段階では確かに managed identityはサポートしていましたが、Azure VM用のIMDSのみのサポートとなっていました。このため、Container Apps上で利用しようとしてもmanaged identityを使ったアクセストークン取得ができませんでした。

github.com

ということで・・・・

せっかくここまで調べたのですし、自分たちにとっても必要となる機能ですのでApp Service/Container Apps対応の修正を行い、Pull Requestを提出させていただきました。

github.com

2024年10月初旬にマージされているので、10月末から11月にかけてのリリースにて公開されるものと思います。

まとめ

この内容を知っておけば、Azure VM、Azure AppService、Azure Functions、Azure Container Appsどの環境を相手にしてもmanaged identityを利用することができるようになると思います。

あとはAKSです。実はAKSもまた少し違った方法が用意されています。そちらについては機会をあらためてご紹介したいと思います。

最後に、私達APC ACS事業部ではAzureによるSystem Modernize、Platform Engineering、Backstage、AIなどに関するお手伝いをさせていただいております。 話を聞かせて欲しいなどありましたらぜひご連絡ください。

株式会社エーピーコミュニケーションズ お問い合わせフォーム

それではまた次の機会でお会いしましょう。