AWSのCDKでちょこちょこ使う細かいパターンのメモ

概要

AWSのCDKでちょこちょこ使う細かいパターンのメモ

IAMロールをインラインで用意するケース

ecr-accessという名前で、アクション'ecr:'、リソース''、許可の組み合わせで作成する例

import iam = require('@aws-cdk/aws-iam');

const myRole = new iam.Role(this, "MyRole", {
  assumedBy: new iam.ServicePrincipal('codebuild.amazonaws.com'),
  inlinePolicies: {
    'ecr-access': new iam.PolicyDocument({
      statements: [
        new iam.PolicyStatement({
          effect: iam.Effect.ALLOW,
          actions: [
            'ecr:*'
          ],
          resources: [
            '*'
          ]
        }),
      ],
    }),
  }
});

バケットへのアクセス用ロール(自アカウント利用版)

import cdk = require('@aws-cdk/core');
import s3 = require('@aws-cdk/aws-s3');
import iam = require('@aws-cdk/aws-iam');

const bucket = new s3.Bucket(this, 'MyBucket', {
  bucketName: 'bucket name here',
});

const myRole = new iam.Role(this, "MyRole", {
  assumedBy: new iam.AccountPrincipal(cdk.Stack.of(this).account),
  inlinePolicies: {
    's3-access': new iam.PolicyDocument({
      statements: [
        new iam.PolicyStatement({
          effect: iam.Effect.ALLOW,
          actions: [ 's3:GetObject*', 's3:GetBucket*', 's3:List*', 's3:DeleteObject*', 's3:PutObject*', 's3:Abort*' ],
          resources: [ bucket.bucketArn, bucket.bucketArn+'/*' ],
        }),
      ],
    }),
  }
});

CDKによるLambdaへのコードデプロイについて

概要

CDKを使ってLambdaにコードをデプロイする際のメモ(nodejs版)

説明

InlineCode版

  • ちょっとしたプログラムを手軽にセットする際に便利
  • 4096文字の制限があるので大作には向かない
  • 第一引数に流し込んだ文字列をindex.jsにしてくれる
  • nodejs12.xでは使えない(投稿時の確認では「Inline source not allowed for nodejs12.x」エラーが出る)
import lambda = require('@aws-cdk/aws-lambda');
import fs = require('fs');

new lambda.Function(this, "inlineExample", {
    ...
    code: new lambda.InlineCode(
        fs.readFileSync(`${__dirname}/inline-test/example-inline.js`, {encoding: "utf-8"})),
    ...
});

AssetCode版

  • 指定したパス以下をzip圧縮してアップロードしてくれる
  • 対象のパスにindex.jsを入れておく必要あり
    • index.jsを入れ忘れるとハンドラを定義していても「Runtime.HandlerNotFound: index.handler is undefined or not exported」になる(※index.jsである必要は無いが、ハンドラが別ファイルにある場合はhandlerを正しく設定してあげる必要あり、例えば「lambda/hello.js」に「exports.handler」の記述がある場合はhandlerに「lambda/hello.handler」をセットする)
import lambda = require('@aws-cdk/aws-lambda');

new lambda.Function(this, "assetExample", {
    ...
    code: new lambda.AssetCode(`${__dirname}/asset-test`),
    ...
});

vueのルートとなるパスを変更する方法

概要

vueはデフォルトで'/'をルートとして構成されるが任意のパスをルートとしてリンクが生成されるようにする際のメモ

やり方

vue.config.jsで下記のようにするだけ

module.exports = {
    publicPath: "/vroot",
};

こうすると http://localhost:8080/vroot がトップページになるようにリンクが構成される

公式ページにちゃんと書いてあった(検索キーワードが至らなく辿り着かなかった・・・)

cli.vuejs.org

ちなみにpublickPathを"./"にすれば相対パスになるので配置先のパスを気にしなくてよくなる。

AWSのlambdaが上手く動かない時のトラブルシュート(備忘録)

概要

lambdaをjavaで実装中に陥った多様な問題とその解決法を備忘録として記していく(都度追記する予定)

CloudwatchLogsにログが残らない場合

メモリ不足の可能性

  • 現象
    • Internal server error になる
    • CloudWatch Logs を確認すると、開始と終了のログしか残っていない状態
    • try-catchしているのにcatchに入らない場合
  • 可能性
  • 対応
  • メモ
    • ログには使用したメモリが表示されておりMAXを超えていないように見えたとしても、どうやら実行中に瞬発的に消費して落ちるケースがあるみたい

CloudwatchLogsにログが残る場合(例外が捕捉できる場合)

権限不足の可能性

  • 試行
    • まずはtry-catchして例外のメッセージを確認する
  • 可能性
    • 権限不足でアクセスできていない可能性がある
  • 対応
    • 必要な権限をlambdaの実行ロールに付ける

タイムアウトになっている場合

単純に処理時間が長い可能性

lambdaから接続先への通信経路が確立されていない可能性

  • 確認
    • 接続したいリソースはグローバルか?VPC内か?
      • VPC内の場合はルーティングテーブルに問題が無いか?
    • lambda自身はグローバル配置か?VPC内配置か?
      • VPC内配置の場合は配置しているサブネットは正しいか?

VPCの接点回りの料金メモ

概要

VPCにアタッチできる各種サービスの利用料のメモ
※2019年12月時点でのアジアパシフィックリージョンのもの

NATゲートウェイ

  • NAT ゲートウェイあたりの料金 (USD/時)
    • 0.062USD
  • 処理データ 1 GB あたりの料金 (USD)
    • 0.062USD

料金 - Amazon VPC | AWS

  • メモ
    • EIPを消費する
    • 指定したサブネットにENIが作成され、IPが消費される
    • ルートテーブルは自分で書き換える必要がありそう

ゲートウェイタイプの VPC エンドポイント

  • 無料!?
ゲートウェイタイプの VPC エンドポイントの使用に対するデータ処理料金や時間単位料金は発生しません。

料金 - Amazon VPC | AWS

  • メモ
    • ルートテーブルを書き換えなくても使える(内部DNSでやってる?)

AWS PrivateLink

  • 各 AZ の VPC エンドポイント 1 つあたりの料金 (USD/時間)
    • 0.014USD
  • 処理データ 1 GB あたりの料金 (USD)
    • 0.01USD

料金 - AWS PrivateLink | AWS

  • メモ
    • 指定したサブネット毎にENIが作成され、IPが消費される
    • ルートテーブルは自分で書き換える必要がありそう

AWSのユーザーに後からコンソールの利用を設定する方法

概要

AWSのIAMユーザーを作成する際、「アクセスの種類」で「プログラムによるアクセス」だけを選んで作成したが、後になってコンソールにもアクセスさせたくなった時の備忘録

やり方

  • AWSコンソールからIAMに遷移する
  • 左側の「ユーザー」を選択し、右側から任意のユーザーを選択する
  • 「認証情報」タブを選択し、「サインイン認証情報」から「コンソールのパスワード」項目の「管理」リンクをクリックする
  • 「コンソールへのアクセス」を「有効化」にすればOK

※この時、パスワードの自動生成など選択肢があるのでお好みに合わせて設定する

lambdaのテンプレートを使ってslackからlambdaを実行する

概要

lambdaのテンプレート「slack-echo-command」とslackのアプリ「Slash Commands」を使ってslackから任意のコマンドでlambdaを実行する
古い記事を参考にしていたら入力項目や工程が結構違っていたので自分用のメモとして

手順

AWSコンソールで鍵の作成(トークンの暗号化に用いる)

  • 「カスタマー管理型のキー」をクリックして「キーの作成」ボタンをクリックする
  • エイリアス」項目を入力して作成(途中、必要に応じて管理ロール等を設定する)
  • 作成が完了したら最初の一覧画面から「キーID」をメモしておく

AWSコンソールでlambdaの作成

  • 「関数」をクリックして「関数の作成」ボタンをクリックする
  • 「Serverless Application Repository の参照」を選択して「slack-echo-command」を検索し、「slack-echo-command」をクリックする
  • 「アプリケーションの設定」項目で「KeyIdParameter」にメモした「キーID」を入れて「デプロイ」ボタンをクリックする
  • CloudFormationでスタックが作成され各種リソースが自動的に作成されるので少々待つ(2~3分くらい)

SlackでSlash Commandsアプリの追加

  • Slackの設定ボタン(歯車のアイコン)をクリックして「アプリを追加」をクリックする
  • 検索で「Slash Commands」を入力して「インストール」ボタンをクリックする
  • 「コマンド」項目を任意の文字列で埋めておく(スラッシュで始まる必要がある)
    • この例では「/sayhello」とした
  • トークン」項目の文字列をメモしておく
  • 「URL」項目は未だ埋められないので「インテグレーションの保存」ボタンをクリックしてもエラーになるがそのまま放置して後行程へ

AWSコンソールでlambdaの設定

  • 「関数」をクリックして一覧から作成済みの関数をクリックする
  • 「Designer」項目でlambdaが選択されている状態にする(※デフォルトで選択されているはず)
  • 環境変数」項目の「暗号化の設定」項目を開き、「伝送中の暗号化のためのヘルパーの有効化」にチェックを入れ、「伝送中に暗号化する AWS KMS キー」に作成済みのキーを入れる
  • 環境変数」項目のテキストボックスでキーとして「kmsEncryptedToken」が既に入っている行の「値」の方に「Slash Commands」に表示されている「トークン」の値を入れ「暗号化」ボタンをクリックする
    • ちなみにこの行程はAWS CLIのKMSコマンドでencryptしたものを平文で設定する形でもOK(aws kms encrypt --key-id 暗号化に使う鍵のID --plaintext 暗号化したい文字列)
  • 画面最上部の右にある「保存」ボタンをクリックし、API Gatewayからデプロイを実行する
  • デプロイ時に生成されたURLをメモしておく

SlackでSlash Commandsアプリの設定を完成させる

  • メモしたデプロイ先のURLに「/MyResource」を付けたものを「Slash Commands」設定の「URL」項目に入力して「インテグレーションの保存」ボタンをクリックする
  • ※デプロイ先はルートを表している場合が多いので必ず「/MyResource」で終わっているか確認すること

Slackで試してみる

  • 任意のチャネルで「/sayhello aiueo」を送信すると「miya15 invoked /sayhello in directmessage with the following text: aiueo」が返ってくる

連携パラメータについて

プログラムを見ると下記のパラメータを使えるようなので、組み合わせて色々な処理を実行させられそう

  • params.user_name (ex. miya15)
  • params.command (ex. /sayhello)
  • params.channel_name (ex. directmessage)
  • params.text (ex. aiueo)