daiphone’s blog

AWS / JavaScript / Docker / PHP / Python を中心とした技術ネタと、趣味少々

AWS Fargate環境下のLaravelでIAMロールを利用しSESを利用する方法

Summary

  • IAMロールはアクセスキーを発行するよりセキュアである
  • Fargateの場合タスク定義のタスクロールに利用したいリソースのポリシーを設定する
  • aws-sdkだけでなく、aws-sdk-php-laravelをinstallしておく
  • Laravelに記載している環境変数及び環境変数を参照しているプログラムはコメントアウト

ToC

  • Why IAM Role?
  • Attention to setting IAM Role
  • How to setting on AWS Fargate
  • How to reference IAM Role on Laravel

Why IAM Role?

単純にセキュアだからです。

一般的な方法として用いられるIAMユーザーを作成してそのユーザーに対してアクセスキーを生成する方法は、簡単なのですが、アクセスキー漏洩のリスクが伴います。

万が一アクセスキーが漏洩し、そのキーの権限がadministratorと同じ場合、AWSアカウントを乗っ取られたのと同じくらいのインシデントになります。

前職の別プロジェクトの開発者が、アクセスキーを誤ってGitHubに公開してしまい見事に乗っ取られ、仮想通貨マイニング用のインスタンスを20台くらい建てられて数十万の請求をされてました。

そのくらいアクセスキーは慎重に扱わないといけない代物です。

アクセスキーを用いる場合は以下に気をつければ最低限のセキュリティリスクは回避できます。

  • GitHubに挙げない → 当たり前
  • 環境変数に設定する
  • AWSのパラメータストアを利用する

それでも以下リスクは残ります。

  • 開発環境で利用するアクセスキーを誤ってブログに載せてしまう
  • Slack等で他者に共有してしまう
  • アクセスキーのメモをローカルや貸与PCに保管してしまう

上記リスクも避けるためには、そもそもアクセスキーを利用しない方法がベストです。

IAMロールを付与すれば、付与されたAWSサービス内でしか設定したポリシーの権限を利用できません。

また、当たり前ですがプログラムにIAMロールに関する情報を記載する必要がないため漏洩のリスクはありません。

※あるとしたら直接対象のインスタンス等にsshアクセスされてしまって利用されるケースですが、これはまた別の話。

いちいちIAMユーザーの管理をする必要もないのでその点もメリットかと思います。

Attention to setting IAM Role

簡単にまとめますが、以下になります。

  • 最低限の権限を付与する
    • resources → 利用したいAWSサービスのリソースを明示的に指定(*等はなるべく利用しない)
    • action → ロールを適用するAWSリソースが利用するactionのみを指定(フルアクセス等はやめる)
  • 複数のポリシーを組み合わせる
    • 一つのポリシーに大きな権限を渡すと、使い回しがしにくい
    • ポリシーをシンプルにしておくことで、他のリソースに対しても利用できる(ポリシーの管理がしやすい)

How to setting on AWS Fargate

タスク定義の設定における「タスクロール」に利用したいポリシーを定義する

個人的にタスク実行ロールとタスクロールの違いを理解するのに時間がかかりましたが、結論タスクロールに付与する形で問題ないです。

違いは以下です。

タスク実行ロール

Fargateタスクを実行するためのロール

例) タスク定義で設定されているECRイメージを参照する権限を付与 タスクを実行する際に発生するログを出力する権限を付与 etc...

タスクロール

実行されたタスク内のサービスに付与するロール

例) タスク内のプログラムからメール送信するためのSESを利用する権限を付与 ファイルアップロードするためのS3へのアクセス・アップロード権限を付与 etc...

How to reference IAM Role on Laravel

まとめると以下の流れです。

aws-sdk-php-laravelをinstall

通常aws-sdk-phpで事足りるのですが、利用したいAWSサービスによっては、aws-sdk-phpのみだとNGらしいのでinstallしてください。

install及び初期設定方法は以下参照してください。

https://github.com/aws/aws-sdk-php-laravel

環境変数を削除

ここかなりハマりました…

原因の切り分けがうまくできておらず、IAMロールを定義したのに、403エラーが出続けていました。

Laravelの場合、デフォルトだとアクセスキーの設定を.envに記述すると思うのですが、そもそも.envにアクセスキーの環境変数名が存在するだけで

Laravelは.envのみを参照しエラーになります。

ですので、.envにある環境変数名は削除かコメントアウトしてください。

※ちなみに、リソースによっては環境変数名を削除するのではなくnullを指定する必要があると書いてる記事もありますので、利用するリソースがどこで参照されているかを理解して置く必要があります。 ※例えばS3の場合config/filesystems.phpで認証情報を参照するのですが、その際は環境変数の値をnullにすればいいそうです。(未検証)

config/aws.php, config/service.phpのcredentials指定箇所を削除

最後の仕上げです。

環境変数を削除したので、当然環境変数を参照している箇所を削除しないとえらーになります。

今回はSESを利用するための設定変更のため、以下2ファイルの該当箇所を削除します。(※コメントアウトの箇所が該当箇所です。)

config/aws.php

/*
|--------------------------------------------------------------------------
| AWS SDK Configuration
|--------------------------------------------------------------------------
|
| The configuration options set in this file will be passed directly to the
| `Aws\Sdk` object, from which all client objects are created. This file
| is published to the application config directory for modification by the
| user. The full set of possible options are documented at:
| http://docs.aws.amazon.com/aws-sdk-php/v3/guide/guide/configuration.html
|
*/
// 'credentials' => [
//     'key'    => env('AWS_ACCESS_KEY_ID', ''),
//     'secret' => env('AWS_SECRET_ACCESS_KEY', ''),
// ],
'region' => env('AWS_DEFAULT_REGION', 'ap-northeast-1'),
'version' => 'latest',
'ua_append' => [
    'L5MOD/' . AwsServiceProvider::VERSION,
],

config/service.php

 /*
|--------------------------------------------------------------------------
| Third Party Services
|--------------------------------------------------------------------------
|
| This file is for storing the credentials for third party services such
| as Mailgun, Postmark, AWS and more. This file provides the de facto
| location for this type of information, allowing packages to have
| a conventional file to locate the various service credentials.
|
*/
'mailgun' => [
    'domain' => env('MAILGUN_DOMAIN'),
    'secret' => env('MAILGUN_SECRET'),
    'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'),
],
'postmark' => [
    'token' => env('POSTMARK_TOKEN'),
],
// 'ses' => [
//     'key' => env('SES_KEY'),
//     'secret' => env('SES_SECRET'),
//     'region' => env('SES_REGION'),
// ],

Conclusion

これでようやくIAMロールを活用して他のAWSサービスを利用する権限を付与することができました。

アクセスキーの漏洩リスクもないし、アクセスキーをデプロイ時に対象イメージ内に記載する処理を追加する必要もないので、非常にセキュアだと思います。

ぜひ皆さんもIAMロールを活用してセキュアなAWSライフを。

【2020年最新版】Facebookが乗っ取られた場合の対処法

はじめに

先日、複数の友人からFacebook Messangerでこのようメッセージが送られてきました。

f:id:daiphone0228:20200725181830p:plain:h500
明らかに怪しい日本語訳…

はい、勘の良い方はおわかりですよね。

これはいわゆるスパムメッセージです。

動画をタップすると、ログイン情報の入力を促され、そこに入力してしまうと、その情報を抜かれる仕組みだと思います。(詳細は不明、あくまでも推測です。)

友人はこれに気づいていなかったようで、一応連絡することにしました。

すると、「対処法がわからないので、どうしたらいいか教えてほしい」と返信がきました。

曲がりなりにもIT業界に属している身ではあるので、ITリテラシーは最低限あると自負しております。

ということで、対応方法を簡単にまとめて送ってあげました。(と言ってもググった情報まとめただけ)

今回は、その際にまとめた手順を書き起こしたいと思います。

対象者

- Facebookアカウントが乗っ取られたかもしれないと感じている方
- 乗っ取られていないが、今後の対策としてやっておきたい方
- Facebookのアカウント情報を利用して、他のサービス等にログインしている方
- 二段階認証って何?やる意味あんの?って方

注意事項 ※これ重要!!

今回の対応をしたことで、乗っ取られたアカウントが100%安全であるという保証はございません。

仮にこの対応後にも被害が続いたとしては、責任は負いかねますのでご了承ください。

不安でしたら、アカウントを完全に削除する方が安全だと思います。

ただ、それでも友人とのつながりや、思い出を残しておきたいという方は、以下実践してみてください。

万が一、メッセージの動画を開いてしまった方は、様々な情報が抜かれる前に、なる早で下記対応をすることをおすすめします。

何が怖いってシングルサインオンで他のサービス利用できちゃうから、影響範囲が広いのなんの…

確認事項

確認事項としては、以下になります。

  1. 二段階認証の設定有無
  2. 不審なログイン履歴を確認

二段階認証とは

簡単に説明すると、ログインの際に、ログインIDとパスワードだけでなく、自分が登録したデバイススマホ等)に送られてくるトークンを入力することで、本人という確認ができ、ログインが可能になるという仕組みです。

こちらが有効になっていれば、ログインIDとパスワードが第三者の手に渡ったとしても、不正にログインされる心配はございません。

さすがにスマホを物理的に盗むということをしない限りログインができませんからね。

不審なログイン履歴

アクティブなデバイスを閲覧することで、不審なログイン履歴があるか確認できます。

アクティブなデバイスとは、現在Facebookでログインしているデバイスを意味します。

例えば、スマホFacebookを利用し、ご自宅のPCでもFacebookを利用している場合、アクティブなデバイスは2つになります。

仮にログイン情報が漏れた場合、悪意のあるユーザが別のデバイス等からあなたのアカウントにログインして、個人情報等を抜き出す可能性があります。

アクティブなデバイスを限定(例えば自分のスマホのみ)できれば、それ以上悪さをさせないようにできます。

対応の流れ

  • 二段階認証を設定
  • アクティブなアカウントを削除

なお、今回の操作端末はiPhoneになりますが、AndroidでもPCブラウザでも同様の設定変更ができます。

二段階認証設定

まず初めに2段階認証の設定を行います。

※仮に二段階認証がすでに設定されている場合は、この章を飛ばしていただいて結構です。

  1. Facebookアプリ開いて、設定画面に移動

    f:id:daiphone0228:20200725181942p:plain:h500
    設定画面に移動

  2. 「設定とプライバシー」 > 「プライバシーセンター」をタップ

    f:id:daiphone0228:20200725182025p:plain:h500
    プライバシーセンターをタップ

  3. 「二段階認証を使用」をタップ

    f:id:daiphone0228:20200725182051p:plain:h500
    二段階認証を使用をタップ

  4. 「SMSを使用」をタップ

    f:id:daiphone0228:20200725182150p:plain:h500
    認証アプリがある場合は、そちらを使用しても構いません。

  5. 自分の電話番号を選択

    f:id:daiphone0228:20200725182220p:plain:h500
    現在使用中の電話番号が無難ですが、他の電話番号でも可能です

  6. SMSでメッセージが届くので、そのコードをFacebookアプリの入力欄に入力

    f:id:daiphone0228:20200725182313p:plain:h500
    メッセージが届く

  7. 完了

    f:id:daiphone0228:20200725182349p:plain:h500
    「二段階認証がオンになっています」とでれば完了

不審なログイン履歴を削除

次に、ログイン履歴に不審なデバイスがあるか確認し、あれば削除します。

  1. 先ほどと同じ設定画面に移動

    f:id:daiphone0228:20200725182601p:plain:h500
    設定画面に移動

  2. 「設定とプライバシー」 > 「設定」をタップ

    f:id:daiphone0228:20200725182620p:plain:h500
    「設定」をタップ

  3. 「セキュリティとログイン」をタップ

    f:id:daiphone0228:20200725182649p:plain:h500
    セキュリティとログインをタップ

  4. ログインの場所欄にある「すべて見る」をタップ

    f:id:daiphone0228:20200725182716p:plain:h500
    マスキングしている部分にデバイスの種類と位置情報が記載してあります

  5. ログイン一覧が見れる

    f:id:daiphone0228:20200725182807p:plain:h500
    不審なものを選択

  6. 不審なログインがあったら、それをタップし、「ログアウト」をタップ

    f:id:daiphone0228:20200725182844p:plain:h500
    ログアウトを選択すれば強制的にそのデバイスからログアウトされます

  7. 完了

これで安心…というわけではありません。

設定と確認自体は、これで終了です。

しかし、油断は禁物です。

Facebookの乗っ取りは以前からよく話題に上がってましたが、おそらくこれらの設定をしたとしても、セキュリティをかいくぐるような巧妙な乗っ取り手口がどんどん出てくると思います。

今後は不審なメッセージを受信したときは、慌てて開かず、別のSNS(LINE等)を使って、送信元の友人に確認してみるといいかもしれませんね。

あとは、twitter等には似たような被害にあった人がツイートしている可能性が高いので、そこで調べてみるのもいいかと思います。

調べて似たような内容なら、開かず友人に伝えてあげると親切かと思います。

今後の対策

SNSを通じた個人情報の漏洩は、日常的に発生していると思っていいでしょう。

自分のアカウント情報が漏洩することで、他の友人の情報も漏洩する危険性があることを認識して、対策を講じていきましょう。

基本的な対策として以下を心がけると良いでしょう。

- 不審なメッセージは開かない
- 下手に個人情報は載せない
- 別のデバイス(例えば、大学や会社のPC等)でログインをした場合、ちゃんとログアウトする
- そもそも使用頻度の低いアカウントは削除する

おわりに

最近は社内のブログの更新に頭がいってしまい、プライベートのブログはサボりがちです…。

久々に書いたブログが、全然技術に関係ないことで恐縮ですが、どなたかのお役に立てれば幸いです。

WindowsとMacで同じDockerfileを扱うなら、改行コードに気をつけよう

はじめに

社内でWindowsユーザーとMacユーザーがいるプロジェクトなんてよくありますよね。

それぞれで環境も異なるので、開発環境の整備には苦労すると思います。

そんな時にはDocker。

Dockerコンテナで構築する分、それぞれの環境に左右されないし、本番環境へもそのまま利用できる。非常に素晴らしい。

でもそんな環境に依存しないDockerでも気をつけなきゃいけない点がありました。(今回の事象以外にも気をつける点はあると思いますが、経験したことのみ取り上げます。)

前提

自身のMacで開発環境用のDockerfileを作成し、他のメンバーにGitHubで共有していました。

Dockerコンテナ環境

OS: AmazonLinux2
Middleware: Apache 2.4
Language: PHP 7.3
Framework: Laravel
FrontFramework: Vue.js

ディレクトリ構成

project_root
├── README.md
├── docker_directory
│   ├── app
│   │   ├── Dockerfile
│   │   └── entrypoint.sh
│   ├── db
│   │   ├── Dockerfile
│   │   └── conf.d
│   └── docker-compose.yml
└── appliation_directory
    └── src

発生した事象

macOS

# Dockerコンテナ立ち上げる
$ docker-compose up

# Dockerプロセス確認
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
854b4b49d0c5        laravel             "/etc/entrypoint.sh"     6 minutes ago       Up 6 minutes        0.0.0.0:8080->80/tcp     laravel
ee51d4979580        laravel_mariadb     "docker-entrypoint.s…"   6 minutes ago       Up 6 minutes        0.0.0.0:3306->3306/tcp   laravel_mariadb

# 問題ないのでリモートリポジトリにpush
$ git push origin develop

Macではうまくいきました

windowsOS

# macユーザーがpushしたDocker関連のリポジトリをclone
$ git clone

# Dockerコンテナ立ち上げる
$ docker-compose up

# Dockerプロセス確認
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                          PORTS                    NAMES
9b9c7a807748        laravel             "/etc/entrypoint.sh"     3 minutes ago       Restarting (1) 17 seconds ago                            laravel
ff482021b19c        laravel_mariadb     "docker-entrypoint.s…"   3 minutes ago       Up 3 minutes                    0.0.0.0:3306->3306/tcp   laravel_mariadb

ん?

なぜかWindows環境ではlaravelコンテナのみ立ち上がらない…

処理を見てると、Dockerfile内の記述は問題なく成功しているようだ

ということは…Dockerfileの末尾に指定してるCMDコマンドが原因か?

Dockerfileを変更

$ vim Dockerfile
# 変更前
~
CMD ["/etc/entrypoint.sh"]

↓

# 変更後
~
CMD ["/usr/sbin/httpd", "-DFOREGROUND"]

もう一度試す

# Dockerコンテナ立ち上げる
$ docker-compose up

# Dockerプロセス確認
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
9422f7299f27        laravel             "/usr/sbin/httpd -DF…"   22 seconds ago      Up 21 seconds       0.0.0.0:8080->80/tcp     laravel
ee51d4979580        laravel_mariadb     "docker-entrypoint.s…"   8 minutes ago       Up 8 minutes        0.0.0.0:3306->3306/tcp   laravel_mariadb

立ち上がった!

原因

原因は2つありました。

  • CMDコマンドの記述をする際、shell scriptを起動するコマンドを省略していた
  • windows環境にcloneした際に、改行コードがwindowsのCRLF形式に変わってしまっていた。

解決方法

CMDコマンドの記述

Macではshell scriptを./hoge.shのように、記述してもちゃんと起動してくれます。

しかしWindowsでは上手く動かないみたいですね。

ということで以下のように修正

CMD ["/etc/entrypoint.sh"]
↓
CMD ["/bin/bash", "/etc/entrypoint.sh"]

改行コード

.gitattributesファイルは、名前の通り対象gitプロジェクトの属性を指定するファイルです。

ここに改行コードを指定しておくことで、どのホストPCにcloneしてきても、改行コードは統一されます。

今回は対象DockerコンテナがAmazonLinux2だったため、Linuxの改行コードであるLF形式を指定します。

プロジェクトルートに.gitattributesを追加し、以下を記述

$ vim .gitattributes
~
* text=auto eol=lf

:wq

まとめ

調べてみると、本当に初歩的な内容でした。。。

こういった基本的なことをしっかり覚えていき、円滑なプロジェクト運営を行っていきたいと思います。

AWSのCLIによるMFA認証を対話形式のshellで半自動化してみる

はじめに

前回の投稿に引き続き、AWS CLI関連です。 bonjourdaiphone.hatenablog.com

毎回「token取得」→「環境変数にセット」とするのが面倒だったので、 shell scriptで実装してみました。 今回は対話形式にしてみました。

Code

#!/bin/bash
# sh ./InteractiveAwsMfaAuthorization

# start program
echo "Please input your accountId"
read accountId
echo "Please input your userName"
read userName
echo "Please input token code for authentication"
read tokenCode
json=`aws2 sts get-session-token --serial-number arn:aws:iam::$accountId:mfa/$userName --token-code $tokenCode`

echo "set to variables"
AWS_ACCESS_KEY_ID=`echo $json |jq -r '.Credentials.AccessKeyId'`
AWS_SECRET_ACCESS_KEY=`echo $json |jq -r '.Credentials.SecretAccessKey'`
AWS_SESSION_TOKEN=`echo $json |jq -r '.Credentials.SessionToken'`

echo "\n------ Please confirm your environment vriable ------"
echo $AWS_ACCESS_KEY_ID
echo $AWS_SECRET_ACCESS_KEY
echo $AWS_SESSION_TOKEN

echo "\n------ Please input these commands below if you are using bash. ------"
echo "export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID"
echo "export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY"
echo "export AWS_SESSION_TOKEN=$AWS_SESSION_TOKEN"

echo "\n------ Please input these commands below if you are using fish. ------"
echo "set -x AWS_ACCESS_KEY_ID $AWS_ACCESS_KEY_ID"
echo "set -x AWS_SECRET_ACCESS_KEY $AWS_SECRET_ACCESS_KEY"
echo "set -x AWS_SESSION_TOKEN $AWS_SESSION_TOKEN"

実行方法

こちらのshell scriptを任意の場所に置き、実行します。

$ sh ./InteractiveAwsMfaAuthorization.sh
Please input your accountId
-> 012345678901  #AWSのアカウントID
Please input your userName
-> hogehogeuser  #ログイン用ユーザーID
Please input token code for authentication
-> 123456  #MFA Code
set to variables

------ Please confirm your environment vriable ------
AWS_ACCESS_KEY_ID= FTGYHUIJRFTGYHU
AWS_SECRET_ACCESS_KEY= seyufuaiefjadufhufeufaef67
AWS_SESSION_TOKEN= feyufasjiHFUiFJIFjoejfesjfhfdfhuseufsfybfujsfa//////////fweufuah4wkfhu4efeuafhk4ggalifja;f'ag9ejgautfybunckmscaffds

------ Please input these commands below if you are using bash. ------
export AWS_ACCESS_KEY_ID=FTGYHUIJRFTGYHU
export AWS_SECRET_ACCESS_KEY=seyufuaiefjadufhufeufaef67
export AWS_SESSION_TOKEN=feyufasjiHFUiFJIFjoejfesjfhfdfhuseufsfybfujsfa//////////fweufuah4wkfhu4efeuafhk4ggalifja;f'ag9ejgautfybunckmscaffds

------ Please input these commands below if you are using fish. ------
set -x AWS_ACCESS_KEY_ID FTGYHUIJRFTGYHU
set -x AWS_SECRET_ACCESS_KEY seyufuaiefjadufhufeufaef67
set -x AWS_SESSION_TOKEN feyufasjiHFUiFJIFjoejfesjfhfdfhuseufsfybfujsfa//////////fweufuah4wkfhu4efeuafhk4ggalifja;f'ag9ejgautfybunckmscaffds

出力されたコマンドをお使いのshellに合わせた形で実行し、環境変数をセットする。

確認

$ set -x AWS_ACCESS_KEY_ID FTGYHUIJRFTGYHU
$ set -x AWS_SECRET_ACCESS_KEY seyufuaiefjadufhufeufaef67
$ set -x AWS_SESSION_TOKEN feyufasjiHFUiFJIFjoejfesjfhfdfhuseufsfybfujsfa//////////fweufuah4wkfhu4efeuafhk4ggalifja;f'ag9ejgautfybunckmscaffds

$ aws2 ec2 describe-vpcs
{
    "Vpcs": [
        {
            "CidrBlock": "xxx.xx.x.x/16",
            "DhcpOptionsId": "dopt-xxxxxxx",
            "State": "available",
            "VpcId": "vpc-xxxxxxx",
            "OwnerId": "123456789012",
            "InstanceTenancy": "default",
            "CidrBlockAssociationSet": [
                {
                    "AssociationId": "vpc-cidr-assoc-xxxxxxxx",
                    "CidrBlock": "xxx.xx.x.x/16",
                    "CidrBlockState": {
                        "State": "associated"
                    }
                }
            ],
            "IsDefault": true
        }
    ]
}

無事取得できてますね。

補足

なぜ対話形式か?

最初はshell scriptに引数として、accoutId等をつけて実行していましたが、そうすると、historyに残ってしまうため、安全面を考慮して対話形式にしました。

あとは、みんなに配布する際に理解しやすいかなと思って。笑

個人でやるなら、変数に格納するコマンドをどこかにコピペしといて、毎回tokenCodeだけ変更する形でもいいと思います。

まあ結論、好みですね笑

環境変数にセットする部分もshell scriptファイル内でできるのでは?

ご存知の方もいると思いますが、shell script内で環境変数にセットすると

スコープがそのファイル内になってしまうため、ファイルの処理がすべて終了すると、

セットした環境変数は消えます。

直接shellの設定ファイル(.bash_profile等)を書き換えるのもありですが、その部分は人によってまちまちだと思ったので

今回は含んでおりません。

まとめ

最近インフラを触るようになってきて、コマンドを叩いてアレコレする機会が増えました。

shell scriptで自動化することを試したい気持ちもあったのですが、他のブログを見てみると、Pythonでshellを叩いて自動化したりしてるみたいですね。

今回はshell scriptで実装しましたが、今後はPythonでやってみようかなと思います。

AWSでMFA設定が有効なIAMユーザーを使って、CLI経由でリソースにアクセスする方法

はじめに

AWSを本格的に使い始めてもうすぐ1年が経とうとしています。

気づけば、資格を取り、気づけば社内の担当プロジェクトの環境構築をやり、気づけばインフラ全体の整備を任されるところまできました。

最近転職した会社でも、その部分の知見を買われて入社したため、

より知識を深めていかなければと日々奮闘してます。

背景

新たな会社での最初の使命は、インフラ環境の整備でした。

私の会社はインフラ整備が行き届いていなかったため、多くの課題がありました。

課題

  • AWSのベストプラクティスに則っていない
  • 開発者が研究開発用で使うアカウントが存在しない
  • 管理者権限を持つIAMユーザーを共用している
  • IAMユーザーが個々に割り振られていない
  • アプリケーション開発におけるテンプレート構成が存在しない
  • etc...

これらを解決することが私の一つの使命でした。

そのような現状を調べるために、aws cliでアクセスしようとしたところ、

$ aws2 ec2 describe-vpcs
An error occurred (UnauthorizedOperation) when calling the DescribeVpcs operation: You are not authorized to perform this operation.

???????????

アクセスができない!

実は、自身のIAMユーザー作成の際に、MFA認証がされていないセッションからのアクセスは禁止するポリシーを付与していたんです。

面倒だけど、セキュリティを担保する上では必要なので、IAMユーザー側の設定を変更せずに、またCLI用のIAMユーザーを別で作成せずに、解決できる方法を探してました。

先に答え知りたい人向けtips

aws2 sts get-session-token \
    --serial-number arn:aws:iam::{AccountID}:mfa/{LoginUserId} \
    --token-code {TokenCode}

"{}"内をよしなに変更すると、認証可能なアクセスキー等が出力されますので

それを環境変数にセットして通常通りコマンド叩けば完了です。

そもそもMFA設定とは?

多段階認証(Multi-Factor Authnetication)のことです。

詳細はこちら→ wiki

MFA設定しているとCLIが使えない?

MFAを設定していると、各セッションごとに認証が必要になってくるので、

CLIを認証せずにそのまま叩こうとするとエラーになります。

$ aws2 ec2 describe-vpcs
An error occurred (UnauthorizedOperation) when calling the DescribeVpcs operation: You are not authorized to perform this operation.

通常ブラウザでAWSマネジメントコンソールにアクセスして、プライベートウィンドウを開いて再度アクセスした際に、

ログインが必要になるのと同じ原理ですね。

セッションが違うので。

ならばどうする

CLIからTokenCodeを送って、一時的な認証キーを取得します。

認証キー取得

$ aws2 sts get-session-token \
    --serial-number arn:aws:iam::123456789012:mfa/hogehogeuser \
    --token-code 999999
{
    "Credentials": {
        "AccessKeyId": "FTGYHUIJRFTGYHU",
        "SecretAccessKey": "seyufuaiefjadufhufeufaef67",
        "SessionToken": "feyufasjiHFUiFJIFjoejfesjfhfdfhuseufsfybfujsfa//////////fweufuah4wkfhu4efeuafhk4ggalifja;f'ag9ejgautfybunckmscaffds",
        "Expiration": "2020-01-18T18:27:03+00:00"
    }
}

取得した認証キーを環境変数にセットする

bashの場合

#!/bin/bash

export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID
export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY
export AWS_SESSION_TOKEN=$AWS_SESSION_TOKEN

fishの場合

#!/usr/local/bin/fish
set -x AWS_ACCESS_KEY_ID $AWS_ACCESS_KEY_ID
set -x AWS_SECRET_ACCESS_KEY $AWS_SECRET_ACCESS_KEY
set -x AWS_SESSION_TOKEN $AWS_SESSION_TOKEN

動作確認

VPCを取得するコマンドを叩いてみます。

$ aws2 ec2 describe-vpcs
{
    "Vpcs": [
        {
            "CidrBlock": "xxx.xx.x.x/16",
            "DhcpOptionsId": "dopt-xxxxxxx",
            "State": "available",
            "VpcId": "vpc-xxxxxxx",
            "OwnerId": "123456789012",
            "InstanceTenancy": "default",
            "CidrBlockAssociationSet": [
                {
                    "AssociationId": "vpc-cidr-assoc-xxxxxxxx",
                    "CidrBlock": "xxx.xx.x.x/16",
                    "CidrBlockState": {
                        "State": "associated"
                    }
                }
            ],
            "IsDefault": true
        }
    ]
}

無事取得できてますね。

補足

今回のユーザーは「MFAの認証が通っていないとリソースへのアクセスができませんよ」という

ポリシーを独自に付与していたため、このような状況になりました。

通常のポリシーではこのようなことは発生しないと思いますので、必要に応じて利用する形でいいでしょう。

AWSコマンドって便利

AWSを利用していると、CLIを利用してリソースに対して変更を行ったりする機会が増えていきます。

やっぱりこちらのほうがシンプルで簡単なんですよね。

あと、手順をCode化できるし。

GUIでやると、細かい部分の手順が抜けてしまい、再現性が低くなってします。

もちろん最初からCLIでやろうとしても、このコマンドの意味は?とか、

オプションの必要性の有無等、考慮する点が多いので、少しハードルは高いかもしれません。

あと、権限によっては、一瞬で全インスタンス削除とかできちゃいますしね笑

GUIでリソースの基本的な利用方法に慣れる
↓
何度もマネジメントコンソールにアクセスするの面倒だと感じる
↓
やりたい処理をCLIで書き起こす
↓
応用

こんな感じでやっていくと、効率よく学習できると思います。

今、学びたいこと

はじめに

※ほぼ個人的な備忘録になっているので読みたい人だけ読んでください。笑

よく休日に個人で黙々とPCをいじり、いろんな技術情報を探すと、必ず思うことがあります。

「あ、これ試してみたいな。」

こう感じたときに、必ず出てくるのが環境構築の手間ですよね。

まあこれはエンジニアにとっては当たり前のことなのだが、 なるべくこの手間をなくしたいと常に考えております。

そんな試行錯誤していた毎日の中、私は今まで下記のような技術を学んできました。

今まで学んできたこと

※今回はインフラ寄りの技術にフォーカスしてます。

これらの技術を学ぼうとした経緯について、なぜその技術を必要としたのかという観点から話したいと思います。

Ansible

忘れもしない、エンジニア1年生の自分。

レンタルサーバ借りてなにかしたいな」 「VPSサーバ?よくわからんけど契約してみよう」 「試しにWordpressでブログ作ってみるか…」 「環境構築上手くいかない」 「もう一回作り直すか」 「上手くいかない…」 「壊すか」 「また1から作るのめんど…」

当時の私は、ひたすらググってコマンドを叩いて実現させるだけでも精一杯だったので 再現性については全く考えていなかった。

するとどうだろう。何が原因で動かないのかがわからない上に、今まで自分が叩いたコマンドも把握できていなかった。

そこでAnsibleと出会った。

「手順をCode化する = 自分が行った手順を忘れずに管理できる」という点が非常に魅力的だった。

(もっと本質的なメリットがあるが、自分が感じたのは、上記であった。)

AWS

「アプリケーションの開発に関しての知識は少しづつついてきたけど、サーバー・ネットワーク周りはよくわからないな…」 「AWSはそれらをフルマネージドでやってくれるのか、そこから学べば理解しやすいかも」 「目標にもなるし、まずは資格取るか」

私がインフラ寄りの技術を本気で学びたいと思い立ったのは、AWSを学び始めたからだ。 本来IaaSに依存しない形で技術を習得するのがベストだと思うが、 「基本的な技術は知ってるけど、このサービス上での利用方法は知らない」じゃ話にならないので、 まずはサービスや機能が多く、利用者が多いため情報が豊富なAWSを学びたいと思った。

AWSを利用し始めたきっかけも、業務で必要になったからなのだが、その中で自分が学びたいと感じた動機は、 インフラ周りの理解をせずにエンジニアを名乗っている自分に自信が持てなかったからだ。

AWSを学び始めたことで、モダンな開発を行う意識がより強くなった。 流れとしては以下である。

  • AWSを学び始める
  • リソースに関して必要な知識をつける
  • その知識に関連する技術を学ぶ
  • それらがモダンな技術だと知る
  • 技術的な理解をした状態で、AWSのリソースを利用して求められたソリューションを提供する

Docker

「この技術試してみたいな…」 「でもVPSサーバは別で使ってるし、EC2インスタンスは無料枠で収まるよう管理するの面倒だしな…」 「かといってLocal環境を汚したくないし…」 「ふむふむ、Dockerを使えばLocalに独立した環境が作れるし、再構築も簡単だし、完成した環境はクラウドで管理できるのか…求めてやつ、これじゃん!」

業務で必要になったのがきっかけであったが、現在のクラウドネイティブなアプリケーション開発を行う上で、必須になってくる知識だと感じたため学ぼうと決意。 現時点で完璧に使いこなしているわけではないが、AWS Fargateを用いたアプリケーションの環境構築をした経験があるので、ある程度は抵抗なく触れられるという自負はある。

しかし、より個人に特化した開発環境を作る上で、重要になってくる部分であると思うため、今後も学び続けていきたい技術の一つである。

Kubernetes

「Dockerに関しては少しづつ知識ついてきたぞ…」 「Kubernetesは難しそうだから一旦避けよう…」 今の会社:「Kubernetes使って運用管理するから、勉強しといてね」 「ついにきたか…!!!!」 ← イマココ

Dockerを学ぶと必然的に次のステップとして学ぶべき技術であろうKubernetes。 無意識に敷居が高いと感じてしまい触れていなかったのだが、 コンテナ開発基盤をよりスケーラブルに管理できるので、学ぶべき技術である。

実際にオーケストレーションツールとしての利用を考えたときに、各IaaSによってはKubernetesを利用しなくてもある程度同様のことはできると思う。 しかし、各IaaSへの依存度が高くなってしまうと、別のIaaSに移行するときのコストが高く付く恐れがある。

その点、KubernetesはそれぞれのIaaSで準拠された形でサービスが展開されているため、Kubernetesを学べば汎用的な知識を学べると考えている。

今、学びたいこと

結論から言うと、インフラ周りの知識をより深めたいです。

もちろんサーバーサイドのモダンなフレームワークやらフロントエンドの新しい技術やら機械学習に関しての記事やら気になるところは沢山ある。 でも、それらを試す環境が作れないんじゃ、読んで終わりになってしまう。 「へーそんなのあるんだー(棒」 で終わってしまっては、せっかく知り得た情報が無駄になってしまう。 アウトプットという意味でもまずは、実践あるのみだと思う。

誰かが用意した環境をそのまま使う(docker imageとか)のは個人的に好きではない。 理解していない技術を使っている自分にもやもやするからだ。

よって、根幹となる環境構築の知識をつけるのが今年の目標の一つである。

まっさらなサーバーやLocalに構築するイメージでいくと以下になる。

  • AnsibleでDocker環境を構築できる
  • アプリケーション実装に必要なモジュールをDocker内で用意できる
  • それらのコンテナをKubernetesで管理する(ここに関してはまだ知識不足のため保留)
  • 最終的に自分の構築した環境をAWSに展開して正常に動作するか確認

終わりに

つらつらと書いてきましたが、常にイメージしているゴールはこれである。

環境構築からサービスデプロイまで自身で一貫してできるようになる 自信を持ってフルスタックエンジニアと名乗れるようになる

今年から新しい会社に転職した結果、AWS周りの知識を使うことが多くなりました。 肩書はなんとフルスタックエンジニアです。

その名に恥じないように、日々精進していきたいと思います。

初投稿

あけましておめでとうございます。

ずーっと始めよう、始めようと思っていて、躊躇していたBlogを始めることにしました。

outputが目的なので、主に以下のトピックで投稿していきます。

Programming
English
Others

なるべく継続できるように最初は軽めに、ぬるっとやっていきます。