2022年1月31日月曜日

npm を必ずsudo npmにするエイリアス

Ubuntu 20.04

npmコマンドを使うとき、sudo権限が必要なときがあります。なしで入力した場合、コマンドが数秒走ってからパーミッションエラーとかになって時間がもったいない、ということで、エイリアスで常にsudoできるようににしました。

.bashrc で

alias npm='sudo npm'

とするだけ。これで毎回パスワードを求められますが、エラーにはならないので快適になりました。 sudo sudo npm と繰り返してしまっても大丈夫です。


---

なお、こちらには、インストールに関して
グローバルインストールの先を自分のホームディレクトリに変えておくとsudoをつけなくてもインストールできるようになります。

と書いてあります。途中で変えるのが面倒だったので、せめてsudoを忘れないように強制的に前につけるようにしました。

2022年1月21日金曜日

aws cliの出力をjqで取り出す

jqとは: JSONの中身を取り出したいときに使う

jq is a lightweight and flexible command-line JSON processor.

jq is like sed for JSON data - you can use it to slice and filter and map and transform structured data with the same ease that sed, awk, grep and friends let you play with text.

jqはこちらを参考

https://stedolan.github.io/jq/tutorial/

aws cliはこちらを参考

https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-instances.html


使い方 

JSON出力をパイプしてcommandでクエリ

<JSON 出力のコマンド> | jq 'command'

  • パイプなどでコマンドが 長くなっても1組のクォーテーションの中にいれること。
  • クォーテーションはシングルでもダブルでもいい。ほとんどシングルで書かれている(?)。
  • テストはjsonに保存して cat tmp.json | jq ... などとするのがよさそう。

--

aws ec2 describe-instances の出力を例にする。

JSONの出だしがこうなっているとする。

{
  "Reservations": [
    {
      "Groups": [],
      "Instances": [
        {


全部出力

jq '.'

ドット

ドットで つないで、次のネストへの中のInstancesを選択。さらにStateを選択

jq '.Reservations[0].Instances[].State' 

出力例

{

  "Code": 0,

  "Name": "pending"

}

.Stateをパイプしても同じ結果になる

jq '.Reservations[0].Instances[] | .State' 


リスト

jq '.Reservations[]'  

jq '.Reservations' 

の違いに注意。リストの中か、リスト全部が出るかの違い。

jq '.Reservations[0]' 

とするとリストの1番め。以下インデックスで選べる。インデックスの結果がなければ空白が返る。


Reservations[].Instances[]

とすると、Reservations[0],...[最後] まで全部に対しての.Instances[] になります。


複数の値を出力

パイプして書きます。 "\(.ValueA) \(.ValueB)" 

2つの値の間はコンマなどを入れてもよい


例: EC2インスタンスをdescribeして、InstanceId、tagを出力

aws ec2 describe-instances | jq '.Reservations[].Instances[] | "\(.InstanceId) \(.Tags)"' 


例: Lambda全部のFunctionName 

(.Functions[] がリスト全部になっていることに注意)

aws lambda list-functions | jq '.Functions[].FunctionName'


例: LambdaでFuncnctionNameとRuntimeを出力

aws lambda list-functions | jq '.Functions[] | "\(.FunctionName) \(.Runtime)" '

select で条件付け

例: EC2インスタンスをdescribeして、runningのものだけを出力


jq '.Reservations[0].Instances[] | select (.State.Name == "running" )' 

例: cfn でStack名を全て出力

aws cloudformation describe-stacks | jq '.Stacks[].StackName'

例: cfn でCREATE_COMPLETEになっているStackを出力


aws cloudformation describe-stacks | jq '.Stacks[] | select (.StackStatus == "CREATE_COMPLETE" ) | .StackName '

describe-instancesのオプション


aws ec2 describe-instances \
    --query 'Reservations[*].Instances[*].{Instance:InstanceId,Subnet:SubnetId}' \
    --output json


aws ec2 describe-instances | jq '.Reservations[].Instances[] | {Instance: .InstanceId, Subnet: .SubnetId}'

は同じ結果になる。(出力のかっこが少し違うけど)

JSONを一行JSON lineにする

上記の後ろに

| jq -c '.'

をつけると、出力が一行になる。-c はcompactでJSONのPrettyの逆操作。'.' の部分は場合によって .[] だったりするかもしれない。


jqの出力を一行にする


| tr '\n' ','

で改行を,に変える


Cfnのスタック名を全て出力

aws cloudformation describe-stacks | jq '.Stacks[].StackName'

2022年1月20日木曜日

PostmanでContent-MD5をつけてS3 lifecycle configurationを送信する

前回( PostmanでS3バケットにファイルを送信する)の続きで、ヘッダを増やしてAPI送信します。

やること

PostmanでS3のlifecycle configuration APIを送信します。


サンプルはこちらのものを使います。

https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/API/API_PutBucketLifecycleConfiguration.html

bodyは<LifecycleConfiguration>からの部分です。設定は2つあり、

  • id1ではdocuments/フォルダ内のオブジェクトは30日経ったらGlacierに移動
  • id2ではlogs/フォルダのものが365日経ったら削除

headerのうち、PUT、Hostの部分はPostman内で書き込みます。

x-amz-date、Authorization、Content-Lengthは、Postmanがデフォルトで自動で生成してくれます。

Content-MD5もPostman内で計算しますが、別途設定が 必要です。

MD5がないとこのようなエラーが出たりします。

<Error><Code>InvalidRequest</Code><Message>Missing required header for this request: Content-MD5</Message>


PUT /?lifecycle HTTP/1.1 Host: examplebucket.s3.<Region>.amazonaws.com x-amz-date: Wed, 14 May 2014 02:11:21 GMT Content-MD5: q6yJDlIkcBaGGfb3QLY69A== Authorization: authorization string Content-Length: 415 <LifecycleConfiguration> <Rule> <ID>id1</ID> <Filter> <Prefix>documents/</Prefix> </Filter> <Status>Enabled</Status> <Transition> <Days>30</Days> <StorageClass>GLACIER</StorageClass> </Transition> </Rule> <Rule> <ID>id2</ID> <Filter> <Prefix>logs/</Prefix> </Filter> <Status>Enabled</Status> <Expiration> <Days>365</Days> </Expiration> </Rule> </LifecycleConfiguration>


設定

メソッドと宛先に

PUT 、 your-bucketname.s3.your-region.amazonaws.com/?lifecycle

と入力します。your-bucketnameはバケット名、your-regionはregion名です。

PUT /?lifecycle HTTP/1.1 

Host: examplebucket.s3.<Region>.amazonaws.com

となっていた  部分を反映しています。

Pre-request ScriptタブでContent-MD5 計算

タブ内でmd5を計算するスクリプトを書きます。

var md5checksum = CryptoJS.MD5(""+pm.request.body+"");
base64value = CryptoJS.enc.Base64.stringify(md5checksum);
postman.setGlobalVariable("contentMD5", base64value);

100%こちらを参考にしています。

https://raaviblog.com/how-to-generate-content-md5-value-base64-encoded-128-bit-md5-of-the-data/

ここではリクエストボディをMD5ハッシュにして、base64にして、contentMD5というGlobalVariableにアサインしています。


PostmanのEnvironment→Globalsを開き、contentMD5というVARIABLE名を入力します。他のINITIAL VALUE, CURRENT VALUEは空欄です。



Headersタブ

Key: Content-MD5
Value: {{contentMD5}}

をヘッダのテーブルに追加します。これで計算したMD5がヘッダに与えられます。

Body タブ


<LifecycleConfiguration>
から
</LifecycleConfiguration>

までをすべて貼り付けます。

実行

SendするだけでOKです。

ちなみにコードで見るとこうなっています。(省略あり)

curl --location --request PUT 'xxxxx.s3.region.amazonaws.com/?lifecycle' \
--header 'Content-MD5: xxxxx' \
--header 'X-Amz-Content-Sha256: xxxxx' \
--header 'X-Amz-Date: xxxxx' \
--header 'Authorization: AWS4-HMAC-SHA256 Credential=xxxxx/xxxxx/region/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=xxxxx' \
--header 'Content-Type: text/plain' \
--data-raw '<LifecycleConfiguration>
....
</LifecycleConfiguration>'

2022年1月19日水曜日

PostmanでS3バケットにファイルを送信する

 PostmanからS3バケットにファイルをPUTします。

こちらのMedium(英語)を参考にしています。ほとんど同じですがリージョンの設定が増えています。



準備

  • ファイル。例えばtmp1.txt
  • S3バケット。リージョンは何でも可。Public Accessを可能にする。
  • AWSアクセスキーとシークレットキーをコピペできるように
  • Postman アプリ


Postman設定



  • PUTを選択
  • アドレスに<bucket>.s3.<region>.amazonaws.com/foo.txt
    • この場合、foo.txtというファイル名で保存される
    • sub folderも可能


Paramsタブ

  • 入力なし

Authorizationタブ

  • Type AWS Signatureを選択
  • アクセスキーとシークレットキーを入力
  • AWS Regionは 空欄だとus-east-1になる
  • Service Nameはs3 (※sは小文字) とする。






Headersタブ

入力なし

Bodyタブ


Binary -> Select File で選択する

ファイルを用意していなくても、raw で送信することも可能です。






Testsタブ


(オプション)。こちらにあるコードをコピーしている。

pm.test("Status test", function () {
pm.response.to.have.status(200);
});






実行

Sendボタンで実行します。


出力

Status 200 OK が出れば成功しています。(Testsがなくても200表示は出ます)

Header情報

Authorizationの値がsignature v4( AWS4-HMAC-SHA256 Credential=。。。)になっていることがわかります。Postmanが代わりに生成してくれているということですね。

  参考: https://docs.aws.amazon.com/ja_jp/general/latest/gr/sigv4_signing.html



テスト結果

2022年1月11日火曜日

Lambdaでtagを扱うときに403エラーが出たので直した

症状 

LambdaでEC2のタグにアクセスするスクリプトを使っていたのですが、Deployしようとすると403エラーが出るようになりました。

更にこのエラーが出て、Lambdaにアクセスできなくなりました。

Tags failed to load. The filter doesn't include tags. Lambda can't load your tags due to insufficient permissions. Add tag:getResources to your logged-in user, and reload the Lambda console.

Tags failed to load. The filter doesn't include tags. Lambda can't load your tags due to insufficient permissions. Add tag:getResources to your logged-in user, and reload the Lambda console.

解決方法

パーミッションが足りないのが原因なので tag:getResources を自分につければいいみたいです。

https://docs.aws.amazon.com/ja_jp/ARG/latest/userguide/gettingstarted-prereqs.html

を参考にして、ResourceGroupsandTagEditorFullAccessというビルトインのポリシーを追加することにしました。フルアクセスにしましたが、tag:GetResourcesだけを追加しても良さそうです。

ResourceGroupsandTagEditorFullAccess

このポリシーは、アタッチされた IAM ユーザーまたはロールに、タグエディタでResource Groups 操作および読み取りおよび書き込みタグ操作を呼び出すアクセス権限を付与します。リソースのタグを読み書きするには、別のポリシーを使用して、そのリソースに対するアクセス許可も必要です (次の重要な注意を参照)。

このポリシーを(Lambdaにではなく)ユーザにアタッチしたら403エラーは直りました。