LoginSignup
6

More than 1 year has passed since last update.

【初心者】AWS Secrets Manager と AWS Systems Manager Parameter Store を使ってみる

Posted at

1. 目的

  • AWSのセキュリティ関連サービスの復習をしている。パスワードなどの保護すべき値を安全に保存するための仕組みであるAWS Secrets Manager と AWS Systems Manager Parameter Store について、それぞれを試して使い勝手などを確認する。
  • 機能の差異や使い分けについては、Qiita記事「AWSのParameter StoreとSecrets Manager、結局どちらを使えばいいのか?比較」に詳しく整理、網羅されており、それを読むだけで一通り理解できるが、一応自分でどんなものか試してみる。

2. やったこと

  • RDSと、RDSへ接続し操作する用のEC2インスタンスを作成する。
  • RDSに接続する際のパスワードをそれぞれAWS Secrets Manager と AWS Systems Manager Parameter Storeに保存し、EC2インスタンスからの接続時に、値を呼び出して利用する。

3. 構成図

構成図.png

4. 設定手順

4.1 環境準備

[ec2-user@ip-10-0-0-196 ~]$ sudo yum install python3
[ec2-user@ip-10-0-0-196 ~]$ python3 -V
Python 3.7.9
[ec2-user@ip-10-0-0-196 ~]$ sudo pip3 install boto3
[ec2-user@ip-10-0-0-196 ~]$ sudo yum install python-devel mysql-devel
[ec2-user@ip-10-0-0-196 ~]$ sudo yum install python3-devel
[ec2-user@ip-10-0-0-128 ~]$ sudo yum install gcc
[ec2-user@ip-10-0-0-128 ~]$ sudo pip3 install mysqlclient
[ec2-user@ip-10-0-0-128 ~]$ sudo yum localinstall -y https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm
[ec2-user@ip-10-0-0-128 ~]$ sudo yum install -y mysql-community-client
  • RDS DBに接続し、テスト用のテーブルを作っておく。
[ec2-user@ip-10-0-0-128 ~]$ mysql -h mksamba-testdb-202103.XXXXXXXXXXXX.ap-northeast-1.rds.amazonaws.com -P 3306 -u admin -p
mysql> create database mksambadb;
mysql> use mksambadb;
mysql> create table mksambadb.mytable(id int, stamp varchar(30));
mysql> insert into mytable (id, stamp)
    -> values('1', '1000');

4.2 EC2インスタンス(Python3)からの接続確認

  • RDSに接続するためのID/Passwordをコードにそのまま埋め込んで、RDSに接続できることを確認する。
dbconnect01.py
import MySQLdb

connection = MySQLdb.connect(
    host='mksamba-testdb-202103.XXXXXXXXXXXX.ap-northeast-1.rds.amazonaws.com',
    user='admin',
    passwd='PASSWORD',
    db='mksambadb')
cursor = connection.cursor()

cursor.execute("SELECT * FROM mksambadb.mytable")
for row in cursor:
    print(row)
connection.commit()
connection.close()
[ec2-user@ip-10-0-0-128 ~]$ python3 dbconnect01.py
(1, '1000')

4.3 Secret Manager の設定

  • Secret Manager にパスワードを保存する設定を行う。単純にパスワードのみを保存することもできるが、今回は「RDSデータベース認証情報」形式での保存を行う。
  • Secret Managerの画面にて、「新しいシークレットを保存する」を選択し、必要な項目を入力する。
    • シークレットの種類として、「RDSデータベースの認証情報」を選択する。
    • ユーザ名は「admin」、パスワードは設定したパスワード「PASSWORD」を入力する。
    • 暗号化キーとして、あらかじめ作成済のKMSカスタマーマスターキーを指定する。
    • このID/Passwordを使用して接続するRDS DBを選択する。

secret01a.png

  • このsecretの名前を「mksamba-secret-for-rds」とする。

secret02a.png

  • 今回はローテーションは無効のままにしておく。

secret03a.png

  • 最後に値を取得するためのサンプルコードが表示される。これをコピペして利用する。

secret04a.png

secret05a.png

4.4 Secret Manager からの値の取得

  • EC2インスタンスからRDS DBに接続する際に、パスワードをコードに埋め込むのではなく、Secret Managerに保存した値を取得して使用するように設定する。
  • EC2インスタンスに、Secret Manager及びKMSの権限があるIAM Roleを付与する。(今回は検証のため、Poweruser相当の権限を付与)
  • コードは以下のように修正する。注意点として、Secret(ID/Passwordの値を保存)が文字列型のため、辞書型に変更した上で値を取得する。DevelopersIOの記事「PythonでAWS Secrets ManagerからAPIキーを取得するときのちょっとしたポイント」のやり方を利用させて頂いた。
dbconnect02.py
import MySQLdb
import boto3
import base64
from botocore.exceptions import ClientError
import ast

secret_name = "mksamba-secret-for-rds"
region_name = "ap-northeast-1"

session = boto3.session.Session()
client = session.client(
    service_name='secretsmanager',
    region_name=region_name
)

try:
     get_secret_value_response = client.get_secret_value(
        SecretId=secret_name
    )
except ClientError as e:
    if e.response['Error']['Code'] == 'DecryptionFailureException':
        raise e
    elif e.response['Error']['Code'] == 'InternalServiceErrorException':
        raise e
    elif e.response['Error']['Code'] == 'InvalidParameterException':
        raise e
    elif e.response['Error']['Code'] == 'InvalidRequestException':
        raise e
    elif e.response['Error']['Code'] == 'ResourceNotFoundException':
        raise e
else:
    if 'SecretString' in get_secret_value_response:
        secret = get_secret_value_response['SecretString']
    else:
        decoded_binary_secret = base64.b64decode(get_secret_value_response['SecretBinary'])

secret = ast.literal_eval(secret)

connection = MySQLdb.connect(
    host='mksamba-testdb-202103.XXXXXXXXXXXX.ap-northeast-1.rds.amazonaws.com',
    user=secret['username'],
    passwd=secret['password'],
    db='mksambadb')
cursor = connection.cursor()

cursor.execute("SELECT * FROM mksambadb.mytable")
for row in cursor:
    print(row)
connection.commit()
connection.close()

4.5 Parameter Store の設定

  • 今度はパスワードの値をParameter Storeに保存してみる。
  • AWS Systems Managerの画面にて、「パラメータストア」- 「パラメータを作成」を選択する。
    • タイプは「安全な文字列」を選択し、暗号化を行う。
    • あらかじめ作成済のKMS カスタマーマスターキーを指定する。
    • 値として、パスワードの文字列「PASSWORD」を入力する。

secret06a.png

4.6 Parameter Store からの値の取得

  • EC2インスタンスからRDS DBに接続する際に、パスワードをコードに埋め込むのではなく、Parameter Storeに保存した値を取得して使用するように設定する。
  • EC2インスタンスに、Systems Manager及びKMSの権限があるIAM Roleを付与する。(今回は検証のため、Poweruser相当の権限を付与)
  • コードは以下のように修正する。手順はDevelopersIO記事「AWS SDK for Python (Boto3) で AWS Systems Manager パラメータストアから情報を取得する」を参照。
dbconnect03.py
import MySQLdb
import boto3
import json

ssm = boto3.client('ssm', 'ap-northeast-1')
response = ssm.get_parameters(
    Names=[
        'mksamba-password-rds',
    ],
    WithDecryption=True
)

connection = MySQLdb.connect(
    host='mksamba-testdb-202103.XXXXXXXXXXXX.ap-northeast-1.rds.amazonaws.com',
    user='admin',
    passwd=response['Parameters'][0]['Value'],
    db='mksambadb')
cursor = connection.cursor()

cursor.execute("SELECT * FROM mksambadb.mytable")
for row in cursor:
    print(row)
connection.commit()
connection.close()

5. 所感

  • どちらも隠したい値を暗号化して保存しておき、必要な時に取り出して使用する、という点ではそんなに変わりなく使えるかなと思った。費用や、細かい機能の差異(Secret Managerの値の自動更新機能など)の必要性に応じて判断できるようにしたい。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
6