2021年7月31日土曜日

scriptでUnix ターミナルの表示全てを保存する

script コマンドで、terminalの表示を逐一保存することができます。
$ script outputfile.txt

で出力ファイルを決めてスタート。
$ exit

するまで続きます。


出力を見てみると、PS1で設定したフォントの部分がそのまま出て文字化けか?と思ってしまいました。

この出力はターミナルのフォントの部分で、同じターミナルで読むときは問題ないですが、他のエディタなどで読むには辛いので消したいです。置換、削除するとスッキリします。

置換する
月 -> 月

削除する
\[01;3\dm
\[0m
\[00m
\]0;
~

---

Script started on 2021-07-31 14:54:50+09:00 [TERM="screen-256color" TTY="/dev/pts/3" COLUMNS="151" LINES="51"]
<user>@<client>:~$ script --help

Usage:
 script [options] [file]

Make a typescript of a terminal session.

Options:
 -a, --append                  append the output
 -c, --command        run command rather than interactive shell
 -e, --return                  return exit code of the child process
 -f, --flush                   run flush after each write
     --force                   use output file even when it is a link
 -o, --output-limit      terminate if output files exceed size
 -q, --quiet                   be quiet
 -t[], --timing[=] output timing data to stderr or to FILE
 -h, --help                    display this help
 -V, --version                 display version

For more details see script(1).
<user>@<client>:~$ exit
exit

Script done on 2021-07-31 14:54:59+09:00 [COMMAND_EXIT_CODE="0"]

実際のターミナルのスクリーショットはこんな感じでした。分かり難いですが元の色が設定されています。
参考 https://unix.stackexchange.com/questions/200637/save-all-the-terminal-output-to-a-file

2021年7月26日月曜日

AWSコンソール上の名前の欄はタグと連動している

全然知らなかったのでメモ

AWSマネジメントコンソールのリソース名は、タグの"Name"を反映しているようです。

下の図のような項目です。ここではNameがありません。


リソースは例えばEC2インスタンス、VPC、subnet、などです。後から書いてもよい

  • Tag側で書いても、コンソール側で書いてもよい

です。


よく分からないこと

コンソール上で以下の操作をします。

Nameなし(Tag Nameもなし)で作成する

Nameを設定すると、Tag Nameが生成される → これはOK

Nameを削除すると、Tag NameはValue空白で残される → ??

Tagは存在していることになるのだろうか。

aws cliで試してみる

こういうCLIでdescribeします。

aws ec2 describe-tags --filters "Name=resource-id,Values=i-xxxxxxxxxxxxxxxx"


EC2の作成直後は空白です。

{
"Tags": []
}

Tag Name: EC2-a を入力してからdescribeしたときの出力。きちんと出ていますね。

{
"Tags": [
{
"Key": "Name",
"ResourceId": "i-xxxxxxxxxxxxxxxx",
"ResourceType": "instance",
"Value": "EC2-a"
}
]
}

Nameが空白の状態で残ったとき Valueが空白の""で出力されています。

{
"Tags": [
{
"Key": "Name",
"ResourceId": "i-xxxxxxxxxxxxxxxx",
"ResourceType": "instance",
"Value": ""
}
]
}

ということで、タグ自体は存在しているようですが、valueが空白ということでした。


CloudFormationで作成時にTag: Nameを設定

Tags:
- Key: Name
Value: Name-is-also-displayed-on-console

などとすればよいです。

トイレットペーパーホルダーを壁の穴を変えずに静音のものに交換した話

先にまとめ

  • トイレットペーパーホルダーを静音のものに交換しました。
  • 壁にある既存の穴を使えるように、木材でアダプターを作りました。

完成版の写真


比較動画

ビフォー (元々ついていたホルダー。商品名等は不明)


アフター (取り付けたもの。カワジュン SC-483-ST )



準備

動機

トイレットペーパーホルダーがカラカラ音がして気になるので、静音のものに交換することにしました。賃貸なので、既存の壁穴を使えるアダプターを作りました。

選定

新しく買ったペーパーホルダーはネットでも評判がよいKAWAJUNさんのものを買いました。上面が鏡面になっているものや、黒いものやいろいろ種類があるようです。実売4,000円くらい。

カワジュン トイレットペーパーホルダー SC-483-ST 

https://shop-kawajun.jp/fs/kawajun/SC-483-ST


使った道具

  • ドリル一式
  • 19mm厚の木材(もともと別の用途に使っていた残骸)
    • この木材にホルダー本体を留めるためのネジ(15mm程度の長さ)
  • ノコギリ





手順

元のペーパーホルダーホルダーはこんなのでした


外すと穴はこうなっています。幅70ミリのようです。下の穴は使わず、上の2つを使います。



木材に穴を開けます

壁固定用のネジは4mmなので、穴は4.8mmにしています。内側の穴は本体を留める用の間隔30ミリの穴です。けっこう雑に開けました。



アダプタを装着します。


壁に付けます。元々使われていたネジをそのまま使っています。


ペーパーも付けました。木があるのが逆にいい感じかも。




静音ペーパーホルダーの感想

  • とても静かです。無音というわけではないですが。
  • 片手でペーパーを切ることもできます。これはこの製品特有かもしれません。(追記:実際のところは癖で両手で切ってます)


まとめ

  • 静音ペーパーホルダー最高!
  • DIYで壁に穴を開けるか迷っている人は、木材でアダプターを作ってみてはいかがでしょうか。木材の厚みはたまたま家にあった19mmを使いましたが、適当でいいと思います。カマボコ板とかでも。
    • 今回は既存のホルダーで使っていた壁に肯定するネジが充分に長かったので問題ありませんでしたが、ものによってはネジの長さが足りなくなるかもしれません

2021年7月23日金曜日

Lambda@Edgeで使ってブラウザによって見せるページを変えたときのメモ

やったこと

このAWSチュートリアルこの例を組合せてLambda@Edgeをやってみました。

  • ヘッダ情報から、ブラウザがデスクトップ、iOS、Androidを判定して、別のhtmlファイルにアクセスする
  • 構成は、Browser -> Lambda@Edge -> CloudFront -> S3 (static file)
  • 手順はざっくり下記のようになるが、上記リンク先のままでできる
    • S3にdesktop, ios, android用のhtmlファイルを入れる
    • Cloudfrontでパブリック静的サイトにする
    • LambdaEdge対応にする
  • TTLの設定が良く解らず、CloudFrontが更新されるまでのタイミングがうまく見極められなかったので時間が無駄になってしまった感あり

CloudFront リクエストとレスポンスを変更するタイミング

以下のようにタイミングを選べますが、今回はオリジンリクエストで、OriginのS3にデータを取りにいくときに、バケットオブジェクトを変えています。最初間違えて(ビューワーリクエストにしてしまっていた)
Lambda@Edge では、Node.js および Python の Lambda 関数を実行して CloudFront が発信するコンテンツをカスタマイズし、ビューワーに近い AWS 地域でこの関数を実行できます。この関数は、プロビジョニングや管理の必要なく、CloudFront イベントに応答を実行します。Lambda 関数を使用して、次の時点で CloudFront リクエストとレスポンスを変更できます。

CloudFront がビューワーからリクエストを受信した後 (ビューワーリクエスト)

CloudFront がリクエストをオリジンサーバーに転送する前 (オリジンリクエスト)

CloudFront がオリジンからレスポンスを受信した後 (オリジンレスポンス)

CloudFront がビューワーにレスポンスを転送する前 (ビューワーレスポンス) 
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-edge.html 

Error

エラーその1



Correct the errors below and try again. Your function's execution role must be assumable by the edgelambda.amazonaws.com service principal.

これはtrusted policy に追加するはずの、edgelambda.amazon.comが入っていなかったのが問題だった。

エラーその2

Lambda@edgeではCWのservice linked roleがいるらしい


Log group does not exist The specific log group: /aws/lambda/ does not exist in this account or region

というエラーは結局答えは、


ここ とかにあって、

AWSServiceRoleForCloudFrontLogger の中にあるAWSCloudFrontLoggerと同じポリシーをinlineで書き込むと解決。
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "arn:aws:logs:*:*:log-group:/aws/cloudfront/*"
        }
    ]
}

Lambda@EdgeのCWログ

Lambda@Edgeはue-east-1にしか置けないが、ログは実際にLambdaが動作するリージョンにある。 パーミションのエラーと合わせてけっこう嵌っってしまいました。こちらに答え。
https://dev.classmethod.jp/articles/where-is-the-lambda-edge-log/

CloudFrontのログ

CloudFrontのコンソールからEnable。S3バケットを設定する。 gzファイルになっているのでダウンロードして見ていた。面倒なのでAthenaとか使えた方がよいのかも。
LambdaExecutionError が出ているのが解った。動作として間違っていなさそうでも、Errorが出ている。Lambda自体に問題もなさそうだが。
解凍は $ gunzip XXX.gz
項目はこのような感じ。
#Version: 1.0
#Fields: date time x-edge-location sc-bytes c-ip cs-method cs(Host) cs-uri-stem sc-status cs(Referer) cs(User-Agent) cs-uri-query cs(Cookie) x-edge-result-type x-edge-request-id x-host-header cs-protocol cs-bytes time-taken x-forwarded-for ssl-protocol ssl-cipher x-edge-response-result-type cs-protocol-version fle-status fle-encrypted-fields c-port time-to-first-byte x-edge-detailed-result-type sc-content-type sc-content-len sc-range-start sc-range-end

Lambda node.jsでCloudFrontのHTTP headerを出力

User-Agent headerの中を読んでいるらしいが、それが実際どうなっているのかがわからない
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-cloudfront-headers.html

この書き方が便利だった https://stackoverflow.com/questions/13147693/how-to-extract-request-http-headers-from-a-request-using-nodejs-connect
# レスポンス
    console.log("response:");
    console.log(JSON.stringify(response));

# ヘッダー
    console.log("request.headers");
    console.log(JSON.stringify(request.headers));

# NG: こうやると空白が出力される
console.log(res_headers);

# NG: こうやると objectであることが出力されるだけ
    console.log(`headers: "${res_headers}"`);
		headers: "[object Object]"

CloudFrontからのHTTP heder requestを無理やり確認するとこうなる。NodeJSのconsole.logでCW logで見ている。
exports.handler = (event, context, callback) => {

  const request = event.Records[0].cf.request;
	console.log(JSON.stringify(request));

  callback(null, request);
};

こういうのが出てくる。例えばCloudFront-Is-Mobile-Viewerでモバイルかどうかの判定ができる。

2021-07-11T03:25:31.555Z	51136a8b-d242-4354-b640-5643d8a7eee1	INFO

{
    "clientIp": "2001.xxxx...",
    "headers": {
        "cloudfront-is-mobile-viewer": [
            {
                "key": "CloudFront-Is-Mobile-Viewer",
                "value": "false"
            }
        ],
        "cloudfront-is-tablet-viewer": [
            {
                "key": "CloudFront-Is-Tablet-Viewer",
                "value": "false"
            }
        ],
        "cloudfront-is-smarttv-viewer": [
            {
                "key": "CloudFront-Is-SmartTV-Viewer",
                "value": "false"
            }
        ],
        "cloudfront-is-desktop-viewer": [
            {
                "key": "CloudFront-Is-Desktop-Viewer",
                "value": "true"
            }
        ],
        "cloudfront-is-ios-viewer": [
            {
                "key": "CloudFront-Is-IOS-Viewer",
                "value": "false"
            }
        ],
        "cloudfront-is-android-viewer": [
            {
                "key": "CloudFront-Is-Android-Viewer",
                "value": "false"
            }
        ],
        "x-forwarded-for": [
            {
                "key": "X-Forwarded-For",
                "value": "2001:xxx...."
            }
        ],
        "user-agent": [
            {
                "key": "User-Agent",
                "value": "Amazon CloudFront"
            }
        ],
        "via": [
            {
                "key": "Via",
                "value": "2.0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.cloudfront.net (CloudFront)"
            }
        ],
        "accept-encoding": [
            {
                "key": "Accept-Encoding",
                "value": "gzip"
            }
        ],
        "pragma": [
            {
                "key": "Pragma",
                "value": "no-cache"
            }
        ],
        "sec-ch-ua": [
            {
                "key": "sec-ch-ua",
                "value": "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"90\", \"Google Chrome\";v=\"90\""
            }
        ],
        "sec-ch-ua-mobile": [
            {
                "key": "sec-ch-ua-mobile",
                "value": "?0"
            }
        ],
        "sec-fetch-site": [
            {
                "key": "sec-fetch-site",
                "value": "same-origin"
            }
        ],
        "sec-fetch-mode": [
            {
                "key": "sec-fetch-mode",
                "value": "no-cors"
            }
        ],
        "sec-fetch-dest": [
            {
                "key": "sec-fetch-dest",
                "value": "image"
            }
        ],
        "host": [
            {
                "key": "Host",
                "value": "name-of-lambda-edge.s3.region.amazonaws.com"
            }
        ],
        "cache-control": [
            {
                "key": "Cache-Control",
                "value": "no-cache"
            }
        ]
    },
    "method": "GET",
    "origin": {
        "s3": {
            "authMethod": "none",
            "customHeaders": {},
            "domainName": "name-of-lambda-edge.s3.region.amazonaws.com",
            "path": ""
        }
    },
    "querystring": "",
    "uri": "/favicon.ico"
}

2021年7月22日木曜日

[解決済み]ubuntu mozcで日本語入力が変になる

1文字の入力が変になるものと、入力途中でアルファベットが確定されるものがあります。


その1 解決済み

  • Google Chromeをアップデートしたらブラウザ上での日本語入力が変になった
    • 一文字での入力ができない。一文字入力して、変換してエンターするとキャンセルされる
  • 解決しなかったのでバージョンを戻した
  • 半年くらい待ったアップデートしたら、直っていました

環境 Ubuntu 20.04, fcitx-mozc (環境は関係なさそう。Firefoxでは問題なし)

バージョン
google-chrome-stable amd64 
OK 90.0.4430.93-1
NG 91.0.4472.164-1
NG 92.0.4515.107-1

91からおかしくなった。90のままだとセキュリティの問題が・・と通知が出ていて困っている。

ググってみると、同じではないが似たような報告がちらほら出ていて、そのうちアップデートして直っているようです。


その後、ずいぶん待ってからアップデートしたら直っていました。

Version 96.0.4664.110 (Official Build) (64-bit)


こちらによるとfcitx5にすると改善されるとのことでした。


その2 解決済み

  • 入力中に1文字のアルファベットだけが確定されて前に出てしまう。「確定」→「aっくてい」 「低くなるかもしれません」→「低くeなるかもしれまsん」などとなる。
  • fcitx5やChrome 96でも改善されず
  • Chrome、VSCodeでも起きているー>VscodeはChromeのdependency
  • gvimでは起らない。ターミナルでも起らない。
  • 最終的にxkbを再インストールして直りました。

やってみたこと


ゆっくり入力すると、バグる可能性はやや低いのかも?→関係なかった
英字キーボードが悪い? → 他の日本語キーボードでも再現。関係なかった
Mistel 770  有線だけど、分離型の左右でずれている? → 他のキーボードでも再現。関係なかった 

fcitx, fcitx5をpurgeしてから再インストール → 起こる。ただ頻度は減った?

fcitx5でInput Method Panelを組み合わせる → 起こる。頻度は減った??
https://gihyo.jp/admin/serial/01/ubuntu-recipe/0689

MozcのIM setting -> Fcitx Configurationのページを開く。Current Input Methodで他のKeyboardを消して、Mozcだけにする。

→ これが効果あったかも??-> ゼロにはならないが減った気がする?

ちなみに英字キーボードなので、ZenkakuHankakuを別途アサインしています。




別のubuntu20.04 機では問題なかった
- ibus-mozc
- Chrome 97.0.4692.99
- mozc 2.23.2815.102

問題あるものは、
mozc 2.26.4220.102

切り分けができません。。



こちらを参考にして、fcitx5にしてExtensionsー>Input Method Panelをしてみましたが、うまくいきません。特に、GoogleDocなどで日本語入力が見えなくなりました( 確定すると見える)

https://gihyo.jp/admin/serial/01/ubuntu-recipe/0689?page=1

どうやらibusとfcitxが混在しているようです。システムの文字(superキーを押したときの検索とか)はibusになっているような・・・。


xkb を再インストールするのが効果あり


https://askubuntu.com/questions/846702/how-to-reset-xkb

にあるように、

dpkg -S /usr/share/X11/xkb/symbols/pc

とやって

xkb-data: /usr/share/X11/xkb/symbols/pc

と出るので

sudo apt reinstall xkb-data

として完了。



Reading package lists... Done
Building dependency tree       
Reading state information... Done

0 upgraded, 0 newly installed, 1 reinstalled, 0 to remove and 10 not upgraded.
Need to get 349 kB of archives.
After this operation, 0 B of additional disk space will be used.
Get:1 http://jp.archive.ubuntu.com/ubuntu focal/main amd64 xkb-data all 2.29-2 [349 kB]
Fetched 349 kB in 0s (1,514 kB/s)
(Reading database ... 467702 files and directories currently installed.)
Preparing to unpack .../xkb-data_2.29-2_all.deb ...
Unpacking xkb-data (2.29-2) over (2.29-2) ...
Setting up xkb-data (2.29-2) ...
Processing triggers for man-db (2.9.1-1) ...






2021年7月20日火曜日

社内共有フォルダをAWSクラウド化する検討

とある会社では、社内ネットワークからアクセスできる共有フォルダに支払っている料金は

1GB あたり 月100円のようです。支払いは社内の他部門ですが、そこはとりあえず無視します。

・毎日バックアップ(10日)

・社内IDでシングルサインオン


fsxを使うのが良いのかな、と。

料金の例

米国東部 (バージニア北部) リージョンの HDD ストレージを使用して、10 TB の汎用ファイル共有データを保存するとします。典型的な重複排除による節約割合 50〜60% に基づいて、16 MBps のスループット容量 5 TB のマルチ AZ ファイルシステムをプロビジョニングします。今月のバックアップストレージの平均使用量を 5 TB と仮定します。

合計月額料金

ストレージ: 5 TB x 0.025 GB/月 = 128 USD/月

スループット: 16 MBps x 4.50 USD/MBps/月 = 72 USD/月

バックアップ: 5 TB x 0.050 USD/GB-月 = 256 USD/月

合計月額料金: 456 USD (10 TB のデータの場合 0.045 USD/GB-月)

https://aws.amazon.com/jp/fsx/windows/pricing/?nc=sn&loc=3

この例だと、1GBで50円相当くらいです。


Active Directoryは既存のがあると仮定して、それと接続すればよいでしょう。

https://aws.amazon.com/jp/blogs/news/using-amazon-fsx-for-windows-file-server-with-an-on-premises-active-directory/


比較など

https://business.ntt-east.co.jp/content/cloudsolution/column-try-31.html

https://www.fujitsu.com/jp/solutions/infrastructure/construction/multi-cloud/aws/event-column/aws-file-share.html



AWSでEC2の料金が閾値を超えたら止めたい

予算を決めておいて、超えたら課金されているものを止めるとする。

先にまとめ

即時アラートを出すのはそれ自体にお金がかかってしまう。


サービスを止めるのはLambdaで

Python boto3でやるとしてEC2ならのstop_instances()を使って止めればよい。

これが参考になる。(やっているのは時間で自動で止めているもの)

https://aws.amazon.com/jp/premiumsupport/knowledge-center/start-stop-lambda-cloudwatch/

検知方法

検知したあとは、SNSを経由してLambdaを呼べばいい

AWS Budget

設定が簡単だが、即時性がなく、数時間遅れる(最大24時間?)


Cost Explore API

APIでその時点のコストを調べられる。1回0.01USDかかる。


CloudWatch Alarm

予測をしてアラートを出せる。スパイクに対して反応するのかが不明。


2021年7月18日日曜日

AWS Backupの状況をSNSで通知する■

 先にまとめ

AWS Backupの完了などをSNSで通知するにはAWS BackupにSNSを紐付けるのが良い。

手順は、

  • SNSを作る
  • Backupを作る
  • CLIからSNSを紐付ける

となる。

こちらの公式blogに詳しく書かれています。

https://aws.amazon.com/jp/blogs/storage/configuring-notifications-to-monitor-aws-backup-jobs/

---

動機

DynamoDBはRestoreに時間がかかるし読めない(サイズによらない)ということで、通知できないものかと思って調べていました。

Restore can take several hours to complete. (完了するのに数時間かかることがあります)の表示

答えにはたどり着いたのですが、つい最近公式ブログが書かれたので一見落着してしまいました。



調べたこと

EventBridgeを使う案

これも可能です。以下はMusicという名前のチュートリアルのテーブルを復元したときの通知の文面ですが、JSONでの長い文が届いてウッとなってしまいます。

これは変えられないんでしょうか。やたらと情報が多すぎて危険な感じ。これはSNSで共通ですが・・・(TODO)

{"version":"0","id":"48fe1557-f3ca-c8ee-8206-fc1b290a5b5b","detail-type":"AWS API Call via CloudTrail","source":"aws.dynamodb","account":"111122223333","time":"2021-07-16T02:02:54Z","region":"ap-northeast-1","resources":[],"detail":{"eventVersion":"1.08","userIdentity":{"type":"IAMUser","principalId":"AAAAAAAAAAAAAAAAAA","arn":"arn:aws:iam::111122223333:user/username","accountId":"111122223333","accessKeyId":"AAAAAAAAAAAAAAAAAA","userName":"username","sessionContext":{"attributes":{"creationDate":"2021-07-15T20:32:29Z","mfaAuthenticated":"false"}}},"eventTime":"2021-07-16T02:02:54Z","eventSource":"dynamodb.amazonaws.com","eventName":"ListContributorInsights","awsRegion":"ap-northeast-1","sourceIPAddress":"xxx.xxx.xxx.xxx","userAgent":"console.amazonaws.com","requestParameters":{"tableName":"Music-restore-from-console","maxResults":0.0},"responseElements":null,"requestID":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","eventID":"aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa","readOnly":false,"resources":[{"accountId":"111122223333","type":"AWS::DynamoDB::Table","ARN":"arn:aws:dynamodb:ap-northeast-1:111122223333:table/Music-restore-from-console"}],"eventType":"AwsApiCall","apiVersion":"2012-08-10","managementEvent":true,"recipientAccountId":"111122223333","eventCategory":"Management"}}

AWS BackupでSNSを登録する案

BackupからSNSを設定して届く文面の例です。こちらの方がスッキリします。

An AWS Backup Restore job was started. Restored Recovery point ARN : arn:aws:dynamodb:ap-northeast-1:111122223333:table/Music/backup/AAAAAAAAAAAAAA-AAAAAAAA. Restore Job Id : AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA


注意点: 上記どちらも、5分間隔の確認なので遅れがあります。

Monitor events using EventBridge

You can use EventBridge to monitor AWS Backup events. A common use case is to receive an alarm when a backup job fails. AWS Backup emits events to EventBridge in a best-effort manner every 5 minutes.

https://docs.aws.amazon.com/aws-backup/latest/devguide/eventbridge.html

boto3で逐次確認する

かなりマニュアル操作がありますが、確認時間を例えば10秒間隔でも設定できます。単にpythonのsleepで待ち時間を作ってStateを確認するだけです。すぐに結果を知りたいときには使えそうです。

コードは省略。どこか別に書くかもしれません。



 

AWS大阪リージョンの制限について

 2021年3月に大阪リージョンが開設(一般公開)されました。

https://aws.amazon.com/jp/blogs/news/aws-asia-pacific-osaka-region-now-open-to-all-with-three-azs-more-services/


しかし、2021年7月現在では使えない機能が多いような気がするのですが。(2021年12年でも使えないことを確認)

例えば、AWS Configのマネージドルールでも使えないものがあります。

s3-default-encryption-kms

Checks whether the Amazon S3 buckets are encrypted with AWS Key Management Service(AWS KMS). The rule is NON_COMPLIANT if the Amazon S3 bucket is not encrypted with AWS KMS key.

AWSRegion: All supported AWS regions except Asia Pacific (Osaka) Region

https://docs.aws.amazon.com/config/latest/developerguide/s3-default-encryption-kms.html

S3のAWS Configで見てみると、以下はOsakaでは使えません。もちろん、大阪の他にも使えないリージョン(Milanとか)はあります。

  • s3-bucket-level-public-access-prohibited
  • s3-bucket-default-lock-enabled
  • s3-account-level-public-access-blocks-periodic
  • s3-account-level-public-access-blocks


その他にもちょこちょこ見るexcept Osakaを見る気がしており、今のところではメインのリージョンとしては使えなくて、東京のバックアップ用途なんでしょうね。





2021年7月17日土曜日

VSCodeでVimを使っていたときの設定

使わなくなったので供養として置いておく


setting.jsonにこういうのを書いていた。


  // https://github.com/VSCodeVim/Vim

"vim.easymotion": true,
"vim.incsearch": true,
"vim.useSystemClipboard": true,
"vim.useCtrlKeys": true,
"vim.hlsearch": true,
"vim.insertModeKeyBindings": [
{
"before": ["j", "j"],
"after": ["<Esc>"]
}
],
"vim.normalModeKeyBindings": [
{
"before": ["<C-j>"],
"after": ["1", "0", "j"]
},
{
"before": ["<C-k>"],
"after": ["1", "0", "k"]
},
{
"before": ["<C-h>"],
"after": ["1", "0", "h"]
},
{
"before": ["<C-l>"],
"after": ["1", "0", "l"]
},
{
"before": ["down"],
"after": ["g", "j"]
},
{
"before": ["up"],
"after": ["g", "k"]
},
{
"before": ["j"],
"after": ["g", "j"]
},
{
"before": ["k"],
"after": ["g", "k"]
}
],
// "vim.normalModeKeyBindingsNonRecursive": [
// {
// "before": ["<leader>", "d"],
// "after": ["d", "d"]
// },

// {
// "before": ["<C-n>"],
// "commands": [":nohl"]
// }
// ],
"vim.leader": "<space>",
"vim.handleKeys": {
"<C-a>": false,
"<C-f>": false,
"<C-c>": false,
"<C-v>": false,
"<C-x>": false,
"<C-shift+b>": false
},
// https://github.com/VSCodeVim/Vim/issues/2007
"vim.normalModeKeyBindingsNonRecursive": [
{
"before": ["u"],
"after": [],
"commands": [
{
"command": "undo"
}
]
},
{
"before": ["<C-r>"],
"after": [],
"commands": [
{
"command": "redo"
}
]
}
],
// https://girigiribauer.com/tech/20190212/
"vim.whichwrap": "h,l,<,>,[,]",

2021年7月15日木曜日

boto3を使ってAmazon SNSからメールを送ります。

sendMailToMe という名前でトピックを作っていて、自分のメールアドレスを設定しています。トピックのARNをあとで使います。

Python側のコードはこうなります。
import boto3

client = boto3.client('sns')

topic_arn = 'arn:aws:sns:region:accountID:sendMailToMe'
message = 'Hello from boto3'
subject = 'boto3'

response = client.publish(
    TopicArn=topic_arn,
    Message=message,
    Subject=subject,
)

このようなメールが届きます(gmailで受信)



題名はsubject、本文はmessageに対応しています。 ※受信メールの差出人に相当するDisplay nameはSNSトピックでの設定項目ですが、このときはDescriptionと間違えて説明を書いてしまっています。

SNSから届く文面は変えられないらしい

変更できません。今の場合、accountID、region、endpointの情報は見えてしまうことになります。日本語にするのも不可のようです。

URLをクリックして購読停止をさせないようにする

購読停止用のアドレスを消せないので、せめて押しても停止できないようにします。
CLIのconfirm_subscription()アクションでAuthenticateOnUnsubscribe を trueにする。

https://aws.amazon.com/jp/premiumsupport/knowledge-center/prevent-unsubscribe-all-sns-topic/

ほぼ同じ内容の紹介
https://recipe.kc-cloud.jp/archives/4847
https://dev.classmethod.jp/articles/amazon-sns-disable-unsubscribe-link/
https://blog.serverworks.co.jp/sns-remove-unsubscribe-link

2021年7月13日火曜日

AWS CloudFormationでダブルクォーテーションで失敗した話

概要

  • CfnでPseudo Parameterを使おうとして !Ref "AWS::Region" が!Ref “AWS::Region” になっていてエラーが出ていました
  • ダブルクォーテーションが変になっていたのが理由
  • 特にpdfからコピーするときは、フォントが変わっているときもあるので注意

詳しく


Blackbelt のpdf資料を見ながら疑似パラメータのRegionを使おうとしていて、エラーが出ました。


Template format error: Unresolved resource dependencies [?AWS::Region"] in the Resources block of the template

?AWS::Region" というリソースのdependenciesがおかしい、というのが意味わからず。他のページも見て試してみると、どうやらクォーテーションが間違っていたと分かりました。

理由


あとで分かったのはこれが定義したリソースだと思って探したものの、ないですよ、ということのようです。


例えば、以下の JSON テンプレートと YAML テンプレートで ImageID のプロパティで test が参照されているとします。しかし、どちらのテンプレートにもリソースの論理 ID または test という名前のパラメータは含まれていません。

つまり、リソース ID は、次の JSON と YAML テンプレートで正しく定義されていません。これらのテンプレートにより、「テンプレートのリソースブロックにある未解決のリソース依存関係 [test]」というエラーが返されます。 リソースの定義と構文に関する詳細については、「リソース」を参照してください。
https://aws.amazon.com/jp/premiumsupport/knowledge-center/cloudformation-template-validation/

VSCodeのcfn-lintでもエラーが出て同じ説明が出ていました。エラー文がすぐに理解できず反省です。


コピペ失敗したもの

このページをコピペしたのですが・・・


よく見ると違いますね。下のAWS::StackNameの方が正しいクォーテーションです。




PDFだからでしょうか?とにかく気をつけましょう。


ダブルクォーテーションいる/いらない


JSONとYAMLの記法を比較すると、JSONは文字列を全て""を使いますが、YAMLでは省略できます。::がついているAWS::Regionは""が残っていますが、実際のところ、!Ref "AWS::Region" を !Ref AWS::Region と書いてもエラーにはなりません。

"Outputs" : {
   "MyStacksRegion" : { "Value" : { "Ref" : "AWS::Region" } }
}
Outputs:
  MyStacksRegion:
    Value: !Ref "AWS::Region"

2021年7月5日月曜日

AWSの用語をssmacroで省略系に変換して文字数を減らす

かなりオレオレなやり方ですが、ご紹介。 VSCodeのssmacroというExtensionが気に入っていて、よく使っています。認定試験の勉強ではドキュメントをコピペしてまとめていましたが、文字数を減らしたかったので省略形に変換していました。

変換の例

例えば、この文では S3 に置き替えます。

この Amazon Simple Storage Service (Amazon S3) のご紹介では、このウェブサービスの要点の詳細について説明します。このセクションを読むことで、本サービスの内容と、ビジネスへの利用方法についてご理解いただけます。

こうなります。

このS3のご紹介では、このウェブサービスの要点の詳細について説明します。このセクションを読むことで、本サービスの内容と、ビジネスへの利用方法についてご理解いただけます。

https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/Welcome.html


例えば、この文ではKDS、KCLに置き替えます。

You can use Amazon Kinesis Data Streams to collect and process large streams of data records in real time. You can create data-processing applications, known as Kinesis Data Streams applications. A typical Kinesis Data Streams application reads data from a data stream as data records. These applications can use the Kinesis Client Library, and they can run on Amazon EC2 instances. You can send the processed records to dashboards, use them to generate alerts, dynamically change pricing and advertising strategies, or send data to a variety of other AWS services. For information about Kinesis Data Streams features and pricing, see Amazon Kinesis Data Streams.

こうなります。

You can use KDS to collect and process large streams of data records in real time. You can create data-processing applications, known as KDS applications. A typical KDS application reads data from a data stream as data records. These applications can use the KCL, and they can run on EC2s. You can send the processed records to dashboards, use them to generate alerts, dynamically change pricing and advertising strategies, or send data to a variety of other AWS services. For information about KDS features and pricing, see KDS.

https://docs.aws.amazon.com/streams/latest/dev/introduction.html

効果

ものによりますが、10%程度は削れるのではないでしょうか。


ssmacro書き方

書き方は公式か、

こちらの当ブログ記事を見てください。


S3で使っている変換の書き方は、こんな感じにしています。
    {
        "args": {
            "find": "Simple Storage Service( \\(*(Amazon )*(S3)\\)*)*",
            "replace": "S3",
            "all": true,
            "reg": true,
            "flag": "gmi"
        },
        "command": "ssmacro.replace"
    },

Kinesisはこちらで、Firehose, Analytics も判定して短縮形にしています。
    {
        "args": {
            "find": "Kinesis Data (S|F|A)(treams*|irehose|nalytics)",
            "replace": "KD$1",
            "all": true,
            "reg": true,
            "flag": "gmi"
        },
        "command": "ssmacro.replace"
    },

日本語と英語の間は不要なスペースが残りがちなので、消します。
    {
        "args": {
            "find": "([a-z0-9]) ([^\\x00-\\x7F])",
            "replace": "$1$2",
            "all": true,
            "reg": true,
            "flag": "gmi"
        },
        "command": "ssmacro.replace"
    },
    {
        "args": {
            "find": "([^\\x00-\\x7F]) ([a-z0-9])",
            "replace": "$1$2",
            "all": true,
            "reg": true,
            "flag": "gmi"
        },
        "command": "ssmacro.replace"
    },/code>

かかる時間

大きいファイル(20万ワードとか)10数秒かかるときもありますが、そこまで苦にはなりません。

あとはお好みで

数えてみると100以上ルールを作っていました。AWSのサービス名の他にも「畳み込みニューラルネットワーク」→「CNN」とか、いつでも「アベイラビリティーゾーン」→「AZ」とか、「アプリケーション|application」→「app」とか。好みでどんどん設定してくとよいと思います。表記ゆれで全ては判定できなかったりもしますので、あまり完璧を目指さないほうがよいかもしれません。

課題

効率的な正規表現がかけていない気がします。とりあえず苦にならないレベルで動いているので放置中ですが・・・。

2021年7月4日日曜日

S3のETagの確認をboto3で

S3にデータをアップロードしたときに、ファイルが同一であるかを確認する方法として、前後でETagを比較して判定することができます。実際に手を動かしてやってみました。

(環境: コマンドラインはUbuntu20.4, Python 3.7)

公式の記事にはCLIでのチェックサムによるアップロード時の整合性検証の解説があります。
https://aws.amazon.com/jp/premiumsupport/knowledge-center/data-integrity-s3/

ETagとは

ETagはオブジェクトのハッシュタグと同等で、ファイルの内容を反映しています。 32桁のhexで表すことができます(MD5)。

上の記事にはこんな注意書きが。

注意: エンティティタグ (ETag) はオブジェクトのハッシュで、オブジェクトデータの MD5 ダイジェストではない場合があります。ETag が MD5 ダイジェストであるかどうかは、オブジェクトの作成方法と暗号化方法によって異なります。ETag は常に MD5 ダイジェストではないため、アップロードされたファイルの整合性の検証に常に使用できるとは限りません。

ともあれ、AWSのS3のETagはローカルのMD5 ダイジェストと同一であるはずといういうことで、 アップロード後に比較して、整合性を確認します。

ファイルの準備

test.txt というファイルに文字列を書き込みます。なんでもよいです。

echo "This is a test for comparing MD5 hash and S3 Etag." > test.txt
ローカルでのMD5値 opensslコマンドでmd5ハッシュを取得します。
openssl test.txt

Out:
MD5(test.txt)= 617e1d5baa89ead4962dc5469c649f16
抜き出すために grepします。
 openssl md5 test.txt | grep -oP "=\s+\K\w+"
Out:
617e1d5baa89ead4962dc5469c649f16
https://unix.stackexchange.com/questions/207171/get-value-after-specific-word -o ==> option for printing only the matching part of the line -P ==> use perl-regexp \K ==> do not print that comes before \K (zero-width look-behind assertion) \w ==> match word characters もうひとつやり方
md5sum test.txt
Out:
617e1d5baa89ead4962dc5469c649f16  test.txt
test.txtが邪魔なので、こうすると、ハッシュだけを取り出せます。
md5sum test.txt | grep -oP "\w+(?=\s)"

S3にアップロードする

バケットに移動、ドラッグアンドドロップでアップロードします。Etagの項目を見てみると、確かに同じになっています。目視で確認してもいいですね。

boto3 Pythonスクリプトで確認する

次はboto3でローカルおよびS3バケットにアクセスしてEtagの値を取得します。
import boto3
import base64
import hashlib

file_name = "test.txt"
bucket_name = 'your-bucket'
region = 'your-region'
ファイル名、バケット名、リージョンを設定します。

ローカルファイルのmd5 をpythonから確認する

m = hashlib.md5()
with open(file_name, "rb") as f:
    read = f.read()
    m.update(read)

local_md5 = m.hexdigest()
print(local_md5)

Out:
617e1d5baa89ead4962dc5469c649f16
ここでバケットを作ったりファイルのアップロードをboto3でやる場合は、 boto3-s3のドキュメントにある、create_bucket()やupload_file()を使えばよいです。

オブジェクトのヘッダを取得して、ETagを探します。
header['ResponseMetadata']['HTTPHeaders']['etag']

header['ETag']
に同じETagの値が入っています。これが2つなのは、HTTPで送信されてきたときのヘッダと、取得してからのヘッダだからなのでは、と思っていますが自信ないです。(TODO)
s3_client = boto3.client('s3')
header = s3_client.head_object(Bucket=bucket_name, Key=file_name)
ETag = header['ETag'].strip('""')
ETag = get_ETag(bucket_name, file_name)

print(ETag)
print(local_md5)
print(ETag == local_md5)

Out:
617e1d5baa89ead4962dc5469c649f16
617e1d5baa89ead4962dc5469c649f16
True
まとめ S3にアップロードしたオブジェクトのEtagを確認して、ファイルの同一性を確認しました。確認には、boto3を使いました。

PythonのConfigParserで%のエラーが出たときの対処

Pythonでは.iniファイルからConfigParser で読むことができます。そのときに、値に%が入っているとエラーがでることがあり、その対象方法です。

setting.ini ファイルにこのような情報がキーバリューがあったとします。ウィキペディアのトップページです。
[web-page]
URL = https://ja.wikipedia.org/wiki/%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%9A%E3%83%BC%E3%82%B8

呼び出し側の記述を何も考えずにデフォルトのままにすると、config["web-page"]["URL"]の部分で失敗します。

import configparser
config = configparser.ConfigParser()
config.read("setting.ini")
URL = config["web-page"]["URL"]

...

Traceback (most recent call last):
...
  File "/.../anaconda3/lib/python3.7/configparser.py", line 444, in _interpolate_some
    "found: %r" % (rest,))
configparser.InterpolationSyntaxError: '%' must be followed by '%' or '(', found: '%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%9A%E3%83%BC%E3%82%B8'

対処方法

%で補完してくれる機能があってそのときの記号として%を使うとおかしなことになっていますよ、というエラーが出ている状態ですので、
interpolation=None を使って補完を無視します。
import configparser
config = configparser.ConfigParser(interpolation=None)
config.read("setting.ini")
URL = config["web-page"]["URL"] 
これで読み込めます。