ごった煮

色々な事を書いてます

Visual Studio 2022 + Azure Functions + Azure App Configuration + Managed Service Identity の構成をローカル実行する方法について(2022年5月)

Managed Service Identity (MSI) を使用して、App Configuration と接続する構成をとる場合、ローカル環境でも DefaultAzureCredential を使用していれば、問題なく動くはずなのですが 不思議な挙動に悩まされたので、備忘録を残します。

環境及び構成

  • Visual Studio 2022 (v.17.1.3)
  • Azure Functions (v4、in-process)

前提条件

  • ローカルからの認証に使用する Azure のアカウントには、App Configuration Data Reader ロールを付与済み
  • Visual Studio には、対象の App Configuration Data Reader ロールが付与済のアカウントでログイン済み

実装したソースコード

builder.ConfigurationBuilder.AddAzureAppConfiguration(o =>
{
    var connectionString = defaultConfig["AppConfig:ConnectionString"];
    if (string.IsNullOrWhiteSpace(connectionString))
    {
        var endpoint = new Uri(defaultConfig["AppConfig:Endpoint"]);
        o.Connect(endpoint, new DefaultAzureCredential());
    }
    else
    {
        o.Connect(connectionString);
    }

    var context = builder.GetContext();
    o.Select("*");
});

当初期待していた挙動

  • Visual Studio の認証情報を使用して、App Configuration への接続が認証され、App Configuration から設定情報が取得できる

実際の挙動

  • 認証エラーが返却される(401)

対処方法

デフォルトのサブスクリプションを切り替える

自分のアカウントは、複数のサブスクリプションに所属している + 今回接続したかったサブスクリプションがデフォルトのサブスクリプションに設定されていませんでした。

なので、まずデフォルトのサブスクリプションを設定しました。

az account set --subscription {サブスクリプション Id}

これでデフォルトのサブスクリプションが切り替わります。 この状態で、Function App を実行してみます。

Function App の実行結果

  • 認証エラーが返却される(401)

最初と同じ挙動です。

DefaultAzureCredential が使用するテナント Id を指定する

次に、Function App 側で、認証に行くテナントを直接指定します。

2パターン設定方法がありますので、好きな方法で指定します。

パターン1

DefaultAzureCredential の引数として、オプションにテナント Id を指定する方法です。

builder.ConfigurationBuilder.AddAzureAppConfiguration(o =>
{
    var connectionString = defaultConfig["AppConfig:ConnectionString"];
    if (string.IsNullOrWhiteSpace(connectionString))
    {
        var endpoint = new Uri(defaultConfig["AppConfig:Endpoint"]);
        o.Connect(endpoint, new DefaultAzureCredential(new DefaultAzureCredentialOptions
        {
            VisualStudioTenantId = "{{テナント Id}}"
        }));
    }
    else
    {
        o.Connect(connectionString);
    }

    var context = builder.GetContext();
    o.Select("*");
});

パターン2

local.settings.jsonAZURE_TENANT_ID を設定する

{
    "IsEncrypted": false,
    "Values": {
        //--- Development
        "AppConfig:ConnectionString": "",
        "AppConfig:Endpoint": "",
        "AZURE_TENANT_ID": "テナント Id",
    }
}

Azure 上では、このテナント Id を指定する必要はないので、個人的には、ソースコードを変更せずに済むこちらを使用しました。

設定が終わったら、Function App を実行します。

Function App の実行結果

  • 接続成功

テナント Id を指定した状態で、Azure CLI のデフォルトサブスクリプションを他のものに切り替える

次に、テナント Id を Function App で指定した状態で、Azure CLI の設定を元に戻します。

設定は、先ほどの az account set ~ で関係のないサブスクリプション Id を指定してみます。

変更したら、Function App を実行します。

Function App の実行結果

  • 認証エラーが返却される(401)

この挙動を見るに、Visual Studio + Function App の構成で MSI をローカルで使用したい場合、Azure CLI の設定 + テナント Id の指定が必要なようです。

まとめ

これバグなのでは?

Azure Functions Isolated (分離プロセス) にて Function App を停止する方法について

Azure functions の isolated では、Disable 属性が2022年1月現在使用できません。

Disable が使えないと色々厄介なので、やり方をメモとして残します。

やり方

Application 設定に、

キー名 :AzureWebJobs.{Function 名}.Disabled 値 : true

を設定します。

この方法は、in-process でも使用できる現在 Function App でアプリケーションを停止させるための推奨方法です。

まとめ

他にも Singleton 属性など使えないものがあったりするので、実践投入する際は、ご注意ください。

func.exe でデバッグ中にコンソールログが文字化けする際の対処方法

英語版 Windows に英語版 Visual Studio を入れた環境で、Function App のデバッグ中に表示されるコンソールメッセージが文字化けしたので、 対処方法をメモとして残します。

原因

ずばり原因は、コンソールのフォントが日本語に対応していない為でした。

デフォルトのフォントは、Consolas になっており、このフォントは、日本語に対応していない為、日本語が対応しているフォントに変更します。

フォントを変更

  1. コンソールのヘッダを右クリック > Properties を選択
  2. Font タブの Font から、日本語に対応しているフォントを選択。(自分は、HGGothicE を選択しました)

まとめ

これにて一件落着

EF Core 6 で json_value を使いたい

EF Core では、現状 json_value をそのまま使えないですが、どうしても json_value を使いたい用事があったので、出来るように実装しました。

やり方

  1. 生の SQL を書く
  2. DbFunctions で関数呼び出しを追加する

1番なら何でもできますが、今回は、もうちょっと EF Core を活用したいので、2 番で実装します。

実装する

まず DbFunction を定義します。

public static class DBFunctions
{
    public static string JsonValue(string column, string path)
    {
        throw new NotSupportedException();
    }
}

次に、DbContext を組み立てる OnModelCreating で先ほど定義した DbFunction をセットします。 下記のコードは、文字列を返すようにする設定です

modelBuilder.HasDbFunction(typeof(DBFunctions).GetMethod(nameof(DBFunctions.JsonValue)))
    .HasTranslation(args =>
        new SqlFunctionExpression("JSON_VALUE", args, nullable: true, argumentsPropagateNullability: new[] { false, false }, typeof(string), null));

日付型を返したいといった場合は、以下のような感じ

modelBuilder.HasDbFunction(typeof(DBFunctions).GetMethod(nameof(DBFunctions.JsonValueDateTime)))
    .HasTranslation(args =>
        new SqlFunctionExpression("JSON_VALUE", args, nullable: true, argumentsPropagateNullability: new[] { false, false }, typeof(DateTime), null));

使い方は、以下のような感じ

var customer = await _dbContext
    .Customer
    .Where(_ => DBFunctions.JsonValue(_.Value, "$[0].name") != null)
    .Select(_ => new
    {
        name = DBFunctions.JsonValue(_.Value, "$[0].name")
    })
    .ToListAsync();

このコードを実行すると、下記のような SQL に展開されます。

SELECT JSON_VALUE([c].[Value], N'$[0].name') AS [name]
FROM [customer] AS [c]
WHERE JSON_VALUE([c].[Value], N'$[0].name') IS NOT NULL

まとめ

これで json_value が使えるようになりました。

EF Core 7 では、いい加減 json column が対応するみたいなので、一時しのぎですがこれにて一件落着

英語版 Windows 11 でコンソールに表示される日本語が文字化けする話

us 版 Surface Laptop Studio を使っていると、コマンドラインで日本語が文字化けしたので、調査した結果を備忘録として残します。

環境

OS

システムロケール

  • English (United States)

Country or Region

  • Japan

とりあえず調べてみる

PowerShellchcp してみたところ、コードページは、437 でした。

てっきり 65001 かと思ってましたが違ったようです。

UTF-8 に変更する

  • 設定アプリの、Time & Language > Language & Region > Administrative language settings > Change system local を選択
  • Beta: Use Unicode UTF-8 for worldwide language support にチェック
  • 再起動

でシステムの文字コードUTF-8 になります。

まとめ

英語版は、てっきり UTF-8 かと思ってましたが、違うという学びを得ました。(以前 us で買った Surface Go は、こんなことなかった気がするのに。。。)

WSL2 の sudo でパスワードの代わりに Windows Hello を使う

Linux を使っていると、sudo で認証情報を求められますが、WSL の場合、せっかく Windows 上で動いているので、 認証に Windows Hello を使えると嬉しいですよね。

WSL Hello sudo というモジュールを入れると、これが実現できます。 備忘録も兼ねて導入方法を残します。

WSL Hello sudo とは

WSL Hello sudo は、Linux PAM モジュールと sudo で Windows Hello を使えるようにする Windows CLI アプリのセットです。

両方とも、Rust で書かれたツールです。

このツールは、WSL、WSL 2 の両方で使えます。

インストール方法

下記のコマンドを上から順に実行します。

wget http://github.com/nullpo-head/WSL-Hello-sudo/releases/latest/download/release.tar.gz
tar xvf release.tar.gz
cd release
./install.sh

instal.sh を実行すると、モジュールのインストール先を聞かれます。 デフォルトは、/mnt/c/{User フォルダ}/AppData/Local/Programs/wsl-hello-sudo です。

そのほか、インストール先フォルダが無い場合に生成するか、PAM モジュールをすぐに有効化するかなど聞かれるので、y/n で進みます。

最後の PAM を有効化するを y で進めれば使用できるようになります。

有効か・無効化の切り替え方法

下記のコマンドで PAM モジュールの管理画面を表示できます。

sudo pam-auth-update

Windows Hello Authentication を選択して、スペースでオン・オフを切り替えます。(アスタリスクが付いていれば有効)

f:id:papemk2:20220115221042p:plain

アンインストール

install.sh があるフォルダに uninstall.sh が生成されるので、そちらを実行します。

まとめ

これで、sudo を実行する際にパスワードの代わりに Windows Hello が使えるようになりました。 長いパスワードを使っている場合、毎回入れるのが大変だったり、パスワードマネージャからコピペしたりといった面倒な作業が 発生しがちですが、Windows Hello が使えれば、面倒な作業が減って便利なのでぜひ使ってみてください。