Created
September 28, 2018 10:03
-
-
Save kauplan/4ade9e5bd8a5d94d8d36a46507bfa5da to your computer and use it in GitHub Desktop.
技術書典5 か-01 カウプラン機関「シェルスクリプトでサーバ設定を自動化する本」サンプルコード #1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
## | |
## @(#) opensslコマンドでファイルを暗号化/復号する。 | |
## パスワードはパスワードファイルから自動的に読み込む。 | |
## | |
## 事前準備: | |
## $ vi ~/.pass # パスワードファイルを作成 | |
## $ sudo chown ~/.pass # 所有者を root に変更 | |
## $ sudo chmod 600 ~/.pass # root のみアクセス可能に変更 | |
## $ export PASSWORD_FILE=~/.pass # 環境変数に設定 | |
## | |
## 使い方: | |
## $ crypt -h # ヘルプを表示 | |
## $ crypt -e file1 file2... # ファイルを暗号化 | |
## $ crypt -d file1.encrypted ... # ファイルを復号 | |
## | |
set -e # スクリプトにエラーがあれば終了 | |
set -u # 未定義の変数があればエラーにする | |
## openssl コマンドのオプションを指定 | |
## (OpenSSL 1.1 との互換性のため、-md sha256 をつける) | |
OPENSSL_OPTION="-aes-256-cbc -salt -md sha256" | |
## quietモード(空ならコマンドを表示) | |
quiet_mode='' | |
## エラーメッセージを出力して終了 | |
abort () { | |
command=`basename $0` | |
echo "Error ($command): $1" >&2 | |
exit 1 | |
} | |
## コマンドを表示してから実行する | |
run () { | |
[ -z "$quiet_mode" ] && echo "$ $1" >&2 | |
eval $1 | |
} | |
## ヘルプメッセージを表示 | |
print_help () { | |
cat <<HERE | |
Usage: | |
$ crypt -h # show help | |
$ crypt -e file1 file2... # encrypt | |
$ crypt -d file1.encrypted ... # decrypt | |
How to prepare password file: | |
$ vi ~/.pass # create password file | |
$ sudo chown ~/.pass # root user owns password file | |
$ sudo chmod 600 ~/.pass # readable only by root user | |
$ export PASSWORD_FILE=~/.pass # export as environment variable | |
HERE | |
} | |
## コマンドオプションを検証 | |
validate_command_options () { | |
local argc=$1 h=$2 e=$3 d=$4 | |
if [ -n "$h" ]; then | |
print_help | |
exit 0 | |
fi | |
if [ -z "$e" -a -z "$d" ]; then | |
abort "'-e' (encrypt) or '-d' (decrypt) required." | |
fi | |
if [ -n "$e" -a -n "$d" ]; then | |
abort "'-e' (encrypt) and '-e' (decrypt) are exclusive." | |
fi | |
if [ $argc -eq 0 ]; then | |
[ -n "$e" ] && abort "-e: plain file required." | |
[ -n "$d" ] && abort "-d: encrypted file required." | |
fi | |
} | |
## パスワードファイルをチェック | |
check_password_file () { | |
## 環境変数 $PASSWORD_FILE に指定したファイルをチェック | |
local f=${PASSWORD_FILE:-''} | |
[ -n "$f" ] || abort '$PASSWORD_FILE should be set.' | |
[ -f "$f" ] || abort "$f: password file not found." | |
## パスワードファイルは root ユーザのみアクセス可能であるべし | |
## (つまり一般ユーザが読み出し可能ならエラー) | |
if cat $f >/dev/null 2>&1; then # TODO: より正確に検査 | |
abort "$f: should be accessable only by root user." | |
fi | |
} | |
## メイン処理 | |
main () { | |
## 引数が何もないか、または '--help' なら、ヘルプメッセージを表示 | |
if [ $# -eq 0 -o ${1:-''} = '--help' ]; then | |
print_help | |
exit 0 | |
fi | |
## コマンドオプションを解析 | |
local opt h='' e='' d='' q='' | |
while getopts 'hedq' opt; do | |
case $opt in | |
h) h='Y' ;; # show help | |
e) e='Y' ;; # encrypt action | |
d) d='Y' ;; # decrypt action | |
q) q='Y' ;; # quiet mode | |
\?) exit 1;; | |
esac | |
done | |
## コマンドオプションをチェック | |
shift `expr $OPTIND - 1` | |
validate_command_options $# "$h" "$e" "$d" | |
quiet_mode=$q | |
## パスワードファイルからパスワードを読み込み、環境変数に設定 | |
check_password_file # パスワードファイルをチェック | |
PASSWORD=`sudo cat $PASSWORD_FILE` | |
export PASSWORD | |
## ファイルを暗号化または復号する | |
local ext='encrypted' # 暗号化ファイルの拡張子 | |
local openssl_opt="$OPENSSL_OPTION -pass env:PASSWORD" | |
if [ -n "$e" ]; then # 暗号化 (encrypt) | |
for x in $@; do | |
[ "${x%.$ext}" = "${x}" ] || abort "$x: already encrypted." | |
run "openssl enc -e $openssl_opt < $x > $x.$ext" | |
done | |
elif [ -n "$d" ]; then # 復号 (decrypt) | |
for x in $@; do | |
[ "${x%.$ext}" != "${x}" ] || abort "$x: not encrypted." | |
run "openssl enc -d $openssl_opt < $x > ${x%.$ext}" | |
run "chmod 600 ${x%.$ext}" # 他人によるアクセスを防ぐ | |
done | |
else | |
abort "(internal error) unreachable" | |
fi | |
} | |
main $@ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment