.rute1/

キャリア/心理学/読書/Pythonなどなど

Cloud9から既存EC2(tokyo)に初回設定のSSHができない問題を解決

Cloud9から既存EC2(tokyo)に初回設定のSSHができない

Tokyoリージョンに立てた開発用のEC2にCloud9(シンガポールリージョン)からの初期設定のSSHができなくて困りました。
以下のことを行うことで設定できました。

  • nodejsがEC2に入っていることを確認する
    • node -v
  • /home/user/.ssh/authorized_keys にコンソールからコピーした公開鍵を貼る
  • セキュリティーグループのTCP,PORT 22を一旦0.0.0.0/0に解放する
  • Environment pathはデフォルトで/home/ec2-userを見に行くため、ubuntucentosの場合やユーザー名を変更している場合は個別で設定する。
    • /home/ubuntu

セキュリティグループ をよりセキュアに設定したい

セキュリティグループ が0.0.0.0/0に解放したままでは危険のため、セキュリティグループ の設定をAWSシンガポールリージョンのCloud9のIPのみに設定します。
AWSのIP範囲はこちらから確認できます。
AWS IP アドレスの範囲 - アマゾン ウェブ サービス
このドキュメントの通りに、jsonからIPを抜き出します。

# 一旦jsonをファイルに保存
curl https://ip-ranges.amazonaws.com/ip-ranges.json > ip-ranges.json

# Linux等、jqが使える場合
jq -r '.prefixes[] | select(.region=="ap-southeast-1") | select(.service=="CLOUD9") | .ip_prefix' < ip-ranges.json

>>> 13.250.186.128/27
>>> 13.250.186.160/27

これで、13.250.186.128/27と13.250.186.160/27に対してセキュリティグループ のTCP, Port 22を解放すればOKです。
Cloud9のリージョンがシンガポール以外の場合は.region==""の部分を適宜変更してください。

AWS クロスアカウント権限管理 「リソースポリシーからrootに許可するパターン」編

クロスアカウントで色々いじっていて、IAMの権限管理についてのパターンがなんとなくわかってきたのでメモします。

クロスアカウントでの権限管理は色々なパターンがあるようですが、今回扱うのは「AアカウントのリソースポリシーでBアカウントのrootを許可→Bアカウントの中でポリシーアタッチ」のパターンです。

具体的に見ていきましょう。まずはよくあるS3のパターンです。

別アカウントのS3バケットにLambdaからアクセスする

ここではアカウントID:111111111111アカウント1からアカウントID:0000000000000000アカウント0のS3バケットにアクセスしたいとします。 f:id:rutei:20190105180724p:plain
アカウント0のコンソールで、S3のバケットポリシーを以下のように設定します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Example permissions",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::1111111111111:root"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::BUCKET_NAME/*"
        }
    ]
}

ここではアカウント1のrootユーザーに対してS3バケットへのアクセスを許可しています。

次に、許可をもらったアカウント1のコンソールで以下のポリシーを作成し、S3バケットにアクセスするLambdaにアタッチします。

{
    "Version": "2012-10-17",
    "Statement": [ 
            {
            "Action": [
                "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::BUCKET_NAME/*",
            "Effect": "Allow"
        }
    ]
}

これで、ポリシーをアタッチされたLambdaはアカウント0のS3バケットに対してアクセスすることができるようになります。
まずはアカウントのrootユーザーに権限を与える → 権限を得たroot(admin)ユーザーがリソースに対して権限を与えるという流れでわかりやすいと思います。
もちろん、最初にバケットポリシーで許可したActionしかできないようになっているので、例えば今回の場合s3:GetObject以外の操作権限はLambda にもrootユーザーにも与えられていません。
LambdaからObjectを新たにPUTしたりするためには、再びアカウント0の管理者にバケットポリシーからs3:PutObjectを許可してもらう必要があります。

別アカウントのLambdaにLambdaからアクセスする

先ほどと同様にアカウント1のLambdaからアカウント0のLambdaにアクセスしたいとします。
f:id:rutei:20190105181018p:plain
Lambdaの場合はリソースポリシーというものがあるので、ここで、アカウント1のrootユーザーに権限を与えます。
参考: AWS Lambda でリソースベースのポリシーを使用する (Lambda 関数ポリシー) - AWS Lambda この操作は現在AWS CLIAPIでしか行えないようです。

aws lambda add-permission \
--function-name FUNC_NAME \
--statement-id Example permissions \
--action lambda:InvokeFunction \
--principal 111111111111 \
--output json 

上記のコマンドを実行すると以下のjsonが返ってきます。

{
    "Statement": "{\"Action\":[\"lambda:InvokeFunction\"],
                   \"Resource\":\"arn:aws:lambda:YOUR_REGION:000000000000:function:FUNC_NAME\",
                   \"Effect\":\"Allow\",
                   \"Principal\":{\"AWS\":\"111111111111\"},
                   \"Sid\":\"Example permissions\"}"
}

CLIなので、見ためは違いますが、やっていることとしては先ほどのバケットポリシーと対して変わりません。アカウント1のrootユーザーに対してアカウント0のLambdaへのlambda:InvokeFunctionの権限を与えています。
次に、アカウント1のコンソールから、Lambda(アクセスする方)の実行ロールにアカウント0のLambdaへアクセスする権限を与えるポリシーをアタッチします。

{
    "Version": "2012-10-17",
    "Statement": [ 
        {
            "Action": [
                "lambda:InvokeFunction"
            ],
            "Resource": "arn:aws:lambda:YOUR_REGION:000000000000:function:FUNC_NAME",
            "Effect": "Allow"
        }
    ]
}

これで、アカウント1のLambdaからアカウント0のLambdaにアクセスすることができるようになります。

おまけ: kmsのキーポリシーをIAMポリシーで管理する

実はクロスアカウントの権限管理以外にも、似たような権限の与え方をするパターンがあります。
それが、KMSのキーポリシーです。
AWSでは若干複雑なことに、KMSで作ったCMKに対する権限をKMSのキーポリシーで管理するということになっています。
ただ、特にLambdaに関しては実行ロールに付与されているIAMポリシーでLambdaの権限を管理できた方がわかりやすいため、IAMポリシーで管理できた方が便利だと思います。
そういった場合に、キーポリシーをIAMポリシーで管理できるようにするキーポリシーの書き方が以下です。

{
  "Sid": "Enable IAM User Permissions",
  "Effect": "Allow",
  "Principal": {"AWS": "arn:aws:iam::111111111111:root"},
  "Action": "kms:*",
  "Resource": "*"
}

これで、IAMポリシーでKMSのCMKの権限を管理できるようになります。 Lambdaの実行ロールには以下の権限を付与します。

{
    "Version": "2012-10-17",
    "Statement": [
         {
            "Action": [
                "kms:*"
            ],
            "Resource": "arn:aws:kms:YOUR_REGION:111111111111:key/xxxxxxxxxx",
            "Effect": "Allow"
        }
    ]
}

【Python】responder でHello, World ! 0.0.0.0をhostに指定する方法

responder でHello World! 0.0.0.0をhostに指定する方法

人間のためのイケてるPython WebFramework「responder」、そして作者のKenneth Reitzについて - フリーランチ食べたい

こちらの記事で話題になっているresponderを早速試して見ました。
Hello World ! するまでに2つひっかかったポイントがあったので、共有します。
ちなみにresponderどころかDjangoもFlaskも使ったことのない初心者なので、おかしな内容になっているかもしれません。ご容赦ください。
※2018年12月2日時点での情報です。

環境 * AWS EC2 Ubuntu Server 18.04 LTS (HVM), SSD Volume Type * Python 3.6.5

ModuleNotFoundError: No module named 'starlette.lifespan'

とりあえずこちらのクイックスタート通りにHello World ! を書いてみました。   Quick Start! — responder 1.1.2 documentation

import responder
api = responder.API()
@api.route("/")
def hello_world(req, resp):
    resp.text = "hello, world!"
api.run()

実行したところModuleNotFoundError: No module named 'starlette.lifespan’というエラーが出てしまいました。
これはgithubのissueにもあげられていました。
ModuleNotFoundError: No module named ‘starlette.lifespan’ · Issue #255 · kennethreitz/responder · GitHub.

problem solved by using starlette 0.8 version

とりあえず今のところはstarletteのバージョン0.8を使えば解決するようです。
pip install starlette==0.8

hostに0.0.0.0を指定したい

ubuntu@ip-172-31-43-88:~/dev/test$ python hello.py
INFO: Started server process [17400]
INFO: Waiting for application startup.
INFO: Uvicorn running on http://127.0.0.1:5042 (Press CTRL+C to quit)

これはEC2を開発環境にしていると毎回困ることなのですが、localhost127.0.0.1にアクセスするのが困難です。
0.0.0.0を開くようにしないとローカルのブラウザから確認できません。

Responderのコードを読むと、どうやら環境変数として”PORT”が設定されている場合は0.0.0.0:PORTが開かれ、それでない場合は127.0.0.1:5042になるようです。

if "PORT" in os.environ:
    if address is None:
        address = "0.0.0.0"
        port = int(os.environ["PORT"])

if address is None:
    address = "127.0.0.1"
if port is None:
    port = 5042

ということで適用にわかりやすいPORTを設定して、

ubuntu@ip-172-31-43-88:~/dev/test$ export "PORT"=10001

EC2のセキュリティグループも変更します。 f:id:rutei:20181202020216p:plain

そしてブラウザからアクセスすると、 f:id:rutei:20181202020213p:plain

Hello World ! が無事表示されました 。

ubuntu@ip-172-31-43-88:~/dev/test$ python hello.py
INFO: Started server process [17405]
INFO: Waiting for application startup.
INFO: Uvicorn running on http://0.0.0.0:10001 (Press CTRL+C to quit)
INFO: ('m.y.i.p', 53094) - "GET / HTTP/1.1" 200

追記: api.run()の引数にaddressとportを与えても同様のことができるようです。

api.run(address='0.0.0.0',port=10001)

【Python】requestsでボタンを擬似クリック

requestsでボタンを擬似クリック

Beautiful Soupでhrefが取得できないボタン等のクリック動作をrequestsで再現する方法を調べたので、まとめます。

hrefが取得できないボタン

例えばこのページの「CSVダウンロード」ボタン部分などはBeatiful Soupでもhrefが取得しにくいためにrequestsでのスクレイピングが困難です。
CSVダウンロード f:id:rutei:20181130205349p:plain

csvダウンロード」ボタンのソースコードはこのようになっています。

<input class="btn btn-primary" type="submit" value="CSVダウンロード">

おそらくこのボタンを押すとなんらかのscriptが動いてダウンロードが始まるものと思います。
requestsでこのボタンをクリックするという動作を再現することはできないので、seleniumを使うといった選択肢をとることが多いかもしれませんが、場合によってはrequestsだけでボタンをクリックしたのと同等の通信を再現することができます。
以下がその方法です。

crhomeデベロッパーツールでnetworkを見てみる

f:id:rutei:20181130205413p:plain

デベロッパーツールを表示した状態でボタンをクリックすると、networkタブでどのような通信が行われているか確認することができます。
今回のダウンロードもバッチリURLを確認することができました。
URLはhttps://www.itdashboard.go.jp/Csv/downloadで、ここにPOSTでdataを送れば良さそうです。
cookieなどはrequestsのsession()を使えば処理してもらえます。
POSTで送るdataもデベレッパーツールから確認できます。
f:id:rutei:20181130205424p:plain

最終的なコードはこのようになりました。

import requests

# ページにアクセス
session = requests.Session()
res = session.get('https://www.itdashboard.go.jp/DataFeeds/csv')
res.raise_for_status() # エラーならここで例外を発生させる

# dataに項目をセット
data = {
    "_method": "POST",
    "year": "",
    "modelname": "BasicInformationAll"
}

# クリック時の通信
res = session.post('https://www.itdashboard.go.jp/Csv/download', data=data)
res.raise_for_status() # エラーならここで例外を発生させる

# レスポンスで返ってきたコンテンツをcsvとして保存
contentType = res.headers['Content-Type']
contentDisposition = res.headers['Content-Disposition']
ATTRIBUTE = 'filename='
fileName = contentDisposition[contentDisposition.find(ATTRIBUTE) + len(ATTRIBUTE):]

with open(fileName, 'wb') as saveFile:
        saveFile.write(res.content)

ファイルを保存する部分はこちらの記事を参考にしました。
Pythonのrequestsを利用してファイルダウンロードする方法 - Qiita

【GitHub】commit履歴にアイコンや名前が正しく表示されなくなった時の対処法

GitHubのアイコンが表示されない

最近、GitHubのcommit履歴で、自分のアイコンや名前が正しく表示されなくなりました。

以下のコミットは全て私のものなのですが、アイコンが表示されている時と表示されていない時があります。

commit履歴のアイコンが正しく表示されず、デフォルトの表示になっている。マウスオーバーしても、ユーザーネームが表示されない。
アイコンがデフォルト表示になっている

調べて見るとどうやらgit configを正しく設定していないことが原因だとわかりました。

私はMac OSAWSのEC2でgitを操作していたのですが、Mac OSではgit configを設定できていたのでアイコンや名前が表示されていて、EC2ではgit configを設定していないためにアイコンや名前が表示されなかったようです。

git configの設定を行うと、正常にアイコンが表示されるようになりました。 ギットコンフィグを正しく設定したら、正常にアイコンが表示されるようになった。

 

git configコマンドによる設定

私が設定したgit configのコマンドは以下の通りです。

$ git config --global user.name "Tanaka Tarou" #GitHubに登録したユーザーネーム
$ git config --global user.email Taro@example.com #GitHubに登録したメールアドレス

ちなみに現在どう設定されているかは

$ git config user.name
$ git config user.email

で確認することができます。 上記のコマンドを打っても何も返ってこなければgit configの設定がされていないことになります。

git configは奥が深いらしく設定ファイルの置き場所や設定項目は他にも色々あるようです。 詳しくは以下のサイトが参考になります。

参考にしたサイト:Gitの設定をgit configで確認・変更 | note.nkmk.me

 

MacBook Pro のキーボードの隙間にホコリが入る問題を解決した Maxkuキーボードカバー

今年の4月に MacBook Pro 13 inch (2017年モデル)を購入して仕事で使用しています。

機能的にはとても満足しているのですが一つだけかなり気がかりな点がありました。

キーボードの隙間に細かいホコリが入り込んでしまうことです。

こういった小さい埃の入り込みによってキーボードが押せなくなったり、あるいは二度と入力することができなくなったりする不具合も発生するようです。ただでさえMacbook Proはキーボードの不具合が公式に認められているので、神経質になってしまいます。

 

MacBook および MacBook Pro キーボード修理プログラム - Apple サポート

 

 

公式がサポートしてくれるのはまあ良いことなのですが毎日仕事で使用しているので数日使えなくなるような状況になるのも困ります。

そこでキーボードの隙間へのホコリの入り込みそのものの防止するような解決策はないか探しました。

その結果こんなものが見つかったので購入してみました。

 

 

 

 

これはシリコン製のカバーで、キーボードの上に乗っけて使います。

特に何かで固定するわけではないのですが、薄くキーボードの凹凸に沿って忠実に作られているので意図的に剥がそうとしない限りは外れてしまうことは滅多にないと思います。

これを常に貼り付けて PC を使用すればほこりが入ることもなくなるし、またうっかり飲み物などをこぼしてしまった時にもキーボードが浸水する恐れはありません。

気になるタイピングの感触の変化ですが、最初の数回は若干の違和感を感じることはあったものの慣れてしまえばほとんど日常の仕事には影響はない程度でした。またカバーの厚みも数ミリ程度なのでつけたまま PC を閉じることができます。

 

アマゾンのレビューによると数ヶ月間使用するとシリコンの形状が変化しキーボードから浮き上がってしまうこともあるようです。私は今のところ2ヶ月弱使用していますが確かに一部のキーが浮き上がってしまっている箇所もあります。

とはいえ、1000円弱の値段で購入することができたので私はそこまで 気にしていません。むしろ製品自体は気に入っているので買い替えに備えてもう一つ同じ商品を購入しました。

これである程度キーボードへのホコリ侵入問題は解決できたかなと思います。

 

 

f:id:rutei:20180629012135j:plain

色にこだわりはなく青のグラデーションカラーを選んだのは単に最も安かったからという理由だけなのですが、実際に使ってみると意外にも評判が良く褒められることが多いので気に入りました。

2016モデル向けの商品ですが、2017モデルでも問題なく使用できます。

本屋での立ち読みは最も生産性の高い読書法である3の理由

 

お久しぶりです。 4月から就職して晴れて(?)社会人になることができました。

社会人にになると、大学生の頃とは違い自由な時間が少なくなってしまいます。特に困っているのが読書の時間です。動画を見たり音楽を聞いたりするのならまだしも、頭を使う読書は疲れて帰ってきてからではなかなか難しいのです。そのため、最近家で本を読むことよりも最寄りの書店で立ち読みをすることの方が多くなってきました。

そこで気づいたことがあります。立ち読みはかなり生産性の高い読書法だ、ということです。今回はその理由について紹介していきたいと思います。

 

1.タイムド・リーディングである

 

タイムドリーディングという読書手法があります。これは読書に制限時間を設けることで、意識的に読書を習慣化する試みです。

例えば時間を30分と決めたら、必ず30分で読まなければなりません。逆に言えば、30分で吸収できるような情報で、なおかつその本の中で最も必要な部分に注目して読むことになります。

書店で立ち読みする時は長々と内容をじっくり読むようなことは難しいので、自然とこのタイムドリーディング方式になるのです。

 

2.ザッピング読みになる

 

ザッピング読みは速読の基本です。
本を最初から最後まで読むのではなく、目次から、必要な情報を考えてその部分を集中的に読む読書法です。
書店で立ち読みする状況だと、自然とこのザッピング読みができるようになります。
なぜなら、立ち読みしているときは「買おうかどうか迷っている」時だからです。そのため、その本に買う価値があるのか判断するために、欲しい情報が載っているかざっと確認するように読む習慣が勝手に身について行きます。

 

3.立ったまま読む

立ったまま読むことが、なぜ生産性に繋がるのか?
それは集中力が鍵を握っています。実は人間は座っている時よりも立っている時の方が集中できることが、科学的に証明されているのです。

forbesjapan.com

 

最近ではスタンディングデスクという、たったまま作業する用のデスクも開発され、商品化されています。
私も職場で試したことがあるのですが、立ったまま姿勢を維持しなければならないというほどよい緊張感のおかげで、普段よりも長いあいだ集中できているように感じます。

 

これら3つの要因のおかげで、立ち読み読書は家やカフェで読むよりもかなり効率よく読むことができていると考えています。

 

「読む」技術?速読・精読・味読の力をつける? (光文社新書)

「読む」技術?速読・精読・味読の力をつける? (光文社新書)