zuntan02のはてなブログ

備忘録的なものです。時々職場の技術者ブログにも転記してますが、メインはこちらで。

メモ:GASでAWSから来る請求書PDFをアカウント別に名前を付けて保存する

参考

https://korotoro.hatenablog.com/entry/2015/12/05/224731
例によって上記ほぼそのまんまです。エイリアスとかでAWSアカウント毎にメアドが違う場合にわかるように分離したかった。

■事前準備:

・添付ファイルをまとめておくフォルダ名(以下の例:AWS_Tax_Invoice)
・添付ファイルがついたメールの検索条件(以下の例:subject:("Amazon Web Services Tax Invoice Available") has:attachment newer_than:20d')
を以下のコードに反映する必要があるので、それぞれ用意します。

■使い方

1)集めたい添付ファイルのついたメール群を受信しているGmailアカウントにログインしておく
2)https://script.google.com/home で[+新しいプロジェクト]
3)hoge.gsに下記コードを修正のうえ張り付けて実行
4)Googleアカウント承認が走るので承認(初回のみ
5)実行→実行ログを見つめる。。。
6)時計のマークから月一回とか毎日定時とかの実行設定もできる


function labelpick(){
   var f = DriveApp.createFolder('AWS_Tax_Invoice');  //ここに作りたい'フォルダ名'を入れる
   var ID = f.getId(); 
   var folder = DriveApp.getFolderById(ID);
   var threads = GmailApp.search('subject:("Amazon Web Services Tax Invoice Available") has:attachment newer_than:20d'); //受信トレイの'検索条件'を入れる
    
    for (var x=0; x<threads.length; x++) {

      var messages = threads[x].getMessages();

        for (var y=0; y<messages.length; y++) { 
         var attachments = messages[y].getAttachments();
         var recipients  = messages[y].getTo() + '.pdf'; //宛先メアド+.pdfでファイル名を指定する
            for (var z=0; z<attachments.length; z++) {
              var file = attachments[z].setName(recipients);
              var nakami =DriveApp.createFile(file);          
              folder.addFile(nakami);
              DriveApp.getRootFolder().removeFile(nakami);
            }
        }  
    }  
}

【GoogleWorkspace】契約してすぐにアカウントを一括登録しようとしたら50人が上限だった時の解決方法

【問題】

GoogleWorkspaceを独自ドメインで契約して、その日のうちにCSVで200人分くらい登録しようとしたら50人が上限だと言われてしまう

【解決】

ヘルプアシスタント(https://admin.google.com/ の右上にある[?])より、サポートに問い合わせる、でチャット(英語)を経由して確認したところ、アカウント作ったばっかりの時は50人までしか登録できないとのこと。いつ増えるの?と聞くと時間がたてば増える、とのこと。
すぐ増やしたい場合は、お支払いアカウントから[早期支払い]で、引き上げたい上限の半分まで先払いしてほしい、と言われた。200人なら100人分の月額料金を支払って、再度サポートに連絡すると、すぐに上限が引き上げられた(最大72hかかります、と言われた)。

[追記]さらに10人追加したいときは、その半分の5人分を支払えば引き上げてくれた。

以上。

【AWS】IAMパスワードポリシーを設定する

【設定箇所】

[AWS マネジメントコンソール][IAM コンソール]-ナビゲーションペインで [アカウント設定]
f:id:zuntan02:20210520162731p:plain

当初のパスワードポリシー

・パスワードの最小文字数は 8 文字です
・大文字、小文字、数字、および ! @ # $ % ^ & * ( ) _ + - = [ ] { } | 'の文字タイプの組み合わせのうち少なくとも 3 つを含めます。
AWS アカウント名や E メールアドレスと同じにすることはできません

変更後のパスワードポリシー(例

・パスワードの最小文字数は 8 文字です
・1 文字以上のアルファベット大文字 (A~Z) を必要とする
・1 文字以上のアルファベット小文字 (a~z) を必要とする
・少なくとも 1 つの数字が必要
・少なくとも 1 つの英数字以外の文字が必要 (! @ # $ % ^ & * ( ) _ + - = [ ] { } | ')
パスワードは 120 日で有効期限が切れます

120日後、パスワードは失効し、IAM ユーザーは AWS マネジメントコンソールにアクセスする前に新しいパスワードを設定する必要があります。
※IAM ユーザーのパスワードの有効期限まで 15 日以内になると、AWS マネジメントコンソールに警告メッセージが表示されます。

以上

【AWS】EC2のディスク(EBS)拡張_xfsの場合

【手順概要】

1)マネジメントコンソールよりディスクボリューム拡張
2)lsblkとdfでOSから見えるディスクサイズを確認
3)growpartで対象ブロックデバイスパーティションを拡張
4)各ボリュームでファイルシステムを拡張(xfs_growfs)

■マネジメントコンソールよりディスクボリューム拡張

[EC2ダッシュボード]-[ボリューム]
→対象のボリューム: vol-hogehogeを選択

[アクション]-[ボリュームの変更]
「ボリュームの変更」ウィンドウに、ボリューム ID とボリュームの現在の設定
(タイプ、サイズ、IOPS など) が表示されます。
これらの設定のいずれかまたはすべてを 1 回のアクションで変更できます。

f:id:zuntan02:20170929113135p:plain

■lsblkとdfでOSから見えるディスクサイズを確認

ファイルシステムの確認
file -s /dev/nvme0n1p1
/dev/nvme0n1p1: SGI XFS filesystem data (blksz 4096, inosz 512, v2 dirs)

df -hT

Filesystem     Type      Size  Used Avail Use% Mounted on
devtmpfs       devtmpfs  1.9G     0  1.9G   0% /dev
tmpfs          tmpfs     1.9G     0  1.9G   0% /dev/shm
tmpfs          tmpfs     1.9G   33M  1.9G   2% /run
tmpfs          tmpfs     1.9G     0  1.9G   0% /sys/fs/cgroup
/dev/nvme0n1p1 xfs        20G   19G  1.3G  94% /
tmpfs          tmpfs     389M     0  389M   0% /run/user/0
tmpfs          tmpfs     389M     0  389M   0% /run/user/1001

→AmazonLinux2ではファイルシステムext4ではなくXFSとなる。
ファイルシステムext4の場合は
【AWS】EC2のディスク(EBS)拡張_ext4の場合 - zuntan02のはてなブログ
上記をご参照ください

DISKスライス(ブロックデバイス)を確認

lsblk

NAME          MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
nvme0n1       259:0    0  100G  0 disk
- nvme0n1p1   259:1    0   20G  0 part /
- nvme0n1p128 259:2    0    1M  0 part

■growpartで対象ブロックデバイスパーティションを拡張

growpart /dev/nvme0n1 1

CHANGED: partition=1 start=4096 old: size=41938911 end=41943007 new: size=209711071 end=209715167

lsblk

NAME          MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
nvme0n1       259:0    0  100G  0 disk
- nvme0n1p1   259:1    0  100G  0 part /
- nvme0n1p128 259:2    0    1M  0 part


df -h

Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        1.9G     0  1.9G   0% /dev
tmpfs           1.9G     0  1.9G   0% /dev/shm
tmpfs           1.9G   33M  1.9G   2% /run
tmpfs           1.9G     0  1.9G   0% /sys/fs/cgroup
/dev/nvme0n1p1   20G   19G  1.3G  94% /
tmpfs           389M     0  389M   0% /run/user/0
tmpfs           389M     0  389M   0% /run/user/1001
>||
→この時点ではまだ拡張されていない


**■各ボリュームでファイルシステムを拡張(xfs_growfs)
xfs_growfs -d /
>||

meta-data=/dev/nvme0n1p1         isize=512    agcount=11, agsize=524159 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1 spinodes=0
data     =                       bsize=4096   blocks=5242363, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal               bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
data blocks changed from 5242363 to 26213883

df -h

Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        1.9G     0  1.9G   0% /dev
tmpfs           1.9G     0  1.9G   0% /dev/shm
tmpfs           1.9G   33M  1.9G   2% /run
tmpfs           1.9G     0  1.9G   0% /sys/fs/cgroup
/dev/nvme0n1p1  100G   19G   82G  19% /
tmpfs           389M     0  389M   0% /run/user/0
tmpfs           389M     0  389M   0% /run/user/1001

→拡張された

【terrafrom入門_1回目】Windows10+WSL2にterrafromを入れて動かす

【はじめに】

記事を書いた人間はインフラ構成管理について勉強中です。
この記事では、Windows10のWSL2にVisualStudioCodeで入ってterrafromコマンドを実行しながら進めていきます

Win10+WSL2環境の構築方法は

【俺的2021標準環境作成メモ】WSL2 + VSCode + Docker 開発環境 - zuntan02のはてなブログ

を参考にして、必要に応じて行っておいてください

【terrafromのインストール】

ざっと調べたところ、以下の2パターンがあるようでした。

(その1:シンプル)Terraformのバイナリをhashicorpから取得して配置

例)

cd /usr/local/src/
wget https://releases.hashicorp.com/terraform/0.15.1/terraform_0.15.1_linux_amd64.zip
unzip terraform_0.15.1_linux_amd64.zip -d /usr/local/bin/
terraform -v
(その2:現実的)terrafromのバージョンマネージャ「tfenv」をインストールして管理

terrafromはバージョンごとで挙動が大きく異なった過去があるようで、複数バージョンを扱う必要があるとのこと。
tfenvがあればterrafromのバージョン切り替えが簡単にできるので、自分はこちらでいきます。

# githubからcloneしてパスを通します。
git clone https://github.com/tfutils/tfenv.git ~/.tfenv
echo 'export PATH="$HOME/.tfenv/bin:$PATH"' >> ~/.bash_profile
source ~/.bash_profile

tfenv --version
# tfenv 2.2.1

# インストールできるバージョンの一覧
tfenv list-remote

# 最新バージョンを指定してインストール
tfenv install 0.15.1

# バージョン切り替え
tfenv use 0.15.1
terraform -v

# 今回使うバージョンを追加
tfenv install 0.12.24
tfenv use 0.12.24
terraform -v


# 確認
tfenv list
  0.15.1
* 0.12.24 (set by /root/.tfenv/version)

【AWS】Cloudwatchlogsのサブスクリプションフィルター→Teamsに通知するメモ

【概要】

先に書いた
https://zuntan02.hateblo.jp/entry/2021/04/14/183922
をベースに、CloudWatchlogsで特定のロググループに特定の文字列が出たらサブスクリプションフィルター経由でTeamsに通知してみたメモ

[CloudWatchロググループのサブスクリプションフィルターでフィルターパターンにヒット]
 → [AWS Lambda]
  → [Microsoft Teams]

のような通知。例によってとりあえず届けばいい人向け。

※以下はjsonでログが出るようなアプリケーションでの内容です

【詳細】

CloudWatchロググループのサブスクリプションフィルター

フィルターパターン:"ERROR"
サブスクリプションフィルター名:ERROR

Lambdaに届くログのイメージ

実際にはgzip化されているが、展開すると以下が投げられていた

{
  "awslogs": {
    "data": {
    "messageType": "DATA_MESSAGE",
    "owner": "xxxxxxxxxx",
    "logGroup": "/log/group/logname",
    "logStream": "logname.log",
    "subscriptionFilters": [
        "ERROR"
    ],
    "logEvents": [
        {
            "id": "xxxx",
            "timestamp": xxxxx,
            "message": "{\"a\":\"aaaa\",\"b\":\"bbbb\",\"c":\"cccc\",\"d\":\dd(省略)....

こさえたLambda

cwl-to-Teams-python

#!/usr/bin/python3.8
import boto3
import json
import logging
import os
import base64
import gzip

from urllib.request import Request, urlopen
from urllib.error import URLError, HTTPError

logger = logging.getLogger()
logger.setLevel(logging.INFO)

HOOK_URL = os.environ['HookUrl']

def lambda_handler(event, context): 

    # CloudWatchLogsからのデータはbase64エンコードされているのでデコード
    decoded_data = base64.b64decode(event['awslogs']['data'])
    # バイナリに圧縮されているため展開
    json_data = json.loads(gzip.decompress(decoded_data))

    # ログデータ取得
    log_group = json_data['logGroup']
    log_stream = json_data['logStream']
    
    # イベントのメッセージをjsonとしてevent_messageに取り込み
    message = json_data['logEvents'][0]['message']
    event_message = json.loads(message)

    log_a = event_message['a']
    log_b = event_message['b']
    log_c = event_message['c']

    # Teamsに直接通知
    alert_msg = {
     "@type": "MessageCard",
        "@context": "http://schema.org/extensions",
        "themeColor": "0076D7",
        "summary": "エラー出ました",
        "sections": [
            {
                "activityTitle": "エラー出ました",
                "facts": [
                    {
                        "name": "ロググループ名",
                        "value": log_group
                    },
                    {
                        "name": "ログストリーム名",
                        "value": log_stream
                    },
                    {
                        "name": "項目a",
                        "value": log_a
                    },
                    {
                        "name": "項目b",
                        "value": log_b
                    },
                    {
                        "name": "項目c",
                        "value": log_c
                    }
                ]
            }
        ]
    }

    req = Request(HOOK_URL, json.dumps(alert_msg).encode('utf-8'))
    
    
    try:
        response = urlopen(req)
        response.read()
        logger.info("Message posted")
    except HTTPError as e:
        logger.error("Request failed: %d %s", e.code, e.reason)
    except URLError as e:
        logger.error("Server connection failed: %s", e.reason)

環境変数HookUrlにTeamsのWebhookのURLを入れておくとメッセージが飛んでくる・・・はず・・・

※Teamsのコネクタメッセージの書式は以下を参考のこと
https://docs.microsoft.com/ja-jp/microsoftteams/platform/webhooks-and-connectors/how-to/connectors-using

【AWS】CodePipelineの状態をTeamsに送るメモ

【概要】

先に書いた
https://zuntan02.hateblo.jp/entry/2021/04/14/183922
をベースに、CloudWatchEventsによりCodePipelineのステージの挙動(CodePipeline Stage Execution State Change)を拾って
[(CloudWatch Eventsで)CodePipelineの状態変更検知]
 → [Amazon SNS]
  → [AWS Lambda]
   → [Microsoft Teams]
のような通知を作成した。とりあえず届けばいい人向け。
※上記同様HookURLの暗号化のあたりはLambdaの環境変数にそのまま持たせてます

【参考】

https://dev.classmethod.jp/articles/notify-codepipeline-events-to-slack/
例によってほぼそのままです。

【詳細】

1)Lambdaの関数作成

  • 関数名:例)CodePipeline-state-to-teams-python
  • ランタイム:Python 3.8
  • アクセス権限:実行ロール:基本的な Lambda アクセス権限で新しいロールを作成

[設定]-[環境変数]で以下の環境変数を追加
キー:HookUrl
値:TeamsのWebHook

コード

#!/usr/bin/python3.8
import boto3
import json
import logging
import os

from urllib.request import Request, urlopen
from urllib.error import URLError, HTTPError

logger = logging.getLogger()
logger.setLevel(logging.INFO)

HOOK_URL = os.environ['HookUrl']

def lambda_handler(event, context):
    logger.info("Event: " + str(event))
    message = json.loads(event['Records'][0]['Sns']['Message'])
    logger.info("Message: " + str(message))

    region = message['region']
    pipeline_name = message['detail']['pipeline']
    stage_name = message['detail']['stage']
    state = message['detail']['state']

    teams_message = {
        'text': "State %s (Pipeline %s) is now %s :https://%s.console.aws.amazon.com/codepipeline/home?region=%s#/view/%s" % (stage_name, pipeline_name, state, region, region, pipeline_name)
    }

    req = Request(HOOK_URL, json.dumps(teams_message).encode('utf-8'))
    try:
        response = urlopen(req)
        response.read()
        logger.info("Message posted to Teams")
    except HTTPError as e:
        logger.error("Request failed: %d %s", e.code, e.reason)
    except URLError as e:
        logger.error("Server connection failed: %s", e.reason)

2)SNSトピック作成

AmazonSNSを作成し、サブスクリプションとして
プロトコルAWS Lambda
エンドポイント:上記で作成したLambda
を設定する

3)CloudWatchEentsルール作成

[CloudWatch]-[CloudWatch Events]

ルールを作成する

イベントパターン
サービス名:CodePipeline
イベントタイプ:CodePipeline Stage Execution State Change

ターゲット:SNSトピック
→2)で作成したSNトピック名

4)テスト

任意のCodePipelineを実行

State Build (Pipeline <pipeline_name>) is now FAILED : https://ap-northeast-1.console.aws.amazon.com/codepipeline/home?region=ap-northeast-1#/view/<pipeline_name>

の様な通知が届く