ENGINEER BLOG ENGINEER BLOG
  • 公開日
  • 最終更新日

[CloudFormation]CloudFormationで作成したキーペアをローカルに保存

この記事を共有する

目次

はじめに

サービスGの森です。

今回はCloudFormationテンプレートでデプロイしたキーペアを保存する方法について紹介します。

やりたいこと

CloudFormationで構築したキーペアは通常ローカルに保存されません。
...が、パラメータストアに「ec2/keypair/<キーペアのID>」というパラメータ名で自動的に保存されます。

パラメータストアに保存されたキー.png

そこで、このパラメータの値を取得して「秘密鍵(.pem)ファイル」を取得するスクリプトを作成してみます。

やってみた

1. テンプレートとスクリプトの作成

1. まずはEC2とキーペア用のテンプレートを作成します(VPCとサブネットはデフォルトのものを使用する為、IDはDefault値を未指定とします)

ec2.yml

#--------------------------------------------------#
# EC2 & KeyPair 
#--------------------------------------------------#
AWSTemplateFormatVersion: 2010-09-09
Description: EC2 & KeyPair Template
#--------------------------------------------------#
# Parameters
#--------------------------------------------------#
Parameters:
  # EC2用のAMI
  AmiId:
    Description: AMI ID of the EC2 Instance
    Type: AWS::SSM::Parameter::Value
  # デフォルトのVPC
  VpcId:
    Description: ID of VPC
    Type: String
  # デフォルトのサブネット
  SubnetId:
    Description: ID of Subnet
    Type: String
#--------------------------------------------------#
# Resources
#--------------------------------------------------#
Resources:
  # キーペア
  KeyPair:
    Type: AWS::EC2::KeyPair
    Properties:
      KeyFormat: pem
      KeyName: my-keypair
      KeyType: rsa
      Tags: 
        - Key: Name
          Value: my-keypair
  # セキュリティグループ
  Sg:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: ec2-sg
      GroupDescription: Allow SSH
      VpcId: !Ref VpcId
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0
  # EC2インスタンス
  Ec2:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t2.micro
      ImageId: !Ref AmiId
      KeyName: !Ref KeyPair
      SubnetId: !Ref SubnetId
      SecurityGroupIds:
        - !Ref Sg
      Tags:
        - Key: Name
          Value: my-instance
#--------------------------------------------------#
# Outputs
#--------------------------------------------------#
Outputs:
  # キーペアID
  KeyPairId:
    Description: ID of the key pair
    Value: !GetAtt KeyPair.KeyPairId
2. 次にキーペア保存用のスクリプトを作成します

install-key.sh

#!/bin/bash
# 引数を取得
STACK_NAME=$1
OUTPUT_NAME=$2
# 引数チェック
if [ -z "$STACK_NAME" ] || [ -z "$OUTPUT_NAME" ]; then
  echo "エラー: 引数が不足しています"
  exit 1
fi
# キーIDを取得
KEY_ID=$(aws cloudformation describe-stacks \
    --stack-name $STACK_NAME \
    --query "Stacks[0].Outputs[?OutputKey=='$OUTPUT_NAME'].OutputValue" \
    --output text)
# キー名を取得
KEY_NAME=$(aws ec2 describe-key-pairs \
    --key-pair-ids $KEY_ID \
    --query "KeyPairs[0].KeyName" \
    --output text)
# .pemファイルでキーを保存
aws ssm get-parameter \
    --name "/ec2/keypair/$KEY_ID" \
    --with-decryption \
    --query "Parameter.Value" \
    --output text > $KEY_NAME.pem
echo "キーを保存しました"

スクリプトについて

  • 第一引数からスタック名、第二引数からOutput名を取得し、以下の処理を実行します
    • CloudFormationスタックからキーペアID(Output値)を取得
    • 取得したキーペアIDからキーペア名を取得
    • パラメータストアから、キーペアIDに対応する秘密鍵を取得
    • 取得した秘密鍵を「<キーペア名>.pem」として保存

2. 検証

1. Parameterをオーバーライドしてテンプレートをデプロイします
aws cloudformation deploy \
  --stack-name ec2-stack \
  --template-file ec2.yml \
  --parameter-overrides AmiId=<任意のAMIのID> \
    VpcId=<デフォルトVPCのID> \
    SubnetId=<デフォルトサブネットのID>
2. 秘密鍵を取得するスクリプトを実行します
# スクリプトに実行権限を付与
chmod +x install-key.sh
# 秘密鍵を取得するスクリプトを実行(スタック名: ec2-stack, Output名: KeyPairId)
./install-key.sh ec2-stack KeyPairId
3. ローカルに秘密鍵(.pem)ファイルが保存されました!

キーペアファイル.png

4. ユーザーに.pemファイルの実行権限を付与して、今回作成したEC2に接続してみます
# ユーザーに秘密鍵の読み取り権限のみ付与
chmod 400 my-keypair.pem 
# SSH接続
ssh -i <秘密鍵のパス> <接続先EC2インスタンスのIPアドレス>
5. スクリプトから作成した秘密鍵ファイルでEC2に接続できました!

EC2ログイン.png

おわりに

  • 今回スクリプトを作成しましたが、組み込みの機能でこんなのあると便利だなと思いました(S3バケットを指定して保存とか)。
  • CI/CDに組み込むと便利かなと思います。

この記事は私が書きました

森 翔吾

記事一覧

最近はコンテナ・サーバレスを学習しています。 よろしくお願いします。

森 翔吾

この記事を共有する

クラウドのご相談

CONTACT

クラウド導入や運用でお悩みの方は、お気軽にご相談ください。
専門家がサポートします。

サービス資料ダウンロード

DOWNLOAD

ビジネスをクラウドで加速させる準備はできていますか?
今すぐサービス資料をダウンロードして、詳細をご確認ください。