概要

ChatGPTに助けられて作成した

  • SQLのバックアップを行うシェルスクリプト
  • より安全なパスワード生成を行えるRubyスクリプト

この2つを連携させてみました。

スクリプトのフロー図

以下のようにして動きます。

sequenceDiagram participant b as バックアップ participant p as パスワード生成 note over b: 処理実行 note over b: 作業ディレクトリ<br>作成 note over b: MySQL dump b->>p: スクリプト呼び出し note over p: 処理実行 note over p: PW発行 note over p: PWファイル作成 p-->>b: スクリプト実行完了 note over b,p: PWファイルを元に暗号化 note over b: 作業ディレクトリ<br>削除 note over b: 古いバックアップ削除 note over b,p: 古いPWファイルを削除 note over b: 処理完了

スクリプト内容

スクリプト1: DBバックアップ

  • スクリプトタイプ:シェルスクリプト
#!/bin/bash

## 変数ここから ##
# SQLをバックアップするディレクトリ(保管先)を指定します。
backup_dir="/home/backup/mysql"
# 保持するバックアップの世代を日数で指定します。
keep_days=7
# ファイルに付与する日付/作業ディレクトリ名/バックアップファイル名を指定します。
current_date=$(date +%Y%m%d)
backup_name="redmine_mysql_${current_date}"
zip_file="redmine_mysql.${current_date}.zip"
# アカウントファイルを指定します。
credentials_file="$HOME/mysql/account.txt"
# パスワードを生成するスクリプトの格納場所を指定します。
password_generate="$HOME/scripts/ruby/password_generate_for_redmine.rb"
# 上記スクリプトによって生成されたパスワードファイルの格納場所を指定します。
password_file="$HOME/restore_password/mysql-restore.${current_date}.txt"
# バックアップ時に指定するオプションを指定します。
options="--defaults-extra-file=$credentials_file --no-tablespaces --single-transaction"
## 変数ここまで ##

## 処理ここから ##

# 1.アカウントファイルのパーミッションが400かどうかチェックします。
# 400以外は処理そのものを終了します。
permissions=$(stat -c "%a" "$credentials_file")
if [ "$permissions" != "400" ]; then
    echo "アカウントファイルのパーミッションは400である必要があります。"
    exit 1
fi

# 2.一時的なバックアップディレクトリを作成します。
mkdir "${backup_dir}/${backup_name}"

# 3. mysqldumpを実行してデータベースのバックアップを取ります。
mysqldump $options -h localhost redmine > "${backup_dir}/${backup_name}/${backup_name}.sql"

# 4. パスワードによる暗号化を実施します。
ruby "$password_generate"
password=$(cat "$password_file")
cd "${backup_dir}/${backup_name}"
zip -r "${backup_dir}/${zip_file}" -P "$password" .
cd -

# 5. 一時的なバックアップディレクトリを削除します。
rm -rf "${backup_dir}/${backup_name}"

# 6.パスワードの読み取り権限を600に変更します。
chmod 600 $password_file

# 7. 保持期間より古いバックアップファイルを削除します。
find "$backup_dir" -name "redmine_mysql.*.zip" ! -type f -newermt "${keep_days} days ago" -delete
find "$password_file" -name "*.txt" -type f -mtime +$keep_days -delete

スクリプト2:パスワード生成

  • スクリプトタイプ: Ruby
#このRubyスクリプトは、SecureRandomモジュールを使用してランダムなパスワードを生成するためのスクリプトです。
#パスワードの生成に関する様々な設定を変数で行うことができます。
#例えば、パスワードの長さ、数字やアルファベット、大文字や記号を使用するかどうかなどを指定することができます。
#スクリプトは、出力先がファイルか標準出力かを選択できます。
#ファイルに出力する場合は出力先のディレクトリやファイル名を指定することができます。

# モジュールを呼び出します 
require 'securerandom'
require 'fileutils'
require 'date'

### 変数はここからです
## 出力するパスワードの数(行数)を数字で指定します
num_passwords = 1
## 出力先を選択します
# ファイルに出力する場合は 1、標準出力に出力する場合は 0 に設定します
output_to_file = 1
# 出力先のディレクトリを指定します
output_directory = '/home/hoge/restore_password' 
# 出力ファイル名を名前+yyyymmdd形式.txtで指定します
# 最初の''部分の名前を任意の名前に入力ください
output_filename =  'mysql-restore.' + Time.now.strftime("%Y%m%d") + '.txt'
## パスワードの強度を指定します
# パスワード桁数を数字で指定します
password_length = 12
# 数字を用いる場合は1を、用いない場合は0を指定します
use_numbers = 1
# アルファベット小文字を用いる場合は1を、用いない場合は0を指定します
use_alphabet = 1
# アルファベット大文字を用いる場合は1を、用いない場合は0を指定します
use_uppercase = 1
# 記号を用いる場合は1を、用いない場合は0を指定します
use_symbols = 1
## パスワード生成用の文字種を定義します
# 必要に応じて使わない文字を削除することが可能です(lと|, 0とOなど)
characters = ''
characters += '0123456789' if use_numbers == 1
characters += 'abcdefghijklmnopqrstuvwxyz' if use_alphabet == 1
characters += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' if use_uppercase == 1
characters += '!#$%&()*+,-./:;<=>?@[]^_`{|}~' if use_symbols == 1
### 変数はここまでです

# パスワード生成関数を定義します
def generate_password(length, characters)
  SecureRandom.random_bytes(length).unpack('C*').map do |byte|
    characters[byte % characters.length]
  end.join
end

## パスワードファイルを出力する場合(変数 output_to_fileを1にしたとき)の処理です
#出力先のパスを作成します
if output_to_file == 1
  output_path = File.join(output_directory, output_filename)
# 出力先のディレクトリが存在しない場合は作成します
  FileUtils.mkdir_p(output_directory)
# パスワードを出力します
  File.open(output_path, 'w') do |file|
    num_passwords.times do
      password = generate_password(password_length, characters)
      file.puts password
    end
  end
else

## 標準出力に出すだけの場合(変数 output_to_fileを0にしたとき)の処理です
# パスワードを標準出力に出力します
  num_passwords.times do
    password = generate_password(password_length, characters)
    puts password
  end
end

上記、Rubyスクリプトを「変数の定義でファイル出力と標準出力」の2つが選べるようにしたのは幸いでした。(パスワード1つのみを使うので行数も1にしています)