[JAWS-UG CLI] Amazon Kinesis Firehose 入門 (1) 事前準備（S3バケット、Service Role、ロググループ・ログストリームの作成）

# この記事について

[JAWS-UG CLI専門支部 #73 Kinesis Firehose入門](https://jawsug-cli.doorkeeper.jp/events/41915)で実施するハンズオン用の手順書です。


# 前提条件

## 必要な権限

作業にあたっては、以下の権限を有したIAMユーザもしくはIAMロールを利用してください。

- Kinesis Firehoseのフルコントロール権限
- S3のフルコントロール権限
- STSの関するフルコントロール権限
- IAMの関するフルコントロール権限
- CloudWatchの関するフルコントロール権限
- CloudWatch Logsの関するフルコントロール権限

# 0. 準備

## 0.1. リージョンを指定

オレゴンリージョンで実施します。（東京マダー？）

```bash:コマンド
export AWS_DEFAULT_REGION="us-west-2"
```

## 0.2. 資格情報を確認


```bash:コマンド
aws configure list
```

インスタンスプロファイルを設定したEC2インスタンスでアクセスキーを設定せずに実行した場合、以下のようになります。

```text:結果
      Name                    Value             Type    Location
      ----                    -----             ----    --------
   profile                <not set>             None    None
access_key     ****************QSAA         iam-role
secret_key     ****************c1xY         iam-role
    region                us-west-2              env    AWS_DEFAULT_REGION
```

## 0.3. バージョン確認

```bash:コマンド
aws --version
```

```text:結果
aws-cli/1.11.28 Python/2.7.12 Linux/4.4.23-31.54.amzn1.x86_64 botocore/1.4.85
```

## 0.4. バージョンアップ（必要に応じて）

```bash:コマンド
sudo pip install -U awscli
```


# 1. Destinationの準備

Kinesis Firehoseからデータを配信する先となるS3バケットを作成します。

## 1.1. S3バケットの作成

### AWS IDの取得

```bash:コマンド
AWS_ID=$(aws sts get-caller-identity \
    --query Account \
    --output text) \
    && echo ${AWS_ID}
```

```text:結果
************
```

### バケット名の指定

```bash:コマンド
BUCKET_NAME="jawsug-cli-firehose-${AWS_ID}" \
    && echo ${BUCKET_NAME}
```

```text:結果
jawsug-cli-firehose-************
```

#### 同名のバケットがないことを確認

```bash:コマンド
aws s3 ls ${BUCKET_NAME}
```

```text:結果
An error occurred (NoSuchBucket) when calling the ListObjects operation: The specified bucket does not exist
```

### 変数の確認

```bash:コマンド
cat << ETX

    BUCKET_NAME: ${BUCKET_NAME}

ETX
```

```text:結果

    BUCKET_NAME: jawsug-cli-firehose-************

```

### バケットの作成

```bash:コマンド
aws s3api create-bucket \
    --bucket ${BUCKET_NAME} \
    --create-bucket-configuration LocationConstraint=${AWS_DEFAULT_REGION}
```

```json:結果
{
    "Location": "http://jawsug-cli-firehose-************.s3.amazonaws.com/"
}
```

### 作成されたバケットの確認

```bash:コマンド
aws s3 ls | grep ${BUCKET_NAME}
```

```text:結果
2016-11-05 05:49:49 jawsug-cli-firehose-************
```


# 2. ログの出力先の作成

このログは、Kinesis Firehoseに関するエラーログなどを指します。
このハンズオンでは（エラーが起きなければ何も出力されないので）特に確認はしませんが、運用環境では設定することになると思います。

## ロググループの作成

### ロググループ名の指定

```bash:コマンド
LOG_GROUP_NAME="jawsug-cli-firehose"
```

### ロググループ名の重複を確認

```bash:コマンド
aws logs describe-log-groups \
    --log-group-name-prefix ${LOG_GROUP_NAME}
```

```json:結果
{
    "logGroups": []
}
```

### 変数の確認

```bash:コマンド
cat << ETX

    LOG_GROUP_NAME: ${LOG_GROUP_NAME}

ETX
```

```text:結果

    LOG_GROUP_NAME: jawsug-cli-firehose

```

### ロググループの作成

```bash:コマンド
aws logs create-log-group \
    --log-group-name ${LOG_GROUP_NAME}
```

```text:結果
（返値無し）
```

### ロググループの確認

```bash:コマンド
aws logs describe-log-groups \
    --log-group-name-prefix ${LOG_GROUP_NAME}
```

```json:結果
{
    "logGroups": [
        {
            "arn": "arn:aws:logs:us-west-2:************:log-group:jawsug-cli-firehose:*",
            "creationTime": 1478325129343,
            "metricFilterCount": 0,
            "logGroupName": "jawsug-cli-firehose",
            "storedBytes": 0
        }
    ]
}
```

## ログストリームの作成

### ログストリーム名の指定

```bash:コマンド
LOG_STREAM_NAME="handson"
```


### ログストリーム名の重複を確認

```bash:コマンド
aws logs describe-log-streams \
    --log-group-name ${LOG_GROUP_NAME}\
    --log-stream-name-prefix ${LOG_STREAM_NAME}
```

```json:結果
{
    "logStreams": []
}
```

### 変数の確認

```bash:コマンド
cat << ETX

    LOG_GROUP_NAME: ${LOG_GROUP_NAME}
    LOG_STREAM_NAME: ${LOG_STREAM_NAME}

ETX
```

```text:結果

    LOG_GROUP_NAME: jawsug-cli-firehose
    LOG_STREAM_NAME: handson

```

### ログストリームの作成

```bash:コマンド
aws logs create-log-stream \
    --log-group-name ${LOG_GROUP_NAME} \
    --log-stream-name ${LOG_STREAM_NAME}
```

```text:結果
（返値無し）
```


### ログストリームの確認

```bash:コマンド
aws logs describe-log-streams \
    --log-group-name ${LOG_GROUP_NAME}\
    --log-stream-name-prefix ${LOG_STREAM_NAME}
```

```json:結果
{
    "logStreams": [
        {
            "creationTime": 1478325265601,
            "arn": "arn:aws:logs:us-west-2:************:log-group:jawsug-cli-firehose:log-stream:handson",
            "logStreamName": "handson",
            "storedBytes": 0
        }
    ]
}
```

# 3. IAM Roleの作成

Kinesis Firehoseに対し、権限を委任するためのIAM Roleを作成します。（付与する権限は後述）

## IAM Roleの作成

### IAM Role名を指定

```bash:コマンド
ROLE_NAME='service-role-firehose'
```

### 同名のロールがないことを確認

```bash:コマンド
aws iam get-role \
    --role-name ${ROLE_NAME}
```

```text:結果
An error occurred (NoSuchEntity) when calling the GetRole operation: Unknown
```


### 信頼関係の定義

```bash:コマンド
TRUST_POLICY_FILE='Trust-Policy.json'
```

```bash:コマンド
cat << EOF > ${TRUST_POLICY_FILE}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "firehose.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF

cat ${TRUST_POLICY_FILE}
```

```json:結果
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "firehose.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
```

### JSONファイルを検証

```bash:コマンド
jsonlint -q ${TRUST_POLICY_FILE}
```

```text:結果
（返値無し）
```

### 変数の確認

```bash:コマンド
cat << ETX

    ROLE_NAME: ${ROLE_NAME}
    TRUST_POLICY_FILE: ${TRUST_POLICY_FILE}

ETX
```

```text:結果

    ROLE_NAME: service-role-firehose
    TRUST_POLICY_FILE: Trust-Policy.json

```

### IAMロールの作成

```bash:コマンド
aws iam create-role \
    --role-name ${ROLE_NAME} \
    --assume-role-policy-document file://${TRUST_POLICY_FILE}
```

```json:結果
{
    "Role": {
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Action": "sts:AssumeRole",
                    "Principal": {
                        "Service": "firehose.amazonaws.com"
                    },
                    "Effect": "Allow",
                    "Sid": ""
                }
            ]
        },
        "RoleId": "A********************",
        "CreateDate": "2016-11-05T05:58:53.873Z",
        "RoleName": "service-role-firehose",
        "Path": "/",
        "Arn": "arn:aws:iam::************:role/service-role-firehose"
    }
}
```


### IAMロールの確認およびARNの取得

```bash:コマンド
ROLE_ARN=$(aws iam get-role \
    --role-name ${ROLE_NAME} \
    --query Role.Arn \
    --output text) \
    && echo ${ROLE_ARN}
```

```text:結果
arn:aws:iam::************:role/service-role-firehose
```


### ポリシー名の指定

ここでKinesis Firehoseに対して委任する権限を定義します。
具体的には、

- S3へのデータ配信
- CloudWatch Logsへのログの出力

の権限を付与します。

[Controlling Access with Amazon Kinesis Firehose(Grant Firehose Access to an Amazon S3 Destination)](http://docs.aws.amazon.com/firehose/latest/dev/controlling-access.html#using-iam-s3)

※KMSを利用する場合には、必要なポリシーを追記する必要があります。

```bash:コマンド
GRANT_POLICY_FILE='Grant-Firehose-Access-to-S3-Policy.json'
```

### 変数の確認

```bash:コマンド
cat << ETX

    GRANT_POLICY_FILE: ${GRANT_POLICY_FILE}
    BUCKET_NAME: ${BUCKET_NAME}
    AWS_DEFAULT_REGION: ${AWS_DEFAULT_REGION}
    AWS_ID: ${AWS_ID}
    LOG_GROUP_NAME: ${LOG_GROUP_NAME}
    LOG_STREAM_NAME: ${LOG_STREAM_NAME}

ETX
```

```text:結果

    GRANT_POLICY_FILE: Grant-Firehose-Access-to-S3-Policy.json
    BUCKET_NAME: jawsug-cli-firehose-************
    AWS_DEFAULT_REGION: us-west-2
    AWS_ID: ************
    LOG_GROUP_NAME: jawsug-cli-firehose
    LOG_STREAM_NAME: handson

```

### ポリシーの生成

```bash:コマンド
cat << EOF > ${GRANT_POLICY_FILE}
{
    "Version": "2012-10-17",  
    "Statement":
    [
        {
            "Effect": "Allow",      
            "Action":
            [        
                "s3:AbortMultipartUpload",        
                "s3:GetBucketLocation",        
                "s3:GetObject",        
                "s3:ListBucket",        
                "s3:ListBucketMultipartUploads",        
                "s3:PutObject"
            ],      
            "Resource":
            [        
                "arn:aws:s3:::${BUCKET_NAME}",
                "arn:aws:s3:::${BUCKET_NAME}/*"		    
            ]    
        },
        {
           "Effect": "Allow",
           "Action": [
               "logs:PutLogEvents"
           ],
           "Resource": [
               "arn:aws:logs:${AWS_DEFAULT_REGION}:${AWS_ID}:log-group:${LOG_GROUP_NAME}:log-stream:${LOG_STREAM_NAME}"
           ]
        }
    ]
}
EOF

cat ${GRANT_POLICY_FILE}
```

```json:結果
{
    "Version": "2012-10-17",
    "Statement":
    [
        {
            "Effect": "Allow",
            "Action":
            [
                "s3:AbortMultipartUpload",
                "s3:GetBucketLocation",
                "s3:GetObject",
                "s3:ListBucket",
                "s3:ListBucketMultipartUploads",
                "s3:PutObject"
            ],
            "Resource":
            [
                "arn:aws:s3:::jawsug-cli-firehose-************",
                "arn:aws:s3:::jawsug-cli-firehose-************/*"
            ]
        },
        {
           "Effect": "Allow",
           "Action": [
               "logs:PutLogEvents"
           ],
           "Resource": [
               "arn:aws:logs:us-west-2:************:log-group:jawsug-cli-firehose:log-stream:handson"
           ]
        }
    ]
}
```

### JSONファイルを検証

```bash:コマンド
jsonlint -q ${GRANT_POLICY_FILE}
```

```text:結果
（返値無し）
```


### ポリシー名を指定

```bash:コマンド
POLICY_NAME="ServicePolicyFirehose"
```

### 同名のポリシーが無いことを確認

```bash:コマンド
aws iam list-policies \
    --scope Local \
    --query Policies[?PolicyName==${POLICY_NAME}]
```

```json:結果
[]
```

### 変数の確認

```bash:コマンド
cat << ETX

    POLICY_NAME: ${POLICY_NAME}
    GRANT_POLICY_FILE: ${GRANT_POLICY_FILE}

ETX
```

```text:結果

    POLICY_NAME: ServicePolicyFirehose
    GRANT_POLICY_FILE: Grant-Firehose-Access-to-S3-Policy.json

```

### ポリシーの作成、ARNの取得

IAMポリシーをIAM Roleにアタッチする際にポリシーをARNで指定する必要があるため、ここでARNを取得しておきます。

```bash:コマンド
aws iam create-policy \
    --policy-name ${POLICY_NAME} \
    --policy-document file://${GRANT_POLICY_FILE}
```

```json:結果
{
    "Policy": {
        "PolicyName": "ServicePolicyFirehose",
        "CreateDate": "2016-12-19T05:37:59.731Z",
        "AttachmentCount": 0,
        "IsAttachable": true,
        "PolicyId": "A********************",
        "DefaultVersionId": "v1",
        "Path": "/",
        "Arn": "arn:aws:iam::************:policy/ServicePolicyFirehose",
        "UpdateDate": "2016-12-19T05:37:59.731Z"
    }
}
```

```bash:コマンド
POLICY_ARN=$(aws iam list-policies \
    --max-items 1000 \
    --query "Policies[?PolicyName==\`${POLICY_NAME}\`].Arn" \
    --output text \
    ) && echo "${POLICY_ARN}"
```

```text:結果
arn:aws:iam::************:policy/ServicePolicyFirehose
```

### 作成したポリシーの確認

```bash:コマンド
aws iam get-policy \
    --policy-arn ${POLICY_ARN}
```

```json:結果
{
    "Policy": {
        "PolicyName": "ServicePolicyFirehose",
        "CreateDate": "2016-12-03T05:35:18Z",
        "AttachmentCount": 0,
        "IsAttachable": true,
        "PolicyId": "A********************",
        "DefaultVersionId": "v1",
        "Path": "/",
        "Arn": "arn:aws:iam::************:policy/ServicePolicyFirehose",
        "UpdateDate": "2016-12-03T05:35:18Z"
    }
}
```

### 変数の確認

```bash:コマンド
cat << ETX

    ROLE_NAME: ${ROLE_NAME}
    POLICY_ARN: ${POLICY_ARN}

ETX
```

```text:結果

    ROLE_NAME: service-role-firehose
    POLICY_ARN: arn:aws:iam::************:policy/ServicePolicyFirehose

```

### ポリシーをロールにアタッチ

```bash:コマンド
aws iam attach-role-policy \
    --role-name ${ROLE_NAME}\
    --policy-arn ${POLICY_ARN}
```

```text:結果
（返値無し）
```

### IAM Roleにポリシーがアタッチされたことを確認

```bash:コマンド
aws iam list-attached-role-policies --role-name ${ROLE_NAME}
```

```json:結果
{
    "AttachedPolicies": [
        {
            "PolicyName": "service-policy-firehose",
            "PolicyArn": "arn:aws:iam::************:policy/service-policy-firehose"
        }
    ]
}
```

以上