#はじめに
##何のページ?
「AWS触ってみたいけど何をしたらいいかわからない」という人向けにごくごく簡単なAmazon S3でウェブサイトを作る方法を記載します。
ウェブページだけだと何も面白くないので一応AWSでよく使うであろう以下のサービスも使ってログイン機能を実装して行きます。
このへんがわかれば後は気になるサービスをこの仕組みに組み合わせいくとより理解が深まると思います。
- API Gateway
- AWS Lambda
- DynamoDB
##料金について
以下の手順はアカウントを作って1年以内の人には基本的にはお金がかからないようにやってますが無料枠は変動するので随時確認してください。
以下の手順でAWSを利用して発生した損失や損害については一切の責任を負いかねます。
それではまずはウェブページを作って行きましょう。
#概要
まずはじめに作るシステムの概要を説明します。
AWSはたくさんのサービスがあり基本的にはそれらを組みわせて利用します。
今回はこのような組み合わせでDBに登録している人だけがログインできるサイトを作りましょう。
とりあえずは「4つのサービスを使うんだな」ぐらいの理解でよいです。
基本的にはこの図の右から順番にデータベース・サーバサイド関数・API・ウェブページという順番で作っていくと楽ですが、
今回はそれぞれのサービスのつながりを理解するためにあえて左側から作って行きます。
後この図は厳密には利用者端末から直接API Gatewayに矢印があって反対にS3とAPIの間は矢印がないのが正しいです。
(S3はあくまでウェブページ(HTMLファイルやJSファイル)を利用者の端末に送るだけでその送られたデータをもとに利用者端末からAPIにアクセスしておりS3が直接APIを呼んでいるわけではないため)
それはそれで少し分かりづらいかな?と思ったので下記のように並列でつないでます。
#AWSのコンソールにログインする
まずはAWSのコンソールにログインしましょう。
サインインページからログインしてください。
#ウェブページの作成(Amazon S3)
1.S3へのアクセス
まずはウェブページを作って行きましょう。
AWS マネジメントコンソールを開いて中央上部の検索ボックスに「S3」と入力してS3にアクセスします。
2.バケットの作成
まずはバケットを作ります。
Amazon S3のページに来たらバケットを作成ボタンを押します。
バケットとは簡単に言うとフォルダやファイルの集まりです。
詳しい説明はAmazon S3のご紹介をご覧ください。
バケットの作成ボタンを押したら作成画面に遷移すると思います。
作成画面に来たらバケット名に任意の名前を入力し、下の「パブリックアクセスをすべてブロック」を外しましょう。
そうするとチェックボックスの下側に警告が出てくるのですが今回は「静的ウェブサイトホスティング」を行うので、
「現在の設定により、このバケットとバケット内のオブジェクトがパブリックになる可能性があることを承認します。」にチェックをしましょう
他の設定は変更しなくてよいので一番下までスクロールし右下の「バケットを作成」ボタンを押しましょう。
そうするとバケットができるはずなのでこのリンクを押します。
下までスクロールして「静的ウェブサイトホスティング」の「編集する」ボタンを押します
「有効にする」を押します。
インデックスドキュメントとエラードキュメントにそれぞれ「index.html」「error.html」と入力します。
インデックスドキュメントとは特定のページをリクエストされなかった場合に表示されるページのことです。
詳しくはインデックスドキュメントの設定を御覧ください。
エラードキュメントについても同様に今回は利用しませんが必須項目なので設定します。
詳しくはカスタムエラードキュメントの設定を御覧ください。
すべての設定が終わったら下へスクロールし「変更の保存」を押します。
次にアクセス許可を編集します。
ページ上部の「アクセス許可」を押します。
中間までスクロールすると「バケットポリシー」という項目があるので「編集する」ボタンを押します。
ポリシーテキストエリアに以下の内容を貼り付けます
「otameshi1」のところは自身が設定したバケット名にしてください。
(テキストエリアのすぐ上に「バケットARN」という項目があるのでそこを見るとバケット名がわかります)
貼り付けてバケット名を書き換えたら「変更の保存」ボタンを押してください。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::otameshi1/*"
]
}
]
}
##3.HTMLファイルの作成
htmlファイルを作成しましょう。
何でも良いのでメモ帳を開いて以下の文章をコピーして貼り付け、
ファイル名を「index.html」として保存してください。
<html>
<head>
<meta charset="UTF-8" />
</head>
<body>
<form>
<input type="text" placeholder="ID" id="userID" />
<input type="password" placeholder="PassWord" id="password" />
<button>ログイン</button>
</form>
</body>
</html>
##4.HTMLファイルのアップロード
ブラウザからコンソールにログインします。
画面上部の検索画面に「S3」を入力しAmazonS3のページへ移動します。
先程作成したバケットの名前をクリックしてバケットのページで移動します。
移動したらアップロードボタンを押して先程作成した「index.html」をアップロードします。
バケットのメイン画面に戻ってくるはずなので上部のプロパティを押します。
プロパティのページを一番下までスクロールすると「静的ウェブサイトをホスティング」という項目があります。
この項目にあるURLを押してテキストボックスが2つとボタンが一つ並んだページが表示されれば成功です。
ここまでの手順を行うことで簡単にウェブサイトを作ることができます。
ただこれだけでは本当にただのウェブページですのでちゃんとログイン機能を作って行きましょう。
#APIの作成(API Gateway)
次にAPI GatewayでAPIを作っていきましょう。
APIとはものすごく雑に言うとアプリケーションとプログラムの窓口のようなものです。
今回は先程作成したウェブページと後に作成するLambda関数の仲介窓口を作ります。
詳しくはAmazon API Gateway とは何ですか?を御覧ください。
##1.APIの作成
ブラウザからAWS マネジメントコンソールにアクセスします。
画面上部の検索ボックスに「API Gateway」と入力してAPI Gatewayのページへ移動します。
遷移したら右上のオレンジ色の「APIを作成」ボタンを押します。
「APIを作成」ボタンを押すと「APIタイプ選択ページ」が表示されます。
今回は「REST API」を選択します。
このとき(プライベート)を選ばないよう気をつけてください
作成画面が出てくるのでAPI名を任意で入力して「APIの作成」を押してください。
アクションからメソッドの作成を選択します。
するとリストボックスが出てきます。
今回はPOSTを選びましょう。
POSTを選択するとリストボックスの横にチェックマークが表示されるので押します。
チェックマークを押すと右側にセットアップが出てきて統合タイプが選べます。
統合タイプとはこのAPI(窓口)の接続先です。
今は統合タイプをMockにします。
Mockとはお試し用のタイプです。
最終的には統合タイプはLambda関数に変更しますが今はまだ関数ができていないのでMockにします。
Mockを選ぶと保存ボタンが押せるようになるので保存ボタンを押します。
押すとこういう画面になるので右下の「統合レスポンス」をクリック
統合レスポンスを押すと統合レスポンスの設定画面に移動します。
まずは上の矢印を押して詳細を表示します。
そこからマッピングテンプレートの「application/json」をクリックします。
application/jsonをクリックすると右側にテキストエリアが現れるので以下の内容をコピー&ペーストしてください。
貼り付けたら右下の保存ボタンを押してください。
保存ボタンを押したら左上のメソッドの実行を押して戻りましょう。
{
"Message":"これはMockです"
}
次にCORSの有効化を行い先程作成したウェブサイトからでもこのAPIを実行できるようにします。
アクションから「CORSの有効化」を選択します。
POSTにチェックが入っていることを確認して右下の「CORSを有効にして既存のCORSヘッダーを置換」を押します。
##2.APIをデプロイする
最初に作ったウェブページから先程作ったAPIを呼び出して見ましょう。
このAPIを呼び出すためには色々やり方はあるのですが、
今回はAPI Gatewayが用意してくれるSDKを利用しましょう。
基本的な手順はAPI の JavaScript SDK の生成と同じです。
API Gatewayの先程作成したAPIのページでデプロイを選びましょう。
おそらくステージを作っていないのでステージを作るように言われます。
ステージとは窓口そのもので一つのAPIで複数のステージに対してデプロイできます。
例えば本番ステージと開発ステージを作っておき本番ステージには動作確認がとれたものをデプロイし、
開発には現在試験中のものをデプロイするといった使い分けができます。
今回はステージは一つしか使わないので任意の名前をつけてください。
作成するとこういう画面になると思うので「SDKの生成」を押します。
プラットフォームを選択するリストが出てくるので「JavaScript」を選択して「SDKの生成」を押します。
するとフォルダがダウンロードされます。
以下のようなデータがダウンロードできていれば成功です。
##3.ウェブページにAPI呼び出し機能を追加する
S3の最初に作ったバケットのページへ行きます。
先程の「lib」フォルダと「apigClient.js」をアップロードします。
以下のようになっていればOKです。
最初に自身のパソコンのメモ帳で作成した「index.html」を再度メモ帳で開きます。
そして以下の内容に変更します。
<html>
<head>
<meta charset="UTF-8" />
<!--先程アップロードしたJavaScriptファイルを読み込む Start-->
<script type="text/javascript" src="lib/axios/dist/axios.standalone.js"></script>
<script type="text/javascript" src="lib/CryptoJS/rollups/hmac-sha256.js"></script>
<script type="text/javascript" src="lib/CryptoJS/rollups/sha256.js"></script>
<script type="text/javascript" src="lib/CryptoJS/components/hmac.js"></script>
<script type="text/javascript" src="lib/CryptoJS/components/enc-base64.js"></script>
<script type="text/javascript" src="lib/url-template/url-template.js"></script>
<script type="text/javascript" src="lib/apiGatewayCore/sigV4Client.js"></script>
<script type="text/javascript" src="lib/apiGatewayCore/apiGatewayClient.js"></script>
<script type="text/javascript" src="lib/apiGatewayCore/simpleHttpClient.js"></script>
<script type="text/javascript" src="lib/apiGatewayCore/utils.js"></script>
<script type="text/javascript" src="apigClient.js"></script>
<!--読み込んだJavaScriptを利用してAPIを叩く-->
<script type="text/javascript">
function Login()
{
//APIを利用するためのクライアントを生成する
let apigClient = apigClientFactory.newClient();
//入力内容を取得してAPIに渡せる形に整形する
let body =
{
"UserID" : document.getElementById("userID").value,
"Password" : document.getElementById("password").value
};
//生成したクライアントを利用してAPIを叩く
apigClient.rootPost({}, body, {})
.then(function(result){
//取得が成功した場合メッセージエリアの内容を書き換える
let msg;
if("Message" in result["data"]) msg = result["data"]["Message"];
else if("body" in result["data"]) msg = result["data"]["body"];
document.getElementById("msg").innerHTML=msg;
}).catch( function(result){
//This is where you would put an error callback
document.getElementById("msg").innerHTML="メッセージの取得に失敗しました";
});
return false;
}
</script>
</head>
<body>
<input type="text" placeholder="ID" id="userID" />
<input type="password" placeholder="PassWord" id="password" />
<button type="button" onClick="Login()">ログイン</button>
<p id="msg">ログインしてください</p>
</body>
</html>
書き換えたらS3にアップロードして上書きします。
上書きしたらプロパティを選択します。
プロパティのページを一番下までスクロールすると「静的ウェブサイトをホスティング」という項目があります。
この項目にあるURLを押してテキストボックスが2つとボタンが一つ並んだページが表示されているはずです。
ここでログインボタンを押して「これはMockです」と表示されれば成功です。
今後このテキストボックスとボタンが並んだページ(以下 バケットのページ)は数回見るのでブックマークなどをしておきましょう。
#Lambda関数
##1.関数の作成
データベースからデータを取得するためにLambda関数を作成します。
AWSのコンソールページの上部の検索ボックスに「Lambda」と入力してLambdaページへ移動します。
Lambdaのメインページに移動したら「関数の作成」ボタンを押下します。
今回は「一から作成」を選択します。
関数名は任意の関数名を設定します。
ランタイムは「Python 3.7」に設定します。
0からではなく1から作るなので一応こんなふうにハローワールドみたいなことは書いてあります。
とりあえずこれでまずはAPIと接続してみます。
##2.APIと関数の接続
AWSコンソールページの上部の検索ボックスに「API Gateway」と打ち込みAPI Gatewayのページへ移動します。
API GateWayのページへ行き先程作成したAPIを選びます。
APIのページへ遷移します。
右側の「POST」を押します。
右上の統合リクエストをクリックします。
統合タイプをLambda関数に変更します。
リージョンを「ap-northeast-1」に変更します。
Lambda関数に先程作成した関数の名前を入力します。
保存ボタンを押下します。
色々出てきますがすべてOKを押します。
すべて完了したら左上の「メソッドの実行」を押して戻ります。
稲妻マークが付いた「テスト」を押します。
右側のページが「POST メソッドテスト」に変化したら稲妻マークのついたテストを押します。
レスポンス本文に「Hello From Lambda」が表示されていれば成功です。
ここまでできたら画面上部のアクションから「APIのデプロイ」を選択します。
デプロイされるステージで先程作成したステージを選択し「デプロイ」ボタンを押します。
デプロイが終わったらバケットのページへ移動しもう一度ログインボタンを押します。
「"Hello from Lambda!"」と表示されていれば成功です。
#データベースの作成
データベースを作ります。
AWSには色んなデータベースに関するサービスがあります。
今回は25GBまでは無料で使える(2021年1月1日現在)という理由だけでDynamoDBを選びます。
##1.テーブルの作成
これまでと同じようにAWSページの中央上部にある検索ボックスで「DynamoDB」と入力してDynamoDBのページへ移動します。
「テーブルの作成」ボタンを押します。
テーブル名は「UserMaster」にします。
パーティションキーは「UserID」にします。
他の設定はデフォルトでよいので右下の「作成」ボタンを押します。
テーブルの作成は10秒ほどかかるので少し待ちましょう。
##2.項目の作成(レコードの追加)
作成が終わったら項目タブを選択します。
「項目の作成」ボタンを押します。
UserIDに「ABC」を入力します。
UserIDの右側にあるプラスボタンを押します。
メニューから「Append」を選択します。
さらにStringを選択します。
すると列名を入力できるようになるので「Password」と入力します。
Passwordには「XYZ」を入力します
同様に「Name」列を追加して「ユーザ1」と入力します。
最終的に以下のような形になっていればOKです。
内容を確認して右下の保存ボタンを押します。
これでレコードが一つできました。
##3.LambdaからDBを呼び出す権限を付与する
Lambdaのページに切り替えます。
(画面中央の検索テキストボックスで検索する他に左上のサービスからも選ぶことができます)
関数から先程作った関数をクリックします。
アクセス権限タブをクリックします。
検索ボックスにDynamoDBと入力します。
検索でヒットした仲の「AmazonDynamoDBFullAccess」を選択します。
右下の「ポリシーのアタッチ」をクリックします。
Lambdaのページに戻ります。
関数コードを以下のように書き換えます。
import json
import boto3
from boto3.dynamodb.conditions import Key
def lambda_handler(event, context):
try:
resultMessage = login(event)
return {
'isBase64Encoded': False,
'statusCode': 200,
'headers': {},
'Message': '"' + resultMessage + '"'
}
except Exception as e:
print(e)
def login(event):
#入力内容の検証
if event["UserID"] == "":
return "ユーザIDを入力してください"
# テーブルオブジェクトの生成
dynamoDB = boto3.resource("dynamodb")
dynamotable = dynamoDB.Table("UserMaster")
# 検索条件の設定(UserIDのみで検索する)
partition_key = {"UserID": event["UserID"]}
# 検索の実行
res = dynamotable.get_item(Key=partition_key)
# 取得結果の確認
if res is None :
return "ユーザが見つかりません"
elif "Item" not in res :
return "ユーザが見つかりません"
elif len(res["Item"]) < 1:
return "ユーザが見つかりません"
elif res["Item"]['Password'] != event["Password"]:
return "パスワードが違います"
else:
return "こんにちは" + res["Item"]['Name'] + "さん"
書き換えたらデプロイボタンを押します。
これでこの関数が上書きされます。
##最終確認
バケットのページを開きましょう。すでに開いている場合は更新してください。
ユーザIDに「ABC」パスワードに「XYZ」と入力してログインボタンを押し、
「こんにちはユーザ1さん」と表示されれば完了です。
後は各種サービスの設定を好きなように変更して自由にウェブサイトを作って見ましょう。
今回はとりえず言われたとおりにやっただけなので特に不具合もない(はず)ですが本来は不具合が出た箇所を調査したり
不具合がないかどうかを予め試験することが必要です。
今後は不具合の調査方法や試験の手順についても記載していこうと思います。
それでは、お疲れさまでした。