2019/12/06

ziprubyapp: 実行可能なRubyスクリプトアーカイバ

妙なもの第2弾。

ziprubyapp: Make an executable ruby script bundle using zip archive

コンピュータとだけマルチリンガルな私としては、Python と Perl と Ruby と OCaml は同じくらいの頻度で話したり(実際の所、Perlはここ20年でぐっと減りました)するのですが、
PythonPerl でできるなら、Ruby でもやりたい、単一ファイル実行形式でお手軽自作ツール運用したいと思うのは自然な流れなので。

こちらも結果としては、単一ディレクトリに依存ファイル (*.rb だけですが) を置いて ziprubyapp で処理すると、サクッと1ファイルの実行スクリプトにまとめてそれらしく実行してくれます。


zipperlapp: 実行可能なPerlスクリプトアーカイバ

また妙なものを作っています。

zipperlapp: Make an executable perl script bundle using zip archive

Perlに限らずスクリプト言語で書いたコマンドラインツールは、標準的なインタプリタさえあれば、とりあえずコピーして $PATH に放り込めば動く、というポータブルな実行形式としてのお手軽さも魅力の一つだと思っているのです。
でも、今時のモジュールをちゃんと使ったプログラミングでファイルが複数になると、導入時の配置とか考えることが増えて、だんだんポータブルでもお手軽でもなくなっていくのが不満。
「実行ファイルは /home/???/bin の下に置くと、ライブラリは名前付けて /usr/local/lib/perl の下の全プログラム共有空間に置くか、あるいは /home/???/lib の下に個別に @INC 通すスクリプトを置いて、でもそうすると置き場所で毎回書き換えが...」と。
今時だと Ruby の gem とか Python の egg にして /home の下に入れるオプションでインストールして、... とやるのが正しいかもしれないですけど、それでも C 言語のコンパイル済みバイナリのように、ファイル一発コピーでおしまいとはいかず。

この辺りを解決するのが、このzipperlappの目的です。


2019/12/01

suid_sudo: sudo を使った setuid スクリプト用ライブラリ

並行して (?)、suid_sudo という「sudo を使った setuid」のヘルパーライブラリを公開しました。…「『いまさら』を2連発」なんて言わないで。

「一般ユーザ権限だけでは出来ないシステム操作を、ユーザごとにできることを制約して許可したい」という用途はUnixでは結構あり、全てがcapabilityのようなシステム提供の機能では制御できないため、Unix系OSではその多くがsetuidという仕組みを通じて実現されています。例えば、passwdコマンドでは「全員のパスワードが書かれたデータベースの内、自分のパスワードだけを変更できる」とか、そういう類のものです。

そして、もうかなりの昔語りですが、かつて Perl には suidperl という setuid をサポートする仕組みがありました。Unixのセキュリティ上の欠点を克服してスクリプトのsetuidをシミュレートする仕組みでしたが、なかなかkernelの支援なしに安全に作るのは難しく、2010年に削除されてしまいました。
Perlのマニュアルを見ると、

    Use of suidperl is highly discouraged.  If you  think you need it, try alternatives such as sudo first.

    「suidperl」の使用はお勧めしないよ。もし必要だと思ったら、sudoとか別のものを先に試してね!

と書いてあります……なんといい加減な。

というのは、sudo は実行できるコマンドは厳しく制限できるのですが、コマンドそのものは root 権限などでそのまま実行されるので、例えば上の passwd コマンドでいうと、「特定の人だけが全員のパスワードを変更できる」とか「AさんがAさんのパスワードを変更できる(それぞれ自分の、ではない)」のような制限しか出来ないのです。手元では suidperl script を置き換える段階で、この性質にかなり困りました。

というわけで、「じゃぁ sudo でちゃんとユーザ別の分岐処理できる環境を作るか」といって書き始めたところ、結構巨大なライブラリになってしまいました。

セキュリティ的には、実行可能なコマンドが「sudoの設定が許したコマンド」に限定されていて、「権限を落とすだけ」のライブラリなので、suidperlよりは随分楽で、確かに suidperl の better alternative にはなっていますが、それにしても結構複雑な処理が必要でした。

「自分で自分をsudoで呼ぶ」辺りは、できるだけユーザの使い勝手が悪くならないように工夫をしたところです。必要があったら参考にしてくれると良いなと思います。

ちなみに、技術的にこのヘルパーの内部実装で一番セキュリティ的に面倒なところは、「誰が起動したか」をきちんとsudoと連携して把握するところです。sudo は環境変数に「誰」の情報をセットしてくれるのですが、「本当にsudoがセットしたものなのか」がそう簡単にはわからない。その辺りをチェックするために、かなりシステムのいろいろな情報を調べています。それでも root だと色々微妙な判定しきれないケースを作れるので、その辺りは安全サイドに倒しています。(そのせいで、元からrootのときだけ使い勝手がちょっと悪い。)

python-httpauth-lib: Python向けHTTP認証ライブラリ(新しめ)公開

先日シンガポールでのIETFに行っている間に、Python向けのHTTP認証の実装を公開しました。……といっても、これだけだと今更感が大きく漂いますね。

これは、仕事でHTTP APIを使ったプロジェクトを進めている最中、最近のRFCでのDigest認証の更新に対応した実装が世の中に全然ないもので、割と必要にせまられて作ったものです。
一方で、HTTP認証の標準化に関わった人としては「自分で作るならちゃんと作るしかない」、また国際化の標準にもちょっと関わったからにはこちらも「ちゃんとしておきたい」ということで、
  • RFC 7235: 複数認証形式の同時提示への対応。
  • RFC 7617: Basic認証でのUTF-8サポート。
  • RFC 7616: Digest認証のさまざまな機能対応。
    • SHA-256 / SHA-256-sess アルゴリズム。
    • メッセージ認証内容 qop=auth / qop=auth-int の両対応。
    • HTTP応答の逆方向認証への完全な対応。
    • 多言語化対応ヘッダ (RFC 5987) に対応した UTF-8 サポート。
あたりを全部きちんと押さえてあります。

Python側のフレームワークとしては、標準添付のhttp.server, Flask, Eve (サーバ側), requests (クライアント側) 辺りを押さえてあります。共通ルーチン部分は、他のライブラリでも適用可能だと思います。
 どうもこの辺の規格化の仕事は余り実装が充実していないようなので、interopできたらいいなぁと思っているのですが、まずは MD5/SHA-1 以外に対応したDigest認証の実装ってものが殆ど無いので、その辺りの比較対象の the first one としてcontributeしておきたいという思いもあります。
とりあえず、Digest/SHA-256を使わなきゃいけなくなった人には使えるものになっていると思いますが、 試してみて頂ければ。