既存のビルドシステムからコードの断片を引き裂かないようにするために、暗号化されたデータを含む抽象パッケージをゼロからアセンブルすることを検討する別の小さなHOWTOとしてポストを設計することにしました。 たとえば、企業の構成の配布に加えて、一般的な使用例は、debで公開されているパッケージ//example.com/myrepoからお気に入りのエイリアス/構成を新しいシステムに迅速かつ安全にインストールする機能です。
言い換えれば、postinstでopensslを使用する方法に関する投稿です。
問題の声明
システムに3つのファイルをインストールする架空のfoopkgパッケージを想像してください。
- /opt/foopkg/clear.text :セキュリティフリーのテキスト
- /opt/foopkg/sensitive.config:2つのパラメーターを持つ構成。そのうちの1つは秘密です
- / opt / foopkg / topsecret :主な質問への回答を含む秘密ファイル
foopkg.debの形式で配布され、内部リポジトリで利用可能であり、 apt-get install foopkgを使用して任意のサーバーにインストールできるとします。 私たちが怠(であると仮定し、一方で、すべてをリポジトリに保持し、 aptitude update && aptitude safe-upgradeのみを行い、その後は手で何も支配しないと仮定します。 一方、私たちは少し妄想的であり(そうです)、私たち以外の誰かが私たちの秘密の設定/構成を設定したくないとしましょう。 もちろん、パペットについても知っていますが、必要なフォームにすべてが既に自動的に組み込まれている(ただし、これは別のポストサイクルのトピックである)場合に、システム用に別のチャネルを開く必要があるのはなぜですか?
解決策
- パッケージをビルドする前にファイル(またはファイルの断片)を暗号化します
- パッケージを集める
- ???
- 利益
パッケージの署名の問題はこのHOWTOの範囲外であり、equivsを使用してパッケージをビルドします。
ビルド環境の準備:
mkdir -p foobuild/root_dir/opt/foopkg && cd foobuild touch {clear.txt,sensitive.config,topsecret} echo 'Package: foopkg' > control echo 'Pre-Depends: openssl' >> control # minimal control file, see man equivs-control echo -n 'ThisIsOurDeploymentMegaPassphrase' > pass
最も簡単なオプションは、ファイル全体を暗号化することです。
openssl aes-256-cbc -e -kfile ./pass -a -A -in $infile -out $outfile
-Aフラグには少し微妙な点があります。これを使用すると、暗号化された出力は64文字のブロックにぶつかりませんが、1行になります。 これにより、postinstでの復号化プロセスが#!/ Bin / dashのみとなり、少し簡単になります。
ただし、ファイル全体を暗号化するのは面白くない場合があります。 それでは、サブストリングを暗号化します。 これを行うには、まず暗号化境界を決定するマーカーを決定します。 簡単にするために、「___暗号化{」および「} ___」という形式のトークンを使用しましたが、ファイルに含まれる文字列をサブストリングに明確に分割するマーカーはYMMVが適しています。
したがって、すでに暗号化の準備ができているテストファイルは次のようになります。
clear.txt:
This is clear text, free to view, nothing special.
sensitive.config:
clear_param=foo secret_param=___encrypt{bar}___
トップシークレット:
___encrypt{this is multiline and 42}___
また、暗号化手順自体は、たとえば次のようになります。
#!/usr/bin/python import re import subprocess pass_file='./pass' def _encrypt(string): encre = re.compile('___encrypt{(.*?)}___', re.S) # non-greedy enc_string = string for el in encre.findall(string): # use openssl for encryption pipe = subprocess.Popen( ['openssl', 'aes-256-cbc', '-e', '-kfile', pass_file, '-a', '-A'], stdout = subprocess.PIPE, stdin = subprocess.PIPE, stderr = subprocess.PIPE, ) enc_el = pipe.communicate(input='%s' %el)[0] # Note: -A # add decryption markers enc_string = enc_string.replace('___encrypt{%s}___'%el, '___encrypted{%s}___'%enc_el) return enc_string # just for wrapper import sys print _encrypt( open(sys.argv[1], 'r').read() )
視覚的で高速であるため、Pythonで実行しました(shでの文字列の操作は、 固定のサブストリングの追加または抽出よりも複雑です-強い意志と頑固な男性専用です)。 アルゴリズムは最も単純です:ファイルを1行で読み取り、開始マーカーと終了マーカーですべての部分文字列を(貪欲ではなく、あまりキャプチャしないように)見て、暗号化(簡単にするためにopensslを呼び出して)し、それを挿入して、開始マーカーをデコーダーが理解できるマーカーに置き換えます。
最後の2行は、暗号化されたファイルを準備し、パッケージに含めるためにリストに追加する簡単なスクリプトでファイルのリストを確認できるように追加されます。
echo -n "Files: " >> control for file in clear.txt sensitive.config topsecret ; do ./encrypt.py $file > root_dir/opt/foopkg/$file; echo " root_dir/opt/foopkg/$file /opt/foopkg" >> control #note space! done
行頭のスペースは、Pythonだけでなく、debパッケージの制御ファイルでも重要です。
最後に、最後の部分であるクライアント側の復号化で、このパッケージがインストールされます。 これを行うには、次を含むpostinstファイルを作成します。
#!/bin/sh -e set -e PKG=foopkg ELIST="/opt/foopkg/topsecret /opt/foopkg/sensitive.config" warning() { echo "*************************************************" echo "*** WARNING! This is a protected package, ***" echo "*** please contact the maintainer, blah blah. ***" echo "*************************************************" } decrypt() { file="${1}" keyfile="${2}" for line in `grep -o -z -P '___encrypted{(.*?)}___' "${file}"`; do l=`echo $line | sed 's/___encrypted{\(.*\)}___/\1/'` d=`echo $l | openssl aes-256-cbc -d -kfile ${keyfile} -a -A` sed -i.encbackup "s@___encrypted{${l}}___@`echo "${d}"|awk '{printf("%s\\\\n", $0);}'|sed -e 's/\\\n$//'`@g" "${file}" done } # common key source PASSFILE='/root/deployment-password' if [ "$1" = configure ]; then # decrypt all encrypted stuff if [ ! -f ${PASSFILE} ]; then warning exit 1 fi for file in ${ELIST}; do decrypt "${file}" "${PASSFILE}" done fi #DEBHELPER# exit 0
ここでも、すべてが簡単です。 パッケージを作成する段階で、どのファイルが暗号化されており、どのファイルが暗号化されていないかをすでに知っています。スクリプトに追加して、生活を楽にします。 復号化アルゴリズムは似ています:マーカーごとにすべての行を探し、それぞれについて( -Aキーを覚えていますか?ここではそれがより難しいでしょう)暗号を引き出してopensslをフィードし、その後改行を表現に変更します( \ n ) 、置換を行い、改行を(ファイルの最後に追加して)改行を復元します。 残念ながら、ここではpythonを使用できません。このソリューションは、pythonが存在しないか、まだ存在しない最小インストール(たとえば、netinstall)向けに設計されています。 私はそのページの解読コードを開かなかった。それが誰かに読めないと思われる場合は謝罪する。
バックアップファイルの作成はオプションであり、常に役立つとは限りませんが、この場合、以下の復号化の瞬間を説明するために追加しました。
コントロールにpostinstを追加します。
echo "File: postinst 755" >> control # inline postinst file header cat postinst | sed 's/^$/./;s/^/ /;' >> control # inline postinst file body
この場合、Sedは2つの機能を実行します。
- s /^$/./; :制御ファイルが正しく解析されるように、空の行をドットで置き換えます。
- s / ^ / /; :同じ理由で各行の先頭にスペースを追加します。
equivs -build controlコマンドでパッケージを収集し、 foopkg_1.0_all.debを作業ディレクトリに取得します(最終的にははい?)。
私たちはインストールしようとしています(もちろん、ルートへの特権を増やすお気に入りの方法を使用して):
dpkg -i foopkg_1.0_all.deb Selecting previously unselected package foopkg. (Reading database ... 32032154537392375672 files and directories currently installed.) Unpacking foopkg (from .../foopkg/foopkg_1.0_all.deb) ... Setting up foopkg (1.0) ... ************************************************* *** WARNING! This is a protected package, *** *** please contact the maintainer, blah blah. *** ************************************************* dpkg: error processing foopkg (--install): subprocess installed post-installation script returned error exit status 1 Errors were encountered while processing: foopkg grep '' /opt/foopkg/* # package now in unconfigured state, lets see what installed /opt/foopkg/clear.txt:This is clear text, free to view, nothing special. /opt/foopkg/clear.txt: /opt/foopkg/sensitive.config:clear_param=foo /opt/foopkg/sensitive.config:secret_param=___encrypted{U2FsdGVkX19P9SiUFkMBPmoe9JKkngTi24rcwWCJ9gs=}___ /opt/foopkg/sensitive.config: /opt/foopkg/topsecret:___encrypted{U2FsdGVkX18wjp/ArVbp5v7yHazykiX3C2VDM9xavGrECXduajGmSmTipNpSRhZ5}___ /opt/foopkg/topsecret: echo -n 'ThisIsOurDeploymentMegaPassphrase' > /root/deployment-password # ok, lets enable decryption dpkg --configure -a # retry install Setting up foopkg (1.0) ... grep '' /opt/foopkg/* # lets see again -- yep, backups and decrypted files are in place. /opt/foopkg/clear.txt:This is clear text, free to view, nothing special. /opt/foopkg/clear.txt: /opt/foopkg/sensitive.config:clear_param=foo /opt/foopkg/sensitive.config:secret_param=bar /opt/foopkg/sensitive.config: /opt/foopkg/sensitive.config.encbackup:clear_param=foo /opt/foopkg/sensitive.config.encbackup:secret_param=___encrypted{U2FsdGVkX19P9SiUFkMBPmoe9JKkngTi24rcwWCJ9gs=}___ /opt/foopkg/sensitive.config.encbackup: /opt/foopkg/topsecret:this /opt/foopkg/topsecret:is /opt/foopkg/topsecret:multiline /opt/foopkg/topsecret:and /opt/foopkg/topsecret:42 /opt/foopkg/topsecret: /opt/foopkg/topsecret.encbackup:___encrypted{U2FsdGVkX18wjp/ArVbp5v7yHazykiX3C2VDM9xavGrECXduajGmSmTipNpSRhZ5}___ /opt/foopkg/topsecret.encbackup:
パッケージを急流で配布し、ファイルホスティングサイトにアップロードすることができます。コンテンツが意図されていない場所で使用可能になるのを恐れることなく(もちろん、十分に暗号化されたパスワードで)。
潜在的な利点と用途
- この手法は実用的な実装の例と考えることができます-かつてGoogleは望ましい結果を出しませんでした。
- IANAC(私は暗号作成者ではありません)、opensslを信頼しない理由はありません。 そのような方法が意図したとおりに動作しない理由を誰かが示した場合、私は非常に感謝します。
- もちろん、巨大なファイルでの使用を意図したものではありません。
- 私は個人的にこの方法を使用して、設定とプライマリキーを配布し、あまり技術に詳しくない親//友人のマシンでIPSecを設定しています。
- これが誰かにとって重要な場合、rpmベースへの移植は問題を引き起こさないはずです。
- クライアントごとに異なるキーで暗号化をオンにせず、パッケージに署名してリポジトリを設定しなかったため、投稿を短くしようとしました。
最後まで読んでくれたみんなに感謝します。 もちろん、パブリックドメインのすべて。