MFAとGoogle Authenticatorの仕組み

AWSのMFAで使用されるGoogle Authenticatorのワンタイムパスワード(TOTP)は、サーバとクライアントで共有する秘密鍵と現在時刻から確認コードを計算するアルゴリズム。

80ビットの秘密鍵をQRコード(16文字のBase32※(A-Z, 2-7))としてブラウザ上に表示し、サーバとクライアントに同じ秘密鍵が保存される。現在時刻は30秒ごとに値が変わるカウンターに変更されてから確認コードの6桁の数字が計算されてアプリに表示される。

※32種類の英数字のみを用いてバイナリデータを示す

TOTPに対応するサービスはGoogle, Amazon, Microsoft, Twitter, Instagram, Facebook, Dropbox, Github, WordPress, Slackなど。

K: 秘密鍵
TC: 現在時刻(UNIX TIME)
X: 時間ステップ(30)
T0: カウント開始時刻(0)
N: トークンの長さ(6)
ハッシュアルゴリズム: SHA-1

T = floor((TC – T0) / X)
H = HMAC-SHA-1(K, T)
TOTP = Truncate(H)
※RFC 4226 に定められている20バイト文字列から10進数N桁のトークンを得る関数

TOTPの実装方法についてClassmethodさんの解説
https://dev.classmethod.jp/articles/totp-implementation-pure-python/

自分でもやろうと思ったが、HMAC-SHA-1以降のTruncate関数の実装のところがうまくできない。

import os
import base64
import time
import math
import hmac
import hashlib

private_key = os.urandom(5) # 5byte = 80bit
private_key_base32 = (base64.b32encode(private_key))

t1 = time.time()
h = math.floor((t1 - 0) // 30)
sig = hmac.new(private_key_base32, str(h).encode('utf-8'), hashlib.sha1).hexdigest()

MFAが共通の秘密鍵とUnixTime、SHA-1のハッシュ関数からTruncate関数で10進数に変換して30秒ごとに表示しているということがわかりました。UNIXタイムを認証に使う場合、サーバ側とクライアント側でUnixタイムがずれていないことが前提となるため、どうやって担保するのが良いかわかりませんでしたが、アプリケーション側のユーザ認証でもAWSのMFAと同じような秘密鍵を共有した認証の仕組みが作れたら仕組みとして面白いのかなと思いました。

参考サイト
https://sekika.github.io/2016/03/26/GoogleAuthenticator/

AWS EC2インスタンスタイプの決め方

EC2のインスタンスタイプは用途別に集められた「インスタンスファミリー」とCPUなどのスペックを示す「インスタンスサイズ」から構成される。このインスタンスファミリーの数字は世代を表している。
数字が大きければ大きいほど新しい
t2, t3ではt3の方が新しい

### インスタンスタイプの種類
「汎用」、「コンピューティング最適化」、「メモリ最適化」、「高速コンピューティング」、「ストレージ最適化」の5種類がある
一般的な業務システムに適しているのは「汎用」「コンピューティング最適化」

### 汎用
「T3」「T2」 バーストできる。CPUクレジットを貯めておき、突発的に負荷が高まったときに貯めたCPUクレジットを消費して対応できる。コストが安い

「M5」「M4」 ネットワークをバランスよく提供

### コンピューティング最適化
「C5」「C4」: 性能が高いプロフェッサを積んでいる。高速処理が必須の場合、コストパフォーマンスに優れる。

### 機械学習
GPUインスタンスは、P3

### SAP
X1はSAP から、Business Warehouse on HANA (BW) 、Data Mart Solutions on HANA 、Business Suite on HANA (SoH) 、Business Suite S/4HANA を実行するための認定を受けているインスタンスファミリー

なるほど、勉強になるね。

AWS KMSを使ってみる

AWS KMSコンソールでキーを作成します。

Key policy, Cryptographic configuration, public keyが発行される

public key Publickey-*.pemをダウンロードして使用する。
user nameを設定しているので、ユーザのIDを指定してdecryptするのかな。
概要は何となく理解したが。

[Docker] CodeDeployとCodePipeline

buildspec.yml

version: 0.2

env:
  variables:
    AWS_REGION_NAME: ap-northeast-1
    ECR_REPOSITORY_NAME: hpscript
    DOCKER_BUILDKIT: "1"

phases:
  install:
    runtime-versions:
      docker: 19

  pre_build:
    commands:
      - AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' --output text)
      - aws ecr --region ap-northeast-1 get-login-password | docker login --username AWS --password-stdin https://${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/hpscript
      - REPOSITORY_URI=${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION_NAME}.amazonaws.com/${ECR_REPOSITORY_NAME}
      - IMAGE_TAG=$(echo ${CODEBUILD_RESOLVED_SOURCE_VERSION} | cut -c 1-7)
  
  build:
    commands:
      - docker image build -t ${REPOSITORY_URI}:${IMAGE_TAG} .
  post_build:
    commands:
      - docker image push ${REPOSITORY_URI}:${IMAGE_TAG}
      - printf '{"name":"%s","ImageURI":"%s"}' $ECR_REPOSITORY_NAME $REPOSITORY_URI:$IMAGE_TAG > imageDetail.json

artifacts:
  files:
    - imageDetail.json     

appspec.yaml

version: 1
Resources:
- TargetService:
    Type: AWS::ECS::Service
    Properties:
      TaskDefinition: <TASK_DEFINITION>
      LoadBalancerInfo:
        ContainerName: test-container
        ContainerPort: 80

taskdef.json

{
	"executionRoleArn": "arn:aws:iam::hoge:role/escTaskExectionRole",
	"containerDefinitions": [
		{
			"logConfiguration": {
				"logDriver": "awslogs",
				"options": {
					"awslogs-group": "/ecs/fuga-def",
					"awslogs-region": "ap-northeast-1",
					"awslogs-stream-prefix": "esc"
				}
			},
			"portMappings": [
				{
					"hostPort": 80,
					"protocol": "tcp",
					"containerPort": 80
				}
			],
			"cpu": 256,
			"readonlyRootFilesystem": true,
			"memoryReservation": 512,
			"image": "<IMAGE1_NAME>",
			"essential": true,
			"name": "app"
		}
	],
	"memory": "1024",
	"taskRoleArn": null,
	"compatibilities": [
		"EC2",
		"FARGATE"
	],
	"family": "test-def",
	"requiresCompatibilities": [
		"FARGATE"
	],
	"networkMode": "awsvpc",
	"cpu": "512"
}

$ tree
.
├── Dockerfile
├── appspec.yaml
├── buildspec.yml
├── index.html
└── taskdef.json

$ git push ${CODECOMMIT_REPO_URL}

### CodePipeline
Action: Deploy
Action provider: Amazon ECS(Blue/Green)
Region: Asia Pacific(Tokyo)
Input artifact: BuildArtifact, SourceArtifact

AWS CodeDeploy application name: AppECS-test-container-service
AWS CodeDeploy deployment group: DgpECS-test-container-service
Amazon ECS task definition: SourceArtifact
AWS CodeDeploy AppSpec file: SourceArtifact

Input artifact with image details: BuildArtifact
Placeholder text in the task definition: IMAGE1_NAME
Variable namespace: DeployVariables

### エラーメッセージ
An AppSpec file is required, but could not be found in the revision

What’s wrong with you?

リージョン障害とAZ障害

リージョンはある地域を示しており、複数のAZ(アベイラビリティゾーン)で構成
AZはデータセンター

東京リージョンは4つのAZから構成されているため、複数のAZを併用するマルチAZ構成を採っていれば、複数データセンターにまたがる冗長構成になるため、あるAZで障害が発生しても、システムが致命的な影響を受ける可能性を低くできる。

リージョン障害: リージョンに対して1つのインスタンスとして配置される場合などで障害が起きた場合、リージョン全体に影響を受ける

なるほど、AZ構成と、リージョン障害に備えることは別物なのね。

AWS DynamoDBとは?

– Managed NoSQLデータベース(Key Value Store)
– 3つのAZに分散して格納される

### DynamoDBを触ってみる
– table作成

テーブル名: Music
パーティションキー: Artist
ソートキー(任意設定): SongTitle
Default setting
-> Create Table

### DynamoDB操作
$ aws dynamodb put-item –table-name Music –item ‘{ “Artist”: { “S”: “Ryosuke” }, “SongTitle”: { “S”: “FirstSong” }}’
$ aws dynamodb put-item –table-name Music –item ‘{ “Artist”: { “S”: “Ryosuke” }, “SongTitle”: { “S”: “SecondSong” }}’
$ aws dynamodb put-item –table-name Music –item ‘{ “Artist”: { “S”: “Michael” }, “SongTitle”: { “S”: “FirstSong” }}’

$ aws dynamodb scan –table-name Music
$ aws dynamodb get-item –table-name Music –key ‘{ “Artist”: { “S”: “Ryosuke” }, “SongTitle”: { “S”: “SecondSong” }}’
$ aws dynamodb query –table-name Music –key-condition-expression ‘Artist = :Artist’ –expression-attribute-values ‘{ “:Artist”> : { “S”: “Ryosuke” }}’

ほうほう、なるほどー
Redisみたいな感じかー

GitlabからCodeCommitへミラーリング

1. CodeCommitでレポジトリを作成します

2. ミラーリングに必要な権限のIAMポリシー作成

{
  "Version": "2012-10-17",
  "Statement" : [
    {
      "Effect" : "Allow",
      "Action" : [
        "codecommit:GitPull",
        "codecommit:GitPush"
      ],
      "Resource" : "arn:aws:codecommit:ap-northeast-1:xxxx:mirroring"
    }
  ]
}

作成したポリシーのarnは後ほど使用する
arn:aws:iam::xxxx:policy/CodeCommitPolicy

IAM Userを作成する
name: gitlab-mirroring-user
credential type: Access key – Programmatic access
CodeCommitPolicyをattach

HTTPS Git credentials for AWS CodeCommit を作成

### Gitlab
project作成
Mirroring repositories

5分くらい時間がかかってるが、ちゃんと反映されている!
なんか、codecommit, pipelineでデプロイした方が良さそう