Using AWS ECR with Spinnaker and Kubernetes – The Spinnaker Community Blog

Using AWS ECR with Spinnaker and Kubernetes – The Spinnaker Community Blog. Build & Release Engineer @Skuidify. Automating deployments to Kubernetes & Salesforce. Using AWS … 続きを表示. Build & Release Engineer @Skuidify. Automating deployments to Kubernetes & Salesforce. 続きを読む

Rancher2.0 Tech Preview2 ~Create a RKE Cluster~

Rancher2.0 Tech Preview2の主要機能として追加された「Create a RKE Cluster」は、RKE(Rancher Kubernetes Engine)を利用して、AWS、Azure、DigitalOcean、Packet、vSphereに対してKubernetesクラスタを作成することができます。(※2018年2月現在)

Rancher2.0 Tech Preview2からAWS上にKubernetesクラスタを作成してみましょう。

Tech Preview2のインストールはRancher2.0 Tech Preview2についての「Get Started with Rancher 2.0」を参考にしてください。

Rancher2.0 Tech Preview2でAWS上にKubernetesクラスタを作成

1.Rancher2.0 Tech Preview2 Serverにログイン後に、「Add Cluster」ボタンをクリックします。

image.png

2.「Create a RKE Cluster」の「Select」ボタンをクリックします。

image.png

3.nameに任意名を入力(今回はaws-k8s-clusterとします。)して、「Add a new cluster」をクリックします。

image.png

4.「Configure」をクリックします。

image.png

5.「Amazon EC2」を選択し、nameに任意名を入力(今回はaws-k8s-clusterとします。)し、Countは「3」、Regionは「ap-northeast-1」、Access keyとSecret keyはAWSのIMA Management Consoleでグループとユーザを作成し、そのユーザーのものを入力します。そして、「Next:Authenticate & select a network」ボタンをクリックします。

image.png

6.vpcを選択して、「Next:Select a Security Group」ボタンをクリックします。

image.png

7.「Next:Set Instance options」ボタンをクリックします。

image.png

8.「Create」ボタンをクリックします。

image.png

9.kubernetesの構成を作成します。最後に「Create」ボタンをクリックします。

image.png

10.しばらくするとkubernetesクラスタ構築が完了します。

screencapture-35-198-222-0-g-clusters-1517843931311.png

クラスタ名をクリックすると全体のリソース状況が可視化されます。

screencapture-35-198-222-0-c-cluster-8p8bq-1517844232326.png

11.上部メニュー「Nodes」を選択します。

AWS上に構築されたkubernetesクラスタの状況を確認できます。各クラスタ名をクリックするとリソース状況が可視化されます。

image.png

12.「KubeConfig File」ボタンをクリックします。

image.png

kubectlコマンドのconfigファイルをクリップボードにコピーできます。

image.png

kubectlコマンドを実行できるクライアントをローカルまたはサーバで構築します。今回はGCP上にGCEのインスタンス(Ubuntu 16.04 LTS)を1台用意します。

コマンド
$ curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl

$ chmod +x ./kubectl

$ sudo mv ./kubectl /usr/local/bin/kubectl

$ mkdir .kube

$ vim .kube/config
#クリップボードにコピーした内容をペーストして保存します。
:wq

$ kubectl get nodes
NAME               STATUS    ROLES         AGE       VERSION
aws-k8s-cluster1   Ready     etcd,master   26m       v1.8.5-rancher1
aws-k8s-cluster2   Ready     worker        23m       v1.8.5-rancher1
aws-k8s-cluster3   Ready     worker        25m       v1.8.5-rancher1

これで、kubectlコマンドでアプリケーションをデプロイすることが可能となります。

13.AWSのコンソールを確認します。

インスタンスが3台で来ていることが確認できます。

image.png

以上となりますが、AWS以外のAzure、DigitalOcean、Packet、vSphereも同様にRKEでkubernetesクラスタを構築できると思います。

参考資料

RKE(Rancher Kubernetes Engine)

続きを読む

Auroraのメンテナンスイベントについて

Auroraのメンテナンスイベントについて知らなければ!という衝動に突き動かされたわけではなく
意図しないアップグレードで少しやられてしまったので必要に迫られた故、メモ書きする。

メンテナンスの種類

RDSのマネージメントコンソールのクラスターのメンテナンス列で確認できる模様。
確認時に気づいたけれど大幅にUIが変更されたなー。Lambdaは頻繁に変わっているイメージだけど。。。

image.png

利用可能(Available)と必須(Required)がある。

Availableなイベントは延期が可能で、Requiredなイベントはメンテナンスウィウンドウで自動実行される。

Requiredなイベントについて、事前に知る必要がある。

describe-pending-maintenance-actions

Auroraのメンテナンス通知はメールで届いたりしないので、自分でAPIを叩いてメンテナンス情報を取得する必要がある。

describe-pending-maintenance-actions

上記APIを叩くと、以下のようなレスポンスが取得できる。

{
    "PendingMaintenanceActions": [
        {
            "PendingMaintenanceActionDetails": [
                {
                    "Action": "system-update", 
                    "Description": "Aurora 1.16 release"
                }
            ], 
            "ResourceIdentifier": "arn:aws:rds:ap-northeast-1:XXXXXXXX:cluster:XXXXXXXXXXXXXX"
        }
    ]
}

Requiredや、Available等表示されない。
どのように知るか?

API Output

Action

Auroraクラスタのメンテナンスの場合、基本的には”os-upgrade”あるいは”system-update”が返される。

  • os-upgrade:
    AuroraクラスタのOS更新
  • system-update:
    AuroraクラスタのDBエンジン更新
  • db-upgrade:
    主にRDS DBインスタンスにおけるDBエンジンの更新

AutoAppliedAfterDate, ForcedApplyDate

  • AutoAppliedAfterDate:
    更新が適用されるメンテナンスウィンドウの指定。この項目で指定された日付以降の最初のメンテナンスウィンドウでアクションを実行される。
  • ForcedApplyDate:
    指定された場合、メンテナンスウィンドウ外でも指定された日時でメンテナンスが実行される。

「メンテナンスウィンドウ外でも」 

これは絶対チェックやな。

OptInStatus

AutoAppliedAfterDate, ForcedApplyDateが指定されない場合や、指定された日時よりも早くメンテナンスを実行したい場合はapply-pending-maintenance-actionを–opt-in-typeオプションを指定して実行することができる。
メンテナンスに対する選択(opt-in)状態を示す。
opt-in とは「事前許可を求めるやりかた」というようなことらしい。
この項目は明示的にapply-pending-maintenance-actionを実行した場合にのみ追加される。

apply-pending-maintenance-action
ステータスは以下。

  • next-maintenance:
    次のメンテナンスウィンドウ
  • immediate: 即座
  • undo-opt-in: next-maintenanceの指定がキャンセルされた

CurrentApplyDate

CurrentApplyDateは、AutoAppliedAfterDate, ForcedApplyDate, OptInStatusのすべてを考慮したうえで、「現時点で実際にメンテナンスの自動適用が予定されている日時」

結論

AutoAppliedAfterDate 、ForcedApplyDateが設定されているものがRequiredなイベントなので、事前にちゃんと知るようにする。

参考サイト

続きを読む

AWS と Azure と自宅の PC で NVIDIA GPU Cloud (NGC) のコンテナを動かしてみた

こんにちは。エヌビディアの佐々木です。

NVIDIA GPU Cloud (NGC) というサービスをご存知でしょうか。端的に書けば 「NVIDIA が公開している Docker コンテナリポジトリ」 です。CaffeChainerTensorFlow 等の各種ディープラーニング フレームワークや、GAMESSGromacsLAMMPS といった HPC アプリケーションのコンテナが揃っており、もちろん GPU 実行に最適化されています。このコンテナを使えば、計算環境構築の手間をかなり削減することができます。

「Cloud」とあるので、クラウドで GPU を使うためのサービスと思われることがあるのですが、NGC は「コンテナを提供するクラウドサービス」であって、そのコンテナはクラウドに限らず、オンプレミスのコンピューターでも利用できます。

今のところ、コンテナの利用環境としてエヌビディアが正式にサポートするのは AWS の P3 インスタンス と、NVIDIA TITAN V を搭載するコンピューターのみですが、それ以外の環境でも Pascal 世代以降の GPU であれば動作するはずです。

というわけで、次のような3つの環境で試してみました。

  • AWS の P3 インスタンス (Tesla V100 搭載)
  • Microsoft Azure の ND インスタンス (Tesla P40 搭載)
  • 私の自宅 PC (GeForce GTX 1050 Ti 搭載)

※ 私の PC だけちょっと弱めですが、ロープロファイルのカードしか付かないんです…

NGC のアカウントを作る

まず、 NGC のサインアップページでアカウントを作成します。無料です。
2018-01-28_205005.png

NGC の API キーを生成する

アカウントができたらログインして、画面右上の “Get API Key” をクリックしてください。
2018-01-28_205552.png

次に、”Generate API Key” をクリックして API キーを生成します。これは後ほど NGC からコンテナを pull する際に使用します。
2018-01-28_210946.png

生成されたキーは必ずどこかに控えておいてください。”This is the only time your API Key will be displayed.” とあるとおり、二度と表示されません。
2018-01-28_211158.png

さて、アカウントと API Key ができたら、あとは実行環境の準備です。要件は次の通り。

  • Pascal 世代以降の GPU (と、そのドライバ)
  • NVIDIA Docker

では、AWS, Azure, 自宅 PC のそれぞれで試していきます。

実行環境を作る (AWS で)

AWS は NGC の正式サポート環境なので、準備も簡単です。NVIDIA Volta Deep Learning AMI という AMI をエヌビディアが提供していますので、これを使って P3 インスタンスを作れば OK です。ドライバも NVIDIA Docker もインストール済み。別途セットアップする必要はありません。(なお、G2, G3, P2 は、GPU が Kepler や Maxwell 世代なので NGC 非対応)

早速作ってみます。
2018-01-28_212822.png
東京は高いのでオレゴンで、インスタンスタイプは p3.2xlarge (Tesla V100 を1基搭載)を選びました。

インスタンスが動き始めたらログインしてみます。シェルのプロンプトが出る前にこんなことを聞いてきます。

Welcome to the NVIDIA Volta Deep Learning AMI. This environment is provided to
enable you to easily run the Deep Learning containers from the NGC Registry.
All of the documentation for how to use NGC and this AMI are found at
  http://docs.nvidia.com/deeplearning/ngc
Initializing nvidia-docker volume...

Please enter your NGC APIkey to login to the NGC Registry:

ここで、先ほど生成した API キーを入力(ペースト)します。

Logging into the NGC Registry at nvcr.io...Login Succeeded

こうなれば NGC 利用準備完了です。コンテナを動かす前に、 GPU を確認してみます。

$ nvidia-smi
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 384.81                 Driver Version: 384.81                    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  Tesla V100-SXM2...  On   | 00000000:00:1E.0 Off |                    0 |
| N/A   32C    P0    19W / 300W |     10MiB / 16152MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+

本当に Tesla V100 SXM2 だ!テンション上がりますねー

では、コンテナを動かしてみます。NGC サイトの AWS のチュートリアルにある、PyTorch での MNIST 手書き文字認識が動作確認には手軽です。

$ nvidia-docker run --rm -ti nvcr.io/nvidia/pytorch:17.10
17.10: Pulling from nvidia/pytorch
f5c64a3438f6: Pull complete
51899d335aae: Pull complete
<略>

初回なのでいろいろとダウンロードする必要があり、少し時間がかかりますが、うまくコンテナが動き出しました。

=============
== PyTorch ==
=============

NVIDIA Release 17.10 (build 192702)

Container image Copyright (c) 2017, NVIDIA CORPORATION.  All rights reserved.

Copyright (c) 2016-     Facebook, Inc            (Adam Paszke)
Copyright (c) 2014-     Facebook, Inc            (Soumith Chintala)
Copyright (c) 2011-2014 Idiap Research Institute (Ronan Collobert)
Copyright (c) 2012-2014 Deepmind Technologies    (Koray Kavukcuoglu)
Copyright (c) 2011-2012 NEC Laboratories America (Koray Kavukcuoglu)
Copyright (c) 2011-2013 NYU                      (Clement Farabet)
Copyright (c) 2006-2010 NEC Laboratories America (Ronan Collobert, Leon Bottou, Iain Melvin, Jason Weston)
Copyright (c) 2006      Idiap Research Institute (Samy Bengio)
Copyright (c) 2001-2004 Idiap Research Institute (Ronan Collobert, Samy Bengio, Johnny Mariethoz)
All rights reserved.

Various files include modifications (c) NVIDIA CORPORATION.  All rights reserved.
NVIDIA modifications are covered by the license terms that apply to the underlying project or file.

NOTE: The SHMEM allocation limit is set to the default of 64MB.  This may be
   insufficient for PyTorch.  NVIDIA recommends the use of the following flags:
   nvidia-docker run --ipc=host ...

root@b3d044efeae1:/workspace#

コンテナの中で、サンプルスクリプトを動かしてみます。

root@b3d044efeae1:/workspace# cd /opt/pytorch/examples/mnist && python main.py
Train Epoch: 1 [0/60000 (0%)]   Loss: 2.390087
<中略>
Train Epoch: 10 [58880/60000 (98%)]     Loss: 0.272635
Train Epoch: 10 [59520/60000 (99%)]     Loss: 0.082086

Test set: Average loss: 0.0553, Accuracy: 9804/10000 (98%)

root@b3d044efeae1:/opt/pytorch/examples/mnist#

1分半ほどで10エポック完了しました。環境構築の手間いらずで、実に簡単ですね。

実行環境を作る (Azure で)

Microsoft Azure の仮想マシンで、Pascal 以降の GPU を搭載しているのは次の3種類です。

  • NCv2 (Tesla P100)
  • ND (Tesla P40)
  • NCv3 (Tesla V100: ただし、2018年1月時点ではプレビュー提供中)

今回は ND シリーズの一番小さいやつ(ND6s)をData Science Virtual Machine for Linux (Ubuntu)で作りました。これは AWS の NVIDIA Volta Deep Learning AMI のように、GPU ドライバや NVIDIA Docker があらかじめインストールされた仮想マシンイメージです。楽ちんです。

2018-01-28_221052.png

ログインしたら GPU を確認。確かに、Tesla P40 が搭載されていますね。こいつの GPU メモリサイズは 24GB と、P100 や V100 よりも大きいのです。

+-----------------------------------------------------------------------------+
| NVIDIA-SMI 384.111                Driver Version: 384.111                   |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  Tesla P40           Off  | 00008B49:00:00.0 Off |                    0 |
| N/A   25C    P8    11W / 250W |     10MiB / 22912MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+

では、動作確認を。Azure の場合、 AWS の NVIDIA Volta Deep Learning AMI のようにログイン時に NGC のキーを入力していませんので、まずは NGC へのログインが必要です。

下記コマンドの ‘$oauthtoken’ の部分は「環境に応じて適切に置き換えてください」という意味ではなく、「そのまま」入力してください。シェルに変数展開されないようにシングルクォートで括る必要があります。

$ docker login -u '$oauthtoken' --password-stdin nvcr.io <<< 'API キー'
Login Succeeded

あとは、AWS の場合と同じです。こちらでも PyTorch の MNIST を試してみました。同じことをやっても面白くありませんが、「同じものがどこでも動く」というのがコンテナの便利なところなので。

$ nvidia-docker run --rm -ti nvcr.io/nvidia/pytorch:17.10

=============
== PyTorch ==
=============

NVIDIA Release 17.10 (build 192702)

Container image Copyright (c) 2017, NVIDIA CORPORATION.  All rights reserved.

<略>

root@84835550d223:/opt/pytorch/examples/mnist# cd /opt/pytorch/examples/mnist && time python main.py

<略>

Train Epoch: 1 [0/60000 (0%)]   Loss: 2.390087
Train Epoch: 1 [640/60000 (1%)] Loss: 2.350225

<略>

Train Epoch: 10 [58880/60000 (98%)]     Loss: 0.307370
Train Epoch: 10 [59520/60000 (99%)]     Loss: 0.081178

Test set: Average loss: 0.0546, Accuracy: 9813/10000 (98%)

root@84835550d223:/opt/pytorch/examples/mnist#

(当たり前ですが) 無事に動きました。簡単ですね。

実行環境を作る (自宅の PC 等で)

さて、2種類のクラウドを試しましたが、次に自宅の PC でも試してみました。環境は次の通りです。

  • OS: Ubuntu 16.04.3 LTS
  • GPU: GeForce GTX 1050 Ti (Pascal 世代)

Deep Learning AMI のような便利なものはないので、GPUのドライバと NVIDIA Docker は自分でインストールする必要があります。

GPU ドライバのインストール

NVIDIA のドライバダウンロードページから、自分の GPU に対応したドライバのインストーラーをダウンロードしてインストールします。なお、NVIDIA Docker さえ動けば良いので、CUDA Toolkit のインストールは不要です。

NVIDIA Docker のインストール

NVIDIA Docker のインストールには前提条件として Docker が必要です。私はこちらのページを参考にして、Docker CE をインストールしました。実行したコマンドは次の通りです。

sudo apt update
sudo apt install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt update
sudo apt install docker-ce

次に、 NVIDIA Docker をインストールします。こちらのページに手順がまとまっています。実行したコマンドは次の通りです。

curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/ubuntu16.04/amd64/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt update

sudo apt install nvidia-docker2
sudo pkill -SIGHUP dockerd

あと、sudo なしで Docker を実行できるように、自分を docker グループに追加しました。

sudo gpasswd -a 自分 docker

コンテナの動作確認

「またか」という感じですが、PyTorch で MNIST してみます。

$ docker login -u '$oauthtoken' --password-stdin nvcr.io <<< 'API キー'
Login Succeeded
$ nvidia-docker run --rm -ti nvcr.io/nvidia/pytorch:17.10

=============
== PyTorch ==
=============

NVIDIA Release 17.10 (build 192702)

Container image Copyright (c) 2017, NVIDIA CORPORATION.  All rights reserved.

<略>

root@2dc683eff1b2:/opt/pytorch/examples/mnist# cd /opt/pytorch/examples/mnist && python main.py

<略>

Train Epoch: 1 [0/60000 (0%)]   Loss: 2.390087
Train Epoch: 1 [640/60000 (1%)] Loss: 2.350225

<略>

Train Epoch: 10 [58880/60000 (98%)]     Loss: 0.288593
Train Epoch: 10 [59520/60000 (99%)]     Loss: 0.084271

Test set: Average loss: 0.0529, Accuracy: 9821/10000 (98%)

root@2dc683eff1b2:/opt/pytorch/examples/mnist#

無事に動きました!

まとめ

NVIDIA GPU Cloud のコンテナを、2種のクラウドと自宅の PC で動かしてみました。
AWS と Azure は GPU ドライバと NVIDIA Docker インストール済みの仮想マシンイメージが使えるのでとても簡単。それ以外の環境でも、NVIDIA Docker の環境さえ作ってしまえば、あとは毎月更新される最新のコンテナを活用することで、環境構築とメンテナンスをかなり効率化できます。是非お試しを!

関連情報

続きを読む

UnityからAWS Cognito Identity Providerで認証機能を実装する(User_Auth_Flow)

前置き:AWSSDK for Unityでは現状,公式にCognito Identity Providerの機能をサポートしていません.紹介した方法は自己責任で参考にしてください.

UnityからCognito User Poolを使って認証する

この記事ではAWSのCognito User Poolを使用してログイン機能をUnityのアプリケーションに実装し,AWSのリソースにアクセスするためのトークンを取得する方法を紹介します.

Cognito User Poolとは

https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/cognito-user-identity-pools.html

自分でサーバー側の実装を書くことなくユーザー認証機能を実装できます.

手順

環境

AWSの設定

User Poolの作成と設定

UserPool.png

Cognitoからユーザーを管理するためのUser Poolを作成し,以下のように設定します.

  • プール名

    • わかりやすい任意の名前を設定します.
  • 属性
    • 標準属性のチェックを全て外し,ユーザー名とパスワードだけでログインできるように設定します.
  • アプリクライアントの追加

    • “アプリクライアントの追加”をクリックします.
    • アプリクライアント名を設定します.
    • “クライアントシークレットを生成する”をオフにします.

設定し終わったら”確認タブ”からプール作成を終了し,

  • プールIDとプール名 (リージョン名と固有なプール名の組み合わせ)

    • 例) ap-northeast-1_Hoge0Hoge
      を確認します.

さらにアプリの統合>アプリクライアントの設定タブから,

  • “有効なIDプロバイダ”のチェック欄に表示されている”Cognito User Pool”にチェックを入れます.
  • アプリクライアントID (25桁のAlphanumericな値)を確認します.

Identity Poolの作成と設定

IdentityPool.png

Cognitoから”フェデレーテッドアイデンティティ”のページに移動し,”新しいIDプールの作成”をクリックするとIDプール作成ウィザードが開始します.

  • IDプール名を入力します.
  • “認証されていないIDに対してアクセスを有効にする”をオンにするとゲストユーザーとしてアプリを使用することが可能です.ここでは必要ないのでオフのままで大丈夫です.
  • 認証プロバイダーのセクションで”Cognito”タブをクリックし,先ほど確認したユーザープールのIDとアプリクライアントIDを入力します.

Createpolicy.png

“プールの作成”をクリックすると,”AWSの諸々にアクセスするための権限の設定をする必要がある”ということで,ゲストユーザーと認証ユーザーの二つのユーザーについてIAMロールを設定するように言われます.

ここではどちらも”新しいIAMロールの作成”を選択し,そのまま右下の許可を押します.ここで作成した二つのIAMロール(Cognito_*Hoge*Auth_RoleCognito_*Hoge*Unauth_Role)はあとで編集するので名前を覚えておきます.

IAMロールの編集

先ほど作成したロールの権限を編集し,Cognito User Poolに対して認証リクエストを送る権限を付与します.

CogitoIdentityProvider.dll for Unityのビルド

AWS Mobile SDK for UnityではCognito User Poolがサポートされておらず,自分でCognitoIdentityProvider.dllをビルドする必要があります.dotNet版のコードジェネレーターの設定をいじることでUnityに対応したdllを得ることができます.

GitHubのissueに具体的な方法が書かれており,それを翻訳すると以下のようになります.

  1. AWS SDK dot netのリポジトリをクローンします.

  2. aws-sdk-netgeneratorServiceModelscognito-idpmetadata.jsonを編集し,"platforms": ["Unity"],をjsonのrootに追加します.

  3. aws-sdk-netgeneratorServiceClientGeneratorLib/Generators/ProjectFiles/UnityProjectFile.csの265行目でUnityEngine.dllのパスを修正します. UnityEngine.dllの場所はMacOSとWindowsで異なるので注意.ここではWindowsでビルドします.修正後のパスはC:/Program Files/Unity/Editor/Data/Managed/UnityEngine.dllとなります.

  4. aws-sdk-netgeneratorAWSSDKGenerator.slnをVisual Studioで開きます.実行ボタン(上の緑の三角ボタン)を押すとビルドされたコード生成プログラムが実行され,上手くいけばaws-sdk-netsdksrcServicesCognitoIdentityProvider内部にAWSSDK.CognitoIdentityProvider.Unity.csprojというファイルが生成されます.

  5. 次にaws-sdk-netsdkAWSSDK.Unity.slnを開き,Build TypeをReleaseに設定してからビルド(ctrl + shift + B)します.すると新しくaws-sdk-netsdksrcServicesCognitoIdentityProviderbinReleaseunityフォルダが作られ,中にCognitoIdentityProvider.dllが生成されます.

  6. UnityプロジェクトのAssets/下任意の場所にdllを置きます.

metadata.json
{
  "platforms": ["Unity"],
  "active": true, 
  "synopsis": "You can create a user pool in Amazon Cognito Identity to manage directories and users. You can authenticate a user to obtain tokens related to user identity and access policies. This API reference provides information about user pools in Amazon Cognito Identity, which is a new capability that is available as a beta."
}
UnityProjectFile.cs
...
 this.Write(this.ToStringHelper.ToStringWithCulture(Path.Combine((string)this.Session["UnityPath"], "Editor", "Data", "Managed", "UnityEngine.dll")));
...

Unityで認証フローを実装する

AWS Mobile SDK for Unityを公式サイトからダウンロードし,AWSSDK.IdentityManagement.unitypackageをプロジェクトにインポートします.

以下,ブログエントリーを参考にして認証フローと暗号化処理を実装します.

AdminInitiateAuth関数を使った方法が紹介されることが多いですが,パスワードが平文で送信されるのでモバイルアプリで用いるにはセキュリティ的に非常に危険です.今回はSecure Remote Password (SRP)プロトコルをつかった認証フローであるUSER_SRP_AUTHに従います.

暗号化の実装はブログエントリーが詳しく,また依存するHkdfクラスの実装もGistに公開されているものが完動するのでコピペします.Bouncy Castle C#のライブラリが必要なのでBouncy Castle C#のGitHubリポジトリから最新リリースをダウンロードし,.net2.0版のdllをプロジェクトにコピーします.

注意すべき点として, 作成したばかりのユーザーのステータスはFORCE_CHANGE_PASSWORDと設定されており,User Poolからのレスポンス(チャレンジ)として新しいパスワードを要求してきます.下のプログラムではまだ実装しておらず,パスワード変更済みのユーザーに対してログイン処理をかけています.

認証フローが成功すると
* IdToken
* AccessToken
* RefreshToken
の三つが手に入ります.

得られたIdトークンを使ってCredential.AddLogins(IdentityProviderName , IdToken)することで,GetCredentialForIdentityAsync関数を実行した時にAWSのAPIを叩く上で必要なトークンを得ることができます.このトークンを使って認可されるアクション,アクセスできるリソースはIAMで設定したCognito_HogeAuth_Roleに従います.

リフレッシュトークンはPlayerPrefなどに保存し,アプリを起動した際にIdトークンを更新することで自動ログイン処理を行います.

CognitoUserPoolClient.cs
namespace CognitoLogInSample
{
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    using System;
    using System.Globalization;
    using Amazon;
    using Amazon.Runtime;
    using Amazon.CognitoIdentity;
    using Amazon.CognitoIdentity.Model;
    using Amazon.CognitoIdentityProvider;
    using Amazon.CognitoIdentityProvider.Model;

    public class CognitoUserPoolClient : MonoBehaviour
    {
        #region CognitoCredentials
        public string IdentityPoolId;            // IDプールのID
        public string CognitoIdentityRegion;     // リージョン名 例)ap-northeast-1

        private RegionEndpoint _CognitoIdentityRegion
        {
            get { return RegionEndpoint.GetBySystemName(CognitoIdentityRegion); }
        }
        private CognitoAWSCredentials _credentials;

        private CognitoAWSCredentials Credentials
        {
            get
            {
                if (_credentials == null)
                {
                    _credentials = new CognitoAWSCredentials(IdentityPoolId, _CognitoIdentityRegion);
                    _credentials.IdentityChangedEvent += Credentials_IdentityChangedEvent;
                }
                return _credentials;
            }
        }
        #endregion

        #region CognitoIdP
        public string CognitoIdPRegion;          // User Poolのリージョン 例)ap-northeast-1

        private RegionEndpoint _CognitoIdPRegion
        {
            get { return RegionEndpoint.GetBySystemName(CognitoIdPRegion); }
        }

        [SerializeField]
        string userPoolName;                     // User Poolの固有名 アンダーバーで区切ったうちの後半
        [SerializeField]
        string clientId;                         // User PoolのクライアントID

        string UserPoolId
        {
            get
            {
                return string.Format("{0}_{1}", _CognitoIdPRegion, userPoolName);
            }
        }

        public string CognitoIdentityProviderName
        {
            get
            {
                return string.Format("cognito-idp.{0}.amazonaws.com/{1}", _CognitoIdentityRegion.SystemName, UserPoolId);
            }
        }
        #endregion

        AmazonCognitoIdentityProviderClient idpClient;
        AmazonCognitoIdentityClient cognitoIdentityClient;

        public InputField IdInputField;
        public InputField passwordInputField;
        public Toggle clearCredentialToggle;

        TokenCacheManager tokenCacheManager;
        public bool cleanPlayerPrefSetting;

        string currentSession;
        string currentUserName;

        private void Start()
        {
            tokenCacheManager = new TokenCacheManager();
            if (cleanPlayerPrefSetting)
            {
                tokenCacheManager.DeleteCachedToken();
            }
            //AdminAuthenticateWithRefreshToken();
            SignInWithRefreshToken();
        }

        public void OnButtonClick()
        {
            if (clearCredentialToggle.isOn)
            {
                Credentials.Clear();
            }
            SignIn(IdInputField.text, passwordInputField.text);
        }

        #region InitiateAuthFlow

        /// <summary>
        /// Signs In with refresh token (USER_AUTH_FLOW).
        /// </summary>
        void SignInWithRefreshToken()
        {
            tokenCacheManager.GetCachedTokens((getCachedTokensResult) =>
            {
                if (getCachedTokensResult.IsCacheAvailable)
                {
                    Debug.Log(getCachedTokensResult.Token.ToString());
                    // RefreshToken
                    idpClient = new AmazonCognitoIdentityProviderClient(Credentials, _CognitoIdentityRegion);
                    InitiateAuthRequest initiateAuthRequest = new InitiateAuthRequest()
                    {
                        ClientId = clientId,
                        AuthFlow = AuthFlowType.REFRESH_TOKEN_AUTH,
                    };
                    initiateAuthRequest.AuthParameters.Add("REFRESH_TOKEN", getCachedTokensResult.Token.refreshToken);

                    idpClient.InitiateAuthAsync(initiateAuthRequest, (initiateAuthResponse) =>
                    {
                        if (initiateAuthResponse.Exception != null) return;
                        CognitoIdentityProviderToken cognitoIdentityProviderToken = new CognitoIdentityProviderToken
                        {
                            accessToken = initiateAuthResponse.Response.AuthenticationResult.AccessToken,
                            idToken = initiateAuthResponse.Response.AuthenticationResult.IdToken ?? getCachedTokensResult.Token.idToken,
                            refreshToken = initiateAuthResponse.Response.AuthenticationResult.RefreshToken ?? getCachedTokensResult.Token.refreshToken,
                            expireTime = initiateAuthResponse.Response.AuthenticationResult.ExpiresIn
                        };
                        tokenCacheManager.CacheTokens(cognitoIdentityProviderToken);

                        Credentials.AddLogin(CognitoIdentityProviderName, initiateAuthResponse.Response.AuthenticationResult.IdToken);
                        Credentials.GetIdentityIdAsync(responce =>
                        {
                            Debug.Log("Logged In with refreshed IdToken : " + responce.Response);
                        });
                    });
                    idpClient.Dispose();
                }
                else
                {
                    Credentials.Clear();
                    // Redirect to LogIn Dialog
                    Debug.Log("RefreshToken is not available");
                }
            });
        }


        /// <summary>
        /// Sign In.
        /// </summary>
        /// <param name="userName">User name.</param>
        /// <param name="password">Password.</param>
        void SignIn(string userName, string password)
        {
            Debug.Log("Initiate Authentication Flow");

            var cred = new AnonymousAWSCredentials();

            idpClient = new AmazonCognitoIdentityProviderClient(cred, _CognitoIdentityRegion);
            var TupleAa = AuthenticationHelper.CreateAaTuple();

            var initiateAuthRequest = new InitiateAuthRequest
            {
                AuthFlow = AuthFlowType.USER_SRP_AUTH,
                ClientId = clientId,
                AuthParameters = new Dictionary<string, string>(){
                            {"USERNAME", userName},
                            {"SRP_A", TupleAa.Item1.ToString(16)},
                        }
            };

            Debug.Log(initiateAuthRequest.AuthParameters["SRP_A"]);

            idpClient.InitiateAuthAsync(initiateAuthRequest, (initiateAuthResponse) =>
            {
                var challengeName = initiateAuthResponse.Response.ChallengeName;
                if (challengeName == ChallengeNameType.NEW_PASSWORD_REQUIRED)
                {
                    // newPasswordRequired
                    idpClient.Dispose();
                }
                else if (challengeName == ChallengeNameType.PASSWORD_VERIFIER)
                {
                    DateTime timestamp = TimeZoneInfo.ConvertTimeToUtc(DateTime.Now);
                    var usCulture = new CultureInfo("en-US");
                    string timeStr = timestamp.ToString("ddd MMM d HH:mm:ss "UTC" yyyy", usCulture);

                    byte[] claim = AuthenticationHelper.authenticateUser(initiateAuthResponse.Response.ChallengeParameters["USERNAME"],
                                                                         password,
                                                                         userPoolName,
                                                                         TupleAa,
                                                                         initiateAuthResponse.Response.ChallengeParameters["SALT"],
                                                                         initiateAuthResponse.Response.ChallengeParameters["SRP_B"],
                                                                         initiateAuthResponse.Response.ChallengeParameters["SECRET_BLOCK"],
                                                                         timeStr
                                                                        );
                    string claimBase64 = Convert.ToBase64String(claim);

                    var respondToAuthChallengeRequest = new RespondToAuthChallengeRequest()
                    {
                        ChallengeName = initiateAuthResponse.Response.ChallengeName,
                        ClientId = clientId,
                        ChallengeResponses = new Dictionary<string, string>(){
                                    { "PASSWORD_CLAIM_SECRET_BLOCK", initiateAuthResponse.Response.ChallengeParameters["SECRET_BLOCK"]},
                                    { "PASSWORD_CLAIM_SIGNATURE", claimBase64 },
                                    { "USERNAME", userName },
                                    { "TIMESTAMP", timeStr }
                        }
                    };

                    Debug.Log(timeStr);

                    idpClient.RespondToAuthChallengeAsync(respondToAuthChallengeRequest, respondToAuthChallengeResponse =>
                   {
                       try
                       {
                           Debug.LogFormat("User was verified in SRP Auth Flow : {0}", respondToAuthChallengeResponse.Response.AuthenticationResult.IdToken);
                           Credentials.AddLogin(CognitoIdentityProviderName, respondToAuthChallengeResponse.Response.AuthenticationResult.IdToken);

                           tokenCacheManager.CacheTokens(new CognitoIdentityProviderToken()
                           {
                               accessToken = respondToAuthChallengeResponse.Response.AuthenticationResult.AccessToken,
                               idToken = respondToAuthChallengeResponse.Response.AuthenticationResult.IdToken,
                               refreshToken = respondToAuthChallengeResponse.Response.AuthenticationResult.RefreshToken,
                               expireTime = respondToAuthChallengeResponse.Response.AuthenticationResult.ExpiresIn,
                           });
                       }
                       catch (Exception e)
                       {
                           Debug.LogErrorFormat("Encountered exception: {0}", e);
                       }
                       finally
                       {
                           idpClient.Dispose();
                       }
                   });
                }
            });

            currentUserName = userName;
        }
        #endregion

        private void Credentials_IdentityChangedEvent(object sender, CognitoAWSCredentials.IdentityChangedArgs e)
        {
            Debug.Log(string.Format("Identity has changed from {0} to {1}", e.OldIdentityId, e.NewIdentityId));
        }
    }
}

参考資料

続きを読む

Amazon Linux 2 で Rails アプリケーションのサーバーを構成してみる

Amazon Linux 2 の特徴

  • AWS INTEGRATION

    • AWS tools (e.g. AWS CLI) と cloud-init が入った
  • LONG TERM SUPPORT
  • EXTRAS REPOSITORY FOR SOFTWARE PACKAGES
    • amazon-linux-extras で nginx などのパッケージを管理できる
  • ON-PREMISES USE
    • オンプレ利用用途に VM Image などが用意されている
  • SYSTEMD SUPPORT
  • TUNED LTS KERNEL AND NEW TOOLCHAIN
  • SECURITY CONFIGURATIONS
  • SECURITY UPDATES

インスタンスの作成

AMI 選択画面で Amazon Linux 2 LTS Candidate AMI 2017.12.0 (HVM), SSD Volume Type (ami-c2680fa4) を選択してインスタンスを立てる.

公開鍵の追加

vi ~/.ssh/authorized_keys

ユーザーの追加

sudo adduser deploy

ライブラリのインストール

sudo yum -y install 
git make gcc-c++ patch 
openssl-devel 
libyaml-devel libffi-devel libicu-devel 
libxml2 libxslt libxml2-devel libxslt-devel 
zlib-devel readline-devel 
mysql mysql-server mysql-devel 
ImageMagick ImageMagick-devel 
epel-release protobuf-devel

デプロイ先フォルダの用意

sudo mkdir /var/www
sudo chown deploy /var/www/
sudo mkdir /var/www/deploy
sudo chown deploy /var/www/deploy/

nginx のインストール

Amazon Linux 2 では amazon-linux-extras で入れる.

# 確認する
amazon-linux-extras
# install する
sudo amazon-linux-extras install nginx1.12
# ついでに emacs も入れる
sudo amazon-linux-extras install emacs

nginx の起動

# 起動
sudo systemctl start nginx.service
# ステータスの確認
sudo systemctl status nginx.service
# systemd を有効化
sudo systemctl enable nginx.service
# 有効になっているか確認
systemctl is-enabled nginx.service

nginx の設定

# nginx の設定ファイル
sudo vi /etc/nginx/nginx.conf
# 設定再読込
sudo nginx -s reload

ffmpeg

sudo rpm --import http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro
sudo rpm -Uvh http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-1.el7.nux.noarch.rpm
mkdir ~/tmp
cd ~/tmp
wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
sudo yum -y localinstall epel-release-latest-7.noarch.rpm
sudo yum -y install ffmpeg ffmpeg-devel

wkhtmltoimage

https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.4/wkhtmltox-0.12.4_linux-generic-amd64.tar.xz
tar -xvf wkhtmltox-0.12.4_linux-generic-amd64.tar.xz
sudo mv wkhtmltox/bin/wkhtmltoimage /usr/bin/wkhtmltoimage

NodeJS

curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh | bash
source ~/.bashrc
nvm install v8.9.4
nvm use v8.9.4
nvm alias default v8.9.4

Ruby

sudo git clone https://github.com/sstephenson/rbenv.git /usr/local/rbenv
sudo git clone https://github.com/sstephenson/ruby-build.git /usr/local/rbenv/plugin/ruby-build
sudo /usr/local/rbenv/plugin/ruby-build/install.sh
sudo vi /etc/profile.d/rbenv.sh
sudo su -
source /etc/profile.d/rbenv.sh
rbenv install 2.4.3
rbenv global 2.4.3
gem install bundler --no-ri --no-rdoc

タイムゾーン, host の修正

timedatectl, hostnamectl を利用する.

sudo timedatectl set-timezone Asia/Tokyo
sudo hostnamectl set-hostname deploy.dot.com
sudo reboot

New Relic Infrastructure の追加

https://rpm.newrelic.com/accounts/813076 でライセンスキー確認

echo "license_key: YOUR_LICENSE_KEY" | sudo tee -a /etc/newrelic-infra.yml
sudo curl -o /etc/yum.repos.d/newrelic-infra.repo https://download.newrelic.com/infrastructure_agent/linux/yum/el/7/x86_64/newrelic-infra.repo
sudo yum -q makecache -y --disablerepo='*' --enablerepo='newrelic-infra'
sudo yum install newrelic-infra -y

公開鍵

sudo su - deploy
mkdir ~/.ssh
chmod 700 ~/.ssh
touch ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
# デプロイするサービスの公開鍵を追加
vi ~/.ssh/authorized_keys

refs

続きを読む

【CPUの脆弱性対応】古いAmazon Linuxのkernelを最新版にアップデートする

AWSで管理しているAmazon Linuxが古いバージョンのまま放置していることありませんか?

CPUの脆弱性対応におけるAWSの公式ドキュメント

Customers with existing Amazon Linux AMI instances should run the following command to ensure they receive the updated package: sudo yum update kernel.

カーネルをアップデートして最新のカーネルにするように書いてあるのですが、
Amazon Linuxのバージョンが古いインスタンスでは、
単にカーネルのアップデートだけでは、最新のカーネルにアップデートされません。

この記事ではその際の対応手順を説明します。

※ 説明のためにコミュニティAMIにある古いAMIを使って進めます。

対象のマシンにsshし、インフォメーションをチェック

しばらくOSをアップデートされていないインスタンスにsshします。
OSが更新されていない場合は、以下のように

$ ssh hogehost

       __|  __|_  )
       _|  (     /   Amazon Linux AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2016.03-release-notes/
Amazon Linux version 2017.09 is available.

Amazon Linux version 2017.09 is available.
Amazon Linux version 2017.09が利用できます

と表示されていますね。
あまり意識しないと見逃しがちですが、このような情報もしっかり確認しましょう。

さらにカーネルのバージョンを確認します。

$ uname -srv
Linux 4.4.5-15.26.amzn1.x86_64 #1 SMP Wed Mar 16 17:15:34 UTC 2016

カーネルも2016年に作られたバージョンのままになっていますね。

yum.confをチェックし、AMIを特定のバージョンに固定されていないか確認する

AMIを特定のバージョンに固定するにはどうすればよいですか?

上記の公式ドキュメントに書かれているようにAmazon Linuxのマシーンイメージでは、1つのバージョンから次のバージョンへ連続的な更新を提供するように設定されていますが、過去のバージョンでは/etc/yum.confreleasever変数がなかったり、リリースバージョンが固定されていることがあります。

その場合は単にyum updateだけでは最新のパッケージに更新されません。

今回対象のyum.confを見てみると

$ cat /etc/yum.conf
[main]
cachedir=/var/cache/yum/$basearch/$releasever
keepcache=0
debuglevel=2
logfile=/var/log/yum.log
distroverpkg=system-release
exactarch=1
obsoletes=1
gpgcheck=1
plugins=1
installonly_limit=3
deltarpm=0

# by default the yum configuration will point to the latest release
# of Amazon Linux AMI. If you prefer not to automatically move to
# new releases, comment out this line.
releasever=2016.03

#  This is the default, if you make this bigger yum won't see if the metadata
# is newer on the remote and so you'll "gain" the bandwidth of not having to
# download the new metadata and "pay" for it by yum not having correct
# information.
#  It is esp. important, to have correct metadata, for distributions like
# Fedora which don't keep old packages around. If you don't like this checking
# interupting your command line usage, it's much better to have something
# manually check the metadata once an hour (yum-updatesd will do this).
# metadata_expire=90m

# PUT YOUR REPOS HERE OR IN separate files named file.repo
# in /etc/yum.repos.d

releasever2016.03に固定されています。

この状態では、カーネルをアップデートしても変更されません。

$ sudo yum update kernel
Loaded plugins: priorities, update-motd, upgrade-helper
No packages marked for update

そこで更新させるためには以下のように変更する必要があります。

releasever=latest

releaseverを「latest」に変更して、カーネルをアップデート

先ほどのyum.confのリリースサーバーを最新に更新します。

$ cp -ip /etc/yum.conf  /tmp/
$ sudo vi /etc/yum.conf
$ diff /etc/yum.conf /tmp/yum.conf
17c17
< releasever=latest
---
> releasever=2016.03
#更新しました

# kernelをアップデートする
$ sudo yum update kernel
Loaded plugins: priorities, update-motd, upgrade-helper
amzn-main/latest                                                                                                                                                                                                                 | 2.1 kB     00:00
amzn-updates/latest                                                                                                                                                                                                              | 2.3 kB     00:00
Resolving Dependencies
--> Running transaction check
---> Package kernel.x86_64 0:4.9.51-10.52.amzn1 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

========================================================================================================================================================================================================================================================
 Package                                                 Arch                                                    Version                                                               Repository                                                  Size
========================================================================================================================================================================================================================================================
Installing:
 kernel                                                  x86_64                                                  4.9.51-10.52.amzn1                                                    amzn-main                                                   17 M

Transaction Summary
========================================================================================================================================================================================================================================================
Install  1 Package

Total download size: 17 M
Installed size: 71 M
Is this ok [y/d/N]: y
Downloading packages:
kernel-4.9.51-10.52.amzn1.x86_64.rpm                                                                                                                                                                                             |  17 MB     00:01
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : kernel-4.9.51-10.52.amzn1.x86_64                                                                                                                                                                                                     1/1
  Verifying  : kernel-4.9.51-10.52.amzn1.x86_64                                                                                                                                                                                                     1/1

Installed:
  kernel.x86_64 0:4.9.51-10.52.amzn1

Complete!

先ほどは、アップデートするカーネルはありませんでしたが、今回はアップデートされました。

再起動後に再度インスタンスにアクセスして、カーネルがアップデートされたか確認します。

$ ssh hogehost
Last login: Sat Jan 20 02:10:39 2018 

       __|  __|_  )
       _|  (     /   Amazon Linux AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2016.03-release-notes/
No packages needed for security; 138 packages available
Run "sudo yum update" to apply all updates.
Amazon Linux version 2017.09 is available.

$ uname -srv
Linux 4.9.51-10.52.amzn1.x86_64 #1 SMP Fri Sep 29 01:16:19 UTC 2017

カーネルは4.4.5から4.9.51に上がったようですね。ところがまだ最新ではないです。

またsshを行ったら、早速情報が更新されています。

No packages needed for security; 138 packages available
Run “sudo yum update” to apply all updates.

カーネルのアップデートではなく、パッケージのアップデートを勧められています。

全てのパッケージアップデートする

そこでカーネルだけれはなく全てのパッケージをアップデートさせます。

パッケージを全てアップデートすると既存で動いているサービスに影響を与えることがあるので、バージョンの依存関係があるパッケージについては除外しましょう

今回はカーネルを最新にアップデートさせることが目標なので、上記を考慮せずに全てのパッケージをアップデートします。

$ sudo yum update
Loaded plugins: priorities, update-motd, upgrade-helper
Resolving Dependencies
--> Running transaction check
---> Package acpid.x86_64 0:1.0.10-2.1.6.amzn1 will be updated
---> Package acpid.x86_64 0:2.0.19-6.7.amzn1 will be an update
・・・(省略)

# インストールとアップデートをするパッケージが一覧されるのでチェック
========================================================================================================================================================================================================================================================
 Package                                                                Arch                                            Version                                                                Repository                                          Size
========================================================================================================================================================================================================================================================
Updating:
 acpid                                                                  x86_64                                          2.0.19-6.7.amzn1                                                       amzn-main                                           73 k
 at                                                                     x86_64                                          3.1.10-48.15.amzn1                                                     amzn-main                                           66 k
 audit                                                                  x86_64                                          2.6.5-3.28.amzn1                                                       amzn-main                                          272 k
 audit-libs                                                             x86_64                                          2.6.5-3.28.amzn1                                                       amzn-main                                           96 k
・・・(省略)
Installing for dependencies:
 libXcomposite                                                          x86_64                                          0.4.3-4.6.amzn1                                                        amzn-main                                           21 k
 libidn2                                                                x86_64                                          0.16-1.2.amzn1                                                         amzn-main                                          103 k
 libnghttp2                                                             x86_64                                          1.21.1-1.4.amzn1                                                       amzn-main                                           73 k
 libseccomp                                                             x86_64                                          2.3.1-2.4.amzn1                                                        amzn-main                                           79 k
 libunistring                                                           x86_64                                          0.9.3-6.1.amzn1                                                        amzn-main                                          419 k
 perl-Time-HiRes                                                        x86_64                                          4:1.9725-272.5.amzn1                                                   amzn-main                                           46 k
 python27-futures                                                       noarch                                          3.0.3-1.3.amzn1                                                        amzn-main                                           30 k

Transaction Summary
========================================================================================================================================================================================================================================================
Install               ( 7 Dependent packages)
Upgrade  138 Packages

Total download size: 192 M

yum updateでは、インストールを始める前に、インストールとアップデートをするパッケージが一覧されます。
その後にアップデートするか選べるので、パッケージを確認してから、動いているサービスに影響がないか確認するといいと思います。

このままアップデートを実行します。

Is this ok [y/d/N]: y

Downloading packages:
(1/145): acpid-2.0.19-6.7.amzn1.x86_64.rpm                                                                                                                                                                                       |  73 kB     00:00
(2/145): at-3.1.10-48.15.amzn1.x86_64.rpm                                                                                                                                                                                        |  66 kB     00:00
・・・(省略)
  xfsprogs.x86_64 0:4.5.0-9.21.amzn1                              yum.noarch 0:3.4.3-150.70.amzn1                            yum-metadata-parser.x86_64 0:1.1.4-10.20.amzn1                  yum-plugin-priorities.noarch 0:1.1.31-40.29.amzn1
  yum-plugin-upgrade-helper.noarch 0:1.1.31-40.29.amzn1           yum-utils.noarch 0:1.1.31-40.29.amzn1

Complete!

全てのパッケージをアップデートしました。再起動を行い、再度sshします。

$ ssh hogehost
Last login: Sat Jan 20 02:17:24 2018 

       __|  __|_  )
       _|  (     /   Amazon Linux AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2017.09-release-notes/
10 package(s) needed for security, out of 34 available
Run "sudo yum update" to apply all updates.

$ uname -srv
Linux 4.9.51-10.52.amzn1.x86_64 #1 SMP Fri Sep 29 01:16:19 UTC 2017

カーネルのバージョンはかわっていませんが、

10 package(s) needed for security, out of 34 available
Run “sudo yum update” to apply all updates.

バージョンアップ後、さらにセキュリティ問題のためアップデートするように警告されていますね。

すべでのパッケージをアップデートしたことで、最新のカーネルにアップデートできるようになりました。

パッケージ全てをアップデートする(2回目)

最新のカーネルにアップデートするべく、再度アップデートします。

$ sudo yum update
Loaded plugins: priorities, update-motd, upgrade-helper
Resolving Dependencies
・・・(省略)

Installed:
  kernel.x86_64 0:4.9.77-31.58.amzn1

Dependency Installed:
  libtool-ltdl.x86_64 0:2.4.2-20.4.8.5.32.amzn1                                                                                     nss-pem.x86_64 0:1.0.3-4.3.amzn1

Updated:
  aws-cfn-bootstrap.noarch 0:1.4-27.19.amzn1      aws-cli.noarch 0:1.14.9-1.48.amzn1         curl.x86_64 0:7.53.1-13.80.amzn1               docker.x86_64 0:17.09.1ce-1.111.amzn1            docker-storage-setup.noarch 0:0.6.0-1.18.giteb688d4.amzn1
  ec2-net-utils.noarch 0:0.5-1.34.amzn1           ec2-utils.noarch 0:0.5-1.34.amzn1          ecs-init.x86_64 0:1.16.2-1.amzn1               irqbalance.x86_64 2:1.3.0-1.26.amzn1             java-1.7.0-openjdk.x86_64 1:1.7.0.161-2.6.12.0.75.amzn1
  kernel-tools.x86_64 0:4.9.77-31.58.amzn1        krb5-libs.x86_64 0:1.15.1-8.43.amzn1       libcurl.x86_64 0:7.53.1-13.80.amzn1            nss.x86_64 0:3.28.4-12.80.amzn1                  nss-softokn.x86_64 0:3.28.3-8.41.amzn1
  nss-softokn-freebl.x86_64 0:3.28.3-8.41.amzn1   nss-sysinit.x86_64 0:3.28.4-12.80.amzn1    nss-tools.x86_64 0:3.28.4-12.80.amzn1          nss-util.x86_64 0:3.28.4-3.53.amzn1              openssl.x86_64 1:1.0.2k-8.106.amzn1
  python27.x86_64 0:2.7.12-2.121.amzn1            python27-boto.noarch 0:2.48.0-1.2.amzn1    python27-botocore.noarch 0:1.8.13-1.66.amzn1   python27-devel.x86_64 0:2.7.12-2.121.amzn1       python27-libs.x86_64 0:2.7.12-2.121.amzn1
  ruby20.x86_64 0:2.0.0.648-1.30.amzn1            ruby20-irb.noarch 0:2.0.0.648-1.30.amzn1   ruby20-libs.x86_64 0:2.0.0.648-1.30.amzn1      rubygem20-bigdecimal.x86_64 0:1.2.0-1.30.amzn1   rubygem20-psych.x86_64 0:2.0.0-1.30.amzn1
  rubygems20.noarch 0:2.0.14.1-1.30.amzn1         system-release.noarch 0:2017.09-0.1        wget.x86_64 0:1.18-3.28.amzn1

Complete!

再起動してアップデートを反映させます。


$ ssh hogehost
Last login: Sat Jan 20 02:21:06 2018

       __|  __|_  )
       _|  (     /   Amazon Linux AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2017.09-release-notes/

$ uname -srv
Linux 4.9.77-31.58.amzn1.x86_64 #1 SMP Thu Jan 18 22:15:23 UTC 2018

カーネルもCPU脆弱性の対応がされた最新のバージョンになりました。

まとめ

今回2016年のAmazon LinuxのKernelを最新版にアップデートにするには以下のような流れです。

  • yum.conf更新(リリースバージョンを最新にする)
  • yum update(1回目。2016 → 2017にコミットされたバージョンをあげる)
  • yum update(2回目。2017 → 最新の2018にコミットされたバージョンをあげる。)

何回 yum updateが必要なのかは、管理しているインスタンスのバージョンによりますが、
OSのバージョンアップは早いうちからやっていた方が明らかに楽ですし、
パッケージを全てアップデートする場合は既存のサービスに影響を与える可能性もあります。

改めてセキュリティ対策は、コツコツアップデートしていかなければという学びを得ました。

また、sshの情報にしっかり目を通すことで、どうアップデートすべきかわかるので最新のOSに保ちつつ管理していきましょう。

続きを読む

環境構築201801 slackbot

はじめに

環境構築時のメモです。
* Amazon Linux AMI release 2017.09
* nvm 0.33.8 (201712)
* node v9.3.0 (201712) 
* redis v2.4.10(201712)
* hubot-slack v4.4 (201712)
* nginx v1.10.3 (201708)
* pyton v3.6.0 (201712)

初期設定

command
$ cat /etc/system-release1
$ sudo yum update -y
$ sudo yum install -y git

タイムゾーンをJSTに変更する。

command
$ sudo ln -sf  /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
$ sudo vi /etc/sysconfig/clock
---
ZONE="Asiz/Tokyo"
UTC=false
---

OSユーザ(例:hoge)作成

command
$ useradd hoge
$ sudo su - hoge
$ cd /home/hoge
$ mkdir .ssh
$ cd .ssh
$ ssh-keygen -t rsa
$ mv id_rsa.pub authorized_keys
$ chmod 600 authorized_keys
$ cat id_rsa ※内容を接続元PCに保存 hoge.pem
※puttyの場合
・Run PuTTYgenを起動
・Load an existing private file を読み込む(load)
・Save public key hoge.ppk
・上記ファイルを"Private key file for authentication"に設定する。
・wheelユーザに追加およびパスワードなしでsudoを利用できるようにする。
$ vi /etc/group
----
wheel:x:10:ec2-user,hoge
----
$ sudo visudo
---
# %wheel        ALL=(ALL)       NOPASSWD: ALL
%hoge      ALL=(ALL)       NOPASSWD: ALL
---

Nginxインストール

$ sudo useradd www
$ sudo groupadd www
$ sudo yum install nginx
$ sudo cp /etc/nginx/nginx.conf.default /etc/nginx/nginx.conf
$ sudo vi /etc/nginx/nginx.conf
---
server{
   listen    80;
   server_name localhost;
   root ***設置場所***;
   charset utf-8;
   index index.html index.htm index.php;
   access_log /var/log/host.access.log main;
}
---
$ sudo service nginx start
$ sudo chkconfig nginx on

redisインストール

$ sudo yum --enablerepo=epel install redis
$ sudo service redis start
$ sudo chkconfig --level 35 redis on
$ sudo chkconfig --list | grep redis

nodeインストール

$ git clone git://github.com/creationix/nvm.git ~/.nvm
$ vi .bashrc
---
if [ -f ~/.nvm/nvm.sh ];then
        source ~/.nvm/nvm.sh > /dev/null 2>&1
fi
---
$ source ~/.bashrc
$ nvm ls-remote nodeバージョン一覧表示
$ nvm install v6.9.0
$ nvm alias default v6.9.0  #恒久的な切り替え
$ nvm ls-remote
$ node -v
nvm自身のバージョンアップ
text
$ cd ~/.nvm
$ git pull origin master
$ source ~/.bashrc

Python3インストール

text
$ yum install gcc gcc-c++ make git openssl-devel bzip2-devel zlib-devel readline-devel sqlite-devel
$ git clone https://github.com/yyuu/pyenv.git ~/.pyenv
$ vi ~/.bashrc
---
export PYENV_ROOT="${HOME}/.pyenv"
if [ -d "${PYENV_ROOT}" ]; then
export PATH=${PYENV_ROOT}/bin:$PATH
eval "$(pyenv init -)"
fi
---
$ sudo yum install patch
$ pyenv install 3.6.0
$ pyenv global 3.6.0
$ pip install --upgrade pip
$ pip install bigquery-python
$ pip install beautifulsoup4
$ pip install jupyter
$ jupyter notebook --generate-config
$ python -c "from notebook.auth import passwd;print(passwd())" ※設定
$ vi ~/.jupyter/ 内に jupyter_notebook_config.py
---
c.NotebookApp.ip = '*'
c.NotebookApp.open_browser = False
c.NotebookApp.password = 'sha1:*******' ※
---

Slackbot構築

Slackにhubotアプリを追加

Add apps| Slack

hubot01png.png

hubot2.png

Hubotインストール

$ cd ~/.nvm/versions/node/(バージョン)/lib/node_modules
$ npm install hubot yo generator-hubot coffee-script hubot-slack
$ cd ~
$ mkdir hello-hubot
$ cd hello-hubot
$ yo hubot
$ vi external-scripts.json
---
heroku packageを削除
---
動作確認
$ vi ./scripts/examples.coffee
---
module.exports = (robot) ->
#(コメントアウトを外す) robot.hear /badger/i, (res) ->
#(コメントアウトを外す) res.send "Badgers? BADGERS? WE DON'T NEED NO STINKIN BADGERS"
---
$ export HUBOT_SLACK_TOKEN=<API Token>
$ ./bin/hubot -a slack 

Slackでbadgerを入力しリプライを確認
hubot3.png

SlackBot設置

slack からgoogle検索ができるか試す。
下記のアンプルコードを scriptsディレクトリに保存し、hubotを起動する。

./bin/hubot -a slack

サンプルコード|SlackBot

slackから作成したアプリに「search is ***」を送信するとreplyが届く。

hubot5.png

続きを読む

EC2 拡張ネットワーキング 有効化手順

EC2 拡張ネットワーキング 有効化手順

ちゃんとした情報は公式をみよう。

インスタンスタイプに応じて、ixgbevf ドライバ、もしくは amzn-drivers を利用出来る状態に設定し、AMIもしくはインスタンスに利用可能とフラグ付けを行う事によって拡張ネットワーキングが利用可能となる。

インスタンスタイプ ドライバ
c3/c4/d2/i2/r3/m4(16xlarge以外) ixgbevf
c5/f1/g3/h1/i3/m5/p2/p3/r4/x1/m4.16xlarge amzn-drivers

確認事項

Amazon Linuxの場合

通常、対応するためのカーネルモジュールがインストールされている為、作業は不要。

CentOS 6の場合

カーネルモジュールの更新が必要。

CentOS 7の場合

少なくとも 7.4.1708 以降ではカーネルモジュールがインストールされている為、作業は不要。

モジュールの確認

ixgbevfena のカーネルモジュールの状態を確認し、バージョン情報を確認する。
ixgbevf は特定のバージョン以下の場合はカーネルモジュールの更新が必要となる。

対応バージョン

ドライバ 必要バージョン
ixgbevf 2.14.2 以降
ena インストールされている事
$ modinfo ixgbevf
filename:       /lib/modules/3.10.0-693.11.6.el7.x86_64/kernel/drivers/net/ethernet/intel/ixgbevf/ixgbevf.ko.xz
version:        3.2.2-k-rh7.4
license:        GPL
description:    Intel(R) 10 Gigabit Virtual Function Network Driver
author:         Intel Corporation, <linux.nics@intel.com>
rhelversion:    7.4
srcversion:     45F26A06C9B8C3202EA1ADC
alias:          pci:v00008086d000015C5sv*sd*bc*sc*i*
alias:          pci:v00008086d000015A9sv*sd*bc*sc*i*
alias:          pci:v00008086d000015A8sv*sd*bc*sc*i*
alias:          pci:v00008086d00001564sv*sd*bc*sc*i*
alias:          pci:v00008086d00001565sv*sd*bc*sc*i*
alias:          pci:v00008086d00001530sv*sd*bc*sc*i*
alias:          pci:v00008086d00001515sv*sd*bc*sc*i*
alias:          pci:v00008086d0000152Esv*sd*bc*sc*i*
alias:          pci:v00008086d000010EDsv*sd*bc*sc*i*
depends:
intree:         Y
vermagic:       3.10.0-693.11.6.el7.x86_64 SMP mod_unload modversions
signer:         CentOS Linux kernel signing key
sig_key:        2C:BC:98:70:54:63:43:CA:3A:E1:20:C2:BC:EB:98:44:01:95:59:62
sig_hashalgo:   sha256
parm:           debug:Debug level (0=none,...,16=all) (int)
$ modinfo ena
filename:       /lib/modules/3.10.0-693.11.6.el7.x86_64/kernel/drivers/net/ethernet/amazon/ena/ena.ko.xz
version:        1.0.2
license:        GPL
description:    Elastic Network Adapter (ENA)
author:         Amazon.com, Inc. or its affiliates
rhelversion:    7.4
srcversion:     3A6B9F1766C9A0B5CBC7D01
alias:          pci:v00001D0Fd0000EC21sv*sd*bc*sc*i*
alias:          pci:v00001D0Fd0000EC20sv*sd*bc*sc*i*
alias:          pci:v00001D0Fd00001EC2sv*sd*bc*sc*i*
alias:          pci:v00001D0Fd00000EC2sv*sd*bc*sc*i*
depends:
intree:         Y
vermagic:       3.10.0-693.11.6.el7.x86_64 SMP mod_unload modversions
signer:         CentOS Linux kernel signing key
sig_key:        2C:BC:98:70:54:63:43:CA:3A:E1:20:C2:BC:EB:98:44:01:95:59:62
sig_hashalgo:   sha256
parm:           debug:Debug level (0=none,...,16=all) (int)

使用中のドライバ確認

利用可能なインスタンスタイプで起動している場合に、使用中のドライバを確認し、ixgbevf もしくは ena が使用されている事を確認する。
使用されていない場合(driverが vif となっている)は拡張ネットワーキングが有効になっていないので確認が必要。

無効時の例

$ ethtool -i eth0
driver: vif
version:
firmware-version:
bus-info: vif-0
supports-statistics: no
supports-test: no
supports-eeprom-access: no
supports-register-dump: no
supports-priv-flags: no

ixgbevfが有効時の例

$ ethtool -i eth0
driver: ixgbevf
version: 3.2.2-k-rh7.4
firmware-version:
expansion-rom-version:
bus-info: 0000:00:03.0
supports-statistics: yes
supports-test: yes
supports-eeprom-access: no
supports-register-dump: yes
supports-priv-flags: no

カーネルモジュールのインストール

事前準備

kernel kernel-headers kernel-develのバージョンを合わせる必要がある。

最新のkernelにアップデートする事を推奨しますが、旧カーネルの場合は kernel-headerskernel-devel をバージョン指定してインストールを行う事により対応が可能となる。

CentOS 6の中でも最新マイナーバージョン以下を利用する際はyumリポジトリが既にミラーから削除されている為、vault.centos.orgのリポジトリを利用する様に修正が必要となる。

# cat /etc/centos-release
CentOS release 6.2 (Final)

# sed -i.bak -E 's/^mirrorlist=/#mirrorlist=/' /etc/yum.repos.d/CentOS-Base.repo
# sed -i -E 's@^#?baseurl=http://mirror.centos.org/centos/$releasever/@baseurl=http://vault.centos.org/6.2/@' /etc/yum.repos.d/CentOS-Base.repo

CentOSのバージョンに合わせてsedの 6.2 となっている部分を修正する。

また、dkms によるカーネルアップデート時の自動コンパイル設定を行う事を推奨するため、epel リポジトリを有効化する。

準備

epelが設定されていない場合

# yum install -y epel-release
# sed -i -E 's/^enabled=1$/enabled=0/' /etc/yum.repos.d/epel*

各種パッケージのインストール

先にkernel-headersとkernel-develをインストールしておく。
また、ビルド時にperlが要求される場合があるので合わせてインストールする。

# yum install -y kernel-headers-$(uname -r) kernel-devel-$(uname -r) perl

既にkernel-headersがインストールされており、かつkernelよりバージョンが新しいものとなっている場合はダウングレードを行う。

# yum downgrade kernel-headers-$(uname -r)

dkmsはEPELからインストールを行う。

# yum --enablerepo=epel install -y dkms

ixgbevf のインストール

VER_IXGBEVF=4.3.3

curl -L -o "ixgbevf-${VER_IXGBEVF}.tar.gz" "https://downloads.sourceforge.net/project/e1000/ixgbevf%20stable/${VER_IXGBEVF}/ixgbevf-${VER_IXGBEVF}.tar.gz?r=https%3A%2F%2Fsourceforge.net%2Fprojects%2Fe1000%2Ffiles%2Fixgbevf%2520stable%2F${VER_IXGBEVF}%2Fixgbevf-${VER_IXGBEVF}.tar.gz%2Fdownload%3Fuse_mirror%3Djaist&ts=`date +%s`"
tar -xzvf ixgbevf-${VER_IXGBEVF}.tar.gz
rm -f ixgbevf-${VER_IXGBEVF}.tar.gz
mv ixgbevf-${VER_IXGBEVF} /usr/src/

echo 'PACKAGE_NAME="ixgbevf"
PACKAGE_VERSION="'${VER_IXGBEVF}'"
CLEAN="cd src/; make clean"
MAKE="cd src/; make BUILD_KERNEL=${kernelver}"
BUILT_MODULE_LOCATION[0]="src/"
BUILT_MODULE_NAME[0]="ixgbevf"
DEST_MODULE_LOCATION[0]="/updates"
DEST_MODULE_NAME[0]="ixgbevf"
AUTOINSTALL="yes"' | tee /usr/src/ixgbevf-${VER_IXGBEVF}/dkms.conf

dkms add -m ixgbevf -v ${VER_IXGBEVF}
dkms build -m ixgbevf -v ${VER_IXGBEVF}
dkms install -m ixgbevf -v ${VER_IXGBEVF}

amzn-drivers (ena) のインストール

VER_AMZN_DRIVERS=1.5.0

curl -L -o "ena_linux_${VER_AMZN_DRIVERS}.tar.gz" "https://github.com/amzn/amzn-drivers/archive/ena_linux_${VER_AMZN_DRIVERS}.tar.gz"
tar -xzvf ena_linux_${VER_AMZN_DRIVERS}.tar.gz
rm -f ena_linux_${VER_AMZN_DRIVERS}.tar.gz
mv amzn-drivers-ena_linux_${VER_AMZN_DRIVERS} amzn-drivers-${VER_AMZN_DRIVERS}
mv amzn-drivers-${VER_AMZN_DRIVERS} /usr/src/

echo 'PACKAGE_NAME="ena"
PACKAGE_VERSION="'${VER_AMZN_DRIVERS}'"
CLEAN="make -C kernel/linux/ena clean"
MAKE="make -C kernel/linux/ena/ BUILD_KERNEL=${kernelver}"
BUILT_MODULE_LOCATION[0]="kernel/linux/ena"
BUILT_MODULE_NAME[0]="ena"
DEST_MODULE_LOCATION[0]="/updates"
DEST_MODULE_NAME[0]="ena"
AUTOINSTALL="yes"' | tee /usr/src/amzn-drivers-${VER_AMZN_DRIVERS}/dkms.conf

dkms add -m amzn-drivers -v ${VER_AMZN_DRIVERS}
dkms build -m amzn-drivers -v ${VER_AMZN_DRIVERS}
dkms install -m amzn-drivers -v ${VER_AMZN_DRIVERS}

カーネルモジュールの有効化

depmod
cp /boot/initramfs-$(uname -r).img /boot/initramfs-$(uname -r).img.bak
dracut -f

この後、インスタンスを停止する。

拡張ネットワーキングの有効化

属性確認

インスタンスに属性が付与されているかを確認する。
属性が付与されていない場合は無効化されている状態のため、設定を行う。

これらはコンソール上では現れない情報の為、CLIにて作業を行う。

SriovNetSupport の確認

# aws ec2 describe-instance-attribute --attribute sriovNetSupport --region ap-northeast-1 --instance-id <インスタンスID>
{
    "InstanceId": "<インスタンスID>",
    "SriovNetSupport": {}
}

SriovNetSupportが空の場合は無効な為、有効化する必要がある。

EnaSupport の確認

# aws ec2 describe-instances --query 'Reservations[].Instances[].EnaSupport' --region ap-northeast-1 --instance-ids <インスタンスID>
[
]

EnaSupportが空の場合は無効な為、有効化する必要がある。

SriovNetSupport の設定

# aws ec2 modify-instance-attribute --sriov-net-support simple --region ap-northeast-1 --instance-id <インスタンスID>

# aws ec2 describe-instance-attribute --attribute sriovNetSupport --region ap-northeast-1 --instance-id <インスタンスID>
{
    "InstanceId": "<インスタンスID>",
    "SriovNetSupport": {
        "Value": "simple"
    }
}

EnaSupport の有効化

# aws ec2 modify-instance-attribute --ena-support --region ap-northeast-1 --instance-id <インスタンスID>

# aws ec2 describe-instances --query 'Reservations[].Instances[].EnaSupport' --region ap-northeast-1 --instance-ids <インスタンスID>
[
    true
]

属性の設定後、インスタンスを対応タイプで起動し、ethtool -i eth0 で確認する。

続きを読む