この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
AWSアクセスキーは、90日のローテーションが推奨されています。AWS Security Hubでもローテーションのルールがあります。
今回は、SORACOMで使っているAWSアクセスキーのローテーションを自動更新するスクリプトを作ってみました。
AWSアクセスキーのローテーション自動化を推奨するものではありません。組織のルール、付与されている権限の内容、扱っている情報、などによって判断してください。
おすすめの方
- AWSアクセスキーをプログラム等でローテーションしたい方
- SORACOM APIを使いたい方
本記事で扱う内容
本記事では、次の内容を扱います。
- 新しいAWSアクセスキーを作成する
- 新しいSORACOM認証情報を作成する
- SORACOM SIMグループの一覧を取得する
- SORACOM Funnelの設定にあるSORACOM認証情報を更新する
なお、次の内容は扱いません。
- 不要になったAWSアクセスキーの削除
- 不要になったSORACOM認証情報の削除
理由は次の2つです。
- AWSアクセスキー更新後、数日ほど様子を見て古いAWSアクセスキーが使われていないことを確認し、古いAWSアクセスキーを削除するため、時系列が違う(数日後に実施するため)
- 不要になったSORACOM認証情報を削除するために、削除する認証情報IDをどこかで保持する仕組みが必要となる
事前準備
まずは、事前準備としてSORACOM FunnelでAWSアクセスキーを使っている状態にします。
- AWS
- IAMユーザを作成する
- アクセスキーを取得する
- AWS IoT Coreエンドポイント取得
- SORACOM
- AWS認証情報を登録する
- SIMグループを作成する
- SORACOM Funnelの設定をする
- SORACOM APIを使う準備
IAMユーザを作成する
SORACOM Funnelでの利用とアクセスキー発行・削除の権限を持つIAMユーザを作成します。
iam.yaml
AWSTemplateFormatVersion: 2010-09-09
Description: IAM User for SORACOM Funnel
Resources:
# SORACOM Funnel用のIAMユーザ
SoracomFunnelUser:
Type: AWS::IAM::User
Properties:
UserName: soracom-funnel-sample-user
# IAMユーザに付与するIAMポリシー
SoracomFunnelUserPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: soracom-funnel-user-policy
PolicyDocument:
Version: "2012-10-17"
Statement:
# SORACOM Funnel用
- Effect: Allow
Action: iot:Publish
Resource: !Sub arn:aws:iot:${AWS::Region}:${AWS::AccountId}:topic/soracom/*
# AWSアクセスキーの更新用
- Effect: Allow
Action:
- iam:CreateAccessKey
- iam:DeleteAccessKey
Resource: !GetAtt SoracomFunnelUser.Arn
Users:
- !Ref SoracomFunnelUser
デプロイします。
aws cloudformation deploy \
--template-file iam.yaml \
--stack-name SORACOM-Funnel-IAM-User-Sample-Stack \
--capabilities CAPABILITY_NAMED_IAM \
--no-fail-on-empty-changeset
AWSアクセスキーを取得する
aws iam create-access-key \
--user-name soracom-funnel-sample-user
AWS IoT Coreエンドポイント取得
下記コマンドで取得できます。
aws iot describe-endpoint \
--endpoint-type iot:Data-ATS
SORACOMにAWS認証情報を登録する
SORACOM Webコンソールにアクセスし、右上のメニューにある「セキュリティ」を選択します。
続いて、「認証情報ストア」にある「認証情報を登録」を選択します。
種別は「AWS認証情報」を選択し、さきほど取得したアクセスキーを貼り付けて登録します。
AWSアクセスキーの変更は、この認証情報自体を登録し直すので、分かりやすいように認証情報IDに日付を記載しています。
そのためのPrefixとしてaws-soracom-funnel-sample
を利用します。
- aws-soracom-funnel-sample-220810
SIMグループを作成する
適当なSIMグループを作成します。
今回は、「test-1」と「test-2」を使います。
SORACOM Funnelの設定をする
それぞれのSIMグループに対して、SORACOM Funnelの設定を行います。これら2つのSIMグループの「AWS認証情報」をこのあと更新します。(いまは「220810」です)
SORACOM APIを使う準備
- SAMユーザの作成
- SAMユーザのアクセス権限を付与
- SAMユーザの「認証キーID&認証キーシークレット」を取得
上記については、次のブログを参考に行います。
なお、今回のアクセス権限は下記となります。
{
"statements": [
{
"api": [
"Credential:createCredential",
"Group:listGroups",
"Group:putConfigurationParameters"
],
"effect": "allow"
}
]
}
AWSアクセスキーを自動更新する
次の処理を行うスクリプトを作成します。
- 新しいAWSアクセスキーを作成して、SORACOM認証情報を作成して、SORACOM Funnel設定を更新する
- APIトークンの有効期限はデフォルト設定です。
- レートリミットの考慮をしていません。
スクリプトを作成する
app.py
import json
import boto3
import requests
from datetime import datetime
from typing import Tuple
SORACOM_ENDPOINT = 'https://api.soracom.io/v1'
SORACOM_KEY_ID = 'keyId-aaa'
SORACOM_SECRET = 'secret-bbb'
AWS_IAM_USER_NAME = 'soracom-funnel-sample-user'
CREDENTIAL_ID_BASE = 'aws-soracom-funnel-sample'
def main() -> None:
# 新しいAWSアクセスキーを作成
aws_access_key, aws_secret_access_key = create_aws_access_key()
api_key, token = get_token()
# SORACOM認証情報を作成
create_credential(api_key, token, aws_access_key, aws_secret_access_key)
# SIMグループを取得
groups = get_groups(api_key, token)
for item in groups:
if 'SoracomFunnel' not in item['configuration']:
continue
if CREDENTIAL_ID_BASE not in item['configuration']['SoracomFunnel']['credentialsId']:
continue
# SORACOM Funnelの認証情報を更新する
group_id = item['groupId']
print(group_id)
put_group_configuration(api_key, token, group_id)
def create_aws_access_key() -> Tuple[str, str]:
iam = boto3.client('iam')
resp = iam.create_access_key(
UserName=AWS_IAM_USER_NAME
)
return resp['AccessKey']['AccessKeyId'], resp['AccessKey']['SecretAccessKey']
def get_credential_id():
today = datetime.now().strftime('%y%m%d')
return f'{CREDENTIAL_ID_BASE}-{today}'
def get_token() -> Tuple[str, str]:
headers = {'Content-Type': 'application/json'}
data = {
'authKeyId': SORACOM_KEY_ID,
'authKey': SORACOM_SECRET,
}
resp = requests.post(f'{SORACOM_ENDPOINT}/auth', headers=headers, data=json.dumps(data))
d = resp.json()
return d['apiKey'], d['token']
def create_credential(
api_key: str,
token: str,
aws_access_key_id: str,
aws_secret_access_key: str) -> None:
headers = {
'Content-Type': 'application/json',
'X-Soracom-API-Key': api_key,
'X-Soracom-Token': token,
}
data = {
'type': 'aws-credentials',
'credentials': {
'accessKeyId': aws_access_key_id,
'secretAccessKey': aws_secret_access_key,
}
}
credential_id = get_credential_id()
resp = requests.post(
f'{SORACOM_ENDPOINT}/credentials/{credential_id}',
headers=headers,
data=json.dumps(data)
)
def get_groups(api_key: str, token: str) -> None:
headers = {
'Content-Type': 'application/json',
'X-Soracom-API-Key': api_key,
'X-Soracom-Token': token,
}
resp = requests.get(
f'{SORACOM_ENDPOINT}/groups',
headers=headers
)
return resp.json()
def put_group_configuration(api_key: str, token: str, group_id: str) -> None:
headers = {
'Content-Type': 'application/json',
'X-Soracom-API-Key': api_key,
'X-Soracom-Token': token,
}
data = [
{
'key': 'credentialsId',
'value': get_credential_id(),
},
]
resp = requests.put(
f'{SORACOM_ENDPOINT}/groups/{group_id}/configuration/SoracomFunnel',
headers=headers,
data=json.dumps(data)
)
if __name__ == '__main__':
main()
実行する
python app.py
結果を確認する
新しいAWSアクセスキーが発行された(8/15)
作成日が「220815」のAWSアクセスキーができました。
新しいSORACOM認証情報が登録された(8/15)
登録日時が「220815」のAWS認証情報が登録されました。
SIMグループのSORACOM FunnelのAWS認証情報が更新された(8/15)
それぞれのSIMグループのSORACOM Funnelの設定について、AWS認証情報が「220815」に更新されました。
さいごに
SORACOMで使うAWSアクセスキーを自動更新してみました。今回は手元で実行しましたが、Lambdaを使えば完全自動化もできそうです。 ただし、その場合は、失敗した際の検知&通知の仕組みを忘れずに構築すると良いですね。