プログラミング備忘録

仕事で覚えたことのまとめ

AWSコンテンツへのアクセスを限定開放する黒田如水の画像下さい!!!!(2)CloudFrontを設定する

あらすじ

黒田家のAWSのS3にあるファイルやAPIを特定の相手のみが利用できる形で公開するために、CloudFrontを使用する。

亡き友、竹中半兵衛重治が残した言葉を胸に刻み・・・(エモポイント)

CloudFrontとは

S3やAPIAWSのアカウントを持っていない人でも、条件に合致するならアクセスできるようにする、という仕組みです。 もしくはWeb上のアクセスの関所。

設定をしていく ver20210531

AWSコンソールからCloudFrontを立ち上げる

コンソールにログイン後、一番上の検索フィールドでCloudFrontと入力します。 サービスに表示されるCloudFrontを押下しましょう。 f:id:nigou2:20210710152846p:plain

下図のように左上にCloudFrontと表示される画面が立ち上がります。

f:id:nigou2:20210710152917p:plain

今回の目的 Distribution を作る

Distributionとは

Distributionとは、Web上に置かれるアクセスの関所そのものを指します。 Distributionの設定要素はいくつかありますが、

Origin
関所を通ってアクセスを許可するAWSの何か(APIやAPIなど)
Behabior アクセスをどのOriginに振り分けるかのルール

の2つだけ押さえておけば一旦は大丈夫です。 逆に言えば、Distributionを作成する際に、最低でも一つずつOriginBehabiorは必要になります。

Distribution初期設定

画面左のペインから一番上のDistributionsを押下します。 f:id:nigou2:20210710153056p:plain

表示された画面の一番上部のCreate Distributionを押下します。 f:id:nigou2:20210710153115p:plain

英語で記載されたページに遷移したかと思います。 f:id:nigou2:20210710153132p:plain

一応、英文の内容ですが

以下のことがしたい場合はDistributionを作成します。
・静的および動的コンテンツ (.html、.css、.php、グラフィック ファイルなど) の配布を高速化します。
・HTTP または HTTPS を使用してメディア ファイルを配布します
・オブジェクトを追加、更新、または削除し、Web フォームからデータを送信します。
・ライブ ストリーミングを使用して、イベントをリアルタイムでストリーミングします。

ファイルをオリジン (Amazon S3 バケットまたはウェブサーバー) に保存します。
ディストリビューションを作成した後、ディストリビューションにオリジンを追加できます。

つまりDistributionでできることを説明しています。Get Startedしましょう。 するとやたら入力ボックスのある画面が表示されます。 f:id:nigou2:20210710153156p:plain

ただし、これを全部入力する必要はありません。 ここで行うのは上から、前掲の必須の2要素、OriginBehavior、最後にDistibutionの設定になります。

Origin設定

OriginにS3バケットを設定する場合

先頭のOriginDomainNameの枠をクリックし、プルダウン表示される中から対象のバケットを選びます。 f:id:nigou2:20210710153324p:plain 加えてバケット内の特定のフォルダオブジェクトを対象に取りたい場合は、Origin Pathにスラッシュとフォルダ名を記載します。 f:id:nigou2:20210710153338p:plain

Restrict Bucket AccessはYesにします。

Origin Access Identityはそのまま、Grant Read Permissions on BucketYes, Update Bucket Policyとします。 これをしないと、S3側のバケットポリシーが更新されず、Distributionからのアクセスも弾いてしまうので注意が必要です。

また、Distributionの初期設定が終わったらバケットのアクセス状態は公開になっていることを確認してください。 f:id:nigou2:20210710153728p:plain これがONになっていると、Distributionからのアクセスも拒否されてしまいます。

OriginにAPI Gatewayを設定する場合

エンドポイントのURLのうち、ステージ名以降を除いた部分をOriginDomainNameの枠に貼り付けます。 f:id:nigou2:20210710154053p:plain 勝手にhttps://が省略されますが問題ございません。 加えてOrigin Pathにスラッシュとステージ名を記載します。 f:id:nigou2:20210710154117p:plain

共通

Enable Origin Shield は指定しなくても大丈夫です。 指定すると、Origin Shield Regionを指定できるようになります。 Origin Shield Regionを指定すると、レイテンシが小さくなる=そのリージョンに通信が最適化される、らしいです。

f:id:nigou2:20210710153417p:plain

Origin IDを入力します。デフォルトで入るものは長いので、管理する際に分かりやすい文字列に差し替えることをお勧めします。 f:id:nigou2:20210710154142p:plain

Minimum Origin SSL ProtocolTLSv1.2Origin Protocol PolicyHTTPS Onlyを指定します。 詳細が気になる方は「こちら(外部)」を確認してください。 f:id:nigou2:20210710154208p:plain

他、接続のタイムアウト、レスポンスのタイムアウト、ヘッダー指定もありますが、基本はデフォルト値で大丈夫です。

Behavior設定

Viewer Protocol PolicyHTTP and HTTPSにします。HTTPリクエスト、HTTPSリクエストいずれも可という状態です。 Allowed HTTP Methods は許容するHTTPリクエストの種類です。POSTされて動くAPIをOriginに指定しているのであればに一番下のものにしないと動かないので、何も考えず一番下のものでいいと思います。

f:id:nigou2:20210710154316p:plain

その他は一切操作は不要ですが、Real-time Log Configurationについては, リアルタイムでログを蓄積したい、且Kinesisを導入しているなら有効化が可能です。 参考

Distribution設定

ここについても基本的には操作は不要です。 強いて言うと下図のAWS WAF Web ACLは、後から使用します。

f:id:nigou2:20210710154345p:plain これが、Distributionに対して適用するアクセス制限のルールをつかさどります。 ※逆に言うとDistributionを作成するだけだと門番がいない関所を立てたにすぎないので注意

最後に画面最後のCreate Distributionを押下したら完成です。

テスト

再び、左のペインからDistributionsに戻ります。 Create Distributionsの下に、今まで作ったDistributionが並んでいるので、作成したもののIDをクリックします。 f:id:nigou2:20210710154443p:plain

下図のような画面が表示されたら、Domain Nameをコピーしましょう。 f:id:nigou2:20210710154839p:plain

OriginにS3バケットを設定した場合

ブラウザのURLにDomain Name/[ファイル名]を入力します。

例)

Origin Domain Nameを「my_bucket」、Origin Pathを「my_folder」、Domain Nameを「hogehoge.cloudfront.net」と設定しているとします。

画像ファイルであるhttps://my_bucket.s3-ap-northeast-1.amazonaws.com/my_folder/myImage.pnghttps://my_bucket.s3-ap-northeast-1.amazonaws.com/my_folderまでがDomain Nameであるhogehoge.cloudfront.netで代替されているので、 ブラウザにはhogehoge.cloudfront.net/myImage.pngと入力します。

OriginにAPI Gatewayを設定した場合

実際にHTTPリクエストを実行して動作を確認します。 例えばPOSTメソッドのAPIなら下図のようになります。

f:id:nigou2:20210710160238p:plain

もし、POSTしたにもかかわらずThe request could not be satisfied.のようなHTML形式のアラートが返った場合は タブのBehaviorAllowed HTTP MethodsでPOSTが許可されているか確認して下図の通りに設定してください。 f:id:nigou2:20210710160302p:plain

ここまででできたこと

関所と、関所を通らないと辿り着けない場所1個の設定

やらないといけないこと

アクセス制限のルールの設定 (関所に門番を立てる) 関所を通らなければ辿り着けない場所の追加

f:id:nigou2:20210710160352p:plain

f:id:nigou2:20210710160407p:plain

流石「今世の張良」とうたわれた名軍師、黒田如水。今時点で使い道がイメージできている・・・・ 次は複数のコンテンツをCloudFrontに紐づかせる、通称マルチオリジンについてです。

参考

Distribution作成時の設定内容:もっとちゃんとしたやつ

AWSコンテンツへのアクセスを限定開放する黒田如水の画像下さい!!!!(1)CloudFrontって何?

序文

慶長3年、太閤豊臣秀吉崩御。天下人を失った諸大名は徳川、石田の2つの陣営に分かれて政争を始める。 そんな折、九州豊前の大名にして織豊に仕えた名軍師、黒田如水は・・・

S3に格納したファイル、Lambda関数の展開に頭を悩ませていた。

ファイル、家臣にも展開したい。API、同盟相手にも使ってみてもらいたい。が、いずれも敵対する他の大名に見られるわけにはいかない秘中の秘。どうにか安心できる相手にのみファイルやAPIの利用権限を与えられないものだろうか。

そして亡き友、竹中半兵衛重治の遺した言葉を思い出す。

CloudFrontがよいぞ」

目的

S3に格納されている画像ファイルやHTML、RestAPIを、自社の人間に限定して展開したい。 ただし展開対象はAWSCLIはおろかAWSアカウントすら持っていないとする。

CloudFrontとは

Amazon CloudFront は、データ、動画、アプリケーション、および API をすべてデベロッパーにとって使いやすい環境で、低レイテンシーの高速転送により世界中の視聴者に安全に配信する高速コンテンツ配信ネットワーク (CDN) サービスです。 Amazonの説明

分かりやすく説明すると、S3やAPIAWSのアカウントを持っていない人でも、条件に合致するならアクセスできるようにする、という仕組みです。

一応ですが、S3やAPI単位でそれぞれにアクセスを制限する方法もあります。 S3であればバケットポリシーAPIであればリソースポリシーがアクセス時の制限を規定しています。 下図のように特定のリソースについてアクセス可能な相手を制限することも可能ですが、複数のバケットAPIのアクセス条件を一元的に管理することはできません。

f:id:nigou2:20210710150656p:plain
今のままでもよいが、管理が面倒ではある

都度都度APIバケットを解放する度、に設定が必要な上、アクセス制御の条件が変わるたびにバケットAPIを1つ1つ編集しなければなりません。 f:id:nigou2:20210710150534p:plain

戦国きっての名軍師の黒田如水さんはこう考えました。

複数の守城がある場合、敵の進行経路を隘路に制限し、そこにて防陣を敷くべし。 同じアクセス制限のルールを複数に同時に適用するなら、アクセスについての関所を設けるべし。

ということで、複数のリソースについてアクセス制限を同時同義にて行う関所の役割を果たすのがCloudFrontというわけです。

f:id:nigou2:20210710151006p:plain
関所の管理で一元管理

一つ一つのS3やAPIのポリシーを設定する必要もありませんから、管理コストを下げることができます。

f:id:nigou2:20210710151056p:plain

マジですぞ、黒田殿。

TeamsのWebHookのメッセージで改行する方法

まずはこの画像を見ていただきたい

f:id:nigou2:20210710122631p:plain
WebHookのメッセージ

このようにTeamsのメッセージででフォントやリンクを設定する際に、

通常のメッセージなら

f:id:nigou2:20210710123037p:plain

のように書式を設定できますが、WebHookの場合はどうなんでしょう。

使うもの

Microsoft Teams

メッセージを自動で投稿する対象。

WebHook

Teamsのチャネルに設定し、発行されるURLにデータをPOSTするとチャネルに自動でメッセージを送ることができる。

PowerShell

HTTPリクエストのテストに使用する。

Step1 チャネルにWebHookを追加する

WebHookを追加したいチャネルの「・・・」からコネクタを選択し、 f:id:nigou2:20210710125517p:plain

「Incoming Webhook」を選択します。 f:id:nigou2:20210710125635p:plain この時、青いボタンが「追加」になっている場合は コネクタを追加するかの確認画面が立ち上がったりますので「OK」を押します。

再度WebHookを追加したいチャネルの「・・・」からコネクタを選択し、 青いボタンが「構成」になっているのを確認し、押します。 f:id:nigou2:20210710125902p:plain

名前と画像を編集し、左下の「作成」ボタンを押します。 f:id:nigou2:20210710130050p:plain

メッセージを送る際に使用するURLがは行されるので、それをコピーしてから左下の「完了」を押します。 f:id:nigou2:20210710130304p:plain

これでWebHookの設定は完了です。

Step2 WebHook経由でメッセージを送る

※WebHookの発行したURLは「https://hogehoge/webhookb2/fugafuga/IncomingWebhook/poepoe」として説明を続けます。

テストを兼ねてメッセージを送ってみます。 PowerShellで下記のコマンドを実行すると、

$url = "https://hogehoge/webhookb2/fugafuga/IncomingWebhook/poepoe"
$postText = @{
                title = "test-title"
                text="test-message"
                } | ConvertTo-Json -Compress
$body = [Text.Encoding]::UTF8.GetBytes($postText)

Invoke-RestMethod -Method Post -Uri $url -Body $body -ContentType 'application/json'```

下図のように実行されます。 f:id:nigou2:20210710132046p:plain

フォントやリンクのないメッセージであればこれで終了です。

# Step3 本文に書式を設定する

WebHookにPOSTするBODYにマークダウン記法で記載することで、自動投稿メッセージ本文の書式を設定できます。 以下に例を載せておきます。

$postText = @{
                title = "test-title"
                text="**太字**
                <br>
                <font color='red'>赤いフォントの文字</font>
                <br>
                [リンク先](https://www.google.com)"
                } | ConvertTo-Json -Compress

f:id:nigou2:20210710132913p:plain

SQSを使ってAWSのLambda関数を実行させる方法

目的

キューが送信されたら、AWSのLambda関数を実行する。

対象

AWSアカウントを保有する方。

やったこと

PowerAutomationのSQSコネクタを使用してAWSをキックする。

使ったものの説明

Lambda

AWSアカウントを持っていれば使える、クラウド上のプログラム実行環境。

公式

SQS

AWSアカウントを持っていれば使える、ソフト間のメッセージの送受信ツール。

公式

Step1 実行したいLambda関数を用意する

今の時点で実行トリガーなどは設定しないでいいので、とりあえず関数を作ります。 AWSコンソールのサービス検索窓からLambdaのコンソールを開き、「関数の作成」を実行。

f:id:nigou2:20210622100955p:plain
「関数の作成」

一から作成のままで、関数名+ランタイムを設定します。デフォルトの実行ロールは既存のロールでも大丈夫です。

f:id:nigou2:20210622101302p:plain
関数の設定

キューされたメッセージ本文を引数にしたい場合

Lambdaで実行する関数の冒頭部分を以下の構成にすることで、payloadという変数にメッセージ本文が入ります。

def lambda_handler(event, context):

    for record in event['Records']:
       # キューされたメッセージをpayloadという変数に格納
       payload=record["body"]       
  # 以下、処理内容を記載
       print(str(payload))

次に、Lambdaの実行ロールに対してSQS関連のポリシーを与えます。

ポリシーを持たないロールのままだとSQSが実行されたことをLambdaが認識できず、エラーすら表示されないので注意しましょう。

コンソールの設定からアクセス権限を選び、実行ロールをクリックします。

f:id:nigou2:20210622102944p:plain

別タブでIAMロール(AWS上の実行権限)の設定画面が立ち上がるので、アクセス権限タブの「ポリシーをアタッチします」をクリックします。

立ち上がった画面の検索枠に「SQS」と入力すると3つポリシー候補が表示されます。 「AmazonSQSFullAccess」のチェックボックスをONにして、画面最下の「ポリシーのアタッチ」をクリックします。

f:id:nigou2:20210622103355p:plain

※もし「AmazonSQSFullAccess」が表示されない場合は既にポリシーが付与されていないかを確認しましょう。

f:id:nigou2:20210622103716p:plain
IAMロールの画面に一度戻りましょう

これで準備は完了です。

Step2 SQSを構築する

AWSコンソールのサービス検索窓で「Simple Que Service」を選択します。 右上の「キューを作成」を押下し、次の画面で名前を入力します。他の要素はデフォルトのままで問題ないです。

無事にキューが作成出来たら、Lambdaトリガーのタブを選択し、「Lambda関数トリガーを設定」のボタンを押下します。 プルダウンから先ほど作成した関数を選択すれば完了です。

テスト

Queueの画面右上のメッセージを送受信を押下し、適当にメッセージ本文を入力、右上の「メッセージを送信」を押下します。 CloudWatchのロググループで、先ほど紐づけたLambda関数の実行ログを確認し、メッセージを送信した直後のログがあれば成功です。

せっかくなのでSQSのイベント情報を確認してみましょう。 キューから実行するLambda関数で‘print('event: ' , event)‘として、キューを実行します。

CloudEventWatchで確認すると、以下のようなイベントが渡されていることが分かりました。

event:  {'Records': 
    [
        {
            'messageId': '5c362fce-564a-4127-aa9d-2faea4401c4e', 
            'receiptHandle': '◆◆◆◆◆◆', 
            'body': 'test_message', 
            'attributes': {
                'ApproximateReceiveCount': '1',
                'SentTimestamp': '1624683601405', 
                'SenderId': '◆◆◆◆◆◆', 
                'ApproximateFirstReceiveTimestamp': '1624683601417'
            }, 
            'messageAttributes': {}, 
            'md5OfBody': '◆◆◆◆◆◆', 
            'eventSource': 'aws:sqs', 
            'eventSourceARN': 'arn:aws:sqs:%your_region%:◆◆◆◆◆◆:%your_Queue_Name%', 
            'awsRegion': '%your_region%'
            }           
        ]
}

以下のように記載すると、Lambdaではキューメッセージを変数化するだけでなく、送信日時、受信日時も変数として扱えます。 逆に言えば、キューを送ったクラントまでは分からない、ということのようです。

import datetime

def lambda_handler(event, context):

    for record in event['Records']:
        # キューされたメッセージをpayloadという変数に格納
        payload=record["body"]       
        # キューが送付された日時をSentTimestampという変数に格納
        UNISentTimestamp=record["attributes"]["SentTimestamp"]
        # UNIX型日時を通常の日時型に変換
        SentTimestamp = datetime.datetime.fromtimestamp(int(UNISentTimestamp) / 1000)
        print('SentTimestamp: ',SentTimestamp)
        # キューを受信された日時をRecieveTimestampという変数に格納
        UNIReceiveTimestamp =record["attributes"]["ApproximateFirstReceiveTimestamp"]
        # UNIX型日時を通常の日時型に変換
        ReceiveTimestamp=datetime.datetime.fromtimestamp(int(UNIReceiveTimestamp)/1000)   
        print('ReceiveTimestamp:' ,ReceiveTimestamp)
        # 以下、処理内容を記載
        print('message: ', str(payload))

f:id:nigou2:20210626143105p:plain
実行結果

まとめ

Lambdaを実行するだけならAPIゲートウェイでもいいのだが、より設定が簡単なものを使ってみたいという方にはお勧めです。

次回

次はキューメッセージを送付する方法について纏めようと思います。

プログラミングの勉強をVBAから始めた理由

結論

学習しやすかったから

理由1 職場に学習環境が整っていた

新卒の自分が勤めていた部署では、エクセルでのファイル管理、事業の運用が行われていたため、エクセルマクロやエクセルアドインというものが日常的に存在していました。 かつ顧客ごとにエクセルマクロを個別に開発することもよくあったため、現場でエクセルマクロ開発の研修があったりと、エクセルマクロの開発ナレッジもたまっていました。

要するに、VBAでマクロを作れば仕事も楽になる上、会社からも評価される環境で、かつVBAを教わることも容易だった、というのが、学習を始めたきっかけです。

理由2 書くのが簡単だった

エクセルマクロには「マクロの記録」という機能があります。この機能を使うとエクセル上で行った動作がVBAとして書き起こされるので、自分の行いたい操作をVBAで表現したときのイメージがつきやすいのです。 また、VBAの編集画面であるVBEも、ステップイン(1行ごとにVBAを実行すること)が可能かつ、バグ発生時にはその行で止めてくれるので、とにかくデバッグが簡単なんですよね。

f:id:nigou2:20210621202638p:plain
マクロの記憶(魔法のボタン)

要するに、プログラミングを書く行為=コーディングが簡単だった、というのが、学習・開発を続けられた要因でした。

つまり

自分がプログラミングに向いているかを知るという目的に関して言えば、(Windowsユーザーの方なら)これ以上ない言語だと思います。

VBAが書けるからってプログラマとして胸を張れるかは、また別になるんですけども・・・

オチ

Progateを使ってVBA以外にもいろんな言語を勉強しましたが、結局それから2年以上使うことはありませんでした。 VBAで完結できる仕事を頼まれている限りは、わざわざ別の言語で開発する必然性がなくなるのです・・・

いざ「AWSで動くような仕組み作ってよ」と言われてPythonを書いてみると、恐ろしいもので、print('Hello,Wold')すら忘れてましたね・・・

自分はコードを書き続けるか、記事か何かに残すかしないと、あっさり忘れる人間なんだと身に沁みましたね。うん。

ちょこちょこ直す単語帳~大体こういう理解です~

VBA

VisualBasicApplicationsの略。 Microsoftのアプリを動かすプログラム言語です。
どうしても古いイメージが付きまといますが、
他の言語と比べると学習コストが低いと個人的には思っています。

マクロ

VBAで作ったアプリケーション。
エクセルファイルをベースに作ったものならエクセルマクロ。

Python

ローカルアプリ開発からサーバー側の動き、機械学習までできるスーパー言語。
筆者はLambdaでお世話になっています。

AWS

AmazonWebService。
Amazon保有するWeb環境で、翻訳や、プログラムの実行環境そのものなど、さまざまなアプリ向けサービスを提供している。
地球のどこかにある、専用アカウント持ってればアクセスし放題のPCみたいなもののことだと思ってOKです

サーバー

Webアクセスで動かせる、PCみたいなもの。
※Web系の諸単語は勉強中です。。。

筆者

史書読んで論文を書くタイプの文系学生でした。
事業会社勤めになってから、プログラミングで仕事がうまく回ればいいのにと一念発起、マクロを作るところから始めました。