iwate

A software developper in Japan github: https://github.com/iwate

大掃除(twitter)

大掃除シーズンですね。家の大掃除はもちろんですが、今年はネットの大掃除もしてみようかと思い、過去のtweetを削除した。 これがtwitterの制約で結構難しい。難しいはちょっと違うか。やることはAPIたたくだけなんだけどそこにたどり着くまでが長い。だから面倒ってのが妥当かもしれない。 twitterの仕様 Webやアプリからtweetの削除はできる。が、1個ずつしかできない。2009年から使っているのでそれなりの量なのでそれをポチポチしたくない。 そして、自分のプロフィールからたどれるtweetは、2014? 2015?以降の直近3200tweetに限られているらしく、Webやアプリから消すためにたどり着くのは非常に困難。 さらに、APIでユーザIDをキーにして取得できるtweetもプロフィールと同様の3200件に限られる。 アーカイブを申請する EUでGDPRが施工されてから、自身のアーカイブデータをダウンロードできるようになっている。 自身の設定からアーカイブを申請すると2日後ぐらいにはダウンロードできるようになった。 アーカイブはzipでまとまっててダウンロード...
Read post

続々Azure Functions IsolatedでSingleton

dotnet isolatedなAzure FunctionsでどうしてもSingletonしたいシリーズ。 前回こうやればよさそうってとこまでは考えた。 今回は、これを実行するためのライブラリを書いた。 1つは、Azure Functionの実行をシングルトンになるようにせき止めるためのミドルウェア。 使い方は、起動時にミドルウェアを差し込んで、 var host = new HostBuilder() .ConfigureFunctionsWorkerDefaults(app => { app.UseMiddleware<Iwate.AzureFunctions.Middlewares.Singleton.SingletonMiddleware>(); }) .Build(); host.Run(); シングルトンにしたい関数に属性をつける。 public class SingletonFunction { [Function("SingletonFunction")] [Singlet...
Read post

続Azure Functions Isolated でのシングルトン

以前dotnet-isolatedなFunctionでSingletonがどうしても使いたくて、自前ロックを作った。 ただ、これでも完ぺきではなく課題が残ってる。それは実行順序。 前にも書いたが、a)のように並行して動いてしまう関数を、b)OrderIDごとに直列にしたい。 a) +-----------------+ +-----------------+ +-----------------+ |ORDER ID: 100 | |ORDER ID: 100 | |ORDER ID: 101 | |TIMESTAMP: 3s ago| |TIMESTAMP: 2s ago| |TIMESTAMP: 1s ago| +-------+---------+ +-------+---------+ +--------+--------+ | | | +-------v--------------------v----------------...
Read post

The cheap way to make multi tenant SaaS on Azure #1 | Poor man's Azure

Many people say Azure is expensive. But I think Azure isn't so expensive compared AWS or GCP on full workload. However it's true that minimum cost is expensive on Azure. Therefore I've decided to find to make multi tenancy application on Azure as cheap as possible and I'm going to try to write a series of them. In this commemorable first article, I consider front-end and authentication. Azure has many scenarios to host web application, such as WebApps, VM, Container Apps, aks, aci, Static Web...
Read post

Pixel Watch買った

4年前ぐらいに買った初代Fitbit Versaからついに乗り換えた。 Smart watchでスイカ使えるようになった。 スマホ用のPixel WatchアプリをPixel 6 Proにインストールしてポチポチしてセットアップしたんだけど、スイカは新しく発行された。 移管されると思ってたんだけど、そうはならなかった。モバイルスイカのIDをgmailにしてないからかもしらん。 今のチャージ分を使い切ったら試してみる。 充電スタンドほしいんだけどまだなさそう。apple watchの充電スタンドでいけるかなと思って試したら、充電自体はできそうだけど、磁石の極性が違って反発しちゃう。形態のUSB-C統一もそうだけど時計のほうも統一してほしい。 バッテリーライフは今のとこだめそう。Fitbitに比べたらね。 ECGとか、apple watchに負けてる部分が今後埋まったらいいなあ。 ...
Read post

型パズル難しい

あるテーブルへの操作について考える。 1操作をOp型で表す type Op<T> = { table: string pk: (keyof T)[] cols: Partial<T> } keyof Tは型Tが持つプロパティ名のみの型になる。 type MyObj = { prop1: number prop2: string } type MyObjKeys = keyof MyObj // == 'prop1' | 'prop2' Partial<T>は型Tのすべてプロパティをundefined可能にする const obj1: MyObj = {prop1:0} // error porp2は必須 type MyObjPartial = Partial<MyObj> // == { prop1?:number, prop2?:string } const obj2: MyObjPartial = {prop1:0} // OK これらの組み合わせで型Op<T>は、pkには...
Read post

Content Security Policyの困りごと

CSP入れたほうがいいかなあと思って、いくつかのサイトにCSP Reportを仕込んでる。 Report OnlyはCSPに違反するリクエストがあったときに、ブロックはせずに通知だけしてくれるブラウザの機能で、モダンブラウザは大抵対応している。 ブロック入れる前にこれで様子見をしてるが、結構通知がくる。 引っ掛かっているのは次のようなリクエスト。 https://www.google.at/ads/ga-audiences?... https://www.google.cn/ads/ga-audiences?... ... Google Adさんのトップレベルドメインが国別なせいでCSPに登録してない国のGoogleドメインの通知が飛んでくる。 CSPのドメイン指定は、 www.google.* みたいなことはできない。 www.google.evil.xyz とかがすり抜けちゃうから。 えー。つまり、これ全部 CSPに入れる?そんなばかな。 .google.com .google.ad .google.ae .google.com.af .google.com.a...
Read post

WSLからホストを介して外部通信する

WindowsでVPNを使用しているとき、WSLのリクエストはVPNを経由できないらしい。 ので、プロキシなりなんなりでWSLのリクエストをホストに渡して、ホスト側からリクエストを投げないといけない。 Windows 11では設定>アプリ>オプション機能から、Open SSH Server(sshd)をインストールできるので、これでポートフォワードしてみる。 インストールしたら、firewall設定が自動的に設定される。初期値はAllだから適宜見直す。 sshdの起動は管理者権限のPowerShellで PS> Start-Service sshd あとは、WSL側から接続。 # ポートフォワーディングってこれでいいのかな $ ssh -L <target host>:443:<target host>:443 <username>@<host ip> 実は、VPN持ってないから試せてない。 ...
Read post

TypeScriptで型からプロパティ名をとりたいけど...

C#ではリフレクションで簡単に取れる。 IEnumerable<string> propNames = typeof(T).GetProperties().Select(p => p.Name); 同じようなことをしたい。TypeScriptはJavaScriptにトランスパイルされる。つまり、型があるのはコンパイル時点までだから、リフレクションみたいな実行時の解決はできないはず。だから、あるとしたら言語サポートの特殊キーワードだと思うんだけど見つからない。 typeof も keyof も nameof もちゃうんよ。 できないのかなあ。 ほしい用途としてはAPI周り。 async function apiPost<T>(body: T) { const res = await fetch(url, { method: 'post', headers:{'Content-Type':'application/json'}, body: JSON.stringify(body) }...
Read post

Learning Zig #1

ZigがはやってるらしいのでHelloWorldぐらいやっておこうと思った。 Getting Startedに沿って環境を準備。 といっても、zipをダウンロードして展開後そこにPATHを通すだけ。 ついでに、makeも用意した。windows環境なのでGnu for Windowsのバイナリ。 wingetでインストールできるので楽ちん。 PATHは別途通さないとだめ。 > winget install GnuWin32.Make zigの面白いなと思ったところが、c(c++)言語が、そのまま、コンパイルできるらしいということ。 TypeScriptみたいだな。 Goがでたころ、Better Cっていう表現されてたけど、そのままコンパイルできるzigがでてきたのでBetter Cのポジションはzigが奪っていくのかなあ。Goと違ってGCなしなのもいいなと思った。 同じGCなしだと、Rustがあるけど、Rustに比べてZigのメモリ管理はプログラマ任せ。Cみたいにメモリリーク発生してしまうけど、Go同様defer構文があるので、Cよりもプログラマに優しい。 z...
Read post

GPD Micro PC 買っちゃった

最近気になってたGPD Micro PC買っちゃった。 メルカリ中古で38,000円 土曜の朝届いて、土日はこいつをセットアップして遊んだ。 CPUはCelron N4100で、RAMは8G。 Windows 10が入ってたけど、最近Linuxで遊びたかったので、はやりのZorinOS Liteを入れてみた。 でもやっぱり、Linux + Laptopは難しいね。Hibernateやら、CPUの周波数制限でバッテリーライフの向上とかやってたら土日が解けました。 最近英語勉強してるけど、そのおともに使おうと思います。 weblio調べたり、YouGlish見たり、SKELLで用例探して、それらをメモする感じに使おうと思ってます。 今までスマホでやってたけど、スマホのキーボードって結構画面を占有するから、メモするとなるとクラムシェルがいいなあと思ってたんですよね。 しばらく試してみます。 ...
Read post

An error occurred (MalformedCertificate) when calling the UploadServerCertificate operation: Unknown

AWSに証明書をアップロードするときに、エラーが出た。 aws iam upload-server-certificate --server-certificate-name mycert --certificate-body file://cert.pem --private-key file://private.key --certificate-chain file://chain.pem --path /mycert/ An error occurred (MalformedCertificate) when calling the UploadServerCertificate operation: Unknown ググると公式ドキュメントが出てくる https://aws.amazon.com/jp/premiumsupport/knowledge-center/import-ssl-certificate-to-iam/ 曰く API リクエストのパラメータ certificate-body、certificate-chain、private-key に「fil...
Read post

Azure Functions Isolated でのシングルトン

.NET用のAzure Functionsは元々ホストが実行されるプロセスで関数を実行していたが、ホストとワーカーが別プロセスで動作するIsolatedタイプが今後主流になるということで、仕事で新しく作るFunctionsはIsolatedでやっている。 ただまだまだIsolatedが発展途上なのか困りごとにもしばしば直面する。 よく書く処理で一番こたえがたいのがSingletonがサポートされていないことだ。 Singletonは便利なやつで、どんなにスケールアウトされていても、並列実行数を限定することができるし、同一IDは直列に処理したい時に便利だ。 a) +-----------------+ +-----------------+ +-----------------+ |ORDER ID: 100 | |ORDER ID: 100 | |ORDER ID: 101 | |TIMESTAMP: 3s ago| |TIMESTAMP: 2s ago| |TIMESTAMP: 1s ago| +-------+---------+ ...
Read post

I released QjsIpc 🎉

Learning WASM 4 ~ 8 の成果をライブラリ化して公開した。 JS側では今回作成したQuickJSの拡張モジュールでるipcモジュールを使用し、プロシージャを登録して、最終的にlistenメソッドを実行する import * as ipc from 'ipc'; ipc.register('echo', function (payload) { return payload; }); ipc.listen(); .NET側では、QjsIpcEngineのインスタンスを作成し、JSファイルと実行フォルダを指定してQuickJSを実行する。 実行した後は、InvokeAsyncメソッドでJS側に登録したプロシージャを実行できる。 using QjsIpc; await using var engine = new QjsIpcEngine(); engine.Start(new QjsIpcOptions { ScriptFileName = "main.js", AllowedDirectoryPath = Environment.C...
Read post

Learning WASM #8

前回作ったqjs.wasmとJSON-RPCするプログラムを改良して、dotnetからjsへrpcコール中に、jsからdotnetにrpcコールできるようにした。 これでホスト側に生やしたヘルパー関数をゲスト関数が使える。 もう書いたコードが長くなってきたので全部貼ることはしないけど、いつも通りリポジトリにあげてある。 こんなホスト関数を生やしたクラスを用意して、 public class Host { public async Task<int> HostMethod1(int intParam, float floatParam, string stringParam, ObjParam objParam) { await Task.Delay(1); Console.WriteLine("Invoke HostMethod1"); Console.WriteLine($"intParam = {intParam}"); Console.WriteLine($"floatParam...
Read post

Learning WASM #7

前回はqjsのカスタモジュールにreadメソッドとwriteメソッドを生やして、hostのdotnetランタイムと文字列のやり取りをできるようにした。 今回は、文字列がやり取りできるようになったのでJSON-RPCを流して、dotnetからjsの関数をコールしてその結果を得たい。 RPC処理ロジックをカスタムモジュールにするには、Cで書く必要がありちょっと大変なので、いったんmain.jsの中にJavaScriptで書いた import * as host from 'host'; import * as std from 'std'; import ejs from './ejs.mjs'; ejs.fileLoader = function(filename) { const file = std.open(filename,'r'); return file.readAsString(); }; const handlers = {}; function register(methodName, handler) { handlers[metho...
Read post

Learning WASM #6

前回はqjsからhostの関数を呼び出した。 今回は、実際に通信できるように read と write を生やしてみる。 C側は puts や getLine を参考にこんな風に実装。dotnet側には1byteずつread writeする関数を生やして、jsモジュールとしては改行コードもしくはEOFまで書き込み読み込みし続けるreadLine、writeLineとして実装する。 __attribute__((import_name("read")))extern int host_read(); __attribute__((import_name("write")))extern void host_write(int c); static JSValue js_host_read_line(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { int c; DynBuf dbuf; JSValu...
Read post

Learning WASM #5

前回、dotnet上で動かしたwasmtimeの上でJS(QuickJS)を動かした。(ややこしいな QuickJSの性質上、QuickJSで動いているJSとホストであるdotnetで通信させる方法が、ファイルを返した通信に限られる。 標準入出力でも行けないかと思ったけど、process分離して動いてるわけじゃないから標準入出力を共有してるためフックできなかった。 Cのfopenが実装されているので、ファイルだけでなくUNIXソケットファイルとかでも通信可能そうだったけどそうなるとホストがUNIXやLinuxじゃないとだめなので、開発しにくそうでやめた。おんなじ理由でtmpfsを使ったRAM上の通信もやめた。 せっかく、WASMを使ってるんだから、QucikJSに手を入れてホストと通信する関数をはやしてしまえばいいだろうということで書いてみた。 https://github.com/iwate/learn-wasm-with-dotnet/tree/main/challenge05 今回は簡単にwasmtimeのサンプルも記載されている引数なしのhello関数をホストに生や...
Read post

Learning WASM #4

wapmでqjsっていうパッケージを見つけた。 知らなかったのだけど、QuickJSっていう軽量なJSランタイムがあってそれをwasm化したものだった。 https://bellard.org/quickjs/ wapmに上がってるのは公式じゃなくて、サードパーティー。しかもバージョンが2年くらい古い せっかくだから、最新ものにコンパイルしようと試みたけれど、ソース改変なしにはうまくいきそうになかったのでいったんwapmにあるもので遊んでみた。 WithArgs に渡す値ではまったけど動いた。 using System; using System.IO; using System.IO.MemoryMappedFiles; using System.Text; using Wasmtime; namespace Iwate.Challenge04 { class Program { static void Main(string[] args) { var dir = AppDomain.Cur...
Read post

Compile dotnet to wasm

.NETをwasmにAOTしてみる。おそらくランタイムごとwasmになるんかな ひとまずこの人の説明通りやってみる。 https://stackoverflow.com/questions/70474778/compiling-c-sharp-project-to-webassembly まず、emscriptenをいれる。Python3.6が必要ぽいけど入っていたのでそこはスキップ git clone https://github.com/emscripten-core/emsdk.git cd emsdk ./emsdk install latest ./emsdk activate latest 環境変数がセットされたので一応サインアウトからのサインイン。 適当なフォルダでdotnet projectをつくって、nugetconfigでnugetリポジトリを追加する。3rdPartyせいなのね。blazorのとかこれじゃなかったのか。 mkdir sample cd sample dotnet new classlib dotnet new nugetconfig <...
Read post

Redash on Azure WebApps for Container

How to Provisioning 1. Create Azure Database for PostgreSQL server 2. Create Azure WebApps for Container 3. Allow WebApps outbound IPs in PostgreSQL's Connection security firewall 4. Configure compose settings for table provisioning in WebApps's DeployCenter Configure following and execute create_db command. version: '3.3' services: redash: image: redash/redash:10.1.0.b50633 environment: PYTHONUNBUFFERED: 0 REDASH_LOG_LEVEL: INFO REDASH_COOKIE_SECRET: {self gene...
Read post

MAUI

MAUIはじめて見ようと思った。 とりあえず、環境構築から。 https://docs.microsoft.com/ja-jp/dotnet/maui/get-started/installation VS2022が必要らしいので、そこからかー。 RCをインストール中 追記: これ、RCでも本リリースでもだめでPreviewじゃないと今のところできない。 ...
Read post

SaburaIIS

夏休みの自由研究(2か月もたっちゃったけど)として、こんなのを作った。 https://github.com/iwate/saburaiis Azure VMSSのIISにContinuous Deliveryするためのシステムなんだけど、割と良くできていると思う。 挑戦的には、長いこと書いてなかったReactの今はどうなってるのか書いてみるってのが1つ、CosmosDBあんまり使ったことないから使ってみるてのが1つ、bicepも書いたことないから覚えて置こうってことで結構勉強になった。 作った理由はVMSS便利そうなんだけど、アプリケーションの配置がコレジャナイ感あったから。 VMSSへのアプリケーションのデプロイは以下の4つがメジャーっていう認識なんだけど、 カスタムプロビジョニングスクリプト カスタムVHDイメージ Service Fabric Kubernets カスタムプロビジョニングスクリプトやカスタムVHDイメージって新しいバージョンのアプリケーションをデプロイしたいとして、再起動なりVMの入れ替えなり(ローリングアップデート)が必要だから、1日に100...
Read post

Learning WASM #3

Rustでライブラリを作成して、dotnetからそれを呼び出すのを試した。 https://github.com/iwate/learn-wasm-with-dotnet/tree/main/challenge02 まずは、簡単なとこから、ただの2値の足し算をするadd関数をrust -> wasm -> dotnetで実行する rust + wasm で検索したら、wasm-packばっかりで、なかなかただのwasmの生成方法がわからなかったけど、wasiとかwasmtimeでググったら何とか知見が得られた。 まずは、rustでwasmをターゲットにしてコンパイルできるように、ターゲットを足す。 rustup target add wasm32-unknown-unknown 次に、普通にrustのプロジェクトを作る。add関数を外から使いたいからプロジェクトタイプはlibで。 Cargo.tomlはこんな感じでまっさらでいい。 [package] name = "challenge02" version = "0.1.0" authors = ["iwate ...
Read post

Learning WASM #2

Protocol Bufferフォーマットを使用して、dotnetとwasmの間でオブジェクトをやり取りするコードを書いてみた。 https://github.com/iwate/learn-wasm-with-dotnet/tree/main/challenge01 こんな感じのプロトファイルを用意して、 syntax = "proto3"; option csharp_namespace = "Iwate.WasmtimeChallenge"; package greet; message Hello { string message = 1; } dotent側で生成した Hello をバイナリに書き出して、wasmのshared memoryに書き込んでから wasmモジュールのrun を実行する。 shared memoryから Helloをパースするとwasmで加工された情報が受け取れる。 using System; using System.IO; using Google.Protobuf; using Iwate.WasmtimeChallenge; ...
Read post

WebApps as ARR

Last year, I describe WebApps with File Share for hosting static website. I find another way. WebApps can ARR if you transform applicationHost. <!-- D:\home\site\applicationHost.xdt --> <?xml version="1.0"?> <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> <system.webServer> <proxy xdt:Transform="InsertIfMissing" enabled="true" preserveHostHeader="false" reverseRewriteHostInResponseHeaders="false" /> </s...
Read post

Learning WASM #1

dotnetからwasmを実行するのが面白そう。これがモノになったら多言語間をまたいだプラグインシステムが作るんじゃないかな。 まだ、File IOとかNetwork Stackとかは使えないらしいけど、専用関数用意すればよさそう。FastlyとかCloudflareとかはエッジ用のエンジンでwasm実行できるようにしてるしね。 まずは、wasmになれたい。 https://github.com/bytecodealliance/wasmtime-dotnet/blob/main/examples/memory/memory.wat (module (type $t0 (func (param i32 i32))) (import "" "log" (func $.log (type $t0))) (memory (export "mem") 1 2) (data (i32.const 0) "Hello World") (func $run i32.const 0 i32.const 11 call $.log ) (expor...
Read post

Forward Emailを使ってみる

https://forwardemail.net/ というナイスなサービスがある。 メール転送サービスで、SMTPにも対応しているので送信にもカスタムドメインが使える。しかも無料。 課金すると、どこに転送しているのかっていう情報を隠せる。例えばバックエンドをgmailで使用していたら、FREEでは、TXTレコードでフォワーディング先のgmailアカウントを設定する必要があるのでdigればわかってしまうのが、課金すればforwardemailのデータサーバに設定できるようになるので公開しなくて済む。 まあ、2段階認証してるし公開してもいいでしょう。ということで無料プランで利用することにした。 メインで使っているメールボックスはoutlook(今時少ないlive.jp)なので、最初はoutlookに転送していたけど、送信でつまずく。うまいこと、設定できずに、送信者がoutlookのメアドになってしまう。 カスタムDKIM設定できないし迷惑メール行きになるもんで困った。 https://forwardemail.net/faq?domain=iwate.me#lazyframe-M...
Read post

クライアント証明書はIP制限の代替足りえるのか

Covid19でWFHが広く行われるようになって、1年たとうとしてしているがWFHでWeb上の管理画面を使用する機会を得た人も多かったことでしょう。 ただし、いままではWeb上の管理画面にはIP制限がかかっていることが多かったはずです。(何か資料で示せればいいのですが。) WFHがはじまって、VPN終端に負荷がかかり、従来のプライベートネットワークによりセキュリティポリシーを見直し、ゼロトラストセキュリティという言葉も一般に広がりはじめました。 日本では、平井卓也デジタル改革担当大臣が行政の目指すセキュリティポリシーの指針として発言したことも広がるきっかけになりました。 さて、WFHで様々なIPから管理画面にアクセスしたいとした時に、今までのIP制限では都合が悪いのでクライアント証明書制限を検討しています。 しかし、私はクライアント証明書制限が本当にIP制限の代替なのか疑問に思っています。前提として、ID/パスワードでの認証がある管理画面にさらにIP制限をかけているケースで話しています。 IP制限≒地理制限 IPは動的にしろ静的にしろISPによって決まります。さらにISPは...
Read post

母国語で書くことにする - I have decided to write posts in my native language

今まで頑張って英語で書いてきたけど、英語で書くのが億劫になって、全然ブログがかけてなかった。 I have tryed to write posts in English but I cannot write it at all recently because writing in English become a pain. 英語学習もかねて、英語で書きたい気持ちもまだあるんだけど、ここブログとしての体裁を優先して母国語(日本語)で書くことにする。 I still have want to writing in English for learning English. However I am going write it in native language(Jpanese) to update blog high freq. 書き終わった後に、英語訳を加筆するというスタイルを目指す。 I aim a style that add transaltions after write in native language. つまり、今までは英語でブログを書くという1つの...
Read post