- 投稿日:2020-02-22T23:31:05+09:00
KeyVault のシークレット情報をマネージドIDを利用して取得する
どうしてこんなにわかりにくいのだろうか。。
ここを見たけどうまくいかず
https://docs.microsoft.com/ja-jp/azure/key-vault/tutorial-net-create-vault-azure-web-appこれに挑戦してようやく
https://news.mynavi.jp/article/zeroazure-23/はじめに
KeyVaultにServiceBusの接続情報をシークレットという形式で格納することで、Functionsにハードコーディングせずに済むという話。KeyVaultにFunctionsがシークレット情報ください、と問い合わせるわけだが、当然誰彼構わずわたすわけではなく。特定の認証された人にだけ渡すようになっている。これがマネージドID。
大まかな流れ
1.KeyVault(キーコンテナ)を作成
2.作成したキーコンテナにシークレット情報を格納
⇒この時シークレット識別子というのがアサインされるので、これをメモしておく。
3.VisualStadioでキーコンテナからシークレット情報を参照するコーディングを行う
(VSの新規プロジェクト>ASP.Core Web アプリケーションのテンプレートを指定)Program.cs// キーコンテナーのDNS名を設定する var keyVaultEndpoint = "https://keyvault-je-001.vault.azure.net/"; // Azure Key Vaultに接続するための追加の設定を記述する // 1.アプリをAzureに認証するためのアクセストークン取得プロバイダーのインスタンス化 var azureServiceTokenProvider = new AzureServiceTokenProvider(); // 2.Azure Key Vaultに接続するためのクライアントのインスタンス化 var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback)); // 3.Azure Key Vault(キーコンテナー)からシークレットにアクセスするための設定をbuilderに追加 builder.AddAzureKeyVault(keyVaultEndpoint, keyVaultClient, new DefaultKeyVaultSecretManager());4.デプロイして、テスト!してもつながりません。(500系エラー)
5.デプロイしたWebAppsのIDを選択し、こんな感じでオンに切り替えて保存
6.キーコンテナ>アクセスポリシーから「+アクセスポリシーの追加」を選択
7.さっきWebAppsでオンに切り替えたときに作成されたIDが選択可能になっているはずなので、選択してシークレットの一覧、参照を有効にして保存。
後記
Azure Key Vault を使用してサーバー アプリのシークレットを管理する
.NET Core の公式の Key Vault クライアントは、Microsoft.Azure.KeyVault NuGet パッケージの KeyVaultClient クラスです。 これを直接使用する必要はありませんが、— と ASP.NET Core の AddAzureKeyVault メソッドを使用すると、起動時にコンテナーのすべてのシークレットを Configuration API に読み込むことができます。 この手法では、残りの構成で使用するものと同じ IConfiguration インターフェイスを使用して、すべてのシークレットに名前を指定してアクセスできます。 AddAzureKeyVault を使用するアプリには、コンテナーに対する Get と List の両方のアクセス許可が必要です。
マイナビのサイトもMSのLearningでも実装方法はほぼ同じなことに気づきました。
MSのLearningだとProgram.cs内でわずかにこれだけ。キーコンテナを丸ごと読み込んで、必要なものだけアプリ内で抽出して(SeacretNameとの一致するものだけ)利用してるんですね。Program.csusing Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; namespace KeyVaultDemoApp { public class Program { public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((context, config) => { // Build the current set of configuration to load values from // JSON files and environment variables, including VaultName. var builtConfig = config.Build(); // Use VaultName from the configuration to create the full vault URL. var vaultUrl = $"https://{builtConfig["VaultName"]}.vault.azure.net/"; // Load all secrets from the vault into configuration. This will automatically // authenticate to the vault using a managed identity. If a managed identity // is not available, it will check if Visual Studio and/or the Azure CLI are // installed locally and see if they are configured with credentials that can // access the vault. config.AddAzureKeyVault(vaultUrl); }) .UseStartup<Startup>(); } }SecretTestController.csusing System; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; namespace KeyVaultDemoApp.Controllers { [Route("api/[controller]")] public class SecretTestController : ControllerBase { private readonly IConfiguration _configuration; public SecretTestController(IConfiguration configuration) { _configuration = configuration; // ★ごそっと一括で取得 } [HttpGet] public IActionResult Get() { // Get the secret value from configuration. This can be done anywhere // we have access to IConfiguration. This does not call the Key Vault // API, because the secrets were loaded at startup. var secretName = "SecretPassword"; var secretValue = _configuration[secretName]; // ★配列みたいなもので一致しているものだけとっている? if (secretValue == null) { return StatusCode( StatusCodes.Status500InternalServerError, $"Error: No secret named {secretName} was found..."); } else { return Content($"Secret value: {secretValue}" + Environment.NewLine + Environment.NewLine + "This is for testing only! Never output a secret " + "to a response or anywhere else in a real app!"); } } } }
- 投稿日:2020-02-22T22:49:40+09:00
AtCoder Beginner Contest 156 参戦記
AtCoder Beginner Contest 156 参戦記
ABC156A - Beginner
4分で突破. 書くだけ.
N, R = map(int, input().split()) if N >= 10: print(R) else: print(R - 100 * (10 - N))ABC156B - Digits
2分で突破. 書くだけ. K進数の 10 は K で、100 は K2 だと分かっていれば、K で何回割れるか調べるだけと分かるはず.
N, K = map(int, input().split()) result = 0 while N != 0: result += 1 N //= K print(result)ABC156C - Rally
3分半で突破. 書くだけ……なのは、この計算をしなれてるからなんですが. (Xi−P)2 が最小になる P は重心. 減色の K-means で3次元のこの計算をしてます…….
N = int(input()) X = list(map(int, input().split())) P = int(sum(X) / N + 0.5) print(sum((x - P) * (x - P) for x in X))ABC156D - Bouquet
70分半で突破. まず nC0+nC1+...+nCn = 2n を知っていないといけない. 私は知りませんでした orz. パスカルの三角形の Wikipedia 見てたら書いてあって知りました. これで過去に書いた mpow と mcomb を貼って終わりかと思ったら n! を求める部分があって 2≤n≤109 に殺される. a, b はたかだか 105 であることに気づき、nCk を求める別の式に組み替えてようやく解けた. 良問!
def mpow(x, n): result = 1 while n != 0: if n & 1 == 1: result *= x result %= 1000000007 x *= x x %= 1000000007 n >>= 1 return result def mcomb(n, k): a = 1 b = 1 for i in range(k): a *= n - i a %= 1000000007 b *= i + 1 b %= 1000000007 return a * mpow(b, 1000000005) % 1000000007 n, a, b = map(int, input().split()) result = mpow(2, n) - 1 result -= mcomb(n, a) result + 1000000007 result %= 1000000007 result -= mcomb(n, b) result + 1000000007 result %= 1000000007 print(result)
- 投稿日:2020-02-22T17:57:52+09:00
Service Bus(トピック)への書き込み処理
全然参考となる資料が見つからなくて苦戦。。
結局公式ドキュメントにあったんだけどこれを見つけるのに時間がかかった。解決していない事柄
Functionsから受け取った情報をSerivce Busに書き込むこと
Service Busの接続文字列をキーコンテナから取得すること解決までの流れ
1.Service Busのデプロイ(Service Busの名前空間)
2.Service Busのトピック作成
⇒Service Bus 名前空間の共有アクセスポリシー(RootManageSharedAccessKey)からプライマリ接続文字列は入手可能3.チュートリアルのprivatemessagesenderをコピペで関数アプリ(Functions)を作成するも動かず。
4.Service Bus キューの使用を発見し、Visual Stadio 2019(以降VSと表記)を導入して、無事解決。
(Visual Stadio 2019導入は割愛)4-1.プロジェクトを作成し、パッケージの追加を実施
Service Bus NuGet パッケージの追加
新しく作成したプロジェクトを右クリックし、 [NuGet パッケージの管理] を選択します。
[参照] を選択します。 [Microsoft.Azure.ServiceBus] を検索して選択します。
[インストール] を選択し、インストールが完了したら、NuGet パッケージ マネージャーを閉じます。4-2.サンプルコードをコピペ※以下の箇所だけ作成したServiceBusに合わせて更新
Program.csconst string ServiceBusConnectionString = "Endpoint=sb://***********.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=***********"; const string QueueName = "samplequeue";4-3.VS上で実行 ⇒ Service Bus キューの概要からアクティブなメッセージ数が増えていることを確認
4-4.プロジェクトを選択し、右クリック>発行
AppServicePlanなどが自動で作成されるのでしばらく待つ。
再度発行ボタンを押すと、Azure 側へデプロイされる。4-5.Azureへのデプロイが完了したら、該当リソース(App Service)のWebジョブをクリック
4-6.ジョブを選択して、実行を押下 ⇒ Service Bus キューの概要からアクティブなメッセージ数が増えていることを確認
4-7.あれ、、増えてない。。ジョブがアベンドしている?!
4-8.ソースコード見てみると、Enter待ちになってる箇所あり。コメントアウトして、再度デプロイ
Program.cs// Console.ReadKey();
4-9.Azureへのデプロイが完了したら、該当リソース(App Service)のWebジョブをクリック
4-10.ジョブを選択して、実行を押下 ⇒ Service Bus キューの概要からアクティブなメッセージ数が増えていることを確認終了!
- 投稿日:2020-02-22T12:30:50+09:00
今更ながらWPFに置き換えてみる(2)
- 投稿日:2020-02-22T12:20:02+09:00
C# 6.0 の記述方法
C# 6.0 の新機能
- 読み取り専用の自動プロパティ
- 自動プロパティ初期化子
- ラムダ式によるメソッドとプロパティ
- using static
- Null 条件演算子
- 文字列補間
- 例外フィルター
- nameof 式
- Catch ブロックと Finally ブロックでの Await
- インデクサーを使用して関連コレクションを初期化する
読み取り専用の自動プロパティ (Read-only auto-properties)
自動実装プロパティで読み取り専用を記述できるようになった。
class Person { public DateTime Birth { get; } = new DateTime(1999, 12, 31); }
以前の書き方
フィールドを用意する必要があった。class Person { private DateTime birth = new DateTime(1999, 12, 31); public DateTime Birth { get { return this.birth; } } }自動プロパティ初期化子 (Auto-property initializers)
自動実装プロパティの初期値を指定できるようになった。
class Person { public DateTime Birth { get; set; } = new DateTime(1999, 12, 31); }
以前の書き方
コンストラクタで初期化する必要があった。class Person { public Person() { this.Birth = new DateTime(1999, 12, 31); } public DateTime Birth { get; set; } }ラムダ式によるメソッドとプロパティ (Expression-bodied function members)
メソッド (Methods)
簡単なメソッドを1行で書けるようになった。
class Person { private DateTime birth = new DateTime(1999, 12, 31); public int GetAge() => DateTime.Today.Year - this.birth.Year + 1; // 数え年 }
以前の書き方
1行で書けなかった。class Person { private DateTime birth = new DateTime(1999, 12, 31); public int GetAge() { return DateTime.Today.Year - this.birth.Year + 1; // 数え年 } }using static
static クラスのメソッド呼び出し等に、クラス名が省略可能になった。
using static System.Math; static class Util { public static int Range(int value, int lower, int upper) { return Max(Min(value, lower), upper); } }Null 条件演算子 (Null-conditional operators)
イベント発生等を簡潔に書けるようになった。
class Person { private string name; public string Name { get { return this.name; } set { this.name = value; this.NameChanged?.Invoke(this, EventArgs.Empty); } } public event EventHandler NameChanged; }
以前の書き方
null チェックの必要があった。class Person { private string name; public string Name { get { return this.name; } set { this.name = value; var handler = this.NameChanged; if (handler != null) handler(this, EventArgs.Empty); } } public event EventHandler NameChanged; }文字列補間 (String interpolation)
文字列の書式化が簡単になった。
var message = $"ファイル {path} が存在しません。";
以前の書き方
string.Format を使う必要があった。var message = string.Format("ファイル {0} が存在しません。", path);例外フィルター (Exception filters)
未
nameof 式 (The nameof expression)
変数などの名前を文字列として取得できるようになった。
if (path == null) throw new ArgumentNullException(nameof(path));
以前の書き方
文字列で指定する必要があったため、リファクターの対象にならなかった。if (path == null) throw new ArgumentNullException("path");Catch ブロックと Finally ブロックでの Await (Await in Catch and Finally blocks)
未
インデクサーを使用して関連コレクションを初期化する (Initialize associative collections using indexers)
未
- 投稿日:2020-02-22T11:37:30+09:00
[WPF] データに応じてリストの表示形式を切り替える
はじめに
ListBox に代表される ItemsControl コントロールを使って、色々な形式のデータを表示する方法をまとめました。
対応方法
表示する元データ
今回は "データ形式" と "値" を個別に管理するクラスを用意しました。
class MyData { public enum ItemType { Bool, Int, String }; public ItemType Type { get; } public bool BoolValue { get; set; } public int IntValue { get; set; } public string StringValue { get; set; } /* コンストラクタ省略 */ }表示する元リスト
enum型の ItemType に応じて表示形式を切り替えます。
public static List<MyData> Items => new List<MyData>() { new MyData(false), new MyData(true), new MyData(123), new MyData("Hello"), new MyData(null), new MyData(4321), new MyData("こんにちわ"), new MyData(false), new MyData(0), };表示1:データ種別に応じて表示形式を切り替える
ItemsControl.ItemContainerStyleSelector を使い、データ種別に応じて Style を切り替えます。
表示2:データ種別に応じてグルーピングする
ItemsControl.GroupStyle.HeaderTemplateSelector を使い、データ種別に応じて DataTemplate を切り替えます。
表示3:グルーピングしてデータ種別に応じて表示形式を切り替える
ItemsControl.GroupStyle.ContainerStyleSelector を使い、データ種別に応じて Style を切り替えます。
まとめ
説明は冒頭で力尽きてしまいましたが、ソースコードは以下に置いてあります。
参考にさせて頂いたページ
- 投稿日:2020-02-22T09:11:40+09:00
C#から鬼雲(bregonig.dll)を使って正規表現を処理する
目的
grepなど大規模な正規表現検索をしようとすると、C#の
System.Text.RegularExpressions.Regex
だと処理速度が物足りない。
C#だから遅いのかは判っていませんが、ネイティブなライブラリを使えば多少速くなるのではと思い、サクラエディタとかで採用されている鬼雲(bregonig.dll)をC#から使えないかと調べてみた。
既に実現されている方がいたので、たどり着けるようにメモを残しておきます。速度はまだ比較できてませんが、鬼雲の正規表現の機能はC#標準クラスの正規表現よりも充実しているらしいです。
参考サイト
https://hnx8.hatenablog.com/entry/2018/11/25/153251
⇒ https://github.com/hnx8/BregonigDotNetVisual Studioでコンパイルする場合
プロジェクトファイルが上記のGitHubサイトに一緒に入っているので、たぶんそれを使えばできるはず。
Visual Studio無しでコンパイルする場合
※下記は私が勝手にやってみた手順なので、上記の参考サイト様には下記内容について問い合わせしないようお願いします。
bregonig.dllを
サクラエディタのフォルダからコピーするなりダウンロードし、
上記のGitHubサイトから一式ダウンロードして、
BregonigRegex.cs と Program.cs と bregonig.dllを同じフォルダにおき、csc BregonigRegex.cs Program.csでコンパイルすると、Program.exeが出来上がるので、これを実行します。
下記のエラーpattern:「(03|045)-(\d{3,4})-(\d{4})」 間違ったフォーマットのプログラムを読み込もうとしました。 (HRESULT からの例外:0x8007000B) dllの32bit/64bitが妥当ではない可能性もあります。正しいbregonig.dllを実行フォルダに配置してください。が出る場合は、exeとdllのbitが整合していないと思われますので、
csc /platform:x86 BregonigRegex.cs Program.csもしくは
csc /platform:x64 BregonigRegex.cs Program.csでコンパイルしたProgram.exeのいずれかがうまく動作するはずです。
Program.exeを実行して下記のようなログがとれれば、うまく動作しているものと思います。pattern:「(03|045)-(\d{3,4})-(\d{4})」 input:「 Yokohama 045-222-1111 Osaka 06-5555-6666 Tokyo 03-1111-9999 」 ->found:「045-222-1111」(start=10, length=12) ->found:「03-1111-9999」(start=50, length=12) : (中略) : pattern:「[a-f]」 input:「 置換パターンにエラーがある場合0123456789abcdef 」 replacement:(null) ->error:「invalid reg parameter」処理速度の比較(まだ)
ファイル読み込む処理とか対象のファイルとかの準備ができていない。。。
Regexクラスもオプション指定でキャッシュとかコンパイルとかすると多少速くなるようなので、それらも比較したい。
- 投稿日:2020-02-22T00:11:09+09:00
オーバーウォッチのマッチング通知
オーバーウォッチのマッチング長すぎん....?
Overwatchというゲームが僕は大好きですが,ここ最近異様にマッチングが長いです
10分越えなんてざらです
マッチング長いし洗濯でもしてるか...
なんてことすると,いつの間にか強制退出くらってますということでマッチングしたらスマホに通知をもらおう
まず,おおまかな仕組みはこんな感じです
ミソはマッチの検出とお知らせ方法ですマッチ検出
おばっちはマッチが始まるとかっこいいBGMと相手味方のメンバーが表示されます
おばっちから直接データをいただくことはできないので(パッケージ化させているので)
このBGMか画面の違いを取得することでマッチ検出を行おうと思いますBGM
音声認識使おうか?
でもcloud speechは無料で一時間までしか使えんしなぁ
やめた画面遷移
マッチ後の画面学習させてYOLOかなんかで認識しようかなぁ
でも学習させるのめんどいし(マッチング画面はマップによって異なる)
認識率が心配....
ん?
マップによらず共通なのはマッチ前の画面の文字だけだよな?[検索中....]←これ
これ認識させて検出できなかったらマッチ始まったってことでいいんじゃね?
マッチ検出実装
文字の認識にはOCRを使いました
画像から文字を取り出してくれます
C# OCRとググれば先人たちが輝かしいソースを残してくれているのでこれを使いましょうMicrosoft.VisualBasic.Interaction.AppActivate("Overwatch"); SendKeys.SendWait("{PRTSC}"); #ここに先人のコードを入れる→pageという名の変数で帰ってくる if(page.GetText().Contains("検索中")) { 処理 }お知らせ方法
IFTTTです
iPhoneで受け取ろうと思います
1.スマホでiftttのアプリを入れましょう
2.Webhooksからurlで送信できるトリガーを取得しましょう
3.スマホの通知を選択しましょう
4.取得したurlを使ってプログラムを編集しましょうDateTime dt = DateTime.Now; string result = dt.ToString("yyyy/MM/dd HH:mm:ss"); string lnk = "https://maker.ifttt.com/trigger/match/with/key/#########/?value1=" + result; System.Diagnostics.Process.Start(lnk);こんな感じです
日時を含めているのはtwitterでもつぶやこうと思ったので
同じ内容の送信をブロックする機能の対策として追加してますでげだ!
今のところ
検出の誤作動は,ないです
100発100中です
おかげさまでお風呂に入りながらでも,ダッシュで駆けつけることができるようになりましたおしまい
追記
なんかぐぐったらDiscordの機能かなんかで同じようなのあって草
ちなみにコードは大事なとこ以外かなり端折ってます