iwate

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

MAUI

MAUIはじめて見ようと思った。

とりあえず、環境構築から。

https://docs.microsoft.com/ja-jp/dotnet/maui/get-started/installation

VS2022が必要らしいので、そこからかー。

RCをインストール中

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回デプロイしたいみたいな運用には向かないと思うんですよ。
1つのアプリケーションだけなら、まだしも、せっかくVMでフルなIISが使えるのだから、複数のアプリケーション詰め込みたかったりするし、モジュラーモノリス的な使い方。
それには、合わないあって感じた。

他の2つSFとk8sはどうかって言うと、ちょっと重い。手元にあるzipに固めたアプリケーションが動けばいいのに、SFは専用のStatupコード書かなくちゃいけなかったり、コンテナイメージにしなくちゃいけなかったり、そうじゃない感

k8sはwindowsにホストされること前提のアプリケーション(.NET FrameworkとかWCFとか)には鬼門。Windows Containerをワーカーノードにできるって言っても、マスターノードはLinuxを用意しなくちゃいけない。ローカル開発できる環境整えるのが大変なのが応える。Docker Desktopで簡単に整えられるならいいんだけど、今んとこLinux or Windowsだから、LinuxとWindowsを併用しなきゃいけない構成ができない。やるならHyperVなりWSLなりで1から建てろと。

頑張ろうかなとも思ったけど、k8sとかトレンドだし、でもこのzipが展開できればそれでいいのにって感情が勝ったのです。

作ったものは、以下の3つ。

  • SaburaIIS Agent
  • SaburaIIS AdminWeb
  • SaburaIIS CLI

AgentはWindows Serviceとして作ってあって、VMSS内の各VMへプロビジョニングスクリプトでインストール・常駐させておく。

AdminWebとCLIは、設定データを編集するためのものでCosmosDBに入っているJSONをこねくり回す。

CosomosDBにはIISがとるべき姿がJSONで保存されていて、AgentはChangeFeedを監視して、何か変更があれば、差分を計算して適用する。VirtualDOMとDOMの関係に近くてAgentはReact的な役割をする。

SSL証明書は、Key Vaultに、アプリケーションプール毎に環境変数を設定したい時はApp Configurationをつかう。

とにかく、Azureのマネージドサービスを使い倒す方針。

とまあ、いい感じのができたと自分では思うわけです。
ここまで前置き、長かったけど。

他の人の反応が気になるから、Reditに投稿してみたというのが本題。

これ。

https://www.reddit.com/r/AZURE/comments/q4zkq1/github_iwatesaburaiis_a_continuous_delivery_agent/

これが、3k Viewぐらいあるのに、6voteしかなくてダメダメだなあって感じてます。

それで何がいけなかったかなという反省を書きたい。

ものは悪くないって思うので(そう思いたい)、Reditの投稿の仕方、見せ方が悪かったよねっての書き出していこうと思います。

まず、改めて読んでみると、なんだろう。Iが多いかな、セールストークやマーケティングメールにはYouを使えってどっかで読んだことがある。Youにどんなメリットがあるか、これが使えばYouの体験がこうよくなる適なことを書けてきな。

あと、最大の失敗な気がするのが、書いてある説明が、僕の作ったものを100%理解できる前提で、それでいて疑問に思うであろうことがらだけを説明してる。1%も理解してない人に対して説明するように書かないとダメだよねと反省

あと、作ったもの全部見せたいから動画の長さが30分になってしまってる。これじゃあ誰も全部見ないよなあ。僕でさえ見ない。

この反省踏まえて次のアクションは、SaburaIISのコア機能である一回の設定変更で各VMに一斉にアプリケーションを展開する動画を15秒ぐらいの短い尺で作って投稿してみようと思う。

ほっぽてるWASMもそろそろ再開しなきゃなあ

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 <github@iwate.me>"]
edition = "2018"

[dependencies]

wasmにするために唯一やらなくちゃいけないことは#[no_mangle]をつけるってこと。こういうのrustだとなんていうんだろ?dotnet的にattributeって言うのかな?それともjavaみたいにannotation?

#[no_mangle]
fn add(a: i32, b: i32) -> i32 {
    return a + b;
}

調べた。 attributeらしい。#がouter attributeで#!がinnter attributeだって。
https://doc.rust-lang.org/book/appendix-02-operators.html

あとは、ビルドするときにターゲットを指定する。 releaseビルドにしないと、wasmがデバッグ用のコードか何かですごく膨らむ。

cargo build --target=wasm32-unknown-unknown --release

あとは生成されたwasmをdotnetから使うだけ。

using System;
using Wasmtime;

using var engine = new Engine();
using var module = Module.FromFile(engine, "challenge02.wasm");
using var host = new Host(engine);

using dynamic instance = host.Instantiate(module);
var result = instance.add(1, 2);

Console.WriteLine(result);

コンパイルが面倒なので、ビルドイベントでrustのビルドとwasmのコピーもしちゃう。

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net5.0</TargetFramework>
        <Nullable>enable</Nullable>
    </PropertyGroup>

    <ItemGroup>
        <PackageReference Include="Wasmtime" Version="0.27.0-preview1" />
    </ItemGroup>

    <ItemGroup>
      <None Update="challenge02.wasm">
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      </None>
    </ItemGroup>

    <Target Name="RustBuild" BeforeTargets="Build">
        <Exec WorkingDirectory="../rust" Command="cargo build --target=wasm32-unknown-unknown --release" />
        <Copy SourceFiles="../rust/target/wasm32-unknown-unknown/release/challenge02.wasm" DestinationFiles="./challenge02.wasm" />
    </Target>

</Project>

基本はできたので、次はwasm + protocol bufferを返してdotnetからrustを呼び出すコードを書く。

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;
using Wasmtime;

var bytes = new byte[32];
using (var stream = new MemoryStream(bytes))
{
    new Hello { Message = "Hello, " }.WriteDelimitedTo(stream);
    stream.Flush();
}


using var engine = new Engine();
using var module = Module.FromTextFile(engine, "memory.wat");
using var host = new Host(engine);
using var mem = host.DefineMemory("", "mem");

for (var i = 0; i < bytes.Length; i++)
{
    mem.WriteByte(100 + i, bytes[i]);
}

using dynamic instance = host.Instantiate(module);
instance.run();

var result = mem.Span.Slice(100, 32).ToArray();
using var stream1 = new MemoryStream(result);
var hello = Hello.Parser.ParseDelimitedFrom(stream1);
Console.WriteLine(hello.Message);
Console.WriteLine(Helpers.HexDump(result));

出力結果はこんな感じ。

wasmに渡す前は Hello,だったのが Hello,WASM! になって返ってきてる。

Hello,WASM!
00000000   0E 0A 0C 48 65 6C 6C 6F  2C 57 41 53 4D 21 00 00   ・・・Hello,WASM!・・
00000010   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ・・・・・・・・・・・・・・・・

wasmはこんな感じ

(module
    (import "" "mem" (memory 1))
    (data (i32.const 0) "WASM!")
    (func $run
        (memory.copy (i32.add (i32.load8_u (i32.const 102)) (i32.const 102)) (i32.const 0) (i32.const 5))
        (i32.store8 (i32.const 102) (i32.add (i32.load8_u (i32.const 102)) (i32.const 5)))
        (i32.store8  (i32.const 100) (i32.add (i32.load8_u (i32.const 102)) (i32.const 2)))
    )
    (export "run" (func $run))
)

うまいこといった。shared memoryにコピーするのなんかバカっぽいなあ。最初からそっちのバイナリに書き込めればいいんだけど、Span<byte>Streamにする方法がよくわからない。

次は、wasmをwasファイルからじゃなくて、rustとかで生成したやつで試そう。

rust用のprotocol bufferからシリアライズ、デシリアライズしたバイナリでdotnetと通信させてみたい。

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" />
  </system.webServer>
</configuration>
<!-- D:\home\site\wwwroot\web.config -->
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <httpErrors errorMode="Detailed" />
        <urlCompression doStaticCompression="false" doDynamicCompression="false" />
        <rewrite>
            <rules>
                <rule name="BlobNotSlashEnd">
                    <match url="^.*[^/]$" />
                    <action url="https://storageaccount.blob.core.windows.net/containername{PATH_INFO}" type="Rewrite" />
                </rule>
                <rule name="BlobSlashEnd">
                    <match url="^.*/$" />
                    <action url="https://storageaccount.blob.core.windows.net/containername{PATH_INFO}index.html" type="Rewrite" />
                </rule>
            </rules>
        </rewrite>
    </system.webServer>
</configuration>

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
  )
  (export "run" (func $run))
)

これはテキスト形式、本当はバイナリだけど、読みやすいテキスト形式で学習していく。

見た目は、S式だね。func $run ~ callのところを見た感じ、値、値、callと続いてるからスタックマシンぽいね。

https://developer.mozilla.org/en-US/docs/WebAssembly/Understanding_the_text_format

MDNのドキュメントを読みながら解読してく。

(module)

モジュールの塊を表す式(module)が最小のモジュールらしい。中身は空。

モジュールに入ってないコードは不正なんだろうか? module式で纏まってなかったらそれは文って感じだろうし違反しそう。

(func (param i32) (param i32) (result f64) ... )

モジュールに関数を生やすには、 func式を使う。 任意の(引数)(戻り値)が続き、そのあと式の中身が続くぽい。

名前はどこだ? 一番最初のサンプルみるに、引数の前っぽいけど。名前の先頭に$がつくのは作法なのかな。

(module
    (func $myadd (param $l i32) (param $r i32) (result i32)
        local.get $l
        local.get $r
        i32.add)
)

こんな感じかな。引数は local.get でスタックに載せられるみたい。 i32.add はcallしなくていいから組み込み命令なのかな。

スタックマシンだから結果はスタックに乗る感じかな。

戻り値はどうやって指定するんだろ? スタックの一番上が自動的に返されるのかな。

便利なページ見つけた。
https://webassembly.github.io/spec/core/exec/index.html

これで構文がすぐわかるね。

作った関数は、 exportでモジュールのそとに公開できる。

(module
    (func $myadd (param $l i32) (param $r i32) (result i32)
        local.get $l
        local.get $r
        i32.add)
    (export "add" (func $myadd))
)

逆に外の関数を使えるようにするには import が必要。

import          ::= {module name, name name, desc importdesc}
importdesc  ::= func typeidxtable 
                        |       tabletypemem
                        |       memtypeglobal
                        |       globaltype

importにはモジュール名、対象名、説明が必要で説明の種類を見る限り、関数だけじゃななさそう。memoryとかglobalにも使う。tableはちょっとまだわからん。

プリミティブ以外の値はどうすればいいのか、memoryを使って、バッファーを確保して使うみたい。

js側からしたらArrayBufferをwasmに渡して、処理が終わったらそのArrayBufferからデータを取り出す感じ。

function consoleLogString(offset, length) {
  var bytes = new Uint8Array(memory.buffer, offset, length);
  var string = new TextDecoder('utf8').decode(bytes);
  console.log(string);
}

なるほどね。

(memory 1 2) みたいにかけるけど、これは、1が最小ページサイズ、2が最大ページサイズらしい。1ページ64KB。

この共有メモリにprotocol bufferとかmessage packのバイナリ置けば、言語間でオブジェクトをやり取りできそう。もちろんJSONでもいいわけだけど。

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-MEheS8gM4Xs

この説明見る限り、エイリアスじゃなくて、外部のメールアドレスとして追加できればいけそうってのはわかったけど、outlookだとうまくいかず。しょうがないのでgmailで行くことにした。

設定は説明通りですぐに終わった。送信者もきっちりxxxx@iwate.meになってた。

でもメインはoutlookだから、普段はgmailの同期切ってるだよなあと思ったときに気づいた。

https://forwardemail.net/faq#can-i-forward-emails-to-multiple-recipients

複数の宛先に転送できるじゃん。

これでoutlookのほうにも転送設定することで、gmailにもoutlookにも届くようにできた。

これのいいところって、例えば、GoogleもしくはMicrosoftに不遇にもBANされたときに、メールだけは救える冗長性が手に入るってことに気づいた。認証メールとかもどっちにも届くからね。

https://gigazine.net/news/20210209-terraria-stadia-cancel/

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

Covid19でWFHが広く行われるようになって、1年たとうとしてしているがWFHでWeb上の管理画面を使用する機会を得た人も多かったことでしょう。
ただし、いままではWeb上の管理画面にはIP制限がかかっていることが多かったはずです。(何か資料で示せればいいのですが。)
WFHがはじまって、VPN終端に負荷がかかり、従来のプライベートネットワークによりセキュリティポリシーを見直し、ゼロトラストセキュリティという言葉も一般に広がりはじめました。
日本では、平井卓也デジタル改革担当大臣が行政の目指すセキュリティポリシーの指針として発言したことも広がるきっかけになりました。

さて、WFHで様々なIPから管理画面にアクセスしたいとした時に、今までのIP制限では都合が悪いのでクライアント証明書制限を検討しています。

しかし、私はクライアント証明書制限が本当にIP制限の代替なのか疑問に思っています。前提として、ID/パスワードでの認証がある管理画面にさらにIP制限をかけているケースで話しています。

  1. IP制限≒地理制限
    • IPは動的にしろ静的にしろISPによって決まります。さらにISPは国、地域ごとに割り振るIPレンジが決まっています。
    • 固定IPで払い出されてるIPを盗むには、
      • 物理的にLAN内に接続を試みる。(建物に侵入
      • VPNからLAN内に侵入する (VPN終端の脆弱性を狙う、VPNの認証情報を何らかの形で手に入れる
      • IP制限自体の脆弱性をつく(タイニー/オーバー フラグメント攻撃 未対応なサーバーはないと思うけど
  2. クライアント証明書はどうやって配りますか?
    • メールですか? 社内Wikiですか? (これってZipパスワード問題と同じですよね
    • ネットワークを介さない方法で配らないと意味なくないですか?(FIDO
    • OK. 証明書と署名を認証局サーバーでやるからダメなんだ、各PCで鍵を作成して、公開鍵だけを認証局に渡し署名する。
      • それ社員の全PCにやるサポートめっちゃ大変なやつやん

ちゃんとやれば(クライアント証明書は配らず、公開鍵を集める方式)IP制限足りえるけど、生成した鍵を配布するようなやり方でIP制限と同等のセキュリティ強度になるとは思えない。

配り方に気を付ければいいかもしれないけど。メールやWikiで配るのは絶対ダメで認証局まで取りに来てもらう。取りに来るときのセキュリティ強度がしっかりしてればOKなはず。

クライアント証明書の前に2要素認証なんじゃないかな。教えて詳しい人!

母国語で書くことにする - 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つのタスクだったのを、ブログを書く、英語に訳す、の2つのタスクに分解するということだ。

In other words, until now it was a task to a post in English, I divide to following two tasks; writing a post, translating a post.

英語に訳すのは、ブログを書いた後すぐに行うこともあるし、数日空けることもあると思う。

Sometimes I have a time between writing a post and translating a post.

listed.to can draw iframe

iframe google drive

<iframe src="https://drive.google.com/file/d/0B__Gb6a7KXSlSTZZRmhxeXZmdEE/preview" width="640" height="480"></iframe>  


iframe ogp link

<iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fblog.iwate.me%2F21828%2Flisted-can-draw-iframe"></iframe>

iframe google drive

iframe ogp link

How to settings GA4 ecommerce by GTM

GTM Variables

  • Ecommerce Items = ecommerce.items
  • Ecommerce Purchase TransactionId = ecommerce.purchase.transaction_id
  • Ecommerce Purchase Affiliation = ecommerce.purchase.affiliation
  • Ecommerce Purchase Value = ecommerce.purchase.value
  • Ecommerce Purchase Tax = ecommerce.purchase.tax
  • Ecommerce Purchase Shipping = ecommerce.purchase.shipping
  • Ecommerce Purchase Currency = ecommerce.purchase.currency
  • Ecommerce Purchase Coupon= ecommerce.purchase.coupon

GTM Triggers

  • CustomEvent viewitemlist
  • CustomEvent view_item
  • CustomEvent select_item
  • CustomEvent addtocart
  • CustomEvent removefromcart
  • CustomEvent begin_checkout
  • CustomEvent purchase

GTM Tags

  • GA4 settings: trigger = All Pages
  • GA4 event: event name = viewitemlist, trigger = viewitemlist
    • event parameters
      • items = {{Ecommerce Items}}
  • GA4 event: event name = viewitem, trigger = viewitem
    • event parameters
      • items = {{Ecommerce Items}}
  • GA4 event: event name = selectitem, trigger = selectitem
    • event parameters
      • items = {{Ecommerce Items}}
  • GA4 event: event name = addtocart, trigger = addtocart
    • event parameters
      • items = {{Ecommerce Items}}
  • GA4 event: event name = removefromcart, trigger = removefromcart
    • event parameters
      • items = {{Ecommerce Items}}
  • GA4 event: event name = begincheckout, trigger = begincheckout
    • event parameters
      • items = {{Ecommerce Items}}
  • GA4 event: event name = purchase, trigger = purchase
    • event parameters
      • items = {{Ecommerce Purchase Items}}
      • transaction_id = {{Ecommerce Purchase Items}}
      • affiliation = {{Ecommerce Purchase Aaffiliation }}
      • value = {{Ecommerce Purchase Value}}
      • tax = {{Ecommerce Purchase Tax}}
      • shipping = {{Ecommerce Purchase Shipping}}
      • currency = {{Ecommerce Purchase Currency}}
      • coupon= {{Ecommerce Purchase Coupon}}

Links

The following document has a few misstakes. ex purchase parameters and any triggers.

Remote desktop does not work

I always use remote desktop to shutdown main pc in bed.

A few days ago, I update windows patch. After the patch, I cannot connect main pc via remote desktop.

I check event viewer and find the error log.

The device Microsoft Remote Display Adapter (location (unknown)) is offline due to a user-mode driver crash.

Apparently there is an error around the display.

In my case, it is the cause that radeon driver is old.
I updated the driver and I regained remote desktop.

StreamWriter.WriteLine write LF line break code on Linux

I face to misterius issue.

OData batch response of multipart/mixed can not be parsed on Linux. It's good on Windows.
https://github.com/iwate/ODataBatchResponseSample/actions/runs/171318359

I check OData source code. And I've found what I think is the cause.

OData batch response write the content using by RawValueWriter. And RawValueWriter use StreamWriter.

https://github.com/OData/odata.net/blob/182964dd4de0d9271d7e749ff3afde898430326c/src/Microsoft.OData.Core/RawValueWriter.cs#L177

StreamWrite use Environment.NewLineConst.
https://source.dot.net/#System.Private.CoreLib/TextWriter.cs,f3a16a4f25483a3f,references

Environment.NewLineConst is LF on Unix
https://source.dot.net/#System.Private.CoreLib/Environment.UnixOrBrowser.cs,5fbfd9f39ec095a7

You know HTTP multipart content is need CRLF. If you create http writer, you should not use what is dependent on the environment like as StreamWriter.


This issue was fixed in https://github.com/OData/odata.net/issues/1842

Ascertia's code sign certigicate is cheep but...

Ascertia (https://account.ascertia.com/OnlineCA/default) sell certificate and user can test free certificate(30days).

It seems Messiah for me. but I realized import notes.

Note Ascertia Root Certificate Authority is not embedded within Windows or the common browsers but can be downloaded from here and easily added.

Ascertia Root Certificate Authority is not embedded within Windows!
Ascertia Root Certificate Authority is not embedded within Windows!
Ascertia Root Certificate Authority is not embedded within Windows!

oh no...

Microsoft Authenticode

I realized something shocking today.
I thought I'd turn off the WindowsInstaller warning for the Electron App I'm working on, but it looks like I need a Code Sign certificate for Microsoft Authenticode.

I tried to prepare it somehow, but there are few places that will sell it to individuals first. And so expensive 😭

I Contract PO Box

I've contracted post office box https://epost-tokyo.com/ today.

I am preparing my side business recently and I need new address for Notation based on the Specified Commercial Transaction Act.(in Japanese 特定商取引法に基づく表記)

The cost is 19,000 JPY within tax. It is 1,600 JPY / mo. Ummmm, That's nothing to sneeze at for me.

And, I've got new phone number of VoIP because same reason as address. The cost is 330 JPY per month.

Totally, new cost for my side business is 1,900 JPY per month.

The unit price of my side business is 1.49 USD and I have to sell 13 licenses for turn a profit.