その手の平は尻もつかめるさ

ギジュツ的な事をメーンで書く予定です

バイナリぽん置きでGPG passphraseベースの暗号化・復号化を行うツールを書いた

表題のとおりです.

github.com

名前は出オチです (ref: エニグマ (暗号機) - Wikipedia)

色々あってgpgコマンドが無い (入れられない) ような環境でもバイト列を暗号化・復号化したいということがあり (あと脳が悪くてgpgコマンドのオプションを覚えられない),バイナリぽん置きでそれをやるツールを書いたという話です.使い方についてはREADMEをご覧ください.至ってシンプル.
もちろんgpgコマンドとの互換性もあるので,gpgでencryptしたファイルをamugineでdecryptしたり,あるいはその逆をすることも可能となっています.

golangはopenpgpの実装をgolang orgで提供しているので大変便利ですね! https://github.com/golang/crypto/tree/master/openpgp

CompletionStage<T>な変数を同期的に処理したいんですけど〜ってとき

Javaの話です.

CompletionStage<T>を返却するようなメソッドがあって,それを同期的に処理したい (単体テストを書くというシーンが最も多いでしょう) ということが生きているとあります.しかしCompletionStageget()のようなメソッドが生えていないので同期的に処理することができません.thenAccept()を使おうにも,例えばJUnitのテストケースではすっぽ抜けてしまってうまく扱えません (逆にテストケース以外ではうまく働くでしょう).

そんなときにどうするかというと,手っ取り早い方法はCompletableFuture<T>にキャストしてしまうことでしょう.すると,オブジェクトにget()が生えてくるので同期的に値を取り扱うことが可能となります.

例:

final CompletionStage<String> completionStage = getSomething();
final CompletableFuture<String> future = (CompletableFuture<String>) completionStage;
final String got = future.get(); // ここで同期的に取り扱える

最初からCompletableFutureで値を返却してほしいですね.以上です.

技術書典7 (く39D) にて「ATコマンドかるた」を頒布します!!!

技術書典7,SORAZINE技術組(く39D*1 にて「ATコマンドかるた」を頒布いたします.

techbookfest.org

「ATコマンドとはなにか?」という疑問については同時に頒布される SORAZINE 技術組 Vol.2019F 中の,おそらく今のところ日本で最も詳しいATコマンドの解説文章をご覧いただければと思いますが *2,その文中から抜粋しますと,

AT コマンドは AT という文字列で始まる、モデムを制御したりするためのテキストベースのコマンド群です.

というものです.ホラ,皆さん生きているとAT+COPSとかAT+CGDCONTとかよく見たり喋ったりするじゃないですか? ソレのかるたを頒布するという話です.

こんな感じ:

f:id:moznion:20190920162109j:plain

これがATコマンドふだで……

f:id:moznion:20190920162156j:plain

これが機能ふだです.

たのしい48種類のATコマンドのふだをご用意してございます! (なお,コマンドふだと機能ふだは左上の通し番号で対応が付いています)

ATコマンドふだを読み上げて機能ふだを取るもよし,機能ふだを読み上げてATコマンドふだを取るもよし,ニヤニヤ眺めるのもよしと三方よしな仕上がりとなっております! これで皆さんも遊びながらにしてATコマンドを暗記できます,やりましたね!!!

f:id:moznion:20190920161953j:plain

f:id:moznion:20190920163632j:plain

このようなかわいいパッケージでお出迎え.

ところで,いまのところこのかるたの印刷代を全て建て替えてるので売れないと年を越せません!!!!!!
技術書典7,SORAZINE技術組(く39D)でお待ちしています!!! よろしくお願いします……


【おわび】

一部ATコマンドふだに誤植がございまして,そちらは大変申し訳ありませんが人力加筆による修正を加えております

(誤)

f:id:moznion:20190920144627j:plain

AT+CCACT

(正: 修正済み)

f:id:moznion:20190920144712j:plain

AT+CGACT

以上です.

*1:よみがながtypoっているのはご愛嬌

*2:ATコマンド学習されたい向きには超おすすめです

Kyoto.なんか #5で「AWS上に構築する メンテ容易なElasticsearch System」というタイトルで話してきました

表題の通りKyoto.なんか #5で話してきました.もうかれこれ3週くらい前の話なのですね……筆不精がたたっております.

kyoto-nanka.connpass.com

内容としてはここ数年ElasticsearchをAWS上で運用しているのでそのアーキテクチャのご紹介という感じの発表をしたという次第です.現状上手いこと回っております.

この発表の後にElasticの@johtaniさんからのメンションで,クラスタまたぎのレプリケーションがElasticsearch 6.7以降サポートされていることを教えていただきました.ありがとうございます!

それにつけても最近の願いはAWS Elasticsearch Serviceにauto reshard機能が入ることですね,現場からは以上です.

builderscon 2019見本市 (土曜12時から) で自作ガジェット展示します

id:uzulla, id:mackee_wらと共に自作のE-バッジを展示します!
というかこのブログの内容ママです!!

ここには本物があります.
ぜひお立ち寄りください!!!

ところでチップのデータシートを見ながらあれこれコードを書いて試しているんですが,どうやっても一部機能を実装することが出来ないでいます,これはなんなんだ……当日お立ち寄りの方でお詳しい向きがあれば是非教えていただきたく思います!

よろしくお願いいたします.

tcpdumpで今すぐキャプチャ内容を全部ファイルにflushしてくれ!! というとき

tcpdumpはキャプチャした内容をバッファに蓄積してバッチ的にflushするので,うっかりプロセスを即断するとキャプチャしていた内容をdrainできないことがままあります.困りますね.

www.tcpdump.org

Using the SIGUSR2 signal along with the -w flag will forcibly flush the packet buffer into the output file.

というわけでここに書いてあるとおり,SIGUSR2tcpdumpのプロセスに対して発行してあげるとその時点のバッファの内容をファイルに吐き出します (ただし -w フラグによって出力先ファイルを指定している,すなわちファイル書き出しモードにしている必要がある).

If the -w option is specified, make the saved raw packet output ``packet-buffered''; i.e., as each packet is saved, it will be written to the output file, rather than being written only when the output buffer fills.

あるいは -U (--packet-buffered) フラグを -w フラグとともに利用するというのも良いでしょう.ただ,この際はバッファをバイパスして直接ファイルに書き込むような挙動となるので,tcpdumpdaemonとして常に動かしているような環境ではパフォーマンスの問題が発生する可能性があるので注意が必要そうです.


なお,-B オプションを使ってバッファサイズを0にするとどうなのか……というとこれは

tcpdump: invalid packet buffer size 0

と出て動きません.なるほど〜,そりゃそうですね.

TypeScriptを使ってアプリケーションの設定ファイルを書く

アプリケーションの設定ファイルと言えばjsonyamlなんかで書くことが多いと思うんですが,最近はTypeScriptで設定ファイルを書いております.このような感じ:

export interface ApplicationConfig {
  readonly listenPort: number;
  readonly timeout: number;
  readonly apiBaseUrl: string;
  readonly loggerOptions: LoggerOptions;
}

こういう感じで設定のinterfaceを定義しておいて

export class ProductionConfig implements ApplicationConfig {
  readonly listenPort = 5963;
  readonly timeout = 5000;
  readonly apiBaseUrl = "http://internal-api.example.com";
  readonly loggerOptions = {
    level: 'info',
  };
}

// TypeScript (JavaScript) 内で使うなら以下のようにしておくと便利そう (例A)
const productionConfig = new ProductionConfig();
export { productionConfig };

というふうに実際の設定を記述するという感じです.


メリットとしては,

  • 「何が設定項目なのか」が定義により明らかになる
  • 設定漏れが基本的に無い
    • これはinterfaceのサポートによるもの
  • 型のサポートがある
    • 設定の構造化ができる
  • 継承が使える
    • というかTypeScriptの言語機能を使ったコードが書ける

といったあたりが挙げられると思います.

interfaceの定義によって,「どういった項目が設定されるべきなのか」が「型情報も含めて」明示できるというのは利点の一つと言って良いと思います.

また,ウェブアプリケーションだと例えば本番環境用の設定,ステージング環境用の設定,開発環境用の設定……というふうに複数の設定が存在していることがままあると思うのですが,それぞれの環境のためにinterfaceを満足した設定を記述 (実装) してあげるだけで,漏れが無い (つまりそれぞれが等価な振る舞いをする) 設定を安全に用意することができるようになります.
当然のことながら,設定の実装クラスがinterfaceを実装しきらなかった場合はコンパイルエラーが出るので堅牢です.

型のサポートが得られるというのは言うまでもないですね.安全! 型定義の無い設定を取り扱う際に苦労することがままありましたからね……
あと自分で定義したclassについてもpropertyの型にすることができるので便利です.

個人的には継承が使えるというのは便利ポイントの一つだと思っていまして,例えば「基本的な動作はまったく同じなんだけど一部の機能だけ有効 (あるいは無効) にしたい」みたいなことがあったときに継承は便利に使えるかな〜と思っています.例えばこのような感じ:

export interface ApplicationConfig {
  readonly port: number;
  readonly tcpdumpEnabled: boolean;
}

export class ProductionConfig implements ApplicationConfig {
  readonly port = 5963;
  constructor(readonly tcpdumpEnabled: boolean = false) {
  }
}

export class ProductionInspectorConfig extends ProductionConfig{
  constructor() {
    super(true);
  }
}

このようにしておくと,基本的には ProductionConfig と基本的には同じ設定でありながらも, tcpdumpEnabledtrue にした ProductionInspectorConfig をお手軽に作れることとなります.
もちろん通常のソフトウェアにおける継承と同じで,is-aとして取り扱える (に等しい) 状況以外で使うと良くないことが起きると思うしそもそも継承を使うと複雑さが容易に増すので,そこは用法用量を守って……という感じでしょう.というかこれはTypeScriptの言語機能を設定記述に使えるという話に過ぎませんね.


あとはTypeScript (JavaScript) 内で使うのならば個別の設定のインスタンスをexportしてしまうか (上記の例A),あるいはinterface側に例えば以下のようなコードを書いて,それによって得られたインスタンスをexportしてしまえば便利そうです:

export interface ApplicationConfig {
  ...
}

const appConfig: ApplicationConfig = (() => {
  const nodeEnv = process.env.NODE_ENV;
  switch (nodeEnv) {
    case 'local':
      return new LocalConfig();
    case 'staging':
      return new StagingConfig();
    case 'production':
      return new ProductionConfig();
    default:
      throw new Error('invalid NODE_ENV: ' + nodeEnv);
  }
})();
export { appConfig };

また,TypeScript以外でこの設定を利用したい,つまり単なる設定記述言語としてこれを利用したい場合は生成した設定インスタンスJSON.stringify()に食わせてしまえば他の処理系でも取り扱えるJSON形式の設定が得られるのでそのようなスクリプトを書くとポータブル.良いですね.良かった良かった.


と,このような感じでした.TypeScriptは書き味が比較的ライトなので,設定ファイル用途にも書きやすくて良いですね.