LoginSignup
3
2

More than 3 years have passed since last update.

Former2 CLIでAWSリソースからテンプレートファイルを出力してみる

Last updated at Posted at 2021-05-02

概要

説明

  • Former2とは?
    • 既存のAWSリソースからIaCのテンプレートファイルを作成するサードパーティ製ツール
    • GCPでいうところのTerraformer
    • former2はCloudFormationだけでなく、TerraformAWS CDKのテンプレートファイルとして出力できる
    • 以下対応しているテンプレートファイルの一覧
      • CloudFormation
      • Terraform
      • Troposphere
      • CDK (Cfn Primitives) - TypeScript, Python, Java, C#
      • CDK for Terraform - TypeScript
      • Pulumi - TypeScript
      • Diagram - embedded version of draw.io
  • Former2 CLIとは?
    • その名の通りFormer2CommandLineで使用するためのライブラリ
    • 公式に Former2 CLIはまだ実験的なものなので使用は自己責任で、と書いてあるのでリスクが怖い場合使わなければいいと思います。(今のところ自分の環境は特に不具合なしです)
    • Former2 CLIが対応しているAWSのリソース一覧
    • former2/README.md at master · iann0036/former2
    • 大抵のサービスは対応しているようにみえる

内容

Former2 CLIが使用するIAMのユーザー作成&権限付与

Docker環境でFormer2 CLI実行

  • RemoteContainer 環境を使用する

    git clone git@github.com:I-s-23/aws-container-env.git
    
    • VSCodeでCloneしたリポジトリを開く
    • コマンドパレットを開く
    • Windows:Ctrl + Shift + P
    • MAC:Cmd + Shift + P
    • Remote-Containers; Open Folderin Containerと入力する
    • .devcontainerディレクトリの一つ上の階層を選択
    • これでRemoteContainer の環境が起動します
  • aws-cliの認証を行う

    • コンテナ内で以下のコマンドを実行してAWSの認証を通します
    • コマンド押下後、AWS Access Key IDAWS Secret Access Keyの入力を求められるので、事前に作成したIAMユーザーのアクセスキーを入力します
  aws configure
  • Former2 CLIでテンプレートファイルを出力する
    • --output-cloudformationでCloudFormationで出力するテンプレートファイル名を指定
    • --output-terraformはTerraformで出力する場合のオプション
    • オプションについての詳細
  • 以下のコマンドはFormer2 CLIが対応しているAWS内のすべてのリソースを出力するコマンドなので実行に時間がかかります
former2 generate \
  --output-cloudformation "cloudformation.yml" \
  --output-terraform "terraform.hcl" \
  --output-raw-data "debug.json" \
  --sort-output
  • コマンドの実行結果です(アカウント IDなど秘匿情報は手動で隠しております)
    • この記事の内容しか行っていないのでCloudTrailTrailの設定やIAMユーザー、Log出力のS3バケットくらいしかないですね
cloudformation.yml
AWSTemplateFormatVersion: "2010-09-09"
Metadata:
    Generator: "former2"
Description: ""
Resources:
    IAMAccessKey:
        Type: "AWS::IAM::AccessKey"
        Properties:
            Status: "Inactive"
            UserName: "AWSTESTUser"

    IAMAccessKey2:
        Type: "AWS::IAM::AccessKey"
        Properties:
            Status: "Active"
            UserName: "AWSTESTUser"

    CloudTrailTrail:
        Type: "AWS::CloudTrail::Trail"
        Properties:
            TrailName: "cloudtrail-management-events"
            S3BucketName: !Ref S3Bucket
            IncludeGlobalServiceEvents: true
            IsMultiRegionTrail: true
            EnableLogFileValidation: false
            IsLogging: true

    IAMUser:
        Type: "AWS::IAM::User"
        Properties:
            Path: "/"
            UserName: "AWSTESTUser"
            ManagedPolicyArns: 
              - "arn:aws:iam::aws:policy/ReadOnlyAccess"

    OpsWorksUserProfile:
        Type: "AWS::OpsWorks::UserProfile"
        Properties:
            AllowSelfManagement: false
            IamUserArn: "arn:aws:iam::************:user/AWSTESTUser"
            SshUsername: "AWSTESTUser"

    S3StorageLens:
        Type: "AWS::S3::StorageLens"
        Properties:
            StorageLensConfiguration: 
                AccountLevel: 
                    BucketLevel: {}
                Id: "default-account-dashboard"
                IsEnabled: true

    S3BucketPolicy:
        Type: "AWS::S3::BucketPolicy"
        Properties:
            Bucket: !Ref S3Bucket
            PolicyDocument: 
                Version: "2012-10-17"
                Statement: 
                  - 
                    Sid: "AWSCloudTrailAclCheck20150319"
                    Effect: "Allow"
                    Principal: 
                        Service: "cloudtrail.amazonaws.com"
                    Action: "s3:GetBucketAcl"
                    Resource: !Sub "arn:aws:s3:::${S3Bucket}"
                  - 
                    Sid: "AWSCloudTrailWrite20150319"
                    Effect: "Allow"
                    Principal: 
                        Service: "cloudtrail.amazonaws.com"
                    Action: "s3:PutObject"
                    Resource: !Sub "arn:aws:s3:::${S3Bucket}/AWSLogs/************/*"
                    Condition: 
                        StringEquals: 
                            "s3:x-amz-acl": "bucket-owner-full-control"

    S3Bucket:
        Type: "AWS::S3::Bucket"
        Properties:
            BucketName: "aws-cloudtrail-logs-************-b134f084"

    ElastiCacheUser:
        Type: "AWS::ElastiCache::User"
        Properties:
            UserId: "default"
            UserName: "default"
            Engine: "redis"
            AccessString: "on ~* +@all"
            NoPasswordRequired: true
  • Terraformの形式でもちゃんと出力されているようです
terraform.hcl
# https://www.terraform.io/downloads.html

provider "aws" {
    region = "us-east-1"
}

resource "aws_iam_access_key" "IAMAccessKey" {
    status = "Inactive"
    user = "AWSTESTUser"
}

resource "aws_iam_access_key" "IAMAccessKey2" {
    status = "Active"
    user = "AWSTESTUser"
}

resource "aws_cloudtrail" "CloudTrailTrail" {
    name = "management-events"
    s3_bucket_name = "aws-cloudtrail-logs-***********-b134f084"
    include_global_service_events = true
    is_multi_region_trail = true
    enable_log_file_validation = false
    enable_logging = true
}

resource "aws_iam_user" "IAMUser" {
    path = "/"
    name = "AWSTESTUser"
    tags {}
}

resource "aws_opsworks_user_profile" "OpsWorksUserProfile" {
    allow_self_management = false
    user_arn = "arn:aws:iam::***********:user/AWSTESTUser"
    ssh_username = "AWSTESTUser"
}

resource "aws_s3_bucket_policy" "S3BucketPolicy" {
    bucket = "aws-cloudtrail-logs-***********-b134f084"
    policy = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"AWSCloudTrailAclCheck20150319\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"cloudtrail.amazonaws.com\"},\"Action\":\"s3:GetBucketAcl\",\"Resource\":\"arn:aws:s3:::aws-cloudtrail-logs-***********-b134f084\"},{\"Sid\":\"AWSCloudTrailWrite20150319\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"cloudtrail.amazonaws.com\"},\"Action\":\"s3:PutObject\",\"Resource\":\"arn:aws:s3:::aws-cloudtrail-logs-***********-b134f084/AWSLogs/***********/*\",\"Condition\":{\"StringEquals\":{\"s3:x-amz-acl\":\"bucket-owner-full-control\"}}}]}"
}

resource "aws_s3_bucket" "S3Bucket" {
    bucket = "aws-cloudtrail-logs-***********-b134f084"
}
  • もちろん特定のサービスを指定して出力することも可能です
  • EC2を対象としてテンプレートファイルを出力する場合の例
former2 generate \
  --output-cloudformation "cloudformation.yml" \
  --services "EC2" \
  --sort-output
  • EC2関連のリソースのみがテンプレートファイルとして出力されているのがわかります
cloudformation.yml
AWSTemplateFormatVersion: "2010-09-09"
Metadata:
    Generator: "former2"
Description: ""
Resources:
    EC2NetworkInterface:
        Type: "AWS::EC2::NetworkInterface"
        Properties:
            Description: ""
            PrivateIpAddress: !GetAtt EC2Instance.PrivateIp
            PrivateIpAddresses: 
              - 
                PrivateIpAddress: !GetAtt EC2Instance.PrivateIp
                Primary: true
            SubnetId: "subnet-836082d9"
            SourceDestCheck: true
            GroupSet: 
              - "sg-4b844008"

    EC2NetworkInterfaceAttachment:
        Type: "AWS::EC2::NetworkInterfaceAttachment"
        Properties:
            NetworkInterfaceId: "eni-0686f848cd1ac4064"
            DeviceIndex: 0
            InstanceId: !Ref EC2Instance
            DeleteOnTermination: true

    EC2Instance:
        Type: "AWS::EC2::Instance"
        Properties:
            ImageId: "ami-00f045aed21a55240"
            InstanceType: "t2.micro"
            AvailabilityZone: "ap-northeast-1c"
            Tenancy: "default"
            SubnetId: "subnet-836082d9"
            EbsOptimized: false
            SecurityGroupIds: 
              - "sg-4b844008"
            SourceDestCheck: true
            BlockDeviceMappings: 
              - 
                DeviceName: "/dev/xvda"
                Ebs: 
                    Encrypted: false
                    VolumeSize: 8
                    SnapshotId: "snap-0ac31d416f3b41c6c"
                    VolumeType: "gp2"
                    DeleteOnTermination: true
            HibernationOptions: 
                Configured: false
            EnclaveOptions: 
                Enabled: false

    EC2Volume:
        Type: "AWS::EC2::Volume"
        Properties:
            AvailabilityZone: !GetAtt EC2Instance.AvailabilityZone
            Encrypted: false
            Size: 8
            VolumeType: "gp2"
            SnapshotId: "snap-0ac31d416f3b41c6c"
            MultiAttachEnabled: false

    EC2VolumeAttachment:
        Type: "AWS::EC2::VolumeAttachment"
        Properties:
            VolumeId: !Ref EC2Volume
            InstanceId: !Ref EC2Instance
            Device: "/dev/xvda"

所感

  • AWSを使っているけどIaCはしていない、というプロジェクトなどで特にオススメのツールです
  • AWS公式のツールではないらしいが、OSSなので最高
  • 多種多様なAWSのリソースに対応していて便利
  • テンプレートファイルの出力形式に関してCloudFormationTerraformだけでなくAWS CDKとかにも対応しているのが素晴らしい
  • 初めて使うAWSのリソースとかをとりあえずGUIで設定後、Former2でIaCにするのが便利な使い方と思った。
  • 自分はCloudFormationしかわかっていないので同じリソースでTerraformのテンプレートファイルとかと比較すればTerraformの勉強にもよさそうだと思いました

余談

Former2 CLIのインストールに関して

  • 本記事のようにRemoteContainer のDocker環境でなくともnpmFormer2公式のコンテナを使用することも可能

    • どちらの場合でもAWSの認証を通さないと使えないのでaws-cliのインストール推奨
    • ~/.aws/credentialsにAWSの認証情報があればいいので、この部分をコンテナ内にマウントする方法もある
  • npmでのインストール方法

    • npmの場合ローカル環境にNode.jsが必要
npm install -g former2
docker build https://github.com/iann0036/former2.git#master:cli -t iann0036/former2:latest

経緯

  • 今回は社内や社外からFormer2が使えそうか知りたいという意見がきたのでQiitaとして投稿しました
    • あと Former2の使い方説明の記事は何個かあったがFormer2 CLIの記事が見つからなかったというのもあります
  • ちなみに弊社でFormer2の需要が発生した経緯は以下の感じです
    • 協力会社と開発したAWS環境で業務効率化のためCICDを行いたいという依頼がくる
    • 協力会社も弊社もGUIで環境設定や変更を行っていたらしく、CloudFormationaws-cliの使い方がわからないという返答
    • 誰もCLIでの操作方法を知らないのであればTerraformerのように既存のAWSリソースからIaC化すればいいと考えて調査する
    • Former2がよさそうと気付いて試す

参考資料

3
2
1

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
  3. You can use dark theme
What you can do with signing up
3
2