List of Module - text.Baldanders.info
tag:text.Baldanders.info,2024-03-09:/tags
2024-03-09T20:45:42+09:00
帰ってきた「しっぽのさきっちょ」
https://text.baldanders.info/images/avatar.jpg
https://text.baldanders.info/images/avatar.jpg
github.com/goark/mt/v2 をリリースした
tag:text.Baldanders.info,2024-03-09:/release/2024/03/goark-mt-v2/
2024-03-09T11:45:42+00:00
2024-03-09T11:45:46+00:00
Mersenne Twister 疑似乱数生成器を実装した拙作のパッケージを math/rand/v2 に対応することにした
Spiegel
https://baldanders.info/profile/
<p><a href="https://go.dev/">Go</a> 1.22 で <a href="https://pkg.go.dev/math/rand/v2" title="rand package - math/rand - pkg.go.dev"><code>math/rand/v2</code></a> パッケージが登場したため, <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/mt.html" title="Mersenne Twister: A random number generator (since 1997/10)">Mersenne Twister</a> 疑似乱数生成器を実装した拙作の <a href="https://github.com/goark/mt" title="goark/mt: Mersenne Twister; Pseudo Random Number Generator, Implemented by Golang"><code>github.com/goark/mt</code></a> パッケージも <a href="https://pkg.go.dev/math/rand/v2" title="rand package - math/rand - pkg.go.dev"><code>math/rand/v2</code></a> に対応することにした。</p>
<p>まずはバージョンを v2 に上げて,以下のインポート・パスに変更した。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">import</span> <span class="s">"github.com/goark/mt/v2"</span>
</span></span></code></pre></div><p>また <code>go.mod</code> も同様に</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">require github.com/goark/mt/v2 v2.0.1
</span></span></code></pre></div><p>とする。</p>
<p>例として <a href="https://github.com/goark/mt" title="goark/mt: Mersenne Twister; Pseudo Random Number Generator, Implemented by Golang"><code>github.com/goark/mt/v2</code></a> パッケージと <a href="https://pkg.go.dev/math/rand/v2" title="rand package - math/rand - pkg.go.dev"><code>math/rand/v2</code></a> パッケージを組み合わせて標準正規分布する値を1万個生成してみる。
こんな感じ。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="s">"fmt"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"math"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"math/rand/v2"</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="s">"github.com/goark/mt/v2/mt19937"</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">rnd</span> <span class="o">:=</span> <span class="nx">rand</span><span class="p">.</span><span class="nf">New</span><span class="p">(</span><span class="nx">mt19937</span><span class="p">.</span><span class="nf">New</span><span class="p">(</span><span class="nx">rand</span><span class="p">.</span><span class="nf">Int64</span><span class="p">()))</span>
</span></span><span class="line"><span class="cl"> <span class="nx">points</span> <span class="o">:=</span> <span class="p">[]</span><span class="kt">float64</span><span class="p">{}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">max</span> <span class="o">:=</span> <span class="mf">0.0</span>
</span></span><span class="line"><span class="cl"> <span class="nx">min</span> <span class="o">:=</span> <span class="mf">1.0</span>
</span></span><span class="line"><span class="cl"> <span class="nx">sum</span> <span class="o">:=</span> <span class="mf">0.0</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="k">range</span> <span class="mi">10000</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">point</span> <span class="o">:=</span> <span class="nx">rnd</span><span class="p">.</span><span class="nf">NormFloat64</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"> <span class="nx">points</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="nx">points</span><span class="p">,</span> <span class="nx">point</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="nx">min</span> <span class="p">=</span> <span class="nx">math</span><span class="p">.</span><span class="nf">Min</span><span class="p">(</span><span class="nx">min</span><span class="p">,</span> <span class="nx">point</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="nx">max</span> <span class="p">=</span> <span class="nx">math</span><span class="p">.</span><span class="nf">Max</span><span class="p">(</span><span class="nx">max</span><span class="p">,</span> <span class="nx">point</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="nx">sum</span> <span class="o">+=</span> <span class="nx">point</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">n</span> <span class="o">:=</span> <span class="nb">float64</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="nx">points</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"> <span class="nx">ave</span> <span class="o">:=</span> <span class="nx">sum</span> <span class="o">/</span> <span class="nx">n</span>
</span></span><span class="line"><span class="cl"> <span class="nx">d2</span> <span class="o">:=</span> <span class="mf">0.0</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">p</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">points</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">d2</span> <span class="o">+=</span> <span class="p">(</span><span class="nx">p</span> <span class="o">-</span> <span class="nx">ave</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="nx">p</span> <span class="o">-</span> <span class="nx">ave</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">" minimum: "</span><span class="p">,</span> <span class="nx">min</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">" maximum: "</span><span class="p">,</span> <span class="nx">max</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">" average: "</span><span class="p">,</span> <span class="nx">ave</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">"standard deviation: "</span><span class="p">,</span> <span class="nx">math</span><span class="p">.</span><span class="nf">Sqrt</span><span class="p">(</span><span class="nx">d2</span><span class="o">/</span><span class="nx">n</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>これを実行するとこんな感じになる。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">$ go run sample.go
</span></span><span class="line"><span class="cl"> minimum: -4.465497509270884
</span></span><span class="line"><span class="cl"> maximum: 4.409945906326592
</span></span><span class="line"><span class="cl"> average: 0.010399867661332784
</span></span><span class="line"><span class="cl">standard deviation: 1.0027323703801945
</span></span></code></pre></div><p>まぁまぁ妥当な感じ?</p>
<p><a href="https://pkg.go.dev/math/rand" title="rand package - math/rand - Go Packages"><code>math/rand</code></a> および <a href="https://pkg.go.dev/math/rand/v2" title="rand package - math/rand - pkg.go.dev"><code>math/rand/v2</code></a> パッケージのトップレベル関数群の疑似乱数生成器が ChaCha8 になったおかげで seed を与えるのがめっちゃ楽になった。
これだけでもありがたい。
ともかくこれで,乱数生成周りの調査と対応は一通り完了かな。</p>
<h2>ブックマーク</h2>
<ul>
<li><a href="https://text.baldanders.info/release/mersenne-twister-by-golang/">疑似乱数生成器 goark/mt</a></li>
<li><a href="https://text.baldanders.info/golang/pseudo-random-number-generator-v2/">Go 1.22 における疑似乱数生成器</a></li>
<li><a href="https://zenn.dev/spiegel/articles/20240309-golang-math-rand-v2">Go 1.22 の math/rand/v2 を使ってみる</a></li>
</ul>
<h2>参考図書</h2>
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/416Stewy0NS._SL160_.jpg" width="123" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">プログラミング言語Go</a></dt>
<dd>アラン・ドノバン (著), ブライアン・カーニハン (著), 柴田芳樹 (著)</dd>
<dd>丸善出版 2016-06-20 (Release 2021-07-13)</dd>
<dd>Kindle版</dd>
<dd>B099928SJD (ASIN)</dd>
<dd>評価<abbr class="rating fa-sm" title="5"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i></abbr></dd>
</dl>
<p class="description">Kindle 版出た! 一部内容が古びてしまったが,この本は Go 言語の教科書と言ってもいいだろう。感想は<a href="https://text.baldanders.info/remark/2016/07/go-programming-language/" >こちら</a>。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2021-05-22">2021-05-22</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- プログラミング言語Go -->
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/B0CFL1DK8Q?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/51BmDUG6D0L._SL160_.jpg" width="125" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/B0CFL1DK8Q?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">Go言語 100Tips ありがちなミスを把握し、実装を最適化する impress top gearシリーズ</a></dt>
<dd>Teiva Harsanyi (著), 柴田 芳樹 (著)</dd>
<dd>インプレス 2023-08-18 (Release 2023-08-18)</dd>
<dd>Kindle版</dd>
<dd>B0CFL1DK8Q (ASIN)</dd>
<dd>評価<abbr class="rating fa-sm" title="4"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="far fa-star"></i></abbr></dd>
</dl>
<p class="description"><a href="https://book.impress.co.jp/books/1122101133">版元</a>で PDF 版を購入可能。事実上の Effective Go とも言える充実の内容。オリジナルは敢えてタイトルに “tips” という単語を入れるのを避けたのに邦題が「100 Tips」とかなっていて,原作者がお怒りとの噂(あくまで噂)</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2023-08-18">2023-08-18</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- Go言語 100Tips -->
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/4814400535?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/41+ew2wl2jL._SL160_.jpg" width="125" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/4814400535?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">効率的なGo ―データ指向によるGoアプリケーションの性能最適化</a></dt>
<dd>Bartłomiej Płotka (著), 山口 能迪 (翻訳)</dd>
<dd>オライリー・ジャパン 2024-02-24</dd>
<dd>単行本(ソフトカバー)</dd>
<dd>4814400535 (ASIN), 9784814400539 (EAN), 4814400535 (ISBN)</dd>
</dl>
<p class="description">ついに Effective Go のタイトルを冠した本の邦訳が出た。<a href="https://www.oreilly.co.jp/books/9784814400539/">版元</a>で Ebook を買える。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2024-02-22">2024-02-22</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- 効率的なGo : Effective Go -->
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/B015643CPE?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/51t6yHHVwEL._SL160_.jpg" width="113" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/B015643CPE?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">暗号技術入門 第3版 秘密の国のアリス</a></dt>
<dd>結城 浩 (著)</dd>
<dd>SBクリエイティブ 2015-08-25 (Release 2015-09-17)</dd>
<dd>Kindle版</dd>
<dd>B015643CPE (ASIN)</dd>
<dd>評価<abbr class="rating fa-sm" title="5"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i></abbr></dd>
</dl>
<p class="description">SHA-3 や Bitcoin/Blockchain など新しい知見や技術要素を大幅追加。暗号技術を使うだけならこれ1冊でとりあえず無問題。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2015-09-20">2015-09-20</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- 暗号技術入門 第3版 -->
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/B00I8AT1FO?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/41353H+BzFL._SL160_.jpg" width="113" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/B00I8AT1FO?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">数学ガール/乱択アルゴリズム</a></dt>
<dd>結城 浩 (著)</dd>
<dd>SBクリエイティブ 2011-02-25 (Release 2014-03-12)</dd>
<dd>Kindle版</dd>
<dd>B00I8AT1FO (ASIN)</dd>
<dd>評価<abbr class="rating fa-sm" title="5"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i></abbr></dd>
</dl>
<p class="description">工学ガール,リサちゃん登場!</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2015-04-19">2015-04-19</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- 数学ガール/乱択アルゴリズム -->
goark/errs パッケージ v1.3.2 をリリースした
tag:text.Baldanders.info,2023-06-26:/release/2023/06/errs-package-v1_3_2-is-released/
2023-06-26T12:22:20+00:00
2023-06-26T23:10:38+00:00
concurrency-safe なマルチエラー型を作った。
Spiegel
https://baldanders.info/profile/
<p><a href="https://text.baldanders.info/remark/2023/06/benchmark-for-errs-package/" title="拙作 gorak/errs パッケージの性能評価をしてもらった">この前書いた記事</a>で,最後の方に「そうそう <a href="https://pkg.go.dev/errors" title="errors · pkg.go.dev"><code>errors</code></a><code>.Join</code> 互換の関数ってあったほうがいいのかなぁ」と漠然と書いたのだが,その後,複数の goroutine を跨いでエラーハンドリングを行う必要ができたので, concurrency-safe なマルチエラー型 <a href="https://github.com/goark/errs" title="goark/errs: Error handling for Golang"><code>errs</code></a><code>.Errors</code> を作ってリリースした。</p>
<ul>
<li><a href="https://github.com/goark/errs/releases/tag/v1.3.2">Release v1.3.2 · goark/errs · GitHub</a></li>
</ul>
<p>いやぁ,並行処理書くの久しぶりで,色々とバグを潰してたら v1.3.2 まで上がってしまった(笑)</p>
<p>たとえば,こんな感じに使える。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="s">"fmt"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"sync"</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="s">"github.com/goark/errs"</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">generateMultiError</span><span class="p">()</span> <span class="kt">error</span> <span class="p">{</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">errlist</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">errs</span><span class="p">.</span><span class="nx">Errors</span><span class="p">{}</span>
</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">wg</span> <span class="nx">sync</span><span class="p">.</span><span class="nx">WaitGroup</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">i</span> <span class="o">:=</span> <span class="mi">1</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><=</span> <span class="mi">2</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">i</span> <span class="o">:=</span> <span class="nx">i</span>
</span></span><span class="line"><span class="cl"> <span class="nx">wg</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">go</span> <span class="kd">func</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">defer</span> <span class="nx">wg</span><span class="p">.</span><span class="nf">Done</span><span class="p">()</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">errlist</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="nx">fmt</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">"error %d"</span><span class="p">,</span> <span class="nx">i</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"> <span class="p">}()</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">wg</span><span class="p">.</span><span class="nf">Wait</span><span class="p">()</span>
</span></span><span class="line hl"><span class="cl"> <span class="k">return</span> <span class="nx">errlist</span><span class="p">.</span><span class="nf">ErrorOrNil</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">err</span> <span class="o">:=</span> <span class="nf">generateMultiError</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">"%+v\n"</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> <span class="c1">// {"Type":"*errs.Errors","Errs":[{"Type":"*errors.errorString","Msg":"error 2"},{"Type":"*errors.errorString","Msg":"error 1"}]}
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span>
</span></span></code></pre></div><p>また <a href="https://pkg.go.dev/errors" title="errors · pkg.go.dev"><code>errors</code></a><code>.Join()</code> 互換の関数も用意してみた。
こんな感じ。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="s">"errors"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"fmt"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"io"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"os"</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="s">"github.com/goark/errs"</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">generateMultiError</span><span class="p">()</span> <span class="kt">error</span> <span class="p">{</span>
</span></span><span class="line hl"><span class="cl"> <span class="k">return</span> <span class="nx">errs</span><span class="p">.</span><span class="nf">Join</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">ErrInvalid</span><span class="p">,</span> <span class="nx">io</span><span class="p">.</span><span class="nx">EOF</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">err</span> <span class="o">:=</span> <span class="nf">generateMultiError</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">"%+v\n"</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> <span class="c1">// {"Type":"*errs.Errors","Errs":[{"Type":"*errors.errorString","Msg":"invalid argument"},{"Type":"*errors.errorString","Msg":"EOF"}]}
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">errors</span><span class="p">.</span><span class="nf">Is</span><span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">io</span><span class="p">.</span><span class="nx">EOF</span><span class="p">))</span> <span class="c1">// true
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span>
</span></span></code></pre></div><p>今回新たに作った <a href="https://github.com/goark/errs" title="goark/errs: Error handling for Golang"><code>errs</code></a><code>.Errors</code> 型は <code>Unwrap() []error</code> メソッドを持っているため, <a href="https://go.dev/">Go</a> 1.20 以降であれば <a href="https://pkg.go.dev/errors" title="errors · pkg.go.dev"><code>errors</code></a><code>.Is()</code> および <a href="https://pkg.go.dev/errors" title="errors · pkg.go.dev"><code>errors</code></a><code>.As()</code> 関数を使って評価することができる。</p>
<p>これで <a href="https://pkg.go.dev/errors" title="errors · pkg.go.dev"><code>errors</code></a> 標準パッケージと互換性ありと言えるようになったかな?</p>
<h2>ブックマーク</h2>
<ul>
<li>
<p><a href="https://tech.kanmu.co.jp/entry/2023/06/19/150000">次なる<code>pkg/errors</code>を探して - カンムテックブログ</a></p>
</li>
<li>
<p><a href="https://text.baldanders.info/golang/wrapping-multiple-errors/">【Go 1.20 の予習】複数 error を返す Unwrap メソッドについて</a></p>
</li>
<li>
<p><a href="https://text.baldanders.info/release/errs-package-for-golang/">Go 言語用エラーハンドリング・パッケージ</a></p>
</li>
<li>
<p><a href="https://zenn.dev/spiegel/books/error-handling-in-golang">Go のエラーハンドリング</a> : Zenn 本書きました</p>
</li>
</ul>
<h2>参考図書</h2>
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/416Stewy0NS._SL160_.jpg" width="123" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">プログラミング言語Go</a></dt>
<dd>アラン・ドノバン (著), ブライアン・カーニハン (著), 柴田芳樹 (著)</dd>
<dd>丸善出版 2016-06-20 (Release 2021-07-13)</dd>
<dd>Kindle版</dd>
<dd>B099928SJD (ASIN)</dd>
<dd>評価<abbr class="rating fa-sm" title="5"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i></abbr></dd>
</dl>
<p class="description">Kindle 版出た! 一部内容が古びてしまったが,この本は Go 言語の教科書と言ってもいいだろう。感想は<a href="https://text.baldanders.info/remark/2016/07/go-programming-language/" >こちら</a>。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2021-05-22">2021-05-22</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- プログラミング言語Go -->
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/4873118468?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/51pUKQajnaL._SL160_.jpg" width="125" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/4873118468?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">Go言語による並行処理</a></dt>
<dd>Katherine Cox-Buday (著), 山口 能迪 (翻訳)</dd>
<dd>オライリージャパン 2018-10-26</dd>
<dd>単行本(ソフトカバー)</dd>
<dd>4873118468 (ASIN), 9784873118468 (EAN), 4873118468 (ISBN)</dd>
<dd>評価<abbr class="rating fa-sm" title="5"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i></abbr></dd>
</dl>
<p class="description"><a href="https://www.oreilly.co.jp/books/9784873118468/">Eブック版もある</a>。感想は<a href="https://text.baldanders.info/remark/2018/11/concurrency-in-go/">こちら</a>。 Go 言語で並行処理を書くならこの本は必読書になるだろう。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2020-01-13">2020-01-13</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- Go言語による並行処理 -->
goark/errs パッケージ v1.2.1 をリリースした
tag:text.Baldanders.info,2023-02-08:/release/2023/02/errs-package-v1_2_1-is-released/
2023-02-08T03:45:17+00:00
2023-02-08T03:45:37+00:00
Go 1.20 でマルチエラーをサポートするようになったため,その対応
Spiegel
https://baldanders.info/profile/
<p>おそらく私しか使ってないであろう,エラーハンドリング用の <a href="https://github.com/goark/errs" title="goark/errs: Error handling for Golang"><code>/github.com/goark/errs</code></a> パッケージ v1.2.1 をリリースした。</p>
<ul>
<li><a href="https://github.com/goark/errs/releases/tag/v1.2.0">Release v1.2.0 · goark/errs · GitHub</a></li>
<li><a href="https://github.com/goark/errs/releases/tag/v1.2.1">Release v1.2.1 · goark/errs · GitHub</a></li>
</ul>
<p>実は v1.2.0 でチョンボして v1.2.1 として出し直している。
ごめんペコン。</p>
<p><a href="https://go.dev/">Go</a> 1.20 で <code>Unwrap() []error</code> メソッドを持つマルチエラーをサポートするようになったため,その対応。
たとえば,複数の原因エラーがある場合に,標準の <a href="https://pkg.go.dev/errors" title="errors · pkg.go.dev"><code>errors</code></a><code>.Join()</code> 関数などと組み合わせて</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="s">"errors"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"fmt"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"io"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"os"</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="s">"github.com/goark/errs"</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">generateMultiError</span><span class="p">()</span> <span class="kt">error</span> <span class="p">{</span>
</span></span><span class="line hl"><span class="cl"> <span class="k">return</span> <span class="nx">errs</span><span class="p">.</span><span class="nf">New</span><span class="p">(</span><span class="s">"error with multiple causes"</span><span class="p">,</span> <span class="nx">errs</span><span class="p">.</span><span class="nf">WithCause</span><span class="p">(</span><span class="nx">errors</span><span class="p">.</span><span class="nf">Join</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">ErrInvalid</span><span class="p">,</span> <span class="nx">io</span><span class="p">.</span><span class="nx">EOF</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">err</span> <span class="o">:=</span> <span class="nf">generateMultiError</span><span class="p">()</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">errors</span><span class="p">.</span><span class="nf">Is</span><span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">io</span><span class="p">.</span><span class="nx">EOF</span><span class="p">))</span> <span class="c1">// true
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span>
</span></span></code></pre></div><p>てな感じに書くことができる。
ちなみに</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">err</span> <span class="o">:=</span> <span class="nf">generateMultiError</span><span class="p">()</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">"%+v\n"</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>と書き換えて実行すると</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">$ go run sample4.go | jq .
</span></span><span class="line"><span class="cl">{
</span></span><span class="line"><span class="cl"> "Type": "*errs.Error",
</span></span><span class="line"><span class="cl"> "Err": {
</span></span><span class="line"><span class="cl"> "Type": "*errors.errorString",
</span></span><span class="line"><span class="cl"> "Msg": "error with multiple causes"
</span></span><span class="line"><span class="cl"> },
</span></span><span class="line"><span class="cl"> "Context": {
</span></span><span class="line"><span class="cl"> "function": "main.generateMultiError"
</span></span><span class="line"><span class="cl"> },
</span></span><span class="line"><span class="cl"> "Cause": {
</span></span><span class="line"><span class="cl"> "Type": "*errors.joinError",
</span></span><span class="line"><span class="cl"> "Msg": "invalid argument\nEOF",
</span></span><span class="line"><span class="cl"> "Cause": [
</span></span><span class="line"><span class="cl"> {
</span></span><span class="line"><span class="cl"> "Type": "*errors.errorString",
</span></span><span class="line"><span class="cl"> "Msg": "invalid argument"
</span></span><span class="line"><span class="cl"> },
</span></span><span class="line"><span class="cl"> {
</span></span><span class="line"><span class="cl"> "Type": "*errors.errorString",
</span></span><span class="line"><span class="cl"> "Msg": "EOF"
</span></span><span class="line"><span class="cl"> }
</span></span><span class="line"><span class="cl"> ]
</span></span><span class="line"><span class="cl"> }
</span></span><span class="line"><span class="cl">}
</span></span></code></pre></div><p>マルチエラー部分もいい感じに JSON 出力できる。</p>
<p>以前の <a href="https://github.com/goark/errs" title="goark/errs: Error handling for Golang"><code>errs</code></a><code>.Cause()</code> 関数には <code>Deprecated</code> マークを付けた(マルチエラーに対応できないため)。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="c1">// Deprecated: should not be used
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">func</span> <span class="nf">Cause</span><span class="p">(</span><span class="nx">err</span> <span class="kt">error</span><span class="p">)</span> <span class="kt">error</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">unwraped</span> <span class="o">:=</span> <span class="nx">errors</span><span class="p">.</span><span class="nf">Unwrap</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">unwraped</span> <span class="o">==</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">err</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">err</span> <span class="p">=</span> <span class="nx">unwraped</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">err</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p><code>Deprecated</code> マークを付けた型や関数を使用すると lint などで注意喚起してくれる。
便利。</p>
<p><a href="https://github.com/goark/errs" title="goark/errs: Error handling for Golang"><code>errs</code></a><code>.Cause()</code> 関数の代わりと言ってはナニだが <a href="https://github.com/goark/errs" title="goark/errs: Error handling for Golang"><code>errs</code></a><code>.Unwraps()</code> 関数を用意した。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">Unwraps</span><span class="p">(</span><span class="nx">err</span> <span class="kt">error</span><span class="p">)</span> <span class="p">[]</span><span class="kt">error</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">es</span><span class="p">,</span> <span class="nx">ok</span> <span class="o">:=</span> <span class="nx">err</span><span class="p">.(</span><span class="kd">interface</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nf">Unwrap</span><span class="p">()</span> <span class="p">[]</span><span class="kt">error</span>
</span></span><span class="line"><span class="cl"> <span class="p">});</span> <span class="nx">ok</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">es</span><span class="p">.</span><span class="nf">Unwrap</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">e</span> <span class="o">:=</span> <span class="nx">errors</span><span class="p">.</span><span class="nf">Unwrap</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">e</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="p">[]</span><span class="kt">error</span><span class="p">{</span><span class="nx">e</span><span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">nil</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>この関数を使えば原因エラーを <code>[]error</code> で返してくれる(原因エラーが単一の場合もスライスで返すので注意)。</p>
<p>マルチエラーを格納する独自の型を作ることも一瞬考えたが,標準の <a href="https://pkg.go.dev/errors" title="errors · pkg.go.dev"><code>errors</code></a><code>.Join()</code> 関数などで作れば必要十分だと思うし,足りなければ改めて考えるか。
ということで今回はここまで。</p>
<h2>ブックマーク</h2>
<ul>
<li><a href="https://text.baldanders.info/golang/wrapping-multiple-errors/">【Go 1.20 の予習】複数 error を返す Unwrap メソッドについて</a></li>
<li><a href="https://text.baldanders.info/release/errs-package-for-golang/">Go 言語用エラーハンドリング・パッケージ</a></li>
<li><a href="https://zenn.dev/spiegel/books/error-handling-in-golang">Go のエラーハンドリング</a> : Zenn 本書きました</li>
</ul>
<h2>参考図書</h2>
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/416Stewy0NS._SL160_.jpg" width="123" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">プログラミング言語Go</a></dt>
<dd>アラン・ドノバン (著), ブライアン・カーニハン (著), 柴田芳樹 (著)</dd>
<dd>丸善出版 2016-06-20 (Release 2021-07-13)</dd>
<dd>Kindle版</dd>
<dd>B099928SJD (ASIN)</dd>
<dd>評価<abbr class="rating fa-sm" title="5"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i></abbr></dd>
</dl>
<p class="description">Kindle 版出た! 一部内容が古びてしまったが,この本は Go 言語の教科書と言ってもいいだろう。感想は<a href="https://text.baldanders.info/remark/2016/07/go-programming-language/" >こちら</a>。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2021-05-22">2021-05-22</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- プログラミング言語Go -->
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/4814400047?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/41dClAl3WKL._SL160_.jpg" width="125" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/4814400047?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">初めてのGo言語 ―他言語プログラマーのためのイディオマティックGo実践ガイド</a></dt>
<dd>Jon Bodner (著), 武舎 広幸 (翻訳)</dd>
<dd>オライリージャパン 2022-09-26</dd>
<dd>単行本(ソフトカバー)</dd>
<dd>4814400047 (ASIN), 9784814400041 (EAN), 4814400047 (ISBN)</dd>
<dd>評価<abbr class="rating fa-sm" title="4"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="far fa-star"></i></abbr></dd>
</dl>
<p class="description">2021年に出た “<a href="https://www.oreilly.com/library/view/learning-go/9781492077206/">Learning Go</a>” の邦訳版。私は<a href="https://www.oreilly.co.jp/books/9784814400041/">版元</a>で PDF 版を購入。 Go 特有の語法(idiom)を切り口として Go の機能やパッケージを解説している。 Go 1.19 対応。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2022-10-11">2022-10-11</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- 初めてのGo言語 -->
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/4873119693?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/41cBKEBEYyL._SL160_.jpg" width="125" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/4873119693?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">実用 Go言語 ―システム開発の現場で知っておきたいアドバイス</a></dt>
<dd>渋川 よしき (著), 辻 大志郎 (著), 真野 隼記 (著)</dd>
<dd>オライリージャパン 2022-04-22</dd>
<dd>単行本(ソフトカバー)</dd>
<dd>4873119693 (ASIN), 9784873119694 (EAN), 4873119693 (ISBN)</dd>
<dd>評価<abbr class="rating fa-sm" title="4"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="far fa-star"></i></abbr></dd>
</dl>
<p class="description"><a href="https://www.oreilly.co.jp//books/9784873119694/">版元</a>のデジタル版を購入。 Go で躓きやすい点を解説していくのが<a href="https://forkwell.connpass.com/event/262394/">最初の動機</a>らしい。「◯◯するには」を調べる際にこの本を調べるといいかも。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2022-10-26">2022-10-26</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- 実用 Go 言語 -->
go-cvss パッケージ v1.5.0 をリリースした
tag:text.Baldanders.info,2023-01-31:/release/2023/01/go-cvss-package-v1_5_0-is-released/
2023-01-31T07:36:54+00:00
2023-01-31T11:13:37+00:00
一連の変更でようやく CVSSv2 処理系は v3/metric パッケージと互換になった。
Spiegel
https://baldanders.info/profile/
<p>バグ報告が止まらない。
ごめんなさい
ごめんなさい
ごめんなさい…</p>
<p>ということで <a href="https://github.com/goark/go-cvss" title="goark/go-cvss: Common Vulnerability Scoring System (CVSS)"><code>github.com/goark/go-cvss</code></a> パッケージの v1.5.0 をリリースした。</p>
<ul>
<li><a href="https://github.com/goark/go-cvss/releases/tag/v1.5.0">Release v1.5.0 · goark/go-cvss · GitHub</a></li>
</ul>
<p>このバージョンで CVSSv2 のデコードを行うサブパッケージを <code>v2/base</code> から <code>v2/metric</code> に移行した。
こんな感じ。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="c1">//go:build run
</span></span></span><span class="line"><span class="cl"><span class="c1">// +build run
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="s">"fmt"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"os"</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="s">"github.com/goark/go-cvss/v2/metric"</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">bm</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">metric</span><span class="p">.</span><span class="nf">NewBase</span><span class="p">().</span><span class="nf">Decode</span><span class="p">(</span><span class="s">"AV:N/AC:L/Au:N/C:N/I:N/A:C"</span><span class="p">)</span> <span class="c1">//CVE-2002-0392
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Fprintln</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stderr</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">"Severity: %v (%v)\n"</span><span class="p">,</span> <span class="nx">bm</span><span class="p">.</span><span class="nf">Severity</span><span class="p">(),</span> <span class="nx">bm</span><span class="p">.</span><span class="nf">Score</span><span class="p">())</span>
</span></span><span class="line"><span class="cl"> <span class="c1">// Output:
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// Severity: Severity: High (7.8)
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span>
</span></span></code></pre></div><p>これに伴い <code>v2/base</code> パッケージ以下の型定義およびメソッドには <code>Deprecated</code> マークを付けている。
一連の変更でようやく CVSSv2 処理系は <code>v3/metric</code> パッケージと互換になった。
まぁ今どき CVSSv2 を使うことはないと思うけどね。</p>
<p>そもそも <a href="https://github.com/goark/go-cvss" title="goark/go-cvss: Common Vulnerability Scoring System (CVSS)"><code>github.com/goark/go-cvss</code></a> パッケージ自体がかなり試行錯誤していて,随分とカオスな状態になっていたので,この機会に整理できてよかった。
もうバグはないよなぁ。
ないと思いたい。</p>
<h2>2022-01-31 追記</h2>
<p>その後のバグ報告で,上述の <code>Deprecated</code> マークを付けた <code>v2/base</code> パッケージはデータ構造上 CVSSv2 の仕様を満たせないことが分かったので v1.6.0 で drop した。</p>
<ul>
<li><a href="https://github.com/goark/go-cvss/releases/tag/v1.6.0">Release v1.6.0 · goark/go-cvss · GitHub</a></li>
</ul>
<p>とほほ <code>orz</code></p>
<h2>ブックマーク</h2>
<ul>
<li><a href="https://www.first.org/cvss/v2/guide">CVSS v2 Complete Documentation</a></li>
</ul>
<h2>参考図書</h2>
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/416Stewy0NS._SL160_.jpg" width="123" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">プログラミング言語Go</a></dt>
<dd>アラン・ドノバン (著), ブライアン・カーニハン (著), 柴田芳樹 (著)</dd>
<dd>丸善出版 2016-06-20 (Release 2021-07-13)</dd>
<dd>Kindle版</dd>
<dd>B099928SJD (ASIN)</dd>
<dd>評価<abbr class="rating fa-sm" title="5"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i></abbr></dd>
</dl>
<p class="description">Kindle 版出た! 一部内容が古びてしまったが,この本は Go 言語の教科書と言ってもいいだろう。感想は<a href="https://text.baldanders.info/remark/2016/07/go-programming-language/" >こちら</a>。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2021-05-22">2021-05-22</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- プログラミング言語Go -->
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/4814400047?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/41dClAl3WKL._SL160_.jpg" width="125" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/4814400047?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">初めてのGo言語 ―他言語プログラマーのためのイディオマティックGo実践ガイド</a></dt>
<dd>Jon Bodner (著), 武舎 広幸 (翻訳)</dd>
<dd>オライリージャパン 2022-09-26</dd>
<dd>単行本(ソフトカバー)</dd>
<dd>4814400047 (ASIN), 9784814400041 (EAN), 4814400047 (ISBN)</dd>
<dd>評価<abbr class="rating fa-sm" title="4"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="far fa-star"></i></abbr></dd>
</dl>
<p class="description">2021年に出た “<a href="https://www.oreilly.com/library/view/learning-go/9781492077206/">Learning Go</a>” の邦訳版。私は<a href="https://www.oreilly.co.jp/books/9784814400041/">版元</a>で PDF 版を購入。 Go 特有の語法(idiom)を切り口として Go の機能やパッケージを解説している。 Go 1.19 対応。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2022-10-11">2022-10-11</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- 初めてのGo言語 -->
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/4873119693?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/41cBKEBEYyL._SL160_.jpg" width="125" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/4873119693?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">実用 Go言語 ―システム開発の現場で知っておきたいアドバイス</a></dt>
<dd>渋川 よしき (著), 辻 大志郎 (著), 真野 隼記 (著)</dd>
<dd>オライリージャパン 2022-04-22</dd>
<dd>単行本(ソフトカバー)</dd>
<dd>4873119693 (ASIN), 9784873119694 (EAN), 4873119693 (ISBN)</dd>
<dd>評価<abbr class="rating fa-sm" title="4"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="far fa-star"></i></abbr></dd>
</dl>
<p class="description"><a href="https://www.oreilly.co.jp//books/9784873119694/">版元</a>のデジタル版を購入。 Go で躓きやすい点を解説していくのが<a href="https://forkwell.connpass.com/event/262394/">最初の動機</a>らしい。「◯◯するには」を調べる際にこの本を調べるといいかも。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2022-10-26">2022-10-26</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- 実用 Go 言語 -->
go-cvss パッケージ v1.4.2 をリリースした
tag:text.Baldanders.info,2023-01-28:/release/2023/01/go-cvss-package-v1_4_2-is-released/
2023-01-28T03:47:48+00:00
2023-01-31T07:38:00+00:00
さらに今回は fuzzing テストまでしてもらって,ホンマに「マジすんません」って感じである。
Spiegel
https://baldanders.info/profile/
<p>CVSS ベクタ文字列を可視化したいという軽い動機で作った,拙作の <a href="https://github.com/goark/go-cvss" title="goark/go-cvss: Common Vulnerability Scoring System (CVSS)"><code>github.com/goark/go-cvss</code></a> パッケージだが,微妙に使って頂いてるようで,バグ報告をいくつか頂いたため,修正版をリリースした。</p>
<ul>
<li><a href="https://github.com/goark/go-cvss/releases/tag/v1.4.2">Release v1.4.2 · goark/go-cvss · GitHub</a></li>
</ul>
<p>CVSS のベクタ文字列(<code>CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H</code><sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> など)のバリデーションを厳密に行うようにした。
今までベクタ文字列の parse はかなり緩くしていて, metric 名が重複してても(後勝ちで)有効にしてたし,大文字小文字も関係なく有効にしていたが,仕様的にあかんやろ,ということで。
これに伴い,古いコードは drop した(コード管理が煩雑になるので)。</p>
<p>使い方は今までと変わらず</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="s">"flag"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"fmt"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"io"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"os"</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="s">"github.com/goark/go-cvss/v3/metric"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"github.com/goark/go-cvss/v3/report"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"golang.org/x/text/language"</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">template</span> <span class="p">=</span> <span class="s">"- `{{ .Vector }}`"</span> <span class="o">+</span> <span class="s">`
</span></span></span><span class="line"><span class="cl"><span class="s">- </span><span class="cp">{{</span><span class="w"> </span><span class="na">.SeverityName</span><span class="w"> </span><span class="cp">}}</span><span class="s">: </span><span class="cp">{{</span><span class="w"> </span><span class="na">.SeverityValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> (Score: </span><span class="cp">{{</span><span class="w"> </span><span class="na">.BaseScore</span><span class="w"> </span><span class="cp">}}</span><span class="s">)
</span></span></span><span class="line"><span class="cl"><span class="s">
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.BaseMetrics</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.BaseMetricValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">|--------|-------|
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.AVName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.AVValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.ACName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.ACValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.PRName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.PRValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.UIName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.UIValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.SName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.SValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.CName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.CValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.IName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.IValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.AName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.AValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">`</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">flag</span><span class="p">.</span><span class="nf">Parse</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">flag</span><span class="p">.</span><span class="nf">NArg</span><span class="p">()</span> <span class="p"><</span> <span class="mi">1</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Fprintln</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stderr</span><span class="p">,</span> <span class="s">"Set CVSS vector"</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">bm</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">metric</span><span class="p">.</span><span class="nf">NewBase</span><span class="p">().</span><span class="nf">Decode</span><span class="p">(</span><span class="nx">flag</span><span class="p">.</span><span class="nf">Arg</span><span class="p">(</span><span class="mi">0</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Fprintf</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stderr</span><span class="p">,</span> <span class="s">"%+v\n"</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">r</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">report</span><span class="p">.</span><span class="nf">NewBase</span><span class="p">(</span><span class="nx">bm</span><span class="p">,</span> <span class="nx">report</span><span class="p">.</span><span class="nf">WithOptionsLanguage</span><span class="p">(</span><span class="nx">language</span><span class="p">.</span><span class="nx">Japanese</span><span class="p">)).</span><span class="nf">ExportWithString</span><span class="p">(</span><span class="nx">template</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Fprintf</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stderr</span><span class="p">,</span> <span class="s">"%+v\n"</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">io</span><span class="p">.</span><span class="nf">Copy</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stdout</span><span class="p">,</span> <span class="nx">r</span><span class="p">);</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Fprintf</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stderr</span><span class="p">,</span> <span class="s">"%+v\n"</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>などとしておけば</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">$ go run main.go "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"
</span></span><span class="line"><span class="cl">- `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H`
</span></span><span class="line"><span class="cl">- 深刻度: 緊急 (Score: 9.8)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">| 基本評価基準 | 評価値 |
</span></span><span class="line"><span class="cl">|--------|-------|
</span></span><span class="line"><span class="cl">| 攻撃元区分 | ネットワーク |
</span></span><span class="line"><span class="cl">| 攻撃条件の複雑さ | 低 |
</span></span><span class="line"><span class="cl">| 必要な特権レベル | 不要 |
</span></span><span class="line"><span class="cl">| ユーザ関与レベル | 不要 |
</span></span><span class="line"><span class="cl">| スコープ | 変更なし |
</span></span><span class="line"><span class="cl">| 機密性への影響 | 高 |
</span></span><span class="line"><span class="cl">| 完全性への影響 | 高 |
</span></span><span class="line"><span class="cl">| 可用性への影響 | 高 |
</span></span></code></pre></div><p>と出力される。</p>
<p>この <a href="https://github.com/goark/go-cvss" title="goark/go-cvss: Common Vulnerability Scoring System (CVSS)"><code>github.com/goark/go-cvss</code></a> パッケージってコードの半分くらい貰いものだし,さらに今回は fuzzing テストまでしてもらって,ホンマに「マジすんません」って感じである。ありがたや <abbr class="emoji-chars" title="ペコン">🙇</abbr></p>
<p>でも CVSS ってあくまでもリスクの「評価基準」のひとつであって,そこから「どうする」ってのはまた別の話なんだよね。
個人なら CVSS の Base metrics 情報を見て都度判断すればいいけど,組織では <a href="https://resources.sei.cmu.edu/library/asset-view.cfm?assetid=653459" title="Prioritizing Vulnerability Response: A Stakeholder-Specific Vulnerability Categorization (Version 2.0)">SSVC (Stakeholder-Specific Vulnerability Categorization)</a> なんかと組み合わせる必要があるかもしれない。</p>
<p>道具は適材適所で使いましょう,ということで。</p>
<h2>【2022-01-29 追記】 v1.4.4 をリリースした</h2>
<p>またバグ報告があったので修正版をリリースした。
とほほ…</p>
<ul>
<li><a href="https://github.com/goark/go-cvss/releases/tag/v1.4.4">Release v1.4.4 · goark/go-cvss · GitHub</a></li>
</ul>
<p>今回のついでにスコアの計算周りのリファクタリングを行った。
ちょっとスッキリ!</p>
<h2>ブックマーク</h2>
<ul>
<li>
<p><a href="https://www.first.org/cvss/v3.0/specification-document">CVSS v3.0 Specification Document</a></p>
</li>
<li>
<p><a href="https://www.first.org/cvss/v3.1/specification-document">CVSS v3.1 Specification Document</a></p>
</li>
<li>
<p><a href="https://www.ipa.go.jp/security/vuln/CVSSv3.html">共通脆弱性評価システムCVSS v3概説:IPA 独立行政法人 情報処理推進機構</a></p>
</li>
<li>
<p><a href="https://text.baldanders.info/remark/2022/08/software-bills-of-materials/">オープンソース製品とソフトウェア部品表</a></p>
</li>
</ul>
<h2>参考図書</h2>
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/416Stewy0NS._SL160_.jpg" width="123" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">プログラミング言語Go</a></dt>
<dd>アラン・ドノバン (著), ブライアン・カーニハン (著), 柴田芳樹 (著)</dd>
<dd>丸善出版 2016-06-20 (Release 2021-07-13)</dd>
<dd>Kindle版</dd>
<dd>B099928SJD (ASIN)</dd>
<dd>評価<abbr class="rating fa-sm" title="5"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i></abbr></dd>
</dl>
<p class="description">Kindle 版出た! 一部内容が古びてしまったが,この本は Go 言語の教科書と言ってもいいだろう。感想は<a href="https://text.baldanders.info/remark/2016/07/go-programming-language/" >こちら</a>。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2021-05-22">2021-05-22</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- プログラミング言語Go -->
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/4814400047?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/41dClAl3WKL._SL160_.jpg" width="125" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/4814400047?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">初めてのGo言語 ―他言語プログラマーのためのイディオマティックGo実践ガイド</a></dt>
<dd>Jon Bodner (著), 武舎 広幸 (翻訳)</dd>
<dd>オライリージャパン 2022-09-26</dd>
<dd>単行本(ソフトカバー)</dd>
<dd>4814400047 (ASIN), 9784814400041 (EAN), 4814400047 (ISBN)</dd>
<dd>評価<abbr class="rating fa-sm" title="4"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="far fa-star"></i></abbr></dd>
</dl>
<p class="description">2021年に出た “<a href="https://www.oreilly.com/library/view/learning-go/9781492077206/">Learning Go</a>” の邦訳版。私は<a href="https://www.oreilly.co.jp/books/9784814400041/">版元</a>で PDF 版を購入。 Go 特有の語法(idiom)を切り口として Go の機能やパッケージを解説している。 Go 1.19 対応。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2022-10-11">2022-10-11</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- 初めてのGo言語 -->
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/4873119693?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/41cBKEBEYyL._SL160_.jpg" width="125" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/4873119693?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">実用 Go言語 ―システム開発の現場で知っておきたいアドバイス</a></dt>
<dd>渋川 よしき (著), 辻 大志郎 (著), 真野 隼記 (著)</dd>
<dd>オライリージャパン 2022-04-22</dd>
<dd>単行本(ソフトカバー)</dd>
<dd>4873119693 (ASIN), 9784873119694 (EAN), 4873119693 (ISBN)</dd>
<dd>評価<abbr class="rating fa-sm" title="4"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="far fa-star"></i></abbr></dd>
</dl>
<p class="description"><a href="https://www.oreilly.co.jp//books/9784873119694/">版元</a>のデジタル版を購入。 Go で躓きやすい点を解説していくのが<a href="https://forkwell.connpass.com/event/262394/">最初の動機</a>らしい。「◯◯するには」を調べる際にこの本を調べるといいかも。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2022-10-26">2022-10-26</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- 実用 Go 言語 -->
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://nvd.nist.gov/vuln/detail/CVE-2022-3515">CVE-2022-3515</a> より <a href="#fnref:1" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
</ol>
</div>
今年の恵方を取得する
tag:text.Baldanders.info,2023-01-14:/golang/favourable-direction/
2023-01-14T07:21:26+00:00
2023-02-02T11:01:41+00:00
koyomi パッケージに追加した
Spiegel
https://baldanders.info/profile/
<p>正月気分も終わり,近所のスーパーとかで節分グッズが並ぶようになって「そういや今年の恵方はどっちだっけ?」と思って調べてみた。</p>
<p>どうやら,その年の十干で恵方が決定するらしい。</p>
<figure lang="en">
<blockquote class="nobox" style='margin:0 auto;text-align:center;'>
<a href="https://commons.wikimedia.org/wiki/File:Ehou-direction.png"><img src="./Ehou-direction.png" srcset="./Ehou-direction.png 500w" sizes="(min-width:600px) 500px, 80vw" alt="File:Ehou-direction.png - Wikimedia Commons" loading="lazy"></a>
</blockquote>
<figcaption><div>via <q><a href="https://commons.wikimedia.org/wiki/File:Ehou-direction.png">File:Ehou-direction.png - Wikimedia Commons</a></q></div></figcaption>
</figure>
<p>って,4方向を十干で分けるのか。
中途半端やなぁ。</p>
<p>まぁ,でも,その年の十干が分かれば恵方も分かるわけだ。
拙作の <a href="https://github.com/goark/koyomi" title="goark/koyomi: 日本のこよみ"><code>github.com/goark/koyomi</code></a> パッケージにオマケで十干十二支を数え上げる機能を付けているのだが,これに恵方を取得する機能を追加してみた。</p>
<p>こんな感じ。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="s">"fmt"</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="s">"github.com/goark/koyomi/zodiac"</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">year</span> <span class="o">:=</span> <span class="mi">2023</span>
</span></span><span class="line"><span class="cl"> <span class="nx">干</span><span class="p">,</span> <span class="nx">支</span> <span class="o">:=</span> <span class="nx">zodiac</span><span class="p">.</span><span class="nf">ZodiacYearNumber</span><span class="p">(</span><span class="nx">year</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">"%d年は%v%v,恵方は%v (%v°)"</span><span class="p">,</span> <span class="nx">year</span><span class="p">,</span> <span class="nx">干</span><span class="p">,</span> <span class="nx">支</span><span class="p">,</span> <span class="nx">干</span><span class="p">.</span><span class="nf">DirectionJp</span><span class="p">(),</span> <span class="nx">干</span><span class="p">.</span><span class="nf">Direction</span><span class="p">())</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>これを<a href="https://go.dev/play/p/PEKVng6jwFc">実行</a>すると</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">2023年は癸卯,恵方は南南東微南 (165°)
</span></span></code></pre></div><p>と出力される。</p>
<p>というわけで,2023年はだいたい南南東を向いてモグモグすればいいらしい。</p>
<p>この「恵方」というのはその年の歳神様のおられる方位で,居住地から見て恵方にあたる社寺に詣ることを「恵方詣り」と言うらしいのだが,明治以降の鉄道の発達で長距離移動が容易になり,方位に依存する「恵方詣り」が廃れ,代わりに「初詣」が主流になっていったとのこと。
その一方で,節分の「恵方巻き」みたいな文化が平成以降に台頭してくるのは面白い。</p>
<h2>ブックマーク</h2>
<ul>
<li>
<span><a href="http://libro.do-bunkyodai.ac.jp/research/pdf/journal32/12.pdf">食卓の縁起に関する研究 I -恵方巻の受容とその背景- <sup><i class="far fa-file-pdf"></i></sup></a></span>
</li>
<li>
<p><a href="https://ii-nippon.net/%e6%97%a5%e6%9c%ac%e3%81%ae%e9%a2%a8%e7%bf%92/1183.html">恵方の方角!2023年はどっち?恵方の決め方も具体的に解説! | いい日本再発見</a></p>
</li>
<li>
<p><a href="https://ja.wikipedia.org/wiki/%E6%AD%B3%E5%BE%B3%E7%A5%9E">歳徳神 - Wikipedia</a></p>
</li>
<li>
<p><a href="https://text.baldanders.info/remark/2018/02/folklore/">節分どうでしょう</a></p>
</li>
</ul>
<h2>参考図書</h2>
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/B0191845R0?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/41eoVFqiaEL._SL160_.jpg" width="97" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/B0191845R0?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">鉄道が変えた社寺参詣 (交通新聞社新書)</a></dt>
<dd>平山昇 (著)</dd>
<dd>交通新聞社 2012-10-15 (Release 2015-12-07)</dd>
<dd>Kindle版</dd>
<dd>B0191845R0 (ASIN)</dd>
</dl>
<p class="description">面白そうなのでポチってみた。これから読む。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2023-01-14">2023-01-14</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- 鉄道が変えた社寺参詣 -->
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/416Stewy0NS._SL160_.jpg" width="123" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">プログラミング言語Go</a></dt>
<dd>アラン・ドノバン (著), ブライアン・カーニハン (著), 柴田芳樹 (著)</dd>
<dd>丸善出版 2016-06-20 (Release 2021-07-13)</dd>
<dd>Kindle版</dd>
<dd>B099928SJD (ASIN)</dd>
<dd>評価<abbr class="rating fa-sm" title="5"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i></abbr></dd>
</dl>
<p class="description">Kindle 版出た! 一部内容が古びてしまったが,この本は Go 言語の教科書と言ってもいいだろう。感想は<a href="https://text.baldanders.info/remark/2016/07/go-programming-language/" >こちら</a>。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2021-05-22">2021-05-22</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- プログラミング言語Go -->
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/4814400047?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/41dClAl3WKL._SL160_.jpg" width="125" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/4814400047?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">初めてのGo言語 ―他言語プログラマーのためのイディオマティックGo実践ガイド</a></dt>
<dd>Jon Bodner (著), 武舎 広幸 (翻訳)</dd>
<dd>オライリージャパン 2022-09-26</dd>
<dd>単行本(ソフトカバー)</dd>
<dd>4814400047 (ASIN), 9784814400041 (EAN), 4814400047 (ISBN)</dd>
<dd>評価<abbr class="rating fa-sm" title="4"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="far fa-star"></i></abbr></dd>
</dl>
<p class="description">2021年に出た “<a href="https://www.oreilly.com/library/view/learning-go/9781492077206/">Learning Go</a>” の邦訳版。私は<a href="https://www.oreilly.co.jp/books/9784814400041/">版元</a>で PDF 版を購入。 Go 特有の語法(idiom)を切り口として Go の機能やパッケージを解説している。 Go 1.19 対応。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2022-10-11">2022-10-11</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- 初めてのGo言語 -->
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/4873119693?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/41cBKEBEYyL._SL160_.jpg" width="125" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/4873119693?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">実用 Go言語 ―システム開発の現場で知っておきたいアドバイス</a></dt>
<dd>渋川 よしき (著), 辻 大志郎 (著), 真野 隼記 (著)</dd>
<dd>オライリージャパン 2022-04-22</dd>
<dd>単行本(ソフトカバー)</dd>
<dd>4873119693 (ASIN), 9784873119694 (EAN), 4873119693 (ISBN)</dd>
<dd>評価<abbr class="rating fa-sm" title="4"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="far fa-star"></i></abbr></dd>
</dl>
<p class="description"><a href="https://www.oreilly.co.jp//books/9784873119694/">版元</a>のデジタル版を購入。 Go で躓きやすい点を解説していくのが<a href="https://forkwell.connpass.com/event/262394/">最初の動機</a>らしい。「◯◯するには」を調べる際にこの本を調べるといいかも。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2022-10-26">2022-10-26</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- 実用 Go 言語 -->
sshql — SSH 越しに RDBMS にアクセスする
tag:text.Baldanders.info,2022-09-30:/release/sshql/
2022-09-30T12:17:13+00:00
2022-09-30T12:18:06+00:00
拙作 github.com/goark/sshql は SSH 経由で MySQL や PostgreSQL といった RDBMS に接続するための Go パッケージである。
Spiegel
https://baldanders.info/profile/
<p>拙作 <a href="https://github.com/goark/sshql" title="goark/sshql: Go SQL drivers over SSH"><code>github.com/goark/sshql</code></a> は SSH 経由で MySQL や PostgreSQL といった RDBMS に接続するための <a href="https://go.dev/">Go</a> パッケージである。</p>
<ul>
<li><a href="https://github.com/goark/sshql">GitHub - goark/sshql: Go SQL drivers over SSH</a></li>
</ul>
<p><a href="https://github.com/goark/sshql" title="goark/sshql: Go SQL drivers over SSH"><code>github.com/goark/sshql</code></a> パッケージでは以下の Dialer 型の構造体を用意し,これを使って SSH に接続する<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="c1">// Dialer is authentication provider information.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">type</span> <span class="nx">Dialer</span> <span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Hostname</span> <span class="kt">string</span> <span class="s">`json:"hostname"`</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Port</span> <span class="kt">int</span> <span class="s">`json:"port"`</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Username</span> <span class="kt">string</span> <span class="s">`json:"username"`</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Password</span> <span class="kt">string</span> <span class="s">`json:"password"`</span>
</span></span><span class="line"><span class="cl"> <span class="nx">PrivateKey</span> <span class="kt">string</span> <span class="s">`json:"privateKey"`</span>
</span></span><span class="line"><span class="cl"> <span class="nx">IgnoreHostKey</span> <span class="kt">bool</span> <span class="s">`json:"IgnoreHostKey"`</span>
</span></span><span class="line"><span class="cl"> <span class="nx">client</span> <span class="o">*</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">Client</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>パスワード認証の場合は <code>Username</code> と <code>Password</code> にそれぞれ値をセットする。
<code>PrivateKey</code> に認証用の秘密鍵へのパスを指定する場合は <code>Password</code> に秘密鍵のパスフレーズをセットする。
また <code>ssh-agent</code> 等を使って <code>$SSH_AUTH_SOCK</code> ソケットから秘密鍵を取得できる場合は,こちらを優先するようになっている。</p>
<p><code>IgnoreHostKey</code> に <code>true</code> をセットするとホスト認証を無視するようになっているが,セキュリティ上お勧めできないのでご注意を。
ホスト認証は <code>$HOME/.ssh/known_hosts</code> ファイルにホスト鍵が登録されていることが前提で, <code>known_hosts</code> ファイルがない,または <code>known_hosts</code> にホスト鍵がない場合は</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">$ go run main.go
</span></span><span class="line"><span class="cl">ssh: handshake failed: knownhosts: key is unknown
</span></span></code></pre></div><p>という感じにエラーになる。</p>
<p>では,これを使って実際にコードを書いてみる。</p>
<h2><a href="https://github.com/lib/pq" title="lib/pq: Pure Go Postgres driver for database/sql">github.com/lib/pq</a> + <a href="https://github.com/goark/sshql" title="goark/sshql: Go SQL drivers over SSH">github.com/goark/sshql</a></h2>
<p>まずは PostgreSQL 用ドライバ <a href="https://github.com/lib/pq" title="lib/pq: Pure Go Postgres driver for database/sql"><code>github.com/lib/pq</code></a> と <a href="https://github.com/goark/sshql" title="goark/sshql: Go SQL drivers over SSH"><code>github.com/goark/sshql</code></a> を組み合わせるところから。
こんな感じに書ける。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="s">"database/sql"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"fmt"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"os"</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="s">"github.com/goark/sshql"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"github.com/goark/sshql/pgdrv"</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">dialer</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">sshql</span><span class="p">.</span><span class="nx">Dialer</span><span class="p">{</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">Hostname</span><span class="p">:</span> <span class="s">"sshserver"</span><span class="p">,</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">Port</span><span class="p">:</span> <span class="mi">22</span><span class="p">,</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">Username</span><span class="p">:</span> <span class="s">"remoteuser"</span><span class="p">,</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">Password</span><span class="p">:</span> <span class="s">"passphraseforauthkey"</span><span class="p">,</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">PrivateKey</span><span class="p">:</span> <span class="s">"/home/username/.ssh/id_eddsa"</span><span class="p">,</span>
</span></span><span class="line hl"><span class="cl"> <span class="p">}</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">pgdrv</span><span class="p">.</span><span class="nf">New</span><span class="p">(</span><span class="nx">dialer</span><span class="p">).</span><span class="nf">Register</span><span class="p">(</span><span class="s">"postgres+ssh"</span><span class="p">)</span>
</span></span><span class="line hl"><span class="cl">
</span></span><span class="line hl"><span class="cl"> <span class="nx">db</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">sql</span><span class="p">.</span><span class="nf">Open</span><span class="p">(</span><span class="s">"postgres+ssh"</span><span class="p">,</span> <span class="s">"postgres://dbuser:dbpassword@localhost:5432/example?sslmode=disable"</span><span class="p">)</span>
</span></span><span class="line hl"><span class="cl"> <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Fprintln</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stderr</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line hl"><span class="cl"> <span class="k">return</span>
</span></span><span class="line hl"><span class="cl"> <span class="p">}</span>
</span></span><span class="line hl"><span class="cl"> <span class="k">defer</span> <span class="nx">dialer</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span>
</span></span><span class="line hl"><span class="cl"> <span class="k">defer</span> <span class="nx">db</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="nx">rows</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">db</span><span class="p">.</span><span class="nf">Query</span><span class="p">(</span><span class="s">"SELECT id, name FROM example ORDER BY id"</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Fprintln</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stderr</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">rows</span><span class="p">.</span><span class="nf">Next</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">id</span> <span class="kt">int64</span>
</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">name</span> <span class="kt">string</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">rows</span><span class="p">.</span><span class="nf">Scan</span><span class="p">(</span><span class="o">&</span><span class="nx">id</span><span class="p">,</span> <span class="o">&</span><span class="nx">name</span><span class="p">);</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Fprintln</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stderr</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">break</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">"ID: %d Name: %s\n"</span><span class="p">,</span> <span class="nx">id</span><span class="p">,</span> <span class="nx">name</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">rows</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p><code>"postgres+ssh"</code> としてドライバを登録し(名前は何でもOK),この名前を <a href="https://pkg.go.dev/database/sql" title="sql package - database/sql - Go Packages"><code>sql</code></a><code>.Open()</code> 関数で指定しているのがポイントである。
あとは <a href="https://pkg.go.dev/database/sql" title="sql package - database/sql - Go Packages"><code>database/sql</code></a> の機能をそのまま使うことができる。</p>
<p><a href="https://github.com/goark/sshql" title="goark/sshql: Go SQL drivers over SSH"><code>github.com/goark/sshql</code></a><code>/pgdrv</code> パッケージ内部で <a href="https://github.com/lib/pq" title="lib/pq: Pure Go Postgres driver for database/sql"><code>github.com/lib/pq</code></a> パッケージを呼び出しているため</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nx">_</span> <span class="s">"github.com/lib/pq"</span>
</span></span></code></pre></div><p>のようなインポートは不要である。</p>
<h2><a href="https://github.com/jackc/pgx" title="jackc/pgx: PostgreSQL driver and toolkit for Go">github.com/jackc/pgx</a> + <a href="https://github.com/goark/sshql" title="goark/sshql: Go SQL drivers over SSH">github.com/goark/sshql</a></h2>
<p><a href="https://github.com/jackc/pgx" title="jackc/pgx: PostgreSQL driver and toolkit for Go"><code>github.com/jackc/pgx</code></a> は <a href="https://github.com/lib/pq" title="lib/pq: Pure Go Postgres driver for database/sql"><code>github.com/lib/pq</code></a> の後継とも言えるパッケージである。
標準 <a href="https://pkg.go.dev/database/sql" title="sql package - database/sql - Go Packages"><code>database/sql</code></a> パッケージと組み合わせて使うことも可能だが,自身が <a href="https://pkg.go.dev/database/sql" title="sql package - database/sql - Go Packages"><code>database/sql</code></a> 互換のインタフェースを持っていて更に独自の機能も搭載している。
PostgreSQL にアクセスするなら,個人的にはこちらのほうがお勧めである。</p>
<p>拙作 <a href="https://github.com/goark/sshql" title="goark/sshql: Go SQL drivers over SSH"><code>github.com/goark/sshql</code></a> と組み合わせて使うにはちょっと変則的な初期化コードを書く。
こんな感じ。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="s">"context"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"fmt"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"os"</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="s">"github.com/goark/sshql"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"github.com/jackc/pgx/v4/pgxpool"</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">dialer</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">sshql</span><span class="p">.</span><span class="nx">Dialer</span><span class="p">{</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">Hostname</span><span class="p">:</span> <span class="s">"sshserver"</span><span class="p">,</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">Port</span><span class="p">:</span> <span class="mi">22</span><span class="p">,</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">Username</span><span class="p">:</span> <span class="s">"remoteuser"</span><span class="p">,</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">Password</span><span class="p">:</span> <span class="s">"passphraseforauthkey"</span><span class="p">,</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">PrivateKey</span><span class="p">:</span> <span class="s">"/home/username/.ssh/id_eddsa"</span><span class="p">,</span>
</span></span><span class="line hl"><span class="cl"> <span class="p">}</span>
</span></span><span class="line hl"><span class="cl">
</span></span><span class="line hl"><span class="cl"> <span class="nx">cfg</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">pgxpool</span><span class="p">.</span><span class="nf">ParseConfig</span><span class="p">(</span><span class="s">"postgres://dbuser:dbpassword@localhost:5432/example?sslmode=disable"</span><span class="p">)</span>
</span></span><span class="line hl"><span class="cl"> <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Fprintln</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stderr</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line hl"><span class="cl"> <span class="k">return</span>
</span></span><span class="line hl"><span class="cl"> <span class="p">}</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">cfg</span><span class="p">.</span><span class="nx">ConnConfig</span><span class="p">.</span><span class="nx">DialFunc</span> <span class="p">=</span> <span class="nx">dialer</span><span class="p">.</span><span class="nx">DialContext</span>
</span></span><span class="line hl"><span class="cl">
</span></span><span class="line hl"><span class="cl"> <span class="k">if</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">dialer</span><span class="p">.</span><span class="nf">Connect</span><span class="p">();</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Fprintln</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stderr</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line hl"><span class="cl"> <span class="k">return</span>
</span></span><span class="line hl"><span class="cl"> <span class="p">}</span>
</span></span><span class="line hl"><span class="cl"> <span class="k">defer</span> <span class="nx">dialer</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span>
</span></span><span class="line hl"><span class="cl">
</span></span><span class="line hl"><span class="cl"> <span class="nx">pool</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">pgxpool</span><span class="p">.</span><span class="nf">ConnectConfig</span><span class="p">(</span><span class="nx">context</span><span class="p">.</span><span class="nf">TODO</span><span class="p">(),</span> <span class="nx">cfg</span><span class="p">)</span>
</span></span><span class="line hl"><span class="cl"> <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Fprintln</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stderr</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line hl"><span class="cl"> <span class="k">return</span>
</span></span><span class="line hl"><span class="cl"> <span class="p">}</span>
</span></span><span class="line hl"><span class="cl"> <span class="k">defer</span> <span class="nx">pool</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="nx">rows</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">pool</span><span class="p">.</span><span class="nf">Query</span><span class="p">(</span><span class="nx">context</span><span class="p">.</span><span class="nf">TODO</span><span class="p">(),</span> <span class="s">"SELECT id, name FROM example ORDER BY id"</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Fprintln</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stderr</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">rows</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">rows</span><span class="p">.</span><span class="nf">Next</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">id</span> <span class="kt">int64</span>
</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">name</span> <span class="kt">string</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">rows</span><span class="p">.</span><span class="nf">Scan</span><span class="p">(</span><span class="o">&</span><span class="nx">id</span><span class="p">,</span> <span class="o">&</span><span class="nx">name</span><span class="p">);</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Fprintln</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stderr</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">break</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">"ID: %d Name: %s\n"</span><span class="p">,</span> <span class="nx">id</span><span class="p">,</span> <span class="nx">name</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>まず <a href="https://github.com/jackc/pgx" title="jackc/pgx: PostgreSQL driver and toolkit for Go"><code>pgx</code></a><code>.ConnConfig</code> を含む <a href="https://github.com/jackc/pgx" title="jackc/pgx: PostgreSQL driver and toolkit for Go"><code>pgx</code></a><code>/pgxpool.Config</code> 構造体を作って,そこに <code>dialer.DialContext()</code> メソッドを登録するイメージ。
<a href="https://github.com/jackc/pgx" title="jackc/pgx: PostgreSQL driver and toolkit for Go"><code>pgx</code></a> ドライバーをオープンする前に <code>dialer.Connect()</code> つまり SSH 接続を明示的に記述する必要がある。</p>
<p>一見まどろこしく見えるが, <a href="https://github.com/jackc/pgx" title="jackc/pgx: PostgreSQL driver and toolkit for Go"><code>pgx</code></a><code>/pgxpool.Config</code> 構造体を使って logger 登録を含むカスタマイズができるので,実用上はそれほど迂遠なコードではなかったりする。
接続ごとにインスタンスを作れるので,グローバルに名前をつけてドライバーを登録するより合理的かもしれない。</p>
<h2><a href="https://github.com/go-sql-driver/mysql" title="go-sql-driver/mysql: Go MySQL Driver is a MySQL driver for Go's (golang) database/sql package">github.com/go-sql-driver/mysql</a> + <a href="https://github.com/goark/sshql" title="goark/sshql: Go SQL drivers over SSH">github.com/goark/sshql</a></h2>
<p>MySQL 用ドライバ <a href="https://github.com/go-sql-driver/mysql" title="go-sql-driver/mysql: Go MySQL Driver is a MySQL driver for Go's (golang) database/sql package"><code>github.com/go-sql-driver/mysql</code></a> と <a href="https://github.com/goark/sshql" title="goark/sshql: Go SQL drivers over SSH"><code>github.com/goark/sshql</code></a> との組み合わせはこんな感じ。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="s">"database/sql"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"fmt"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"os"</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="s">"github.com/goark/sshql"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"github.com/goark/sshql/mysqldrv"</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">dialer</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">sshql</span><span class="p">.</span><span class="nx">Dialer</span><span class="p">{</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">Hostname</span><span class="p">:</span> <span class="s">"sshserver"</span><span class="p">,</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">Port</span><span class="p">:</span> <span class="mi">22</span><span class="p">,</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">Username</span><span class="p">:</span> <span class="s">"remoteuser"</span><span class="p">,</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">Password</span><span class="p">:</span> <span class="s">"passphraseforauthkey"</span><span class="p">,</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">PrivateKey</span><span class="p">:</span> <span class="s">"/home/username/.ssh/id_eddsa"</span><span class="p">,</span>
</span></span><span class="line hl"><span class="cl"> <span class="p">}</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">mysqldrv</span><span class="p">.</span><span class="nf">New</span><span class="p">(</span><span class="nx">dialer</span><span class="p">).</span><span class="nf">RegisterDial</span><span class="p">(</span><span class="s">"ssh+tcp"</span><span class="p">)</span>
</span></span><span class="line hl"><span class="cl">
</span></span><span class="line hl"><span class="cl"> <span class="nx">db</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">sql</span><span class="p">.</span><span class="nf">Open</span><span class="p">(</span><span class="s">"mysql"</span><span class="p">,</span> <span class="s">"dbuser:dbpassword@ssh+tcp(localhost:3306)/dbname"</span><span class="p">)</span>
</span></span><span class="line hl"><span class="cl"> <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Fprintln</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stderr</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line hl"><span class="cl"> <span class="k">return</span>
</span></span><span class="line hl"><span class="cl"> <span class="p">}</span>
</span></span><span class="line hl"><span class="cl"> <span class="k">defer</span> <span class="nx">dialer</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span>
</span></span><span class="line hl"><span class="cl"> <span class="k">defer</span> <span class="nx">db</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="nx">rows</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">db</span><span class="p">.</span><span class="nf">Query</span><span class="p">(</span><span class="s">"SELECT id, name FROM example ORDER BY id"</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Fprintln</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stderr</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">rows</span><span class="p">.</span><span class="nf">Next</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">id</span> <span class="kt">int64</span>
</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">name</span> <span class="kt">string</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">rows</span><span class="p">.</span><span class="nf">Scan</span><span class="p">(</span><span class="o">&</span><span class="nx">id</span><span class="p">,</span> <span class="o">&</span><span class="nx">name</span><span class="p">);</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Fprintln</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stderr</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">break</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">"ID: %d Name: %s\n"</span><span class="p">,</span> <span class="nx">id</span><span class="p">,</span> <span class="nx">name</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">rows</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p><a href="https://github.com/lib/pq" title="lib/pq: Pure Go Postgres driver for database/sql"><code>github.com/lib/pq</code></a> のときとは違いドライバー名ではなくプロトコル名(通常は <code>"tcp"</code> など)として登録し DSN に登録したプロトコル名(ここでは <code>ssh+tcp</code>)を含める。
あとは <a href="https://pkg.go.dev/database/sql" title="sql package - database/sql - Go Packages"><code>database/sql</code></a> の機能をそのまま使うことができる。</p>
<p><a href="https://github.com/goark/sshql" title="goark/sshql: Go SQL drivers over SSH"><code>github.com/goark/sshql</code></a><code>/mysqldrv</code> パッケージ内部で <a href="https://github.com/go-sql-driver/mysql" title="go-sql-driver/mysql: Go MySQL Driver is a MySQL driver for Go's (golang) database/sql package"><code>github.com/go-sql-driver/mysql</code></a> パッケージを呼び出しているため</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nx">_</span> <span class="s">"github.com/go-sql-driver/mysql"</span>
</span></span></code></pre></div><p>のようなインポートは不要である。</p>
<h2>参考図書</h2>
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/416Stewy0NS._SL160_.jpg" width="123" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">プログラミング言語Go</a></dt>
<dd>アラン・ドノバン (著), ブライアン・カーニハン (著), 柴田芳樹 (著)</dd>
<dd>丸善出版 2016-06-20 (Release 2021-07-13)</dd>
<dd>Kindle版</dd>
<dd>B099928SJD (ASIN)</dd>
<dd>評価<abbr class="rating fa-sm" title="5"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i></abbr></dd>
</dl>
<p class="description">Kindle 版出た! 一部内容が古びてしまったが,この本は Go 言語の教科書と言ってもいいだろう。感想は<a href="https://text.baldanders.info/remark/2016/07/go-programming-language/" >こちら</a>。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2021-05-22">2021-05-22</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- プログラミング言語Go -->
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>今回のパッケージは <a href="https://github.com/mattn/pqssh"><code>github.com/mattn/pqssh</code></a> の事実上の fork である。同パッケージに敬意を表して拙作の方も MIT ライセンスで提供している。感謝! <a href="#fnref:1" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
</ol>
</div>
SSH 越しに DB サーバにアクセスする
tag:text.Baldanders.info,2022-09-10:/release/2022/09/sql-over-ssh/
2022-09-10T09:04:56+00:00
2022-09-30T12:18:06+00:00
mattn さんが公開されているパッケージを参考に組んでみた
Spiegel
https://baldanders.info/profile/
<p>PostgreSQL や MySQL などの RDBMS サービスにアクセスするために <a href="https://go.dev/">Go</a> では標準で <a href="https://pkg.go.dev/database/sql" title="sql package - database/sql - Go Packages"><code>database/sql</code></a> パッケージを用意している
(実際にサービスにアクセスするためには <a href="https://github.com/lib/pq" title="lib/pq: Pure Go Postgres driver for database/sql"><code>github.com/lib/pq</code></a> や <a href="https://github.com/go-sql-driver/mysql" title="go-sql-driver/mysql: Go MySQL Driver is a MySQL driver for Go's (golang) database/sql package"><code>github.com/go-sql-driver/mysql</code></a> といったドライバ・パッケージを使う必要がある)。
たとえばこんな感じ。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="nx">db</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">sql</span><span class="p">.</span><span class="nf">Open</span><span class="p">(</span><span class="s">"postgres"</span><span class="p">,</span> <span class="s">"postgres://dbuser:dbpassword@dbserver:5432/example?sslmode=require"</span><span class="p">)</span>
</span></span></code></pre></div><p>ただし,これはクライアントからサービスに直結する場合で,たとえば VPS 内の RDBMS サービスに SSH 経由でアクセスする必要がある場合は少し工夫が必要である。
ありがたいことに PostgreSQL サービスに SSH 経由でアクセスするためのパッケージを <a href="https://github.com/mattn">mattn</a> さんが公開して下さっている。</p>
<ul>
<li><a href="https://github.com/mattn/pqssh">mattn/pqssh</a></li>
<li><a href="https://zenn.dev/mattn/articles/d1b114e2d4a421">Go で SSH 超しに PostgreSQL に接続できる database/sql ドライバを作った。</a></li>
</ul>
<p>ありがたや <abbr class="emoji-chars" title="ペコン">🙇</abbr></p>
<p>で,実は MySQL サービスに SSH 経由でアクセスする必要ができたので,上のパッケージを参考に自作してみた。</p>
<ul>
<li><a href="https://github.com/goark/sshql">goark/sshql: Go SQL drivers over SSH</a></li>
</ul>
<p>このパッケージを使ってこんな感じに書ける。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="s">"database/sql"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"fmt"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"os"</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="s">"github.com/goark/sshql"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"github.com/goark/sshql/mysqldrv"</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">dialer</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">sshql</span><span class="p">.</span><span class="nx">Dialer</span><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Hostname</span><span class="p">:</span> <span class="s">"sshserver"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Port</span><span class="p">:</span> <span class="mi">22</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Username</span><span class="p">:</span> <span class="s">"remoteuser"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Password</span><span class="p">:</span> <span class="s">"passphraseforauthkey"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">PrivateKey</span><span class="p">:</span> <span class="s">"/home/username/.ssh/id_eddsa"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">mysqldrv</span><span class="p">.</span><span class="nf">New</span><span class="p">(</span><span class="nx">dialer</span><span class="p">).</span><span class="nf">RegisterDial</span><span class="p">(</span><span class="s">"ssh+tcp"</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="nx">db</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">sql</span><span class="p">.</span><span class="nf">Open</span><span class="p">(</span><span class="s">"mysql"</span><span class="p">,</span> <span class="s">"dbuser:dbpassword@ssh+tcp(localhost:3306)/dbname"</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Fprintln</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stderr</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="k">defer</span> <span class="nx">dialer</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"> <span class="k">defer</span> <span class="nx">db</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="nx">rows</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">db</span><span class="p">.</span><span class="nf">Query</span><span class="p">(</span><span class="s">"SELECT id, name FROM example ORDER BY id"</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Fprintln</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stderr</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">rows</span><span class="p">.</span><span class="nf">Next</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">id</span> <span class="kt">int64</span>
</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">name</span> <span class="kt">string</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">rows</span><span class="p">.</span><span class="nf">Scan</span><span class="p">(</span><span class="o">&</span><span class="nx">id</span><span class="p">,</span> <span class="o">&</span><span class="nx">name</span><span class="p">);</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Fprintln</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stderr</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">break</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">"ID: %d Name: %s\n"</span><span class="p">,</span> <span class="nx">id</span><span class="p">,</span> <span class="nx">name</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">rows</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>MySQL の場合 SSH でアクセスするための Dialer を登録して,登録文字列を DSN に含める必要がある。</p>
<p>さらに,このパッケージを使った PostgreSQL への SSH 越しのアクセスはこんな感じに書ける。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="s">"database/sql"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"fmt"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"os"</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="s">"github.com/goark/sshql"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"github.com/goark/sshql/pgdrv"</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">dialer</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">sshql</span><span class="p">.</span><span class="nx">Dialer</span><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Hostname</span><span class="p">:</span> <span class="s">"sshserver"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Port</span><span class="p">:</span> <span class="mi">22</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Username</span><span class="p">:</span> <span class="s">"remoteuser"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Password</span><span class="p">:</span> <span class="s">"passphraseforauthkey"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">PrivateKey</span><span class="p">:</span> <span class="s">"/home/username/.ssh/id_eddsa"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">pgdrv</span><span class="p">.</span><span class="nf">New</span><span class="p">(</span><span class="nx">dialer</span><span class="p">).</span><span class="nf">Register</span><span class="p">(</span><span class="s">"postgres+ssh"</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="nx">db</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">sql</span><span class="p">.</span><span class="nf">Open</span><span class="p">(</span><span class="s">"postgres+ssh"</span><span class="p">,</span> <span class="s">"postgres://dbuser:dbpassword@localhost:5432/example?sslmode=disable"</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Fprintln</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stderr</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="k">defer</span> <span class="nx">dialer</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"> <span class="k">defer</span> <span class="nx">db</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="nx">rows</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">db</span><span class="p">.</span><span class="nf">Query</span><span class="p">(</span><span class="s">"SELECT id, name FROM example ORDER BY id"</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Fprintln</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stderr</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">rows</span><span class="p">.</span><span class="nf">Next</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">id</span> <span class="kt">int64</span>
</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">name</span> <span class="kt">string</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">rows</span><span class="p">.</span><span class="nf">Scan</span><span class="p">(</span><span class="o">&</span><span class="nx">id</span><span class="p">,</span> <span class="o">&</span><span class="nx">name</span><span class="p">);</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Fprintln</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stderr</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">break</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">"ID: %d Name: %s\n"</span><span class="p">,</span> <span class="nx">id</span><span class="p">,</span> <span class="nx">name</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">rows</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>やっぱ <a href="https://pkg.go.dev/database/sql" title="sql package - database/sql - Go Packages"><code>sql</code></a><code>.Open()</code> 関数の第1引数で専用ドライバを指定するほうがシンプルだよなぁ。
DSN 文字列をいじらなくて済むし。</p>
<div class="box"><p><strong>【2022-09-30 追記】</strong></p>
<p><a href="https://github.com/jackc/pgx" title="jackc/pgx: PostgreSQL driver and toolkit for Go"><code>github.com/jackc/pgx</code></a> パッケージと組み合わせて使えるようにした。
詳しくは以下の記事を参考のこと。</p>
<ul>
<li><a href="https://text.baldanders.info/release/sshql/">sshql — SSH 越しに RDBMS にアクセスする</a></li>
</ul>
</div>
<h2>InsecureIgnoreHostKey() 関数で叱られる</h2>
<p>mattn さんの <a href="https://github.com/mattn/pqssh"><code>github.com/mattn/pqssh</code></a> パッケージの中で</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="nx">sshConfig</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">ClientConfig</span><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">User</span><span class="p">:</span> <span class="nx">d</span><span class="p">.</span><span class="nx">Username</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Auth</span><span class="p">:</span> <span class="p">[]</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">AuthMethod</span><span class="p">{},</span>
</span></span><span class="line"><span class="cl"> <span class="nx">HostKeyCallback</span><span class="p">:</span> <span class="nx">ssh</span><span class="p">.</span><span class="nf">InsecureIgnoreHostKey</span><span class="p">(),</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>という記述があり,最初はそのまま真似してたのだが,例によって lint に「あかんがな!」と叱られた。</p>
<p><code>HostKeyCallback</code> 項目は SSH ログイン時のホスト認証の動作をするもので, <a href="https://pkg.go.dev/golang.org/x/crypto/ssh" title="ssh package - golang.org/x/crypto/ssh - Go Packages"><code>ssh</code></a><code>.InsecureIgnoreHostKey()</code> は何もせず <code>nil</code> を返却するだけの関数を渡している。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="c1">// InsecureIgnoreHostKey returns a function that can be used for
</span></span></span><span class="line"><span class="cl"><span class="c1">// ClientConfig.HostKeyCallback to accept any host key. It should
</span></span></span><span class="line"><span class="cl"><span class="c1">// not be used for production code.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">func</span> <span class="nf">InsecureIgnoreHostKey</span><span class="p">()</span> <span class="nx">HostKeyCallback</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kd">func</span><span class="p">(</span><span class="nx">hostname</span> <span class="kt">string</span><span class="p">,</span> <span class="nx">remote</span> <span class="nx">net</span><span class="p">.</span><span class="nx">Addr</span><span class="p">,</span> <span class="nx">key</span> <span class="nx">PublicKey</span><span class="p">)</span> <span class="kt">error</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">nil</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>こりゃあ,確かにあかんわ(笑)</p>
<p>最終的に今回の <a href="https://github.com/goark/sshql" title="goark/sshql: Go SQL drivers over SSH"><code>github.com/goark/sshql</code></a> パッケージでは一応ホスト認証を行っているが <code>~/.ssh/known_hosts</code> ファイルに登録されていないホストや登録されている鍵が異なる場合は問答無用でエラーを返すようにした。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">$ go run sample.go
</span></span><span class="line"><span class="cl">ssh: handshake failed: knownhosts: key is unknown
</span></span></code></pre></div><p>まぁ,こういうパッケージはバッチ処理とかにしか使わないだろうし,ええじゃろう。</p>
<p>なお <a href="https://github.com/goark/sshql" title="goark/sshql: Go SQL drivers over SSH"><code>sshql</code></a><code>.Dialer</code> 構造体は</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="c1">// Dialer is authentication provider information.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">type</span> <span class="nx">Dialer</span> <span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Hostname</span> <span class="kt">string</span> <span class="s">`json:"hostname"`</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Port</span> <span class="kt">int</span> <span class="s">`json:"port"`</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Username</span> <span class="kt">string</span> <span class="s">`json:"username"`</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Password</span> <span class="kt">string</span> <span class="s">`json:"password"`</span>
</span></span><span class="line"><span class="cl"> <span class="nx">PrivateKey</span> <span class="kt">string</span> <span class="s">`json:"privateKey"`</span>
</span></span><span class="line"><span class="cl"> <span class="nx">IgnoreHostKey</span> <span class="kt">bool</span> <span class="s">`json:"IgnoreHostKey"`</span>
</span></span><span class="line"><span class="cl"> <span class="nx">client</span> <span class="o">*</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">Client</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>と定義しているけど <code>IgnoreHostKey</code> 要素に <code>true</code> をセットするとホスト認証をすっ飛ばしてくれる。</p>
<h2>ブックマーク</h2>
<ul>
<li><a href="https://gist.github.com/vinzenz/d8e6834d9e25bbd422c14326f357cce0">Using MySQL / MariaDB via SSH in Golang · GitHub</a></li>
<li><a href="https://cyruslab.net/2020/10/23/golang-how-to-write-ssh-hostkeycallback/">Golang – How to write ssh.HostKeyCallback – cyruslab</a></li>
<li><a href="https://github.com/simukti/sqldb-logger">simukti/sqldb-logger: A logger for Go SQL database driver without modifying existing *sql.DB stdlib usage.</a></li>
</ul>
<h2>参考図書</h2>
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/416Stewy0NS._SL160_.jpg" width="123" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">プログラミング言語Go</a></dt>
<dd>アラン・ドノバン (著), ブライアン・カーニハン (著), 柴田芳樹 (著)</dd>
<dd>丸善出版 2016-06-20 (Release 2021-07-13)</dd>
<dd>Kindle版</dd>
<dd>B099928SJD (ASIN)</dd>
<dd>評価<abbr class="rating fa-sm" title="5"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i></abbr></dd>
</dl>
<p class="description">Kindle 版出た! 一部内容が古びてしまったが,この本は Go 言語の教科書と言ってもいいだろう。感想は<a href="https://text.baldanders.info/remark/2016/07/go-programming-language/" >こちら</a>。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2021-05-22">2021-05-22</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- プログラミング言語Go -->
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/4873119979?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/41WaZWxEzVL._SL160_.jpg" width="125" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/4873119979?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">Go言語による分散サービス ―信頼性、拡張性、保守性の高いシステムの構築</a></dt>
<dd>Travis Jeffery (著), 柴田 芳樹 (翻訳)</dd>
<dd>オライリージャパン 2022-08-03</dd>
<dd>単行本(ソフトカバー)</dd>
<dd>4873119979 (ASIN), 9784873119977 (EAN), 4873119979 (ISBN)</dd>
<dd>評価<abbr class="rating fa-sm" title="4"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="far fa-star"></i></abbr></dd>
</dl>
<p class="description"><a href="https://www.oreilly.co.jp/books/9784873119977/">版元</a>でデジタル版を購入。<a href="https://technical-book-reading-2.connpass.com/">読書会</a>の課題図書。ハンズオンぽい構成でコードがたくさん書かれているのがよい。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2022-08-03">2022-08-03</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- Go言語による分散サービス -->
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/B09C2XBC2F?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/31PDIZXO9tL._SL160_.jpg" width="160" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/B09C2XBC2F?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">デベロッパーゴースーパーゴラン Tシャツ</a></dt>
<dd>Geek Go Super Golang Tees</dd>
<dd>ウェア&シューズ</dd>
<dd>B09C2XBC2F (ASIN)</dd>
<dd>評価<abbr class="rating fa-sm" title="4"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="far fa-star"></i></abbr></dd>
</dl>
<p class="description">ついカッとなってポチった。反省はしない</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2022-04-10">2022-04-10</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- Golang Tシャツ -->
Go パッケージの移行状況
tag:text.Baldanders.info,2022-03-19:/release/2022/03/status-of-migrations/
2022-03-19T12:15:27+00:00
2022-04-10T04:54:10+00:00
ダラダラやってるといつまで経っても終わらないので,移行状況を記しておく
Spiegel
https://baldanders.info/profile/
<p>現在 <a href="https://github.com/goark" title="Playing with Go Language">github.com/goark</a> に <a href="https://go.dev/">Go</a> パッケージを移行中だが,ダラダラやってるといつまで経っても終わらないので,覚え書きとして移行状況を記しておく。
この記事は移行が完了するまで随時更新される。</p>
<table>
<thead>
<tr>
<th>Package</th>
<th style="text-align:center">Bin</th>
<th style="text-align:center"><a href="https://github.com/goark" title="Playing with Go Language">goark</a></th>
<th style="text-align:center">Blog</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="https://github.com/goark/gpgpdump">gpgpdump: OpenPGP packet visualizer</a></td>
<td style="text-align:center"><span><i class="fa-solid fa-check"></i></span></td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
<td style="text-align:center"><a href="https://text.baldanders.info/release/gpgpdump/"><span><i class="fa-regular fa-square-check"></i></span></a></td>
</tr>
<tr>
<td><a href="https://github.com/goark/depm">depm: Visualize depndency packages and modules</a></td>
<td style="text-align:center"><span><i class="fa-solid fa-check"></i></span></td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
<td style="text-align:center"><a href="https://text.baldanders.info/release/dependency-graph-for-golang-modules/"><span><i class="fa-regular fa-square-check"></i></span></a></td>
</tr>
<tr>
<td><a href="https://github.com/goark/books-data">books-data: Search for Books Data</a></td>
<td style="text-align:center"><span><i class="fa-solid fa-check"></i></span></td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
<td style="text-align:center"><a href="https://text.baldanders.info/release/books-data/"><span><i class="fa-regular fa-square-check"></i></span></a></td>
</tr>
<tr>
<td><a href="https://github.com/goark/gnkf">gnkf: Network Kanji Filter by Golang</a></td>
<td style="text-align:center"><span><i class="fa-solid fa-check"></i></span></td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
<td style="text-align:center"><a href="https://text.baldanders.info/release/gnkf/"><span><i class="fa-regular fa-square-check"></i></span></a></td>
</tr>
<tr>
<td><a href="https://github.com/goark/gimei-cli">gimei-cli: 姓名・住所データ生成ツール</a></td>
<td style="text-align:center"><span><i class="fa-solid fa-check"></i></span></td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
<td style="text-align:center"></td>
</tr>
<tr>
<td><a href="https://github.com/goark/cov19jpn">cov19jpn: COVID-2019 in Japan; Importing Google COVID-19 Public Forecasts</a></td>
<td style="text-align:center"><span><i class="fa-solid fa-check"></i></span></td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
<td style="text-align:center"></td>
</tr>
<tr>
<td><a href="https://github.com/goark/ml">ml: Make Link with Markdown Format</a></td>
<td style="text-align:center"><span><i class="fa-solid fa-check"></i></span></td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
<td style="text-align:center"></td>
</tr>
<tr>
<td><a href="https://github.com/goark/pa-api">pa-api: APIs for Amazon Product Advertising API v5 by Golang</a></td>
<td style="text-align:center"></td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
<td style="text-align:center"><a href="https://text.baldanders.info/release/pa-api-v5/"><span><i class="fa-regular fa-square-check"></i></span></a></td>
</tr>
<tr>
<td><a href="https://github.com/goark/aozora">aozora-api: APIs for Aozora-bunko RESTful Service by Golang</a></td>
<td style="text-align:center"></td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
<td style="text-align:center"><a href="https://text.baldanders.info/release/aozora-api-package-for-golang/"><span><i class="fa-regular fa-square-check"></i></span></a></td>
</tr>
<tr>
<td><a href="https://github.com/goark/openbd-api">openbd-api: APIs for openBD by Golang</a></td>
<td style="text-align:center"></td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
<td style="text-align:center"><a href="https://text.baldanders.info/release/openbd-api-package-for-golang/"><span><i class="fa-regular fa-square-check"></i></span></a></td>
</tr>
<tr>
<td><a href="https://github.com/goark/errs">errs: Error handling for Golang</a></td>
<td style="text-align:center"></td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
<td style="text-align:center"><a href="https://text.baldanders.info/release/errs-package-for-golang/"><span><i class="fa-regular fa-square-check"></i></span></a></td>
</tr>
<tr>
<td><a href="https://github.com/goark/gocli">gocli: Minimal Packages for Command-Line Interface</a></td>
<td style="text-align:center"></td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
<td style="text-align:center"><a href="https://text.baldanders.info/release/gocli-package-for-golang/"><span><i class="fa-regular fa-square-check"></i></span></a></td>
</tr>
<tr>
<td><a href="https://github.com/goark/mt">mt: Mersenne Twister; Pseudo Random Number Generator, Implemented by Golang</a></td>
<td style="text-align:center"></td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
<td style="text-align:center"><a href="https://text.baldanders.info/release/mersenne-twister-by-golang/"><span><i class="fa-regular fa-square-check"></i></span></a></td>
</tr>
<tr>
<td><a href="https://github.com/goark/krconv">krconv: Convert kana-character to roman-alphabet</a></td>
<td style="text-align:center"></td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
<td style="text-align:center"></td>
</tr>
<tr>
<td><a href="https://github.com/goark/kkconv">kkconv: Hiragana-Katakana Conversion</a></td>
<td style="text-align:center"></td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
<td style="text-align:center"></td>
</tr>
<tr>
<td><a href="https://github.com/goark/go-cvss">go-cvss: Common Vulnerability Scoring System (CVSS)</a></td>
<td style="text-align:center"></td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
<td style="text-align:center"></td>
</tr>
<tr>
<td><a href="https://github.com/goark/cov19data">cov19data: Importing WHO COVID-2019 Cases Global Data</a></td>
<td style="text-align:center"></td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
<td style="text-align:center"></td>
</tr>
<tr>
<td><a href="https://github.com/goark/csvdata">csvdata: Reading CSV Data</a></td>
<td style="text-align:center"></td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
<td style="text-align:center"></td>
</tr>
<tr>
<td><a href="https://github.com/goark/fetch">fetch: Fetch Data from URL</a></td>
<td style="text-align:center"></td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
<td style="text-align:center"></td>
</tr>
<tr>
<td><a href="https://github.com/goark/koyomi">koyomi: 日本のこよみ</a></td>
<td style="text-align:center"></td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
<td style="text-align:center"></td>
</tr>
</tbody>
</table>
<h2>移行しないパッケージ(多分)</h2>
<p>最終的に archive にする(多分)</p>
<table>
<thead>
<tr>
<th>パッケージ</th>
<th>理由</th>
<th style="text-align:center">Archive</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="https://github.com/spiegel-im-spiegel/logf">logf</a></td>
<td><a href="https://github.com/rs/zerolog">rs/zerolog</a> に乗り換えた</td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
</tr>
<tr>
<td><a href="https://github.com/spiegel-im-spiegel/writers">writers</a></td>
<td>全く使ってない</td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
</tr>
<tr>
<td><a href="https://github.com/spiegel-im-spiegel/gcavoc">gcavoc</a></td>
<td>全く使ってない</td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
</tr>
<tr>
<td><a href="https://github.com/spiegel-im-spiegel/gprompt">gprompt</a></td>
<td><a href="https://github.com/nyaosorg/go-readline-ny">nyaosorg/go-readline-ny</a> に乗り換えた</td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
</tr>
<tr>
<td><a href="https://github.com/spiegel-im-spiegel/file">file</a></td>
<td>全く使ってない</td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
</tr>
<tr>
<td><a href="https://github.com/spiegel-im-spiegel/jpera">jpera</a></td>
<td><a href="https://github.com/goark/koyomi">koyomi</a> パッケージに移行・統合した</td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
</tr>
<tr>
<td><a href="https://github.com/spiegel-im-spiegel/jzodiac">jzodiac</a></td>
<td><a href="https://github.com/goark/koyomi">koyomi</a> パッケージに移行・統合した</td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
</tr>
<tr>
<td><a href="https://github.com/spiegel-im-spiegel/gjq">gjq</a></td>
<td>全く使ってない</td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
</tr>
<tr>
<td><a href="https://github.com/spiegel-im-spiegel/jvnman">jvnman</a></td>
<td>全く使ってない</td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
</tr>
<tr>
<td><a href="https://github.com/spiegel-im-spiegel/go-myjvn">go-myjvn</a></td>
<td>全く使ってない</td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
</tr>
<tr>
<td><a href="https://github.com/spiegel-im-spiegel/godump">godump</a></td>
<td><a href="https://github.com/goark/gnkf">gnkf</a> に組込み済み</td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
</tr>
<tr>
<td><a href="https://github.com/spiegel-im-spiegel/gocodic">gocodic</a></td>
<td>全く使ってない</td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
</tr>
<tr>
<td><a href="https://github.com/spiegel-im-spiegel/icat4json">icat4json</a></td>
<td>全く使ってない</td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
</tr>
<tr>
<td><a href="https://github.com/spiegel-im-spiegel/gitioapi">gitioapi</a></td>
<td>全く使ってない</td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
</tr>
<tr>
<td><a href="https://github.com/spiegel-im-spiegel/xls2csv">xls2csv</a></td>
<td>外部パッケージのパスとバージョンを更新したものをリリースして凍結</td>
<td style="text-align:center"><span><i class="fa-regular fa-square-check"></i></span></td>
</tr>
<tr>
<td><a href="https://github.com/spiegel-im-spiegel/emojis">emojis</a></td>
<td>全く使ってない</td>
<td style="text-align:center"><span><i class="fa-regular fa-square"></i></span></td>
</tr>
</tbody>
</table>
<h2>その他の TODO</h2>
<p><span><i class="fa-regular fa-square-check"></i></span> <a href="https://github.com/spiegel-im-spiegel">github.com/spiegel-im-spiegel</a> の Readme を修正する</p>
<p><span><i class="fa-regular fa-square-check"></i></span> Zenn の「<a href="https://zenn.dev/spiegel/books/error-handling-in-golang">Go のエラーハンドリング</a>」の改訂</p>
<h2>ブックマーク</h2>
<ul>
<li><a href="https://text.baldanders.info/remark/2022/03/github-team/">独り GitHub Team を作ってみた</a></li>
</ul>
<h2>参考図書</h2>
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/416Stewy0NS._SL160_.jpg" width="123" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">プログラミング言語Go</a></dt>
<dd>アラン・ドノバン (著), ブライアン・カーニハン (著), 柴田芳樹 (著)</dd>
<dd>丸善出版 2016-06-20 (Release 2021-07-13)</dd>
<dd>Kindle版</dd>
<dd>B099928SJD (ASIN)</dd>
<dd>評価<abbr class="rating fa-sm" title="5"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i></abbr></dd>
</dl>
<p class="description">Kindle 版出た! 一部内容が古びてしまったが,この本は Go 言語の教科書と言ってもいいだろう。感想は<a href="https://text.baldanders.info/remark/2016/07/go-programming-language/" >こちら</a>。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2021-05-22">2021-05-22</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- プログラミング言語Go -->
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/B09C2XBC2F?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/31PDIZXO9tL._SL160_.jpg" width="160" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/B09C2XBC2F?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">デベロッパーゴースーパーゴラン Tシャツ</a></dt>
<dd>Geek Go Super Golang Tees</dd>
<dd>ウェア&シューズ</dd>
<dd>B09C2XBC2F (ASIN)</dd>
<dd>評価<abbr class="rating fa-sm" title="4"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="far fa-star"></i></abbr></dd>
</dl>
<p class="description">ついカッとなってポチった。反省はしない</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2022-04-10">2022-04-10</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- Golang Tシャツ -->
go-cvss パッケージ正式版 v1.0.0 をリリースした
tag:text.Baldanders.info,2022-02-20:/release/2022/02/go-cvss-package-v1_0_0-is-released/
2022-02-20T00:47:18+00:00
2022-02-20T00:51:04+00:00
PR をいただいたコードをベースにちょろんと機能を足して正式版 v1.0.0 としてリリースした。
Spiegel
https://baldanders.info/profile/
<p>私がモタモタしている間に CVSS v3.1 の環境評価基準(Environmental Metrics)のコードを PR でいただきました。
ありがたや <abbr class="emoji-chars" title="ペコン">🙇</abbr></p>
<p>いただいたコードをベースにちょろんと機能を足して正式版 v1.0.0 としてリリースした。</p>
<ul>
<li><a href="https://github.com/spiegel-im-spiegel/go-cvss/releases/tag/v1.0.0">Release v1.0.0 · spiegel-im-spiegel/go-cvss · GitHub</a></li>
</ul>
<p>当初「欲しい」と思っていた機能は網羅されたので正式版でいいかな,と。
まぁ,半分以上貰ったコードなんだけどね(笑) 改めまして,ありがとうございます <abbr class="emoji-chars" title="ペコン">🙇</abbr></p>
<p>ベンダ等が出す基本評価基準(Base Metrics)の処理は今までどおり。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="c1">//go:build run
</span></span></span><span class="line"><span class="cl"><span class="c1">// +build run
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="s">"fmt"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"io"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"os"</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="s">"github.com/spiegel-im-spiegel/go-cvss/v3/metric"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"github.com/spiegel-im-spiegel/go-cvss/v3/report"</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">template</span> <span class="p">=</span> <span class="s">`| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.BaseMetrics</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.BaseMetricValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">|--------|-------|
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.AVName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.AVValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.ACName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.ACValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.PRName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.PRValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.UIName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.UIValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.SName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.SValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.CName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.CValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.IName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.IValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.AName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.AValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">`</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">bm</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">metric</span><span class="p">.</span><span class="nf">NewBase</span><span class="p">().</span><span class="nf">Decode</span><span class="p">(</span><span class="s">"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"</span><span class="p">)</span> <span class="c1">//CVE-2021-44716: net/http: limit growth of header canonicalization cache
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Fprintln</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stderr</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">r</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">report</span><span class="p">.</span><span class="nf">NewBase</span><span class="p">(</span><span class="nx">bm</span><span class="p">).</span><span class="nf">ExportWithString</span><span class="p">(</span><span class="nx">template</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Fprintln</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stderr</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">io</span><span class="p">.</span><span class="nf">Copy</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stdout</span><span class="p">,</span> <span class="nx">r</span><span class="p">);</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Fprintln</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stderr</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>てな感じに書けば</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">$ go run sample1.go
</span></span><span class="line"><span class="cl">| Base Metrics | Metric Value |
</span></span><span class="line"><span class="cl">|--------|-------|
</span></span><span class="line"><span class="cl">| Attack Vector | Network |
</span></span><span class="line"><span class="cl">| Attack Complexity | Low |
</span></span><span class="line"><span class="cl">| Privileges Required | None |
</span></span><span class="line"><span class="cl">| User Interaction | None |
</span></span><span class="line"><span class="cl">| Scope | Changed |
</span></span><span class="line"><span class="cl">| Confidentiality Impact | High |
</span></span><span class="line"><span class="cl">| Integrity Impact | High |
</span></span><span class="line"><span class="cl">| Availability Impact | High |
</span></span></code></pre></div><p>と出力される。
また</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="nx">r</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">report</span><span class="p">.</span><span class="nf">NewBase</span><span class="p">(</span><span class="nx">bm</span><span class="p">).</span><span class="nf">ExportWithString</span><span class="p">(</span><span class="nx">template</span><span class="p">)</span>
</span></span></code></pre></div><p>を</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="nx">r</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">report</span><span class="p">.</span><span class="nf">NewBase</span><span class="p">(</span><span class="nx">bm</span><span class="p">,</span> <span class="nx">report</span><span class="p">.</span><span class="nf">WithOptionsLanguage</span><span class="p">(</span><span class="nx">language</span><span class="p">.</span><span class="nx">Japanese</span><span class="p">)).</span><span class="nf">ExportWithString</span><span class="p">(</span><span class="nx">template</span><span class="p">)</span>
</span></span></code></pre></div><p>と書き換えれば</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">$ go run sample1.go
</span></span><span class="line"><span class="cl">| 基本評価基準 | 評価値 |
</span></span><span class="line"><span class="cl">|--------|-------|
</span></span><span class="line"><span class="cl">| 攻撃元区分 | ネットワーク |
</span></span><span class="line"><span class="cl">| 攻撃条件の複雑さ | 低 |
</span></span><span class="line"><span class="cl">| 必要な特権レベル | 不要 |
</span></span><span class="line"><span class="cl">| ユーザ関与レベル | 不要 |
</span></span><span class="line"><span class="cl">| スコープ | 変更なし |
</span></span><span class="line"><span class="cl">| 機密性への影響 | なし |
</span></span><span class="line"><span class="cl">| 完全性への影響 | なし |
</span></span><span class="line"><span class="cl">| 可用性への影響 | 高 |
</span></span></code></pre></div><p>と日本語になる(英語と日本語しか対応してません)。</p>
<p>今回の環境評価基準までのベクタ値を含めた評価であれば</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="c1">//go:build run
</span></span></span><span class="line"><span class="cl"><span class="c1">// +build run
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="s">"fmt"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"io"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"os"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"strings"</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="s">"github.com/spiegel-im-spiegel/go-cvss/v3/metric"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"github.com/spiegel-im-spiegel/go-cvss/v3/report"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"golang.org/x/text/language"</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">template</span> <span class="p">=</span> <span class="s">`- CVSS Version </span><span class="cp">{{</span><span class="w"> </span><span class="na">.Version</span><span class="w"> </span><span class="cp">}}</span><span class="s">
</span></span></span><span class="line"><span class="cl"><span class="s">- Vector: </span><span class="cp">{{</span><span class="w"> </span><span class="na">.Vector</span><span class="w"> </span><span class="cp">}}</span><span class="s">
</span></span></span><span class="line"><span class="cl"><span class="s">
</span></span></span><span class="line"><span class="cl"><span class="s">## Base Metrics
</span></span></span><span class="line"><span class="cl"><span class="s">
</span></span></span><span class="line"><span class="cl"><span class="s">- Base Score: </span><span class="cp">{{</span><span class="w"> </span><span class="na">.BaseScore</span><span class="w"> </span><span class="cp">}}</span><span class="s">
</span></span></span><span class="line"><span class="cl"><span class="s">
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.BaseMetrics</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.BaseMetricValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">|--------|-------|
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.AVName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.AVValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.ACName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.ACValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.PRName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.PRValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.UIName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.UIValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.SName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.SValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.CName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.CValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.IName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.IValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.AName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.AValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">
</span></span></span><span class="line"><span class="cl"><span class="s">## Temporal Metrics
</span></span></span><span class="line"><span class="cl"><span class="s">
</span></span></span><span class="line"><span class="cl"><span class="s">- Temporal Score: </span><span class="cp">{{</span><span class="w"> </span><span class="na">.TemporalScore</span><span class="w"> </span><span class="cp">}}</span><span class="s">
</span></span></span><span class="line"><span class="cl"><span class="s">- </span><span class="cp">{{</span><span class="w"> </span><span class="na">.SeverityName</span><span class="w"> </span><span class="cp">}}</span><span class="s">: </span><span class="cp">{{</span><span class="w"> </span><span class="na">.SeverityValue</span><span class="w"> </span><span class="cp">}}</span><span class="s">
</span></span></span><span class="line"><span class="cl"><span class="s">
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.TemporalMetrics</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.TemporalMetricValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">|--------|-------|
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.EName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.EValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.RLName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.RLValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.RCName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.RCValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">
</span></span></span><span class="line"><span class="cl"><span class="s">## Environmental Metrics
</span></span></span><span class="line"><span class="cl"><span class="s">
</span></span></span><span class="line"><span class="cl"><span class="s">- </span><span class="cp">{{</span><span class="w"> </span><span class="na">.SeverityName</span><span class="w"> </span><span class="cp">}}</span><span class="s">: </span><span class="cp">{{</span><span class="w"> </span><span class="na">.SeverityValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> (</span><span class="cp">{{</span><span class="w"> </span><span class="na">.EnvironmentalScore</span><span class="w"> </span><span class="cp">}}</span><span class="s">)
</span></span></span><span class="line"><span class="cl"><span class="s">
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.EnvironmentalMetrics</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.EnvironmentalMetricValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">|--------|-------|
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.CRName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.CRValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.IRName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.IRValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.ARName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.ARValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.MAVName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.MAVValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.MACName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.MACValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.MPRName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.MPRValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.MUIName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.MUIValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.MSName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.MSValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.MCName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.MCValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.MIName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.MIValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">| </span><span class="cp">{{</span><span class="w"> </span><span class="na">.MAName</span><span class="w"> </span><span class="cp">}}</span><span class="s"> | </span><span class="cp">{{</span><span class="w"> </span><span class="na">.MAValue</span><span class="w"> </span><span class="cp">}}</span><span class="s"> |
</span></span></span><span class="line"><span class="cl"><span class="s">`</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">em</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">metric</span><span class="p">.</span><span class="nf">NewEnvironmental</span><span class="p">().</span><span class="nf">Decode</span><span class="p">(</span><span class="s">"CVSS:3.1/AV:P/AC:H/PR:H/UI:N/S:U/C:H/I:H/A:H/E:F/RL:U/RC:C/CR:M/IR:H/AR:M/MAV:L/MAC:H/MPR:L/MUI:R/MS:U/MC:L/MI:H/MA:L"</span><span class="p">)</span> <span class="c1">//Random CVSS Vector
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Fprintln</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stderr</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">r</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">report</span><span class="p">.</span><span class="nf">NewEnvironmental</span><span class="p">(</span><span class="nx">em</span><span class="p">,</span> <span class="nx">report</span><span class="p">.</span><span class="nf">WithOptionsLanguage</span><span class="p">(</span><span class="nx">language</span><span class="p">.</span><span class="nx">Japanese</span><span class="p">)).</span><span class="nf">ExportWith</span><span class="p">(</span><span class="nx">strings</span><span class="p">.</span><span class="nf">NewReader</span><span class="p">(</span><span class="nx">template</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Fprintln</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stderr</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">io</span><span class="p">.</span><span class="nf">Copy</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stdout</span><span class="p">,</span> <span class="nx">r</span><span class="p">);</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Fprintln</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stderr</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>などとすれば</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">$ go run sample2.go
</span></span><span class="line"><span class="cl">- CVSS Version 3.1
</span></span><span class="line"><span class="cl">- Vector: CVSS:3.1/AV:P/AC:H/PR:H/UI:N/S:U/C:H/I:H/A:H/CR:M/IR:H/AR:M/MAV:L/MAC:H/MPR:L/MUI:R/MS:U/MC:L/MI:H/MA:L
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">## Base Metrics
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">- Base Score: 6.1
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">| 基本評価基準 | 評価値 |
</span></span><span class="line"><span class="cl">|--------|-------|
</span></span><span class="line"><span class="cl">| 攻撃元区分 | 物理 |
</span></span><span class="line"><span class="cl">| 攻撃条件の複雑さ | 高 |
</span></span><span class="line"><span class="cl">| 必要な特権レベル | 高 |
</span></span><span class="line"><span class="cl">| ユーザ関与レベル | 不要 |
</span></span><span class="line"><span class="cl">| スコープ | 変更なし |
</span></span><span class="line"><span class="cl">| 機密性への影響 | 高 |
</span></span><span class="line"><span class="cl">| 完全性への影響 | 高 |
</span></span><span class="line"><span class="cl">| 可用性への影響 | 高 |
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">## Temporal Metrics
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">- Temporal Score: 6
</span></span><span class="line"><span class="cl">- 深刻度: 警告
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">| 現状評価基準 | 評価値 |
</span></span><span class="line"><span class="cl">|--------|-------|
</span></span><span class="line"><span class="cl">| 攻撃される可能性 | 攻撃可能 |
</span></span><span class="line"><span class="cl">| 利用可能な対策のレベル | なし |
</span></span><span class="line"><span class="cl">| 脆弱性情報の信頼性 | 確認済 |
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">## Environmental Metrics
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">- 深刻度: 警告 (6.5)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">| 環境評価基準 | 評価値 |
</span></span><span class="line"><span class="cl">|--------|-------|
</span></span><span class="line"><span class="cl">| 機密性の要求度 | 中 |
</span></span><span class="line"><span class="cl">| 完全性の要求度 | 高 |
</span></span><span class="line"><span class="cl">| 可用性の要求度 | 中 |
</span></span><span class="line"><span class="cl">| 調整後の攻撃元区分 | ローカル |
</span></span><span class="line"><span class="cl">| 調整後の攻撃条件の複雑さ | 高 |
</span></span><span class="line"><span class="cl">| 調整後の必要な特権レベル | 低 |
</span></span><span class="line"><span class="cl">| 調整後のユーザ関与レベル | 要 |
</span></span><span class="line"><span class="cl">| 調整後のスコープ | 変更なし |
</span></span><span class="line"><span class="cl">| 調整後の機密性への影響 | 低 |
</span></span><span class="line"><span class="cl">| 調整後の完全性への影響 | 高 |
</span></span><span class="line"><span class="cl">| 調整後の可用性への影響 | 低 |
</span></span></code></pre></div><p>などと出力される。</p>
<p>まぁ,個人で使う場合は現状評価基準や環境評価基準の評価はしないけどね。
あれは組織が脆弱性のリスク管理に使うものだし。</p>
<p>なお環境評価基準は v3.0 と v3.1 で評価方法が若干異なるがスコアの算出は v3.1 のロジックで行っている(筈)。
まぁ,今時わざわざ v3.0 を使う組織はないじゃろう。</p>
<p>というわけで個人の手遊びで書くのを躊躇していたのだが,多少でも使っていただいている人がいて PR までいただけるのはありがたい話である(大事なことなので何度でも繰り返すw)。</p>
<h2>ブックマーク</h2>
<ul>
<li><a href="https://www.first.org/cvss/v3.0/specification-document">CVSS v3.0 Specification Document</a></li>
<li><a href="https://www.first.org/cvss/v3.1/specification-document">CVSS v3.1 Specification Document</a></li>
<li><a href="https://www.ipa.go.jp/security/vuln/CVSSv3.html">共通脆弱性評価システムCVSS v3概説:IPA 独立行政法人 情報処理推進機構</a></li>
<li><a href="https://text.baldanders.info/remark/2020/01/cvss-v3_1/">CVSS v3.1</a></li>
</ul>