20211124のAWSに関する記事は18件です。

EKSをできるだけCloudFormationで構築した話

背景 業務でEKSを含むアーキテクチャの設計構築を任されました。しかしながら周りにEKS経験者がおらず独学で構築方法も学びました。そしてデプロイ後も保守性の高くなるようなEKSの構築方法に大分悩まされました。 そこで直面した課題や解決方法を共有します。 はじめに 具体的なソースコードはGitHubリポジトリで公開しています。 ここでは、試行錯誤の道のりみたいなものを書きます。 今回のゴール 以下のようなEKS on Fargateを含むアーキテクチャを作成したい。 (パブリック/プライベートサブネットは2AZに跨ぐ必要あるのでそれぞれ2つずつ作っているが、図では簡略化) EKSクラスターの構築アプローチ EKSクラスターを構築する方法は大きく以下の2つあると考えられる。 1. EKS側からの構築 ・eksctlコマンド EKS関連のインフラ(クラスター、Fargateプロファイル、VPC等)はeksctlで簡単に構築することができる。一番楽に作るとすれば、以下のコマンドだけでEKSの所属するVPC、サブネット、NAT Gatewayなど色々なものが自動的に作れる。 $ ekctl create cluster ・kubectl EKS内のアプリケーションはマニフェストで構成管理し、kubectlコマンドでデプロイする。 $ kubectl apply -f manifest.yml 2. AWS側からの構築 ・CloudFormation等のIaCで構築する。EKSクラスター自体やFargateプロファイルはCFnテンプレートで構築できるようサポートされている。(ドキュメント) ・一方、EKS内のアプリケーションはさすがにCFnで作るわけにはいかず、マニフェストで作成・デプロイする必要がある。 EKS側からの構築に頼る場合の問題点 ALBを前段に置く時 EKSクラスターにインターネットから直接アクセスさせるようなことは少なく、クラスターの前段にALBを配置してロードバランシングさせるような構成が多いと思いはず。 この時、AWS Load Balancer ControllerをクラスターにインストールしてEKS側からALBもデプロイすることが一般的な構築方法だと考えられる。(ドキュメントにもこの構築方法あり) この手法の場合、Ingressマニフェストを記述しkubectl applyするとALBが作成される。そうするとALBが自動的にEKSクラスタと紐付けられる。 最初はこの、「EKS側からの構築」アプローチで進めていたが、問題が発生した。 ALB(Ingress)とそれにアタッチするリソースの結合が保てない 要件の一つとして、セキュリティのためALBにWAFをアタッチする必要があった。この時、一つの疑問が生じた。 「Ingressマニフェストを更新してEKS側からALBを更新しても、WAFはアタッチは保持されるんだろうか…?」 そこで検証してみたが、不安は的中した。。 $ kubectl applyでIngressをデプロイし直すとWAFは外れたり外れなかったりした。 これではEKSのバージョンアップ等、運用中に更新が入った時にWAFが外れてしまい、知らず知らずのうちに当初の構成と違うものになる恐れがある。 (バグの可能性あり、今後改善されるかもしれないが) 現実的な構成として、ALBに関連付けられるリソースはWAF以外にもRoute53, ACM, セキュリティグループなどたくさんある。これらとの結合を保持させるようEKS側で実装させるのは難易度が高い。。 (ただ、WAFのアタッチだけならIngressマニフェストのannotationで記述して保持することができます) CloudFormationで構築してみた そこで、「ALBをIngressマニフェストでEKS側から構築するんじゃなくて、CloudFormationでAWS側から構築してEKSと結合できないか?」と考えた。これが実現できればCloudFormationの記述でALBに関連づけられるリソース群(WAF, Route53, SG等)との結合保持も担保できる。 しかも現場でよく使っているCFnテンプレートを簡単に使いまわすことができ、Ingressマニフェストを書く必要なくなり工数削減にもなる。 しかし、ここでも問題が発生した… 1. 問題点:TargetGroupが設定できない CloudFormationで作成したALBと、EKS側で(マニフェストで)作成したEKSアプリケーションの結合がうまくできなかった。 EKS on Fargateを用いている場合、ターゲットグループでIPタイプでバックエンドを指定する必要がある。 AWS Load Balancer ControllerでALBをデプロイした際は、この結合をEKS側がよしなにやっており、起動中のPodのIPアドレスを自動でターゲッティングしてくれていた。 しかし、今回ターゲッティングは自動でしてくれない。PodのIPは動的に変わるから手動で指定することも不可能。 2. 解決策:TargetGroupBindingを使用 何か解決策はないか…。とネットを彷徨っていたら、バッチリのものを見つけました。 TargetGroupBinding これはAWS Load Balancer Controllerのカスタムリソースで、ターゲットグループARNと、ALBにアタッチされているセキュリティグループを書いたマニフェストをデプロイすることで、以下のように実行中のPodを自動でターゲッティングしてくれるというもの。 これにより、AWS LoadBalancerControllerは使うものの、ALB自体ではなくPodターゲッティングだけEKS側に任せて、ALBはCloudFormationで管理できるようになった。  まとめ ・ALB-EKSを連携する場合、AWS LoadBalancer ControllerでALBをデプロイする方法が一般的だと思われるが、その時にはALBと他リソース(WAF, Route53等)のアタッチ保持問題が発生する。 ・そこで、CloudFormation等AWS側でALBをデプロイし、TargetGroupBindingによりEKSと結合させる手法をとった。 ・これにより、以下2点の問題が解決できた。 1. ALBとそれにアタッチするリソースとの結合をEKSアップデートがあっても保持させる。 2. 従来の(EKSがないアーキテクチャでの)オペレーション通り、大半のリソースはCloudFormationで管理し、アプリケーションに関連する部分だけK8sマニフェストで記述して構築、管理の工数を削減。  最後に 今回の構成のCloudFormationやマニフェストファイル、デプロイ手順は私のGitHubリポジトリで公開しています。 参考までにどうぞ。 参考1:AWS Load Balancer ControllerのTargetGroupBindingを試す 参考2:TargetGroupBinding を使って AWS EKS で Kubernetes を無停止かつ DNS 切り替え無しでバージョンアップしました
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ラジオで今流れている曲を Slack に投稿する

現在の職場でラジオを流しているのですが、たま~に気に入った曲があって、調べたりします。 ですが、いちいちラジオ局のサイトを開いて流れている曲を検索するのが実に面倒です。 なので、定期的にラジオ局のサイトを見に行って、流れている曲を見つけて投稿してくれるアプリを作りましょう? 例として、ここでは TOKYO FM で流れている曲を毎分調べて Slack に投稿するというシチュエーションを設定します。 今回使用する AWS のサービスは以下の通りです。 Lambda Secrets Manager IAM CloudWatch Logs EventBridge (CloudWatch Events) 前提 AWS アカウントを持っている Python をインストールしている Slack のアカウントとチャンネルを作成している オンエア曲のサイトを見てみる TOKYO FM のオンエア曲一覧はこちらで確認することができます。 開発者ツールで確認する 今流れている曲は一覧の一番上にある曲なので、開発者ツールのコンソールで以下のコマンドを実行して確認してみましょう。 document.querySelector('#searchResult .entry'); querySelectorAll ではなく querySelector を使用することで最初に見つかった要素、すなわち一番上にある曲が取得できます。 また、アルバムジャケット・曲名・アーティスト名は以下のように取得できます。 // アルバムジャケット document.querySelector('#searchResult .entry .entryThum img').src; // 曲名 document.querySelector('#searchResult .entry .entryTxt a').innerText; // アーティスト名 document.querySelector('#searchResult .entry .entryArtist').innerText; 手順 Slack のアプリを作成する https://api.slack.com/apps にアクセスし、「Create App」をクリックします。 「From scratch」をクリックします。 アプリ名を入力し、ワークスペースを選択します。 アプリの作成が完了すると、アプリの概要が表示されるので、「Edit Manifest」をクリックします。 Manifest の編集画面が表示されたら、以下のように入力して「Save Changes」をクリックします。 _metadata: major_version: 1 minor_version: 1 display_information: name: Now Playing settings: org_deploy_enabled: false socket_mode_enabled: false token_rotation_enabled: false features: bot_user: display_name: Now Playing Bot oauth_config: scopes: bot: - chat:write - chat:write.customize 左のメニューから「OAuth & Permissions」をクリックし、OAuth Tokens for Your Workspace の中の「Install to workspace」をクリックします。 権限リクエストの画面が表示されるので「Allow」をクリックすると、先ほどの画面にもどり今度は Bot User OAuth Token が表示されているはずです。 その値をテキストエディタに貼り付けておいてください。 作成したアプリを Slack チャンネルに追加する アプリを追加したい Slack チャンネルを選び、右クリックして「Open channel details」をクリックします。 「Integrations」を選択し、Apps のところの「Add an app」をクリックします。 作成したアプリを選択し、「Add」をクリックします。 トークンを Secrets Manager に格納する AWS コンソールから Secrets Manager を開き、「Store a new secret」をクリックします。 「Other type of secret」を選択し、画面下の方でトークンを入力します。 今回はキーを token, 値を先ほどメモしておいたトークンにします。 入力したら「Next」をクリックします。 次の画面で Secret name を入力します。ここでは slack-bot-user-oauth-token とします。 入力したら「Next」をクリックします。 残りの画面はそのままで進み、登録します。 すると、一覧に先ほど登録したものが出てくるようになります。 これでトークンの登録は完了です。 Lambda 実行用の IAM Role を作成する AWS コンソールから IAM を開き、左のメニューから「Roles」を選択、その後「Create role」をクリックします。 Choose a use case のところで「Lambda」を選択し、「Next: Permissions」をクリックします。 次の画面ではアタッチするロールを選択する画面になります。フィルターで検索するなどして以下のロールを選択します。 AWSLambdaBasicExecutionRole IAMFullAccess SecretsManagerReadWrite 選択したら、「Next: Tags」「Next: Review」の順にクリックします。 Role name, Role description を入力し、Policies が先ほど選択した 3 つになっていることを確認して、「Create role」をクリックします。 今回は Role name を slack-post-now-playing-role にしました。 Lambda function を作成する 方針としては以下のようになります: オンエア曲のサイトにアクセスして曲情報を取得する 前回取得した情報と異なるとき、Slack に投稿する 投稿した曲情報を格納する AWS コンソールから Lambda を開き、「Create function」をクリックします。 「Author from scratch」を選択し、Basic information の中身は以下のようにします Function name: slack-post-now-playing Runtime: Python 3.9 Basic information の下にある「Change default」をクリックし、Execution role は「Use an existing role」を選択します。 Existing role には前の項で作成した slack-post-now-playing-role を選択します。 選択したら「Create function」をクリックします。 ローカルで Lambda function を作成してアップロードする 今回は Python の外部ライブラリを使用するため、コードは AWS コンソール上ではなく自分の PC 上で作成して zip にしたものをアップロードします。 まず、作業用フォルダを作成し、その中に移動します。 mkdir -p now-playing cd now-playing/ lambda_function.py というファイルを作成し、中身は以下のようにします。 lambda_function.py import base64 import hashlib import json import re import boto3 import requests from botocore.exceptions import ClientError from bs4 import BeautifulSoup def get_song_info() -> dict: """オンエア曲のサイトからスクレイピング Notes: - BeautifulSoup を使用して URL から取得したソースのパースを行っています。 Returns: dict: 曲情報 """ url = 'https://www.keitai.fm/search/view/au/' r = requests.get(url) soup = BeautifulSoup(r.content, 'html.parser') if soup: jacket_url = soup.select('#searchResult .entry .entryThum img')[0]['src'] if not re.match('https?://', jacket_url): jacket_url = url + jacket_url title_obj = soup.select('#searchResult .entry .entryTxt a') or soup.select('#searchResult .entry .entryTxt') title = re.sub(r'\r\n\s+', '', title_obj[0].string) artist = soup.select('#searchResult .entry .entryArtist')[0].string return { 'jacket_url': jacket_url, 'title': title, 'artist': artist, } else: return {} def get_hash(title: str, artist: str) -> str: """曲名・アーティスト名からハッシュを生成する。この値をもとに現在流れている曲が変わったことを検知する。 Args: title: artist: Returns: str: hash. """ return hashlib.sha512(f'{title}{artist}'.encode('utf-8')).hexdigest() def song_is_updated(hash512: str) -> bool: """曲が変わった? Notes: - 最終的にスクリプトは毎分実行になるので、曲情報が更新されていない=ハッシュが以前のものと同じであることを検知します。 Args: hash512: Returns: bool: True if 変わった, False otherwise. """ client = boto3.client('iam') user_tags = client.list_user_tags(UserName='slack-post-now-playing-tags') for tag in user_tags['Tags']: if tag['Key'] == 'hash' and tag['Value'] == hash512: return False return True def update_tag(hash512: str) -> None: """曲情報のハッシュを更新する。 Notes: - IAM ユーザのタグを使用してお金をケチります。 Args: hash512: Returns: """ client = boto3.client('iam') client.tag_user( UserName='slack-post-now-playing-tags', Tags=[ { 'Key': 'hash', 'Value': hash512, } ], ) def get_secret() -> dict: """トークンを取得する。 例外が発生した場合は例外の内容を取得する。 Notes: - トークンの内容は秘密なので Secrets Manager で管理します。 - せっかく曲情報の格納で IAM ユーザのタグを使ってお金をケチったのに、ここでお金がかかります。 Returns: """ secret_name = "arn:aws:secretsmanager:us-east-1:567877680446:secret:slack-bot-user-oauth-token-cDkd36" region_name = "us-east-1" session = boto3.session.Session() client = session.client( service_name='secretsmanager', region_name=region_name ) try: get_secret_value_response = client.get_secret_value( SecretId=secret_name ) except ClientError as e: if e.response['Error']['Code'] == 'DecryptionFailureException': return {'exception': 'DecryptionFailureException'} elif e.response['Error']['Code'] == 'InternalServiceErrorException': return {'exception': 'InternalServiceErrorException'} elif e.response['Error']['Code'] == 'InvalidParameterException': return {'exception': 'InvalidParameterException'} elif e.response['Error']['Code'] == 'InvalidRequestException': return {'exception': 'InvalidRequestException'} elif e.response['Error']['Code'] == 'ResourceNotFoundException': return {'exception': 'ResourceNotFoundException'} else: if 'SecretString' in get_secret_value_response: secret = get_secret_value_response['SecretString'] else: secret = base64.b64decode(get_secret_value_response['SecretBinary']) return json.loads(secret) def post(channel: str, song_info: dict) -> dict: """Slack に投稿する。 Args: channel: song_info: Returns: See Also: - https://api.slack.com/methods/chat.postMessage """ secret = get_secret() if 'exception' in secret: return {'exception': secret['exception']} elif 'token' not in secret: return {} data = { 'channel': channel, 'blocks': [ { "type": "section", "text": { "type": "mrkdwn", "text": f"*{song_info['title']}*\n{song_info['artist']}" }, "accessory": { "type": "image", "image_url": song_info['jacket_url'], "alt_text": "cd_image" } } ], 'icon_emoji': ':radio:', 'text': f"{song_info['artist']} - {song_info['title']}", 'username': 'Now Playing Bot', } headers = { 'Content-Type': 'application/json', 'Authorization': f"Bearer {secret['token']}", } response = requests.post( 'https://slack.com/api/chat.postMessage', data=json.dumps(data), headers=headers, ) return response.json() def lambda_handler(event, context): song_info = get_song_info() hash512 = get_hash(song_info['title'], song_info['artist']) if song_is_updated(hash512): update_tag(hash512) res = post(event['channel'], song_info) else: res = {} return { "statusCode": 200, "body": json.dumps(res), } pip を使ってライブラリのインストールを行います。 pip install --target ./package requests beautifulsoup4 boto3 ライブラリを zip に圧縮します。 cd package/ zip -r ../my-deployment-package.zip . lambda_function.py を zip に追加します。 cd .. zip -g my-deployment-package.zip lambda_function.py Lambda function のタイムアウト時間を設定する 関数の画面で「Configuration」を選択します。 左のメニューから「General configuration」、「Edit」と選択し、タイムアウトを「0 min 15 sec」に設定します。 Lambda function に zip をアップロードする AWS コンソールから Lambda を選択し、作成していた slack-post-now-playing をクリックします。 Code source のあたりで右側の「Upload from」をクリックし、「.zip file」を選択します。 「Upload」をクリックして先ほどの my-deployment-package.zip を選択したら、「Save」をクリックします。 ウィンドウが閉じたら「Test」を選択します。 Test event が表示されたら Template に hello-world を選択し、Name は slack-post-now-playing とします。 イベントを入力し、「Save changes」をクリックします。 今回は sandbox というチャンネルに投稿します。 { "channel": "sandbox" } テスト Test event の右側にある「Test」を押してテストしてみましょう。 すると・・・プシュ、コココッ? 通知が来ました!チャンネルを見てみましょう! うおおおめでとうございます! Now Playing Bot さんがラジオのアイコンで今流れている曲を投稿してくれました! 試しに何回か続けて「Test」を押してみましょう。 すると、違う曲が投稿される or 何も起こらないはずです。 今流れている曲が前回と変わらない場合は投稿されないようになっていれば成功です! 実際の運用へ向けて 無事投稿のテストが成功したところで、 最後に、流れている曲を毎分調べて更新があったら自動的に投稿してくれる仕組みを作ります。 設定 AWS コンソールから Amazon EventBridge を開きます。 ※ CloudWatch Events は Amazon EventBridge に生まれ変わったようです。 左のメニューから「Rules」を選び、「Create rule」をクリックします。 Name and description のところで Name を slack-post-now-playing-rule とします。 Define pattern のところで「Schedule」を選択し、Fixed rate every を 1 Minutes に設定します。 Select targets のところで Target を Lambda function に指定し、Function に作成したものを指定します。 Configure input のところは「Constant (JSON text)」を選択し、{"channel":"sandbox"} (sandbox のところはチャンネル名) と入力して、下の「Create」をクリックします。 しばらくして、以下のように曲が自動で投稿されるようになったら成功です! まとめ 今回は AWS のサービスを使って、ラジオで今流れている曲を Slack に自動投稿するアプリを作ってきました。 なお、今回と同じ仕組みでサービスを 1 か月間運用した場合、料金は以下のようになります。 合計: 0.616 USD (2021/11/24 現在、1 ドル 115 円換算で 70.84 円) Secrets Manager シークレットを 1 つ保存: 0.40 USD API コール: 43,200 回 x 0.05 USD/10,000 コール = 0.216 USD API コール数: 60 分 x 24 時間 x 30 日 = 43,200 回 その他のサービスは基本的に無料枠の範囲内で利用できます。 Lambda: 月 100 万リクエストまで無料なので問題なし CloudWatch Logs: 5 GB まで無料だが、ログの有効期限を 1 day など短めにすれば無料枠を超過することはない また、Secrets Manager を使わなければ 0 円で運用することも一応可能です。 みなさんも機会がありましたら是非やってみてください。 私はこれを作ったばかりのとき、投稿されるたびに Slack の画面を確認していたので仕事が進みませんでしたので気を付けてください? ありがとうございました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CloudWatch Syntheticsでシステム監視する

パーソンリンク アドベントカレンダー 3日目です? 案件で外部監視のために調査したAWSの機能紹介をします。 概要 CloudWatch Syntheticsとは、CloudWatchの機能の一つで外部監査を実現するサービスです。 外部監視とは外部から見た接続状況の監視です。 CloudWatch Syntheticsを利用するためにまずCanaryを作成します。 Canaryとはスケジュールに沿って実行されるスクリプトであり、実態はLambdaレイヤです。 Canaryの設計図にGUIワークフロービルダーを選ぶと、フォーム形式で検証するためのアクションを指定できます。 要素のクリックや存在確認などを行えるため、死活監視だけでなく簡単なE2Eテストもできます。 セレクタはXpath指定です。 上記アクションをそれぞれ指定した際のPythonのスクリプトです。 customer_actions_1などの関数が、フォームで指定したアクションになります。 import asyncio from aws_synthetics.selenium import synthetics_webdriver as syn_webdriver from aws_synthetics.common import synthetics_logger as logger, synthetics_configuration TIMEOUT = 10 async def main(): url = "https://example.com" browser = syn_webdriver.Chrome() # Set synthetics configuration synthetics_configuration.set_config({ "screenshot_on_step_start" : True, "screenshot_on_step_success": True, "screenshot_on_step_failure": True }); # ページがロードできることを確認する def navigate_to_page(): browser.implicitly_wait(TIMEOUT) browser.get(url) await syn_webdriver.execute_step("navigateToUrl", navigate_to_page) # Execute customer steps # ページ内の要素をクリックする def customer_actions_1(): browser.find_element_by_xpath("//h1[@id='success']").click() await syn_webdriver.execute_step('click', customer_actions_1) # 要素が存在することを確認する def customer_actions_2(): browser.find_element_by_xpath("//h1[@id='success']") await syn_webdriver.execute_step('verifySelector', customer_actions_2) # ターゲット要素内の文字列を確認する def customer_actions_3(): browser.find_element_by_xpath("//h1[@id='success'][contains(text(),'sample text')]") await syn_webdriver.execute_step('verifyText', customer_actions_3) # ターゲット要素にテキストを入力する def customer_actions_4(): browser.find_element_by_xpath("//h1[@id='success']").send_keys("sample text") await syn_webdriver.execute_step('input', customer_actions_4) # 要素をクリックしてナビゲーションを期待する def customer_actions_5(): browser.find_element_by_xpath("//h1[@id='success']").click() await syn_webdriver.execute_step('redirection', customer_actions_5) logger.info("Canary successfully executed") async def handler(event, context): # user defined log statements using synthetics_logger logger.info("Selenium Python workflow canary") return await main() 確認 可用性 > Step のタブで実行結果が確認できます。 削除 検証用などで消す場合、Canaryによって作成された関連リソースは自動的に削除されないので、以下も削除する必要があります。 ・Lambda関数とレイヤー ・CloudWatchアラーム ・CloudWatchLogsのロググループ ・AmazonS3オブジェクトとバケット ・IAMロール 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

API Gatewayにカスタムドメインを割り当てる。

API GWにカスタムドメインを設定する。 前提条件 ドメインを取得済み(今回はFreenom利用)。 Route53にホストゾーン作成済み。 FreenomへNSレコードの値を登録済み。 東京リージョンでAWS ACMで証明書を発行済み。(Route53へCNAMEも登録済み) CDKのversion 1.134.0 (build dd5e12d) 必要なリソースの準備と設定(CDK) import * as cdk from '@aws-cdk/core'; import * as lambda from '@aws-cdk/aws-lambda'; import * as apigw from '@aws-cdk/aws-apigateway'; import * as acm from '@aws-cdk/aws-certificatemanager'; import * as route53 from '@aws-cdk/aws-route53'; import * as route53Tragts from '@aws-cdk/aws-route53-targets'; export class CustomdomainapiStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // const const ApigwCustomDomainName = "my-custom-domain.tk"; const ApigwCertificateArn = "arn:aws:acm:ap-northeast-1:************:certificate/*********"; const hostzoneId = "*******************"; const apiName = "test211124"; const apiStageName = "v1"; const apiUsagePlanName = "testusage211124" const apiKeyName = "testusage211124" const lambdaName = "test211124" // == Lambda == const testLambda = new lambda.Function(this, `Lambda`, { code: lambda.Code.fromAsset(`src/${lambdaName}`), functionName: lambdaName, handler: "index.handler", runtime: lambda.Runtime.NODEJS_14_X, }) // == API Gateway == const testApi = new apigw.RestApi(this, "APIGW", { restApiName: apiName, deployOptions: { stageName: apiStageName, }, endpointTypes: [ apigw.EndpointType.REGIONAL ], apiKeySourceType: apigw.ApiKeySourceType.HEADER, domainName: { domainName: ApigwCustomDomainName, certificate: acm.Certificate.fromCertificateArn(this, "Certificate", ApigwCertificateArn), securityPolicy: apigw.SecurityPolicy.TLS_1_2, endpointType: apigw.EndpointType.REGIONAL, } }); // apiUsagePlan const apiUsagePlan = testApi.addUsagePlan("UsagePlan", { name: apiUsagePlanName, throttle: { rateLimit: 10, burstLimit: 2 } }); apiUsagePlan.addApiStage({ stage: testApi.deploymentStage }) // apiKey const key = new apigw.ApiKey(this, "Key", { apiKeyName: apiKeyName }); apiUsagePlan.addApiKey(key); // Path const testPath = testApi.root.addResource("test"); const deeptestPath = testPath.addResource("test"); // Method // root path testApi.root.addMethod("GET", new apigw.LambdaIntegration(testLambda), { methodResponses: [ { statusCode: "200", } ], apiKeyRequired: true }); // /test path testPath.addMethod("GET", new apigw.LambdaIntegration(testLambda), { methodResponses: [ { statusCode: "200", } ], apiKeyRequired: true }); // /test/test path deeptestPath.addMethod("GET", new apigw.LambdaIntegration(testLambda), { methodResponses: [ { statusCode: "200", } ], apiKeyRequired: true }); const hostZone = route53.PublicHostedZone.fromHostedZoneAttributes(this, "HostZone",{ hostedZoneId: hostzoneId, zoneName: ApigwCustomDomainName, } ); new route53.ARecord(this, "ARecord", { zone: hostZone, recordName: ApigwCustomDomainName, target: route53.RecordTarget.fromAlias( new route53Tragts.ApiGateway(testApi), ), } ); } } 200返せば何でもいい(Mockでも十分)だが、一応Lambdaのコードも。 src/test211124/index.js "use strict"; exports.handler = main; async function main(event) { try { console.log("start function"); console.log(`event : ${JSON.stringify(event)}`); return { statusCode: 200, body: "hello" }; } catch (err) { console.error(`[Error] ${JSON.stringify(err)}`); return { statusCode: 500, body: JSON.stringify(err.message) }; } } 検証 postmanで実行。 https://my-custom-domain.tk/ https://my-custom-domain.tk/test https://my-custom-domain.tk/test/test 上記にアクセスできれば成功。 他 手動でRoute53のホストゾーンにAレコードを作成する場合 レコード作成時にエイリアスを指定しAPI GWの選択一覧に出てくるAPIエンドポイントは、カスタムエンドポイントのコンソールの「設定」タブに表示されているもので、ステージ作成時に発行されているものとは異なる。 パス(Optional) カスタムドメインのAPIマッピングの際に指定可能でOptionalとなっているパス。 ルートの位置を指定するものと思っていたが、イメージと違ったのでメモ。 (今考えてみると複数指定できる時点で元の考え方はおかしいのだが、、) 例えば、以下のようなAPIを作成し、2つのリソースを持たせたとする。 http://abcdef012.execute-api.ap-northeast-1.amazonaws.com/v1/ http://abcdef012.execute-api.ap-northeast-1.amazonaws.com/v1/test このAPIにカスタムドメインmy-custom-domain.comを設定し、上記のようにマッピング(パス指定なし)すると、それぞれ以下のようにしてアクセスする必要がある。 https://my-custom-domain.tk/ https://my-custom-domain.tk/test つまりデフォルトでv1にマッピングされるのでカスタムドメインでのアクセス時に/v1/を入れる必要がなくなる。 ここで、v1を明示して指定させたい時、このパス(Optional)にてv1と書く。 すると、上記のURLではアクセスできなくなり、以下のように指定するようになる。 https://my-custom-domain.tk/v1 https://my-custom-domain.tk/v1/test もちろんパス部には何を書いてもいい(/とかは入れられない)のでパスにv1ではなくhogeと入力すると https://my-custom-domain.tk/hoge https://my-custom-domain.tk/hoge/test となる。 それいつ使うの? 例えば、リバプロが全段に置いてあり、特定文字列(例えばapi)がパスの先頭に入っていたらこちらに振り分けるみたいな構成がとられていたりすると、必ずhttps://my-custom-domain.tk/api/という始まり方でアクセスされることになる。このapiをステージ名に設定してあげればいいのは確かにそうだが、ステージの使い方的にイケてない。(APIのversionをパスに設定することになる。) 上記の例でhogeをパスに指定すると、APIのパス構成の中には影響せずにパスを指定することができることからここに apiをいれてあげれば、その影響を無視することができそう。 上ではリバプロとしたが、CloudFrontを置いて、S3をオリジンとする静的Webページのコンテンツとそこで利用されるAPIのドメインを揃える場合にも同一の現象が起こる。CloudFront Distributionにおいて、コンテンツのパスをルートとし、apiコールのパスを/apiのように切り分ける場合である。 (lambda@edgeとかでパスを削り落としてもいいがコストになりそう。) 複数のマッピングができるということ 一つのカスタムドメインに対して、複数のAPIのstageを紐づけてパスで切り分けることができる。 参考 https://wp-kyoto.net/set-api-key-to-api-gateway-by-aws-cdk/ https://dev.classmethod.jp/articles/aws-cdk-all-resources-for-api-gateway/
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[初心者向け]AWSを使って外部サイトからkintoneにレコードを追加

やりたいこと 外部サイトで入力したデータをマスタ(kintone)に登録 動作確認環境 作業端末:windows10 マスタデータ:kintone テストの流れ kintoneアプリ作成 AWS Lambda関数の作成 AWS Lambda環境構築 AWS API Gateway環境構築 外部ページの作成 1.kintoneアプリ作成 1-1.テスト用のアプリを作成 ○アプリ名:テストアプリ ○項目1:レコード番号 ○項目2:文字列(1行)   ➤フィールド名:テキスト   ➤フィールドコード:text  1-2.APIトークンの生成 アプリの設定>設定>APIトークンからレコード閲覧アクセス権有りのAPIトークンを生成し保存(APIトークンを控える) 2.AWS Lambda関数の作成 ※node.jsのインストールはこちらを参考にしました。 2-1.作業フォルダ作成 コマンドプロンプトからnpmを実行し作業フォルダを作成 $mkdir <作業フォルダを作成> (例:c:\temp\kintone_postなど) $cd <作業フォルダのパスを指定> $npm init --yes $npm config set strict-ssl false $npm install express ejs request $npm install axios --save ※「npm config set strict-ssl false」は証明書エラー回避のため 2-2.index.jsを編集 2-1で作成した作業フォルダにindex.jsを作成し編集 index.js var aws = require('aws-sdk'); const axios = require('axios'); var request = require('request'); /* kintone用のパラメータ(変更が必要) */ var DOMAIN = '<サブドメイン名>.cybozu.com'; //kintone環境のドメイン var APP_ID = <kintoneアプリのID>; //アプリID /* 変更は不要 */ var BASE_URL = "https://" + DOMAIN + '/k/v1/'; var headers = {'X-Cybozu-API-Token': '<kintoneのAPIトークン>'}; exports.handler = function(event, context, callback) { /* リクエスト本文取得 */ const body = JSON.parse(JSON.stringify(event.body)); var body_postrecords = { app: APP_ID, record:{ text:{value:body.text} } } } //レコードの作成 var options_postrecords = { url: BASE_URL + 'record.json', method: 'POST', headers: headers, 'Content-Type': 'application/json', data: body_postrecords } //レコードを送信 axios.request(options_postrecords).then((res) => { callback(null, res.data["id"]); }).catch((err) => { console.log(err); }); }; 2-3.ZIPファイルに圧縮 $zip -r kintonepost.zip index.js node_modules/ 3.AWS Lambda環境構築 3-1.関数の作成 関数名のみ入力し、後はデフォルトのまま関数を作成 3-2.ZIPファイルをアップロード 3-3.関数の動作確認 テストを実行し、エラーのレスポンスがないことを確認 エラーが出た場合は、index.jsの内容やLambda関数の設定のタイムアウト値などを見直してみる… 4.AWS API Gateway環境構築 4-1.APIの作成① APIを作成からREST APIの構築を選択 4-2.APIの作成➁ API名を入力し、APIを作成 4-3.APIの作成③ APIにメソッドを追加 4-4.APIの作成④ POSTを選択し、Lambda関数を入力し保存 4-5.CORSの有効化 4-6.メソッドリクエストの設定 メソッドリクエストのリクエスト本文にコンテンツタイプを追加 コンテンツタイプ:application/json モデル名:Empty 4-7.統合リクエストの設定 統合リクエストのマッピングテンプレートを追加し、テンプレートを「メソッドリクエストのパススルー」で生成しbody-jsonをbodyにしてから保存する 4-8.統合レスポンスの設定 統合レスポンスにもマッピングテンプレートを「メソッドリクエストのパススルー」で生成し保存する さっきもbody-jsonを変更した場合はこちらも直す 4-9.テスト APIの動作確認を行い、レスポンス本文にkintoneに追加したレコード番号が返ってきたらOK エラーが発生するようならLambda関数のタイムアウトやAPIのLambdaプロキシ統合の使用にチェックが入っていないかなどを疑う 4-10.APIのデプロイ アクションからAPIのデプロイを実行 4-11.URIのチェック APIのURIを控えて、APIの構築が完了です。 5.外部サイト側の設定 5-1.APIの送信 PHPの場合… index.php // APIのURI $url = '<APIのURI>'; // リクエストヘッダ: パラメータを json で渡す $content = json_encode(array( 'text' => 'hogehoge3' )); $context = array( 'http' => array( 'method' => 'POST', 'header' => "Content-Type: application/json\r\n" // APIキーの設定がある場合はコメント外す // . "x-api-key:<APIキー>\r\n" . "Content-Length: " . strlen($content) . "\r\n" , 'content' => $content ) ); // APIのコール $resultJson = file_get_contents($url, false, stream_context_create($context)); // レスポンス確認 $json = mb_convert_encoding($resultJson, 'UTF8', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN'); $arr = json_decode($json); $record_no = $arr->body; 参考サイト 参考にさせていただき、ありがとうございました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

GitHubActionsのSelf-hosted runnerを必要な時だけ起動する

以前書いた「GitHubActionsのSelf-hosted runnerで、SpringNativeのビルド時間を短縮する」の続きです。 SpringNativeでNativeイメージ化する際のビルド時間の短縮に「Self-hosted runner」に強めのEC2インスタンスを使用してビルド時間の短縮した話を書きました。 https://qiita.com/renave/items/561904b2988ebb6f0534 今回は費用の節約のために「Self-hosted runnerを必要な時だけ起動する」ようにしたお話です。 こちら、強めのEC2インスタンスなので起動しっぱなしにすると結構お金がかかります。 使うたびに手動で起動/停止するのも大変です。 そこで、 1:GHA実行時に標準のUbuntuのrunnerを使用し、Self-hosted runnerインスタンスを起動。 2:Self-hosted runnerでSpringNativeのビルド処理を実行。 3:ワークフローが終了したらインスタンスを停止する。 4:念のため、業務終了後の夜間にも停止をスケジュール。 するようにしました。 「actions-runner/run.sh」自動起動設定 インスタンスを起動する際に、自動で「Self-hosted runner」の「actions-runner/run.sh」を実行させる必要があります。 これには「rc.local」を利用します。 rootでrc.local作成 sudo su - sudo vi /etc/rc.local 既にインストール済みの「actions-runner/run.sh」を絶対パスで記述 rc-local.serviceで実行する場合は、rc.localファイルに「RUNNER_ALLOW_RUNASROOT="1"」を設定するのがポイントです。 そうしないとrc-local.serviceで実行できません。 #!/bin/bash export RUNNER_ALLOW_RUNASROOT="1" /home/****/actions-runner/run.sh & 続いて、rc-local.serviceの自動起動設定、サービスリスタート、ステータス確認をします。 systemctl enable rc-local.service systemctl restart rc-local.service systemctl status rc-local.service rc-local.serviceが以下のように正常起動していればOKです。 ● rc-local.service - /etc/rc.local Compatibility Loaded: loaded (/etc/systemd/system/rc-local.service; enabled; vendor preset: enabled) Drop-In: /usr/lib/systemd/system/rc-local.service.d └─debian.conf Active: active (running) since Mon 2021-11-22 15:32:43 UTC; 12s ago Process: 1643 ExecStart=/etc/rc.local start (code=exited, status=0/SUCCESS) Main PID: 1644 (run.sh) Tasks: 15 (limit: 37282) Memory: 35.0M CGroup: /system.slice/rc-local.service ├─1644 /bin/bash /home/***/actions-runner/run.sh └─1648 /home/***/actions-runner/bin/Runner.Listener run Nov 22 15:32:43 ********* systemd[1]: Starting /etc/rc.local Compatibility... Nov 22 15:32:43 ********* systemd[1]: Started /etc/rc.local Compatibility. Nov 22 15:32:45 ********* rc.local[1648]: √ Connected to GitHub Nov 22 15:32:46 ********* rc.local[1648]: Current runner version: '2.284.0' Nov 22 15:32:46 ********* rc.local[1648]: 2021-11-22 15:32:46Z: Listening for Jobs Self-hosted runnerのEC2インスタンスを停止→起動してみましょう EC2コンソールから停止 Githubでrunnerの確認 停止したので「Offline」になりました。 GithubActionsのworkflow こんな感じの起動スクリプトをworkflowに書いて動かしてみましょう。 name: Self-hosted runner startup workflow  ~中略 env: SHR_INSTANCE_ID: '<YOUR_SELF_HOSTED_RUNNER_INSTANCE_ID>' jobs: startup: name: startup runs-on: ubuntu-20.04 timeout-minutes: 10  ~中略 steps: #AWS Credentials - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v1 with: aws-access-key-id: ${{secrets[matrix.cfg.access-key-id]}} aws-secret-access-key: ${{secrets[matrix.cfg.secret-access-key]}} aws-region: ${{secrets[matrix.cfg.default-region]}} - name: startup self-hosted runner run: | SHR_INSTANCE_STATUS=$(aws ec2 describe-instance-status --instance-ids ${SHR_INSTANCE_ID} | jq -r .InstanceStatuses[].InstanceStatus.Status) echo "SHR_INSTANCE_STATUS=${SHR_INSTANCE_STATUS}" if [ -z "${SHR_INSTANCE_STATUS}" ] ; then echo "Starting Self-Hosted runner. Please wait." aws ec2 start-instances --instance-ids ${SHR_INSTANCE_ID} sleep 10 for ((i=1; i<100; i++)); do SHR_WAIT_STATUS=$(aws ec2 describe-instance-status --instance-ids ${SHR_INSTANCE_ID} | jq -r .InstanceStatuses[].InstanceStatus.Status) echo "[Check status...${i}] ${SHR_WAIT_STATUS}" if [ "${SHR_WAIT_STATUS}" = "ok" ] ; then echo "Self-Hosted runner started." break; fi sleep 10 done else echo "Self-Hosted runner already is running." fi exit 0 ※ forで回している理由は、whileだとエラーになってしまうみたい。GHAでは禁止されているのかな? こんな感じで起動処理が走ります 起動済みであればこんな感じ 起動後 actions-runnerのスクリプトが起動すると、Idle状態になります。 後続のビルド処理は「runs-on: self-hosted」で「needs: [startup]」のworkflowを作ればOK build: name: build needs: [startup] runs-on: self-hosted  以下、省略~ ジョブ終了後に「Self-hosted runner」を停止する こちらもbuild後に実行させるように「shutdown」ワークフローを書きます。 shutdown: name: shutdown needs: [build] runs-on: ubuntu-20.04 timeout-minutes: 10  ~中略 steps: #AWS Credentials - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v1 with: aws-access-key-id: ${{secrets[matrix.cfg.access-key-id]}} aws-secret-access-key: ${{secrets[matrix.cfg.secret-access-key]}} aws-region: ${{secrets[matrix.cfg.default-region]}} - name: shutdown self-hosted runner run: | SHR_WAIT_STATUS=$(aws ec2 describe-instance-status --instance-ids ${SHR_INSTANCE_ID} | jq -r .InstanceStatuses[].InstanceStatus.Status) echo "SHR_INSTANCE_STATUS=${SHR_INSTANCE_STATUS}" if [ "${SHR_WAIT_STATUS}" = "ok" ] ; then aws ec2 stop-instances --instance-ids ${SHR_INSTANCE_ID} echo "Self-Hosted runner is stopping." sleep 10 for ((i=1; i<100; i++)); do SHR_WAIT_STATUS=$(aws ec2 describe-instance-status --instance-ids ${SHR_INSTANCE_ID} | jq -r .InstanceStatuses[].InstanceStatus.Status) echo "[Check status...${i}] ${SHR_WAIT_STATUS}" if [ -z "${SHR_WAIT_STATUS}" ] ; then echo "Self-Hosted runner stopped." break; fi sleep 10 done echo "Self-Hosted runner stopped." else echo "Self-Hosted runner already stopped." fi exit 0 こんな感じで、停止処理がビルド処理完了後に動きます。 停止しました。 業務終了時間に停止させる 停止忘れが無いように、念のため業務に影響のない夜間に自動で停止をスケジュールしておきます。 自動停止には、AWSのEvent Bridgeで「Stop-Instances」のイベントを使用します。 こんな感じで設定できます。 16:00 UTC(JSTで25時)に停止するようにしてます。 この辺は運用に合わせて適宜設定するといいと思います。 公式ドキュメントも参考にしてください https://docs.aws.amazon.com/ja_jp/eventbridge/latest/userguide/eb-create-rule-schedule.html 今後の改善 「停止処理」は、ビルド処理がひととおり完了した後に実施していますが、複数人で同時にworkflowを走らせた場合などに困ることがありそうなので、この点はランナーの状態を確認したり、複数台用意して、offlineのランナーを選出して使ったり。 不都合があれば、そんな処理を入れていこうかなと思っています。 P.S. いかがでしょうか? Self-hosted runnerにハイスペックなマシンを使うことでCIの処理時間(今回はSpringNativeのビルド)を短くすることができますが、費用も気にした方がいいのでこういう形にしてみました。 今回の処理を入れることでビルド時間はインスタンス起動時間分遅くなりますが、お金のことなのでそこはどちらを取るか。といったところでしょうか。 なお、EC2インスタンスを停止していてもEBSボリューム代はかかるので、ご留意ください。 参考になれば幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWSの料金を毎日Slackに通知する

クラウド破産が起きないようにAWSの料金を毎日通知するやつを作りたかったのですが忙しくて... 重い腰を上げてやっとです。LINEに通知してもでもいいのですが手軽なのでSlackで行きます。 Slackシリーズ結構やってきましたので他の記事も参考に 今回のアーキテクチャ Lambdaを作成 今回動かすコードを貼り付けましょう import datetime import json import urllib.request import boto3 import os import logging logger = logging.getLogger() logger.setLevel(logging.INFO) def lambda_handler(event, context): url = "https://slack.com/api/chat.postMessage" headers = { "Content-type" : "application/json", "Authorization" : "Bearer "+ "< Token >" } response = boto3.client('cloudwatch', region_name='us-east-1') get_metric_statistics = response.get_metric_statistics( Namespace='AWS/Billing', MetricName='EstimatedCharges', Dimensions=[ { 'Name': 'Currency', 'Value': 'USD' } ], StartTime=datetime.datetime.today() - datetime.timedelta(days=1), EndTime=datetime.datetime.today(), Period=86400, Statistics=['Maximum'] ) cost = get_metric_statistics['Datapoints'][0]['Maximum'] date = get_metric_statistics['Datapoints'][0]['Timestamp'].strftime('%Y年%m月%d日') text = "%sまでのAWSの料金は、$%sです。" % (date, cost) payload = { "channel": "< 通知したいチャンネルID>", "text" : text } req = urllib.request.Request(url=url, headers=headers, data=json.dumps(payload).encode('utf-8')) with urllib.request.urlopen(req) as res: logger.info(res.read().decode("utf-8")) LambdaにIAMロールをアタッチ LambdaにCloudWatchの読み取り権限を付与します。IAMのページに遷移して先程作成したLambdaを選択します。 「ポリシーをアタッチします」をクリック CloudWatchReadOnlyAccessを選択して「ポリシーのアタッチ」をクリックします。 Eventbridgeの設定 1日1回定期実行を行うにはEventbridgeをLambdaと連携して使います。  cron(0 3 * * ? *)は毎日、日本時間の午前12時ということを表している。  参考文献 ・Rate または Cron を使用したスケジュール式
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS CLIのdebugオプションは何が出力されるのか

ssm接続失敗する場合に--debugをつけた例で一体何が出力されるのか見てみました。 出力内容が何を指しているのか、基本的に英語で同行に出力があるのでわかりやすかったです。 <実行コマンド> % AWS_PROFILE=credential-name aws ssm start-session --region=ap-northeast-1 --target i-xxxxxxxx --debug <cli関連リソースのバージョン1> 2021-11-19 12:05:44,110 - MainThread - awscli.clidriver - DEBUG - CLI version: aws-cli/2.2.14 Python/3.8.8 Darwin/20.6.0 exe/x86_64 <引数1> 2021-11-19 12:05:44,110 - MainThread - awscli.clidriver - DEBUG - Arguments entered to CLI: ['ssm', 'start-session', '--region=ap-northeast-1', '--target', 'i-xxxxxxxxxx', '--debug'] <ハンドラー呼び出し> 2021-11-19 12:05:44,131 - MainThread - botocore.hooks - DEBUG - Event building-command-table.main: calling handler <function add_s3 at 0x7f8af8839a60> 2021-11-19 12:05:44,132 - MainThread - botocore.hooks - DEBUG - Event building-command-table.main: calling handler <function add_ddb at 0x7f8af7e7a160> 2021-11-19 12:05:44,132 - MainThread - botocore.hooks - DEBUG - Event building-command-table.main: calling handler <bound method BasicCommand.add_command of <class 'awscli.customizations.configure.configure.ConfigureCommand'>> 2021-11-19 12:05:44,132 - MainThread - botocore.hooks - DEBUG - Event building-command-table.main: calling handler <function change_name at 0x7f8af7e1e8b0> 2021-11-19 12:05:44,132 - MainThread - botocore.hooks - DEBUG - Event building-command-table.main: calling handler <function change_name at 0x7f8af7e288b0> 2021-11-19 12:05:44,132 - MainThread - botocore.hooks - DEBUG - Event building-command-table.main: calling handler <function alias_opsworks_cm at 0x7f8af884a4c0> 2021-11-19 12:05:44,132 - MainThread - botocore.hooks - DEBUG - Event building-command-table.main: calling handler <function add_history_commands at 0x7f8af7ec2ee0> 2021-11-19 12:05:44,132 - MainThread - botocore.hooks - DEBUG - Event building-command-table.main: calling handler <bound method BasicCommand.add_command of <class 'awscli.customizations.devcommands.CLIDevCommand'>> 2021-11-19 12:05:44,132 - MainThread - botocore.hooks - DEBUG - Event building-command-table.main: calling handler <function add_waiters at 0x7f8af8840700> <json読み込み> 2021-11-19 12:05:44,133 - MainThread - botocore.loaders - DEBUG - Loading JSON file: /usr/local/aws-cli/awscli/data/cli.json <ハンドラー呼び出し> 2021-11-19 12:05:44,136 - MainThread - botocore.hooks - DEBUG - Event top-level-args-parsed: calling handler <function resolve_types at 0x7f8af7f749d0> 2021-11-19 12:05:44,136 - MainThread - botocore.hooks - DEBUG - Event top-level-args-parsed: calling handler <function no_sign_request at 0x7f8af7f75550> 2021-11-19 12:05:44,136 - MainThread - botocore.hooks - DEBUG - Event top-level-args-parsed: calling handler <function resolve_verify_ssl at 0x7f8af7f754c0> 2021-11-19 12:05:44,136 - MainThread - botocore.hooks - DEBUG - Event top-level-args-parsed: calling handler <function resolve_cli_read_timeout at 0x7f8af7f75670> 2021-11-19 12:05:44,136 - MainThread - botocore.hooks - DEBUG - Event top-level-args-parsed: calling handler <function resolve_cli_connect_timeout at 0x7f8af7f755e0> 2021-11-19 12:05:44,136 - MainThread - botocore.hooks - DEBUG - Event top-level-args-parsed: calling handler <built-in method update of dict object at 0x7f8af88e3c40> <regionの変数を設定> 2021-11-19 12:05:44,136 - MainThread - botocore.session - DEBUG - Setting config variable for region to 'ap-northeast-1' <cli関連リソースのバージョン2 ※1と比べてprompt/offが追加になっている> 2021-11-19 12:05:44,137 - MainThread - awscli.clidriver - DEBUG - CLI version: aws-cli/2.2.14 Python/3.8.8 Darwin/20.6.0 exe/x86_64 prompt/off <引数2> 2021-11-19 12:05:44,137 - MainThread - awscli.clidriver - DEBUG - Arguments entered to CLI: ['ssm', 'start-session', '--region=ap-northeast-1', '--target', 'i-xxxxxxxxxx', '--debug'] <ハンドラー呼び出し> 2021-11-19 12:05:44,137 - MainThread - botocore.hooks - DEBUG - Event session-initialized: calling handler <function add_timestamp_parser at 0x7f8af883a0d0> 2021-11-19 12:05:44,137 - MainThread - botocore.hooks - DEBUG - Event session-initialized: calling handler <function register_uri_param_handler at 0x7f8af7bd1dc0> 2021-11-19 12:05:44,138 - MainThread - botocore.hooks - DEBUG - Event session-initialized: calling handler <function add_binary_formatter at 0x7f8af88a8b80> 2021-11-19 12:05:44,138 - MainThread - botocore.hooks - DEBUG - Event session-initialized: calling handler <function no_pager_handler at 0x7f8af7bce280> 2021-11-19 12:05:44,138 - MainThread - botocore.hooks - DEBUG - Event session-initialized: calling handler <function inject_assume_role_provider_cache at 0x7f8af7c31790> <インスタンスメタデータサービス(IMDS)エンドポイント> 2021-11-19 12:05:44,142 - MainThread - botocore.utils - DEBUG - IMDS ENDPOINT: http://169.254.169.254/ <ハンドラー呼び出し> 2021-11-19 12:05:44,149 - MainThread - botocore.hooks - DEBUG - Event session-initialized: calling handler <function attach_history_handler at 0x7f8af7ec2dc0> 2021-11-19 12:05:44,149 - MainThread - botocore.hooks - DEBUG - Event session-initialized: calling handler <function inject_json_file_cache at 0x7f8af7e79040> <json読み込み> 2021-11-19 12:05:44,173 - MainThread - botocore.loaders - DEBUG - Loading JSON file: /usr/local/aws-cli/botocore/data/ssm/2014-11-06/service-2.json <ハンドラー呼び出し> 2021-11-19 12:05:44,197 - MainThread - botocore.hooks - DEBUG - Event building-command-table.ssm: calling handler <function add_custom_start_session at 0x7f8af8857430> 2021-11-19 12:05:44,197 - MainThread - botocore.hooks - DEBUG - Event building-command-table.ssm: calling handler <function add_waiters at 0x7f8af8840700> <json読み込み> 2021-11-19 12:05:44,220 - MainThread - botocore.loaders - DEBUG - Loading JSON file: /usr/local/aws-cli/botocore/data/ssm/2014-11-06/waiters-2.json <引数を配列化しているように見える> 2021-11-19 12:05:44,221 - MainThread - awscli.clidriver - DEBUG - OrderedDict([('target', <awscli.arguments.CLIArgument object at 0x7f8af8f93f40>), ('document-name', <awscli.arguments.CLIArgument object at 0x7f8af8f7e280>), ('parameters', <awscli.arguments.CLIArgument object at 0x7f8af8f7e190>)]) <ハンドラー呼び出し> 2021-11-19 12:05:44,221 - MainThread - botocore.hooks - DEBUG - Event building-argument-table.ssm.start-session: calling handler <function add_streaming_output_arg at 0x7f8af883a670> 2021-11-19 12:05:44,221 - MainThread - botocore.hooks - DEBUG - Event building-argument-table.ssm.start-session: calling handler <function add_cli_input_json at 0x7f8af7c39040> 2021-11-19 12:05:44,222 - MainThread - botocore.hooks - DEBUG - Event building-argument-table.ssm.start-session: calling handler <function add_cli_input_yaml at 0x7f8af7c39310> 2021-11-19 12:05:44,222 - MainThread - botocore.hooks - DEBUG - Event building-argument-table.ssm.start-session: calling handler <function unify_paging_params at 0x7f8af7e7a790> <json読み込み> 2021-11-19 12:05:44,244 - MainThread - botocore.loaders - DEBUG - Loading JSON file: /usr/local/aws-cli/botocore/data/ssm/2014-11-06/paginators-1.json <ハンドラー呼び出し> 2021-11-19 12:05:44,244 - MainThread - botocore.hooks - DEBUG - Event building-argument-table.ssm.start-session: calling handler <function add_generate_skeleton at 0x7f8af7f65f70> 2021-11-19 12:05:44,244 - MainThread - botocore.hooks - DEBUG - Event before-building-argument-table-parser.ssm.start-session: calling handler <bound method OverrideRequiredArgsArgument.override_required_args of <awscli.customizations.cliinput.CliInputJSONArgument object at 0x7f8af8fac0d0>> 2021-11-19 12:05:44,245 - MainThread - botocore.hooks - DEBUG - Event before-building-argument-table-parser.ssm.start-session: calling handler <bound method OverrideRequiredArgsArgument.override_required_args of <awscli.customizations.cliinput.CliInputYAMLArgument object at 0x7f8af8fac100>> 2021-11-19 12:05:44,245 - MainThread - botocore.hooks - DEBUG - Event before-building-argument-table-parser.ssm.start-session: calling handler <bound method GenerateCliSkeletonArgument.override_required_args of <awscli.customizations.generatecliskeleton.GenerateCliSkeletonArgument object at 0x7f8af8fac250>> 2021-11-19 12:05:44,245 - MainThread - botocore.hooks - DEBUG - Event load-cli-arg.ssm.start-session.target: calling handler <awscli.paramfile.URIArgumentHandler object at 0x7f8af8a1dd90> 2021-11-19 12:05:44,246 - MainThread - botocore.hooks - DEBUG - Event process-cli-arg.ssm.start-session: calling handler <awscli.argprocess.ParamShorthandParser object at 0x7f8af7bf4f40> <targetの値を展開?> 2021-11-19 12:05:44,246 - MainThread - awscli.arguments - DEBUG - Unpacked value of 'i-xxxxxxxxxx' for parameter "target": 'i-xxxxxxxxxx' <ハンドラー呼び出し> 2021-11-19 12:05:44,246 - MainThread - botocore.hooks - DEBUG - Event load-cli-arg.ssm.start-session.document-name: calling handler <awscli.paramfile.URIArgumentHandler object at 0x7f8af8a1dd90> 2021-11-19 12:05:44,246 - MainThread - botocore.hooks - DEBUG - Event load-cli-arg.ssm.start-session.parameters: calling handler <awscli.paramfile.URIArgumentHandler object at 0x7f8af8a1dd90> 2021-11-19 12:05:44,246 - MainThread - botocore.hooks - DEBUG - Event load-cli-arg.ssm.start-session.cli-input-json: calling handler <awscli.paramfile.URIArgumentHandler object at 0x7f8af8a1dd90> 2021-11-19 12:05:44,246 - MainThread - botocore.hooks - DEBUG - Event load-cli-arg.ssm.start-session.cli-input-yaml: calling handler <awscli.paramfile.URIArgumentHandler object at 0x7f8af8a1dd90> 2021-11-19 12:05:44,246 - MainThread - botocore.hooks - DEBUG - Event load-cli-arg.ssm.start-session.generate-cli-skeleton: calling handler <awscli.paramfile.URIArgumentHandler object at 0x7f8af8a1dd90> 2021-11-19 12:05:44,246 - MainThread - botocore.hooks - DEBUG - Event calling-command.ssm.start-session: calling handler <bound method CliInputArgument.add_to_call_parameters of <awscli.customizations.cliinput.CliInputJSONArgument object at 0x7f8af8fac0d0>> 2021-11-19 12:05:44,246 - MainThread - botocore.hooks - DEBUG - Event calling-command.ssm.start-session: calling handler <bound method CliInputArgument.add_to_call_parameters of <awscli.customizations.cliinput.CliInputYAMLArgument object at 0x7f8af8fac100>> 2021-11-19 12:05:44,248 - MainThread - botocore.hooks - DEBUG - Event calling-command.ssm.start-session: calling handler <bound method GenerateCliSkeletonArgument.generate_skeleton of <awscli.customizations.generatecliskeleton.GenerateCliSkeletonArgument object at 0x7f8af8fac250>> <credentialsの情報を使って値を探している> 2021-11-19 12:05:44,248 - MainThread - botocore.credentials - DEBUG - Looking for credentials via: env 2021-11-19 12:05:44,249 - MainThread - botocore.credentials - DEBUG - Looking for credentials via: assume-role 2021-11-19 12:05:44,249 - MainThread - botocore.credentials - DEBUG - Looking for credentials via: assume-role-with-web-identity 2021-11-19 12:05:44,249 - MainThread - botocore.credentials - DEBUG - Looking for credentials via: sso 2021-11-19 12:05:44,249 - MainThread - botocore.credentials - DEBUG - Looking for credentials via: shared-credentials-file 2021-11-19 12:05:44,249 - MainThread - botocore.credentials - INFO - Found credentials in shared credentials file: ~/.aws/credentials <json読み込み> 2021-11-19 12:05:44,251 - MainThread - botocore.loaders - DEBUG - Loading JSON file: /usr/local/aws-cli/botocore/data/endpoints.json <ハンドラー呼び出し> 2021-11-19 12:05:44,260 - MainThread - botocore.hooks - DEBUG - Event choose-service-name: calling handler <function handle_service_name_alias at 0x7f8af71f3f70> 2021-11-19 12:05:44,264 - MainThread - botocore.hooks - DEBUG - Event creating-client-class.ssm: calling handler <function add_generate_presigned_url at 0x7f8af71a11f0> <ssmのタイムアウト値を設定> 2021-11-19 12:05:44,268 - MainThread - botocore.endpoint - DEBUG - Setting ssm timeout as (60, 60) <ハンドラー呼び出し> 2021-11-19 12:05:44,269 - MainThread - botocore.hooks - DEBUG - Event provide-client-params.ssm.StartSession: calling handler <function base64_decode_input_blobs at 0x7f8af88a9310> 2021-11-19 12:05:44,269 - MainThread - botocore.hooks - DEBUG - Event before-parameter-build.ssm.StartSession: calling handler <function generate_idempotent_uuid at 0x7f8af7212f70> 2021-11-19 12:05:44,269 - MainThread - botocore.hooks - DEBUG - Event before-call.ssm.StartSession: calling handler <function inject_api_version_header_if_needed at 0x7f8af7219820> <startsessionのリクエストとパラメータ定義> 2021-11-19 12:05:44,269 - MainThread - botocore.endpoint - DEBUG - Making request for OperationModel(name=StartSession) with params: {'url_path': '/', 'query_string': '', 'method': 'POST', 'headers': {'X-Amz-Target': 'AmazonSSM.StartSession', 'Content-Type': 'application/x-amz-json-1.1', 'User-Agent': 'aws-cli/2.2.14 Python/3.8.8 Darwin/20.6.0 exe/x86_64 prompt/off command/ssm.start-session'}, 'body': b'{"Target": "i-xxxxxxxxxx"}', 'url': 'https://ssm.ap-northeast-1.amazonaws.com/', 'context': {'client_region': 'ap-northeast-1', 'client_config': <botocore.config.Config object at 0x7f8af9006520>, 'has_streaming_input': False, 'auth_type': None}} <ハンドラー呼び出し> 2021-11-19 12:05:44,270 - MainThread - botocore.hooks - DEBUG - Event request-created.ssm.StartSession: calling handler <bound method RequestSigner.handler of <botocore.signers.RequestSigner object at 0x7f8af90064f0>> 2021-11-19 12:05:44,270 - MainThread - botocore.hooks - DEBUG - Event choose-signer.ssm.StartSession: calling handler <function set_operation_specific_signer at 0x7f8af7212e50> <aws signature認証 ver4で計算> 2021-11-19 12:05:44,270 - MainThread - botocore.auth - DEBUG - Calculating signature using v4 auth. <正規化されたリクエスト?をPOST> 2021-11-19 12:05:44,270 - MainThread - botocore.auth - DEBUG - CanonicalRequest: POST / content-type:application/x-amz-json-1.1 host:ssm.ap-northeast-1.amazonaws.com x-amz-date:20211119T030544Z x-amz-target:AmazonSSM.StartSession content-type;host;x-amz-date;x-amz-target c28b334d3f45995e3de686b8ad27d0xxxxxxxxxx <暗号化アルゴリズムと暗号化された情報> 2021-11-19 12:05:44,270 - MainThread - botocore.auth - DEBUG - StringToSign: AWS4-HMAC-SHA256 20211119T030544Z 20211119/ap-northeast-1/ssm/aws4_request fa203ba78860d8f9a6481f9c51fd844aee7d1613ceee66xxxxxxxxxx <暗号化された署名の情報> 2021-11-19 12:05:44,270 - MainThread - botocore.auth - DEBUG - Signature: 17268c890a3be216ba7fb686bd7f4614760fd5xxxxxxxxxxxxxxx <httpリクエスト> 2021-11-19 12:05:44,270 - MainThread - botocore.endpoint - DEBUG - Sending http request: <AWSPreparedRequest stream_output=False, method=POST, url=https://ssm.ap-northeast-1.amazonaws.com/, headers={'X-Amz-Target': b'AmazonSSM.StartSession', 'Content-Type': b'application/x-amz-json-1.1', 'User-Agent': b'aws-cli/2.2.14 Python/3.8.8 Darwin/20.6.0 exe/x86_64 prompt/off command/ssm.start-session', 'X-Amz-Date': b'20211119T030544Z', 'Authorization': b'AWS4-HMAC-SHA256 Credential=xxxxx/20211119/ap-northeast-1/ssm/aws4_request, SignedHeaders=content-type;host;x-amz-date;x-amz-target, Signature=17268c890a3be216ba7bd7f461476xxxxx', 'Content-Length': '33'}> <証明書> 2021-11-19 12:05:44,271 - MainThread - botocore.httpsession - DEBUG - Certificate path: /usr/local/aws-cli/botocore/cacert.pem <新規https接続の開始> 2021-11-19 12:05:44,271 - MainThread - urllib3.connectionpool - DEBUG - Starting new HTTPS connection (1): ssm.ap-northeast-1.amazonaws.com:443 <接続状態:403> 2021-11-19 12:05:44,359 - MainThread - urllib3.connectionpool - DEBUG - https://ssm.ap-northeast-1.amazonaws.com:443 "POST / HTTP/1.1" 403 None <レスポンスヘッダ> 2021-11-19 12:05:44,360 - MainThread - botocore.parsers - DEBUG - Response headers: {'Server': 'Server', 'Date': 'Fri, 19 Nov 2021 03:05:44 GMT', 'Content-Type': 'application/octet-stream', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive'} <接続失敗> 2021-11-19 12:05:44,361 - MainThread - botocore.parsers - DEBUG - Response body: b'Server authentication failed: <UnauthorizedRequest xmlns=""><message>Forbidden.</message></UnauthorizedRequest>\n' <ハンドラー呼び出し> 2021-11-19 12:05:44,370 - MainThread - botocore.hooks - DEBUG - Event needs-retry.ssm.StartSession: calling handler <bound method RetryHandler.needs_retry of <botocore.retries.standard.RetryHandler object at 0x7f8af9295070>> <リトライはしない> 2021-11-19 12:05:44,370 - MainThread - botocore.retries.standard - DEBUG - Not retrying request. <ハンドラー呼び出し> 2021-11-19 12:05:44,370 - MainThread - botocore.hooks - DEBUG - Event after-call.ssm.StartSession: calling handler <bound method RetryQuotaChecker.release_retry_quota of <Exceptionの中身> <botocore.retries.standard.RetryQuotaChecker object at 0x7f8af9006bb0>> 2021-11-19 12:05:44,374 - MainThread - awscli.clidriver - DEBUG - Exception caught in main() Traceback (most recent call last): File "awscli/clidriver.py", line 459, in main File "awscli/clidriver.py", line 594, in __call__ File "awscli/clidriver.py", line 770, in __call__ File "awscli/customizations/sessionmanager.py", line 64, in invoke File "botocore/client.py", line 278, in _api_call File "botocore/client.py", line 597, in _make_api_call botocore.exceptions.ClientError: An error occurred (403) when calling the StartSession operation: Server authentication failed: <UnauthorizedRequest xmlns=""><message>Forbidden.</message></UnauthorizedRequest> An error occurred (403) when calling the StartSession operation: Server authentication failed: <UnauthorizedRequest xmlns=""><message>Forbidden.</message></UnauthorizedRequest> ssm接続成功の時のデバッグログは「証明書」の次の行あたりから違ってくる。 <新規https接続の開始> 2021-11-19 12:17:57,889 - MainThread - urllib3.connectionpool - DEBUG - Starting new HTTPS connection (1): ssm.ap-northeast-1.amazonaws.com:443 <接続状態:200> 2021-11-19 12:17:58,087 - MainThread - urllib3.connectionpool - DEBUG - https://ssm.ap-northeast-1.amazonaws.com:443 "POST / HTTP/1.1" 200 729 <レスポンスヘッダ(失敗の時なかったリクエストIDが確認できる)> 2021-11-19 12:17:58,088 - MainThread - botocore.parsers - DEBUG - Response headers: {'Server': 'Server', 'Date': 'Fri, 19 Nov 2021 03:17:58 GMT', 'Content-Type': 'application/x-amz-json-1.1', 'Content-Length': '729', 'Connection': 'keep-alive', 'x-amzn-RequestId': 'd343e616-9d53-4bb2-9474-cdc5fxxxx'} <レスポンスボディ> 2021-11-19 12:17:58,089 - MainThread - botocore.parsers - DEBUG - Response body: b'{"SessionId":"user-name-09fdxxxxxxxx","StreamUrl":"wss://ssmmessages.ap-northeast-1.amazonaws.com/v1/data-channel/user-name-0f6fxxxxxxxxx?role=publish_subscribe","TokenValue":"xxxxxxxxxxxxxxxxxxxxx"}' <ハンドラー呼び出し> 2021-11-19 12:17:58,090 - MainThread - botocore.hooks - DEBUG - Event needs-retry.ssm.StartSession: calling handler <bound method RetryHandler.needs_retry of <botocore.retries.standard.RetryHandler object at 0x7f8e7dad5070>> <リトライはしない> 2021-11-19 12:17:58,090 - MainThread - botocore.retries.standard - DEBUG - Not retrying request. <ハンドラー呼び出し> 2021-11-19 12:17:58,090 - MainThread - botocore.hooks - DEBUG - Event after-call.ssm.StartSession: calling handler <bound method RetryQuotaChecker.release_retry_quota of <botocore.retries.standard.RetryQuotaChecker object at 0x7f8e7d845bb0>> Starting session with SessionId: user-name-0042bxxxxxxxxx bash cd ~ sh-4.2$ bash Last login: Fri Nov 19 11:46:59 JST 2021 on pts/0 [ec2-user@srv ~]$ cd ~ [ec2-user@srv ~]$ 調べて為になったけど、ssm接続不可の場合の切り分けのヒントにはあまりならない、、? ちなみに接続不可の切り分けはcloudtrailにも出力されず(接続成功のログしか出力されず認証で失敗のログは出なかった)この場合は接続先インスタンスの/var/log/amazon/ssmや/var/lib/amazon/ssm内のファイルを確認すれば良いそう。(見てない)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

S3上のファイル容量を取得して、Python で集計する

はじめに PoC を担当しているのですが、S3 上の既存ファイルの容量を調査する必要がありました。 具体的には、S3上のファイルサイズの全体感を掴みたいので、 S3上の全てのファイル容量を調べて、最大値、最小値、中央値、平均値を出したいという内容でした。 ネット上にはS3上の情報を取得する記事は数があったのですが、集計まで行なっている記事は少なかったため、記録として残しておきます。 環境 ❯ wmic os get caption Caption Microsoft Windows 10 Pro ❯ aws --version aws-cli/2.2.11 Python/3.8.8 Windows/10 exe/AMD64 prompt/off ❯ python --version Python 3.10.0 AWS CLI でファイルサイズを取得する 設定 AWS CLI のインストールと設定がお済みでない方は、以下のページなどを参考に行なっていただければと思います。 公式ドキュメント AWS CLIのインストールから初期設定メモ aws configureと打って以下のように設定値が表示されるようになったら、準備完了です。 ❯ aws configure AWS Access Key ID [****************AAAA]: AWS Secret Access Key [****************BBBB]: Default region name [ap-northeast-1]: Default output format [json]: S3コマンド まずは、AWS CLI のS3コマンドを試してみます。 aws s3 ls s3://${BUCKET}/${OBJECT_PATH}/ --recursive --human --sum ❯ aws s3 ls s3://BucketName/ObjectPath/ --recursive --human --sum 2021-11-02 10:22:46 1.7 MiB ObjectPath/テスト1.pdf 2021-11-13 22:16:34 4.5 MiB ObjectPath/テスト2.pdf 2021-11-29 13:11:12 8.6 MiB ObjectPath/テスト3.pdf ... recursive: 再帰的にリストを出力する human: ファイルサイズに単位を付与して出力する sum: サマリー (オブジェクト個数と合計サイズ) を出力する 単にファイル容量を確認したいだけなら、これで問題ありません。 しかし、何かしらのフォーマットの出力にはこのS3コマンドは対応していません。 大量のデータを集計をする以上、json など何かしらのフォーマットで扱いたいです。 そこで、S3apiコマンドを使います。 S3apiコマンド 簡単に言うと、S3コマンドのパワーアップバージョンです。 詳しくは、こちらの記事が参考になります。 バケット単位の取得で、S3コマンドのときの--humanオプションは使えないので、単位は byte での出力となります。 aws s3api list-objects-v2 --bucket ${BUCKET} 上記のコマンドでS3上のファイルの全情報を json で出力してもいいのですが、今回は容量の情報だけが必要です。 そのため、ファイル容量の一覧を抽出して配列に入れて、適当なテキストファイルに出力してみます。 抽出には、--queryオプションを使います。 ❯ aws s3api list-objects-v2 --bucket BucketName --query "Contents[].Size" >> s3_search.txt s3_search.txt [ 100960, 1656243, 9890, ... ] サイズを取得して、扱いやすいように配列としてフォーマット化することができました。 ここまでくれば、あとはスクリプトを書いていい感じに集計すれば完了です。 Python でスクリプトを作成する Python を選んだ理由は、以下の2つです。 データ集計系のライブラリが充実している 素早く書いて実行できる S3apiコマンドで出力した配列のテキストファイルを使ってもいいのですが、せっかくなのでスクリプト上でファイル容量の取得まで行います。 まず、Boto3(AWS SDK for Python)Boto3 をインストールします。 これで、S3apiコマンドをPython上で呼び出せます。 pip install boto3 準備は整いましたので、あくまで一例ながら以下のように書いてみました。 import boto3 import statistics # S3apiを叩いてファイル情報を取得 s3_client = boto3.client('s3') response_contents = s3_client.list_objects_v2( Bucket = 'bucket_name' ).get('Contents') # ファイルサイズを配列として取得 size_list = [] for rc in response_contents: size = rc.get('Size') size_list.append(size) # 集計して出力 print('最大値:{}、最小値:{}、中央値:{}、平均値:{}' .format(max(size_list), min(size_list), statistics.median(size_list), statistics.mean(size_list)) ) 出力結果は、以下のような感じです。 最大値:4194340、最小値:98.0、中央値:361.0、平均値:10286.569 ただし、上記のコードでは一度のAPI呼び出しで取得できる1000件を上限にしている点に注意してください。 これは、今回のようなストレージのデータを取得するような API は、レスポンスが膨大な量になることが多いためです。 このような制限を、ページネーションといいます。 長くなってしまうのでここでは詳しく触れませんが、以下の記事などを参考に少し手を加える必要があります。 AWS S3で1000件以上のオブジェクトを操作する方法 おわりに 大学以来、久々に Python を触りました。そういえば、業務では初めてです。 普段は C# をメインで書いているので、こういうのをサクッと書くのにやっぱり Python 向いてるなと思いました。 こういうスクリプト考える作業、とても好きです。 参照 https://dev.classmethod.jp/articles/aws-cli-count-s3-filesize/ https://inokara.hateblo.jp/entry/2020/12/03/000341 https://www.fenet.jp/aws/column/aws-beginner/946/ https://serverfault.com/questions/84815/how-can-i-get-the-size-of-an-amazon-s3-bucket
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【AWS】ひとりでもOrganizationsを使うと便利で勉強になる話(AWS SSOの始め方を手厚く)

はじめに NTTテクノクロスの三井一能です。NTTテクノクロス Advent Calendar 2021の初日の記事です。 何についての紹介か? AWSが大好きなみなさんは、きっと個人でも検証用にAWSアカウントを所有していると思います。個人であれば一つ持っていることがほとんどなのではないでしょうか。AWSには、マルチアカウント管理向けに、AWS Organizations(以下、Organizationsと表記)という機能があります。でもアカウントが一つだけなので、自分には関係ないと思っていたりしませんか? この記事では、アカウント一つでもOrganizationsを組む(ひとりオーガニと個人的に呼んでいます)ことで便利だよ、ということを伝えたいと思います。 記事の後半では、ハンズオンでAWS SSOを構築、動作確認していきます。スクリーンショット多めですが、この記事の内容だけで最後まで辿りつけるようにしたつもりです。所要時間は1時間ぐらいだと思います。 AWS Organizationsとは AWS Organizationsは、複数のアカウントを統合的に管理できるAWSのサービスです。Organizationsを構成することで、次のようなメリットを導入することができます。 請求の一元化 組織全体のAWSアカウントの請求を代表アカウント(マネジメントアカウント)に一元化できる アカウント作成の自動化 AWSアカウントの新規作成で、カード情報、連絡先の入力が不要となるため、CLIを使った自動化が可能になる アカウントの集中管理 AWS SSOを使ったAWSアカウントアクセスの一元化と簡素化を図れる AWSアカウントをグループ化してポリシーを適用し、利用サービスを制限できる AWSの他サービスと連携させることにより、システム環境を一元的に保護できる(Backup, Config, Security Hub, GuardDuty, CloudTrail) ひとりオーガニとは? 一つのAWSアカウントでOrganizationsを利用する構成のことです(自称)。Organizationsを導入することでメリットを享受することができます。 AWS SSOが利用できること(いちばんのメリット) AWSアカウントにはどのようにアクセスしていますか?まさか rootアカウントで使っている人はいないと思いますが、通常はIAMユーザ でログインしていると思います。適切な権限で作業するために、スイッチロールを使うわけですが、面倒ではないでしょうか。 AWS SSO は、1回のサインインで、Organizations内のAWSアカウントへの権限アクセスを容易にしてくれるサービスです。言い換えると、上のスイッチロールの面倒さを意識せずに、適切な権限でAWSアカウントにアクセスすることができるのです。また、一時クレデンシャルもAWS SSOが発行してくれるので、長期クレデンシャルが必要なければIAMユーザーは不要です。 セキュリティガバナンスの仕組みを導入できる(学べる) Organizations の機能であるサービスコントロールポリシー (SCP) を利用して、アカウントに対して使用可能な最大アクセス許可を設定することができます。具体的な例は次のサイトを参照してほしいですが、たとえば、AWSアカウントで使用するリージョンを東京(ap-northeath-1)と北部バージニア(us-east-1)に限定することができます。 Security HubやGuardDuty はAWSアカウント単体で使うこともできますが、Organizationsで統括して管理することもできます。このあたりはマルチアカウント管理では必ず必要になってくるため、ひとりオーガニでも導入しておくと勉強になります。 この記事のゴール この記事の後半では、ひとりオーガニ環境で、AWS SSOを導入し、マネジメントコンソールと、AWS CLI で操作ができるところまでの手順を紹介します。 対象とする読者 AWS を 1アカウントから使い始めてマネジメントコンソールが使えるようになった初中級者の方 OrganizationsやAWS SSOを使ったことがない方 準備するもの この記事を見て、自分でもやってみようという方は、AWSアカウントを一つ用意してください。 また、AWS CLIによる動作確認をしたい場合は、AWS CLIバージョン2 をインストールした環境を準備してください。 AWS SSO用語の理解 AWS SSOを使用する場合、AWS SSOユーザーやアクセス権限セットという用語が出てきます。AWSアカウントのアクセス権限との関係を整理しておきましょう。 AWS SSOユーザー AWS SSOを利用する場合、利用者がサインインする対象です。複数のAWSアカウントを利用する場合もサインインはこの一回だけになります。 アクセス権限セット AWS SSO内で管理される権限のテンプレートです。AWS SSOユーザーがAWSアカウントのアクセスに利用するアクセス権限セットを選択すると、各AWSアカウントに対応するAWS SSO管理ロールが自動作成されます。一つのAWSにアカウントに対し複数のアクセス権限セットを選択することも可能です。 構築 Organizationsを作成する AWSマネジメントコンソールを表示します。 Organizations のダッシュボードを表示し、「組織の作成する」をクリックします。 組織のルート直下に、AWSアカウントが所属する形になっています。 以上で、Organizationsの作成は完了です。 AWS SSOを作成する 次にAWS SSOを作成していきます。 マネジメントコンソールでAWS SSOのダッシュボードを表示します。今回は東京リージョンにAWS SSOを作っていくため、リージョンが「東京」になっていることを確認してください。 「AWS SSOを有効にする」をクリックしてください。 次のような画面が表示されます。画面下の「ユーザポータルのURL」は、あとでAWS SSOにアクセスする際に使用することを覚えておいてください。 設定 次に、AWS SSOを設定していきます。 AWS SSOユーザーの作成 左メニューから「ユーザー」を選択し、「ユーザーを追加」をクリックします。 ユーザー情報を入力し、「次:グループ」をクリックします。 今回はグループは作成しません。「ユーザーを追加」をクリックします。 マネジメントコンソールでの作業は以上です。 作成したユーザーに次のようなメールが届きます。「Accept invitation」をクリックして、パスワードを設定してください。 アクセス権限セットの作成 次は、アクセス権限セットを準備していきます。 左メニューの「AWSアカウント」を選択し、「アクセス権限セット」をクリックします。 「アクセス権限セットを作成」をクリックします。 アクセス権限セットの作成方法は、既存の事前定義済みの職務機能ポリシーから選択するか、独自のポリシーを作成するかを選択できます。 既存の事前定義済みの職務機能ポリシーとして、次のようなものが用意されています。 ここでは、 AdministratorAccess と ViewOnlyAccess を選んでいきます。 まず、 AdministratorAccess から。 AdministratorAccess を選択し、「次:タグ」をクリックします。 タグの追加は省略して、「次:確認」をクリックします。 詳細に表示されるセッション時間について補足します。この時間は、AWS SSOからこの権限でAWSアカウントにアクセスできる時間になります。デフォルトは1時間ですが、作成済みのアクセス権限の編集で、1時間から12時間の間で変更することができます。 「作成」をクリックし完了です。 同じ要領で、 アクセス権限セット ViewOnlyAccess も作成します。 アクセス権限セットをAWS SSOユーザーに割り当てる 今までに作成したAWS SSOユーザーとアクセス権限セット、AWSアカウントを関連付けます。 左メニューから「AWSアカウント」を選択し、アクセスしたいAWSアカウントをチェックし、「ユーザーの割り当て」をクリックします。 AWS SSOユーザーをチェックして、「次:アクセス権限セット」をクリックします。 アクセス権限セット AdministratorAccess と ViewOnlyAccess をチェックし、「完了」をクリックします。 左メニューの「AWSアカウント」を選択します。「Permission sets」 にAWSアカウントに割り当てられたアクセス権限セットが表示されています。 動作確認 マネジメントコンソールアクセスに使用する AWS SSO ユーザーポータルのURL(覚えていますか?)をWebブラウザで表示します。 「AWS account」、さらにAWSアカウントを選択すると、そのアカウントにアクセスできるアクセス権限セットの一覧が表示されます。 アクセス権限セットの右にある「Management console」をクリックすると、その権限でマネジメントコンソールにアクセスできます。アクセス権限が期待どおりか、 ViewOnlyAccess でアクセスしてみましょう。 リードオンリーの権限しかないはずなので、たとえば S3 のバケットは作成できません。試してみましょう。 期待どおり、バケット作成に失敗しました。 AWS CLIに使用する AWSアカウントにCLI でアクセスしたいという人もいると思います。AWS CLIバージョン2はAWS SSOに対応しています。 2種類の方法を紹介します。 一時クレデンシャルを環境変数で指定する AWS SSO にサインインした画面で、アクセス権限セット ViewOnlyAccess の右に表示される「Command line or programmatic access」をクリックします。 AWS CLIの動作環境に合わせて、環境変数の設定コマンドをコピーします。今回はPowerShell を使用します。 PowerShell を起動し、環境変数設定をペーストして実行します。 PS> $Env:AWS_ACCESS_KEY_ID="ASIXXXXXXXXXXXXXXXX" PS> $Env:AWS_SECRET_ACCESS_KEY="A0gXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" PS> $Env:AWS_SESSION_TOKEN="IQoJXXXXXX…..XXXXXXXXXXXXXXXXXXXXXXXXXXXX==" 該当のアクセス権限セットは、ViewOnlyAccess なので、S3バケットは参照できますが、バケット作成・削除はできません。動作を確認してみましょう。 PS> aws s3 ls 2021-11-22 20:50:38 advent2021-santa-present PS> aws s3 mb s3://advent2021-claus-present --region ap-northeast-1 make_bucket failed: s3://advent2021-claus-present An error occurred (AccessDenied) when calling the CreateBucket operation: Access Denied 問題ないですね。 AWS CLIのプロファイルを使用 AWS CLI バージョン2は、AWS SSOと連携して使用することができます。 AWS SSO用のプロファイルを作成します。 PS> aws configure sso AWS SSOユーザーポータルのURLを入力します。 SSO start URL [None]: https://d-9XXXXXXXXX.awsapps.com/start AWS SSOは、東京リージョンに作成したので、「ap-northeast-1」を入力します。 SSO Region [None]: ap-northeast-1 このあと、Webブラウザが起動し、AWS SSOユーザー認証が求められます。 次の画面が表示されたら、Webブラウザは閉じても大丈夫です。 アクセスするAWSアカウントを選択しますが、ひとりオーガニで一つしかないため、自動選択されました。 The only AWS account available to you is: 638XXXXXXXXX Using the account ID 638XXXXXXXXX 次にアクセス権限セットを選択します。 There are 2 roles available to you. Using the role name "ViewOnlyAccess" あとは、AWS CLIのデフォルトのリージョン、出力フォーマットを入力します。 CLI default client Region [None]: ap-northeast-1 CLI default output format [None]: json 最後に、プロファイルの名前を入力します。 CLI profile name [ViewOnlyAccess-638XXXXXXXXX]: readonly AWS CLIからの動作を確認しましょう。このアクセス権限セットは、参照権限しかないため、S3バケットは参照できますが、作成はできません。 PS> aws s3 ls --profile readonly 2021-11-22 20:50:39 advent2021-santa-present PS> aws s3 mb s3://advent2021-claus-present --profile readonly make_bucket failed: s3://advent2021-claus-present An error occurred (AccessDenied) when calling the CreateBucket operation: Access Denied 期待どおりに動作しています。 セッション時間について デフォルトのアクセス権限セットのセッション時間は1時間です。セッションが切れてしまった場合は次のようなメッセージが表示されます。 PS> aws s3 ls --profile readonly The SSO session associated with this profile has expired or is otherwise invalid. To refresh this SSO session run aws sso login with the corresponding profile. AWS CLIでSSOログインして、新しくセッションを開始してください。 PS> aws sso login --profile readonly ちょっとだけ仕組みをのぞく AWS SSOのアクセス権限セットは、AWSアカウントに管理ロールを自動作成するという話をしました。確認してみましょう。 IAMダッシュボードで、IAMロールを表示してください。「AWSReservedSSO_」で始まるロール名が、AWS SSOがアクセス権限セットからAWSアカウントに対して自動作成したロールになります。 ロール名をクリックしてみます。アクセス権限セットとロールの権限は同じであることを確認してください。AWS SSOからアクセス権限セットをクリックした場合、AWSアカウントに対してはこのロールの権限でアクセスしていることになります。 「信頼関係」を見てみます。ここでは、AWS SSOとIAMロールとの間で認証の連携が行われているんだな、ということだけ理解しておきましょう。 まとめ この記事では、AWSアカウント一つの運用においても、Organizationsを使うことで、便利になったり、勉強になるということを紹介しました。AWS SSOを導入し、AWSアカウントへのアクセス権限の切り替えの方法を、マネジメントコンソールおよびAWS CLIで動作確認しました。 普段使いのAWSアカウントで、OrganizationsおよびAWS SSOを活用してみてください。 明日のNTTテクノクロス Advent Calendar 2021は、 @ea-yasuda による『リモート時代の「今どこにいるの?」をpythonで』に関する記事です。面白そうです。 お楽しみに!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWSで手っ取り早くJupter notebookを動かした話

AWSで手っ取り早くJupyter notebookを起動させてみます 認証等を考えると色々振り回されるのですが、動かすだけなら割と簡単でした 認証周りは検証が不十分なので、とりあえず動かすことに主に紹介します 環境 AWS環境 Deep Learning AMI (Ubuntu 18.04) Version 35.0 g4dn.xlarge Jupyter notebookの設定 今回の環境ではJupyter notebookはインストール済みなので、とりあえず設定を変えてみます Port 8081からアクセスできるようにします vi ~/.jupyter/jupyter_notebook_config.py c = get_config() c.NotebookApp.ip = '0.0.0.0' c.NotebookApp.open_browser = False c.NotebookApp.port = 8081 c.NotebookApp.token = '' Jupyter notebook起動 バックグラウンドで起動します jupyter notebook & AWSのセキュリティ許可 AWSのインバウンドルールで忘れずに8081を許可します (「ソース」は0.0.0.0/0ではなく正しい値を設定した方がセキュアです) 機会があれば、Jupyter notebookをよりセキュアにする話でも書いてみようと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

aws-cli の list_objects_v2() 関数 の 取得上限 1000 オブジェクトの罠

S3 バケットから、数テラのデータをダウンロードしていて、ハマりました。 AWS の 関数、list_objects_v2() は、1000件までしかオブジェクトを取得できないという問題があるようでした。 https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectsV2.html これを回避するには、1000件ごとに、Continuationtoken を渡してやる必要があるようです。 結果的には、普通に以下のコマンドでダウンロードできました。内部的に、Continuationtoken を渡しているようです。 # aws s3 sync s3://<bucket_name> f:\<folder_name> 試しに、Python スクリプトを作成して今回は Windows11 で実行してみましたができていたようでした。 import boto3 import os s3_client = boto3.client('s3') def download_dir(): """ params: - prefix: pattern to match in s3 - local: local path to folder in which to place files - bucket: s3 bucket with target contents - client: initialized s3 client object """ local='.\<folder_name>' bucket='<bucket_name>' prefix='' keys = [] dirs = [] next_token = '' base_kwargs = { 'Bucket':bucket, 'Prefix':prefix, } while next_token is not None: kwargs = base_kwargs.copy() if next_token != '': kwargs.update({'ContinuationToken': next_token}) results = client.list_objects_v2(**kwargs) contents = results.get('Contents') for i in contents: k = i.get('Key') if k[-1] != '/': keys.append(k) else: dirs.append(k) next_token = results.get('NextContinuationToken') for d in dirs: dest_pathname = os.path.join(local, d) if not os.path.exists(os.path.dirname(dest_pathname)): os.makedirs(os.path.dirname(dest_pathname)) for k in keys: dest_pathname = os.path.join(local, k) if not os.path.exists(os.path.dirname(dest_pathname)): os.makedirs(os.path.dirname(dest_pathname)) client.download_file(bucket, k, dest_pathname) if __name__ == "__main__": client = boto3.client('s3') resource = boto3.resource('s3') download_dir() (参考) https://newbedev.com/boto3-to-download-all-files-from-a-s3-bucket
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

list_objects_v2 の 1000 オブジェクトの罠

S3 バケットから、数テラのデータをダウンロードしていて、ハマりました。 AWS の 関数、list_objects_v2() は、1000件までしかオブジェクトを取得できないという問題があるようでした。 https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectsV2.html これを回避するには、1000件ごとに、Continuationtoken を渡してやる必要があるようです。 結果的には、普通に以下のコマンドでダウンロードできました。内部的に、Continuationtoken を渡しているようです。 # aws s3 sync s3://<bucket_name> f:\<folder_name> 試しに、Python スクリプトを作成して今回は、Windows11 で実行してみましたができていたようでした。 import boto3 import os s3_client = boto3.client('s3') def download_dir(): """ params: - prefix: pattern to match in s3 - local: local path to folder in which to place files - bucket: s3 bucket with target contents - client: initialized s3 client object """ local='.\<folder_name>' bucket='<bucket_name>' prefix='' keys = [] dirs = [] next_token = '' base_kwargs = { 'Bucket':bucket, 'Prefix':prefix, } while next_token is not None: kwargs = base_kwargs.copy() if next_token != '': kwargs.update({'ContinuationToken': next_token}) results = client.list_objects_v2(**kwargs) contents = results.get('Contents') for i in contents: k = i.get('Key') if k[-1] != '/': keys.append(k) else: dirs.append(k) next_token = results.get('NextContinuationToken') for d in dirs: dest_pathname = os.path.join(local, d) if not os.path.exists(os.path.dirname(dest_pathname)): os.makedirs(os.path.dirname(dest_pathname)) for k in keys: dest_pathname = os.path.join(local, k) if not os.path.exists(os.path.dirname(dest_pathname)): os.makedirs(os.path.dirname(dest_pathname)) client.download_file(bucket, k, dest_pathname) if __name__ == "__main__": client = boto3.client('s3') resource = boto3.resource('s3') download_dir() (参考) https://newbedev.com/boto3-to-download-all-files-from-a-s3-bucket
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ヘキサゴナルアーキテクチャを使ってドメインモデルをAWS Lambdaファンクションで実装してみた

はじめに 2021年11月20日から21日にかけて、JAWS Pankration 2021 ~Up till Down~が開催されました。筆者はその中で DDD on AWS Lambdaというタイトルのセッションを担当しました。このセッションでは、ヘキサゴナルアーキテクチャを利用してドメインモデルをAWS Lambdaファンクションに実装する方法、また制御の反転(IoC)を利用してユニットテストを容易にする方法について紹介しました。 この記事を書いたのは 今回、JAWS Pankrationは新たな試みとして、広く海外のコミュニティーメンバーにも参加してもらうために、全てのスライドを英語で記述しポケトークを利用して逐次通訳しながらセッションを行いました。海外のコミュニティーメンバーにも見てもらいたかったので、このために実装したサンプルアプリケーションのリポジトリのREADME.mdも英語で記述しましたが、JAWS Pankrationのセッションが終了した後、やはり日本語でもこの内容を紹介したいと思い、この記事で紹介することにしました。この記事を見て興味を持たれた方は、サンプルアプリケーションのGitHubのリポジトリをぜひご覧ください。 JAWS Pankration 2021に登壇した理由 マイクロサービスアーキテクチャが注目され、サービスの分割手法としてドメイン駆動設計への関心が再度高まると共に、自社のサービスにAWS Lambdaを利用した場合にどのようにドメインモデルを実装するか、またユニットテストを容易にするにはどうすれば良いかという質問をされる機会が増えました。そこで自分なりに考えた結果、ヘキサゴナルアーキテクチャの概念を利用してドメインモデルを外部から隔離し、また制御の反転(IoC)を利用することで、クラス間を疎結合にしてユニットテストを容易にするのが良いのではないかと仮説を立て、実際にサンプルアプリケーションを実装してみることにしました。実装してみると個人的には割と良いと感じたので、GitHubにサンプルアプリケーションとして公開し、JAWS Pankration 2021の場でこのアイデアを紹介してみようと思いました。JAWS PankrationにCFPを提出したところ、幸運にも採択されて発表することができました。 JAWS Pankration 2021で発表したトピック JAWS pankration 2021のセッションでお話ししたトピックは以下の通りです。 ドメイン駆動設計 マイクロサービスアーキテクチャによるサービスの分割方式としてEric Evansのドメイン駆動設計が再び注目されています。ドメイン駆動設計はビジネスエキスパートが用いる用語をユビキタス言語として抽出し、ユビキタス言語が共通認識として利用される範囲をコンテキストの境界と位置付け、境界づけされたコンテキストでドメインモデルを定義します。ビジネス要件に対してドメインモデルを設計し、モデルに適切なデータと振る舞いを持たせることで、ドメインエキスパートの知識を正しく実装に反映させることを目的としています。多くの時間をかけてモデルの設計を行って満足し、その後の実装と乖離してしまうのではなく、アジャイル的にドメインモデル、ユニットテスト、実装を繋げて、繰り返し改善し開発していくスタイルが個人的には気に入っています。 ヘキサゴナルアーキテクチャ ヘキサゴナルアーキテクチャはAlistair Cockburnが提唱したアーキテクチャパターンで、ポートとアダプターパターンとも呼ばれます。ヘキサゴナルアーキテクチャでは、アプリケーションを利用するドライバ(アクター)は特定のテクノロジー用のプロシージャ呼び出し、またはメッセージに変換される要求を送信し、それをアプリケーションポートに渡します。アプリケーションはドライバーのテクノロジーについては関知しません。アプリケーションからインフラストラクチャなど外部へ連携する場合は、ポートを介してアダプターに送信します。アダプターは連携先の受信テクノロジーに必要な形式に適切に変換します。 制御の反転(IoC)と依存性の注入(DI) Robert C.Martinによって提唱された依存関係逆転の原則(DIP)は、上位レベルの実装コードは下位レベルの詳細の実装コードに依存してはいけないというものです。この原則に従ってクラス間の依存を抽象クラスと継承を用いて設計し、また疎結合を実現するために制御の反転(IoC)を行う依存性の注入(DI)を実現するためにPython injectorライブラリを利用しました。 サンプルアプリケーションについて サンプルアプリケーションはこちらのGitHubリポジトリで確認できます。このサンプルアプリケーションではワクチンの予約システムを例に一部の機能のみを実装しています。ワクチンの予約システムには様々なビジネス要件がありますが、ここでは以下の要件を定義、実装しています。 ワクチン接種希望者は、自分のIDと空き時間スロットのIDを指定して予約を行うことができる ワクチン接種希望者は、一人につき2つまで空き時間スロットの予約を取ることができる ワクチン接種希望者は、同一日時のスロットを予約することはできない これらのビジネス要件をドメインモデルで実装しました。 クラスダイアグラムとシーケンスダイアグラム サンプルアプリケーションのクラスダイアグラムは以下の通りです。DIPの原則に従い、ポートクラスとアダプタークラスは抽象クラスを継承する形で実装しています。 またクラス間のシーケンスダイアグラムは以下の通りです。 クラスの実装 サンプルアプリケーションのクラスはクラスダイアグラムで示したようにドメインモデル、ポート、アダプターに分かれます。また各クラス間はインターフェイスの役割を持つ抽象クラスへ依存する形となっています。Pythonで実装しているため、インターフェイスの代わりに抽象クラスを利用しています。 ドメインモデル(抜粋) ドメインモデルはシンプルな実装になっています。 from slot import Slot class Recipient: def __init__(self, recipient_id:str, email:str, first_name:str, last_name:str, age:int): self.__recipient_id = recipient_id self.__email = email self.__first_name = first_name self.__last_name = last_name self.__age = age self.__slots = [] @property def recipient_id(self): return self.__recipient_id ... def add_reserve_slot(self, slot:Slot) -> bool: if self.are_slots_same_date(slot): return False if self.is_slot_counts_equal_or_over_two(): return False self.__slots.append(slot) slot.use_slot() return True インターフェイスとなる抽象クラス(一部) インターフェイスとして抽象クラスを利用しています。ユニットテストでは、Amazon DynamoDBへアクセスする具象クラスの代わりに、この抽象クラスを継承するダミークラスを定義しテストを行っています。 以下はドメインモデルがポートクラスを経由してアクセスするアダプタークラスのインターフェイスの例です。 from abc import ABCMeta, abstractmethod from recipient import Recipient class IRecipientAdapter(metaclass=ABCMeta): @abstractmethod def load(self, recipient_id:str) -> Recipient: raise NotImplementedError() @abstractmethod def save(self, recipient:Recipient) -> bool: raise NotImplementedError() インジェクトされるクラス インジェクトされるクラスは抽象クラスにのみ依存しておりインジェクトされるクラスの実装とは疎結合になっています。この例ではドメインモデルのサービスクラスがポートクラスへアクセスしていますが、ポートクラスの抽象クラスを参照しています。 from injector import inject from i_recipient_port import IRecipientPort from i_slot_port import ISlotPort class ReservationService: @inject def __init__(self, recipient_port:IRecipientPort, slot_port:ISlotPort): self.__recipient_port = recipient_port self.__slot_port = slot_port def add_reservation(self, recipient_id:str, slot_id:str) -> bool: recipient = self.__recipient_port.recipient_by_id(recipient_id) slot = self.__slot_port.slot_by_id(slot_id) if recipient == None or slot == None: return False print(f"recipient: {recipient.first_name}, slot date: {slot.reservation_date}") ret = recipient.add_reserve_slot(slot) if ret == True: ret = self.__recipient_port.add_reservation(recipient) return ret Lambdaファンクションのハンドラ LambdaファンクションのハンドラではDynamoDBへのアクセスを行うコンクリートクラスをインジェクトするためのバインドを定義しています。app.pyはRequestPortクラスのメソッドを経由してドメインモデルのサービスクラスへアクセスします。 class RequestPortModule(Module): def configure(self, binder): binder.bind(ReservationService, to=ReservationService( RecipientPort(DDBRecipientAdapter()), SlotPort(DDBSlotAdapter()))) def lambda_handler(event, context): ''' API Gateway event adapter retrieve reservation request parameters ex: '{"recipient_id": "1", "slot_id":"1"}' ''' body = json.loads(event['body']) recipient_id = body['recipient_id'] slot_id = body['slot_id'] injector = Injector([RequestPortModule]) request_port = injector.get(RequestPort) status = request_port.make_reservation(recipient_id, slot_id) ユニットテストコード(抜粋) ユニットテストではダミークラスをインジェクトしてテストを実施しています。 import pytest ... recipient_id = "1" email = "fatsushi@example.com" first_name = "Atsushi" last_name = "Fukui" age = 30 slot_id = "1" reservation_date = datetime(2021,12,20, 9, 0, 0) location = "Tokyo" # ダミークラス class DummyRecipientAdapter(IRecipientAdapter): def load(self, recipient_id:str) -> Recipient: return Recipient(recipient_id, email, first_name, last_name, age) def save(self, recipient:Recipient) -> bool: return True ... # インジェクションのバインドの設定 class DummyModule(Module): def configure(self, binder): binder.bind(ReservationService, to=ReservationService( RecipientPort(DummyRecipientAdapter()), SlotPort(DummySlotAdapter()))) # テストターゲットのフィクスチャ @pytest.fixture() def fixture_reservation_service(): injector = Injector([DummyModule]) reservation_service = injector.get(ReservationService) return reservation_service def test_add_reservation(fixture_reservation_service): target = fixture_reservation_service recipient_id = "dummy_id" slot_id = "dummy_id" ret = target.add_reservation(recipient_id, slot_id) assert True == ret サンプルアプリケーションのビルドとデプロイ GitHubリポジトリからプロジェクトを取得したら以下の手順でビルドとデプロイが可能です。 Serverless Application Model サンプルプログラムはAWS Serverless Application Model (SAM) でビルド、デプロイするようになっています。このプロジェクトには以下の内容が含まれています。 src - アプリケーションのLambdaファンクション events - ファンクションのローカル実行で利用できるイベント tests/unit - アプリケーションコードのユニットテスト template.yaml - アプリケーションのAWSリソースが定義されたSAMテンプレート ビルドとデプロイ サンプルアプリケーションをビルド、デプロイするにはSAM CLIを利用します。事前にSAM CLIをインストールしておく必要があります。SAM CLIのインストールの詳細はこちらをご覧ください。 ビルドでデプロイを実行するためには以下のコマンドを実行します。 sam build --use-container sam deploy --guided 初期データの登録 初期データを登録するAWS CLIを利用したコマンドが用意されています。事前にAWS CLIのインストール、アカウント情報の設定が必要です。以下のshellコマンドを実行します。 chmod +x setup/add_ddb_data.sh setup/add_ddb_data.sh SAMビルドとローカルでの実行 Lambdaファンクションをローカルで実行するには以下のコマンドを実行します。 sam build --use-container sam local invoke HelloWorldFunction --event events/event.json ユニットテストの実行 このサンプルアプリケーションは、Lambdaファンクションのユニットテストのサンプルにもなっています。ユニットテストを実行するためには、事前にユニットテストに必要なモジュールをインストールします。 pip install -r tests/requirements.txt --user ユニットテストを実行します。 python -m pytest tests/unit -v まとめ ヘキサゴナルアーキテクチャのコンセプトを利用してAWS Lambdaファンクションでドメインモデルを実装してみました。この記事が皆さんにとって少しでも参考になれば幸いです。 本投稿は、個人の意見で、所属する企業や団体は関係ありません。 また掲載しているサンプルプログラム等の動作に関しても一切保証しておりません。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

受験談 AWS Certified SysOps Administrator - Associate 認定

3度目の正直でSOAに合格しました! この記事は以下アドベントカレンダー2 12/3(金)の記事でもあります。 対象者 これからSOA他、AWS認定資格の受験をしようとしている方 Udemyが好きな方 Udemyって何?なんて読むの?おいしいの?と思われた方 結論 Udemy活用しまくり SAAを最初に受験しましたが、その時の受験談は以下をご覧ください。自分の受験前のAWS知識レベルも記載してありますのでご参考までに。この時もUdemyをめちゃ活用しまくりました。SAA対策講座は比較的多く揃っているのでお勧めです! 上記触れていますが、SAA受験時は参考書やBlack Beltなどは一切触れずUdemy講座に絞って勉強しまくりました。セールもいい感じのタイミングでやってるので、どういう講座があるかをあらかじめチェックしておいて、購入はセール期間中にという感じです。 SAA->SAP->SOA 本記事はSOAの受験談ですが、SAAとSOAの間にSAPを取得してます。 この時ももちろんUdemyの講座を活用。 SAAに比べると流石に講座の数は少ないですが(日本語の講座しか見てません。。英語無理。。)、上記は模擬試験が全5回、1回75問のボリュームです。ひたすら繰り返して理解を深めました。 SAAの受験談でも触れていますが、復習も兼ねて以下を再度通しました。個人的には初めてAWSを触る人にはお勧めです。基本のアーキテクチャを丁寧に解説してくれるので、手を動かしながら理解できると思います。 肝心のSOA 試験詳細は以下に譲りますが、どの認定資格にもだいたい「最低x年のAWS 技術の実践経験」とありますが、気にしません!実務経験を待っていたらいつまでも合格できません笑 さて。冒頭にも書きましたが3回目の受験でした・・。受験してから次の受験が可能になるまでに2週間空けないといけないのですが、下表の通り立て続けに受験しました。 受験日 結果 2021-10-16 不合格 2021-11-02 不合格 2021-11-23 合格 正直1回目の時にかなり手応えがあったのですが、微妙に足りなかった・・。2回目は撃沈。3回目は720点の合格ラインを大きく上回る結果に。3回目ともなると、「あー、この問題前も出てたな」というのが分かるようにもなってきました笑 確かに不合格になってからも勉強は続けていましたが、問題によって当たり外れもありそうです(・・・全てをきっちり理解していれば良いのでしょうが) SOAはC02となり、ラボという実際にAWSコンソールを操作する試験が追加されています。ちなみに受験1回目のラボ試験と受験3回目のラボ試験は一部同じような問題が出てました。ラボ自体の問題はUdemyの講座を勉強する過程でコンソールの操作にある程度慣れておけば、問題文に沿って操作してなんとなか解ける気がします。 それよりも知識問題に苦戦しました。Udemyは以下の講座を活用。模擬問題4回分、1回70問、合計280問ありますので、ひたすら繰り返す形で勉強しました。3度目となると心も折れそうになりましたが、ここまできたからには記憶が新しいうちにとも思い。 Udemy模擬試験活用時のアドバイス Udemyの模擬試験講座は、システム上70問など全問解答してから答え合わせをするフローになってます。よくレビューや他の学習談の記載を見ると、「一問一答の形だったら嬉しい」とありますが、私の場合はブラウザ2つ開いて問題のページと解答のページを交互に見ながら進めてました。これで一問一答形式で進められますので、個人的にはお勧めです。 ということで 「Udemyの講座=>わからない問題や理解が浅い言葉などはスプレッドシートに移して理解を深める」、このサイクルをひたすら回して回して回して・・3回目にして・・SOAも無事に合格できました。 SOA=>SAP=>SOAときて、次はどうしようかなと思っているのですが、Udemyに講座があるかな?で決める気がします笑 自分のスタイルを確立することをお勧めしますが、これからCloud PractitionerやSAAを受けてみようかなという方は、きっとUdemy講座にお世話になることと思います!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【SAP-C01試験対策】DDoS攻撃に対する対策

はじめに AWS上のDDoS攻撃に対するセキュリティ技術を勉強するために以下の公式ドキュメントおよび研修を参考にしたので内容をまとめます。 背景 本記事はAWSソリューションアーキテクトプロフェッショナルに合格するために、Udemyの模擬試験を解いて分からなかった部分を勉強してまとめるものです。 試験対策用のため、分からない知識を補足したり試験で問われなさそうなところを省略したりしながらまとめています。 なるべくわかりやすい記載を心がけますが、最終目的は自己学習用であるということをご容赦ください。 DDoS攻撃とは 複数のソースを使用してウェブサイトやアプリケーションに負荷をかけ、正当なエンドユーザーのアクセスを妨害する攻撃。 Distributed Denial of Service attack(分散型サービス拒否攻撃)の略。 OSI参照モデルとDDoS攻撃の種類(主なもの) # レイヤー アプリケーション 攻撃の例 7 アプリケーション データ HTTPフラッド、DNSクエリフラッド 6 プレゼンテーション データ SSLの悪用 4 トランスポート セグメント SYNフラッド 3 ネットワーク パケット UDPリフレクション攻撃 インフラストラクチャ攻撃 UDPリフレクション攻撃:標的サーバのIPになりすまし、サーバから増幅されたレスポンスが返るようなリクエストを送る。 SYNフラッド:大量の接続を作成し放置することで標的サーバのTCPサービスを使い果たさせる。 アプリケーションレイヤー攻撃 HTTPフラッド:HTTPリクエストを大量に送信してアプリケーションを過負荷状態にする。 DNSフラッド:大量のリクエストを送り付けてDNSサーバのリソースを使い果たさせる。 アーキテクチャによる対策 # サービス 概要 BP1 CroudFrontGlobal Accelerater 正しい形式の接続のみ受け入れ、攻撃がオリジンに到達できないようにする。 BP2 WAF ウェブACLルールと関連付けることで送信元IPをブロックする BP3 Route53 ・シャッフルシャーディング機能により、ネームサーバーが利用不可となった場合に別のエッジロケーションでネームサーバに再試行する。・anycastストライピングによりDNSを最適な場所で処理させる。・DNSクエリの送信元と量から、信頼できるユーザからのリクエストを優先する。 BP4 APIGateway AWSのコンポーネントをパブリックアクセスから隠す BP5 ネットワークACLセキュリティグループ 許可された送信元のアクセスのみに限定する BP6 ELB 正しい形式のTCP接続のみを受け入れる。 BP7 EC2 Auto Scalingによりパフォーマンスを向上させる。 DDoS攻撃の検知・保護に役立つサービス CloudWatch:正常な動作を追跡、把握し、DDoS攻撃を識別する。 VPCフローログ:ネットワークトラフィックの異常を識別する。 AWS GuardDuty:AWS上の操作や動作をモニタリングし、セキュリティ上の脅威を検出する。 AWS Shield:DDos攻撃からウェブサイトを保護する。 AWS Shield Standard:CroudFrontやRoute53でTCPのレイヤー3,4に対する既知の攻撃から保護する。 AWS Shield Advanced:Standardに加えEC2等でも、レイヤー3,4,7に対する攻撃から保護する。リアルタイム通知およびAWSから24時間365日のサポートを受けられる。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Amazon Linux 2022 Preview の様子見

11/22 に、Amazon Linux 2022 (以降AL2022)のプレビューリリースが発表されました。 Announcing preview of Amazon Linux 2022 Preview 時点ですが、どんなものかというのを見てみました。 概要 ニュースの概要、自分なりに掻い摘んでピックアップすると以下がポイントかなと思います。 今後、2年毎のメジャーバージョン更新方針とした。 5年間のサポートが保証される。(標準サポート2年、メンテナンス3年) Fedra Project ベースに、四半期毎の更新が適用される。 リポジトリロック機能ができた。 Kernelに起動したままパッチを充てられる。(未実装) 一番大きいのは、リリースサイクルポリシーが定まったことで、利用者として計画が立てやすくなったことかなと思います。 リポジトリのロック機能。詳細はわからないですが、「テスト終わってリリースしようとしたら、 yum からとってきた rpm が更新されてて本番での動作が変わった」みたいな悲劇を避けられるものなのかと期待してます。 確認してみたこと 以下、確認していきます。 作ってみた SSM Session Manager で繋いでみた yum 使ってみた amazon linux extra みてみた -> ⚠️使えませんでした リポジトリのバージョン固定 -> ⚠️今時点コマンド戻りなし 作ってみた 作るとき、EC2 で普通に行う 「インスタンス起動」では、 AL2022は出てきません。AMIリストから選択します。 一応、以下のように作ってます。 インスタンスタイプは t2.micro デフォルトVPC、デフォルトSecurityGroup AmazonSSMFullAccess がついた IAM Role をつける キーペアはつける 現時点では SSM Agent は入っていないので、一度 SSH で繋いで確認しました。 Kernel が 5.10 でインストールされてるのがわかります。 [ec2-user@ip-172-31-47-247 ~]$ [ec2-user@ip-172-31-47-247 ~]$ cat /etc/amazon-linux-release Amazon Linux release 2022 (Amazon Linux) [ec2-user@ip-172-31-47-247 ~]$ uname -a Linux ip-172-31-47-247.ap-northeast-1.compute.internal 5.10.75-82.359.amzn2022.x86_64 #1 SMP Mon Nov 15 18:04:59 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux [ec2-user@ip-172-31-47-247 ~]$ SSM Session Manager で繋いでみた 「SSHは閉じてセキュアに!」といきたいので、 Session Manager に切り替えます。 デフォルトではインストールされてないので、まずインストールします。(検証する時、以下のコマンドを UserData に入れて 入れてしまった方が楽かも) 良し悪しは怪しいですが、 AmazonLinux2 手順 を実施したらインストールできました。 sudo yum install -y https://s3.ap-northeast-1.amazonaws.com/amazon-ssm-ap-northeast-1/latest/linux_amd64/amazon-ssm-agent.rpm Before [ec2-user@ip-172-31-47-247 ~]$ yum info amazon-ssm-agent Amazon Linux 2022 repository 21 MB/s | 22 MB 00:01 メタデータの期限切れの最終確認: 0:00:06 時間前の 2021年11月23日 14時26分42秒 に実施しました。 エラー: 表示するための一致したパッケージはありません [ec2-user@ip-172-31-47-247 ~]$ After [ec2-user@ip-172-31-47-247 ~]$ yum info amazon-ssm-agent メタデータの期限切れの最終確認: 0:03:21 時間前の 2021年11月23日 14時26分42秒 に実施しました。 インストール済みパッケージ 名前 : amazon-ssm-agent バージョン : 3.1.501.0 リリース : 1 Arch : x86_64 サイズ : 111 M ソース : amazon-ssm-agent-3.1.501.0-1.src.rpm リポジトリー : @System repo から : @commandline 概要 : Manage EC2 Instances using SSM APIs URL : http://docs.aws.amazon.com/ssm/latest/APIReference/Welcome.html ライセンス : Apache License, Version 2.0 説明 : This package provides Amazon SSM Agent for managing EC2 Instances using SSM APIs [ec2-user@ip-172-31-47-247 ~]$ systemctl status amazon-ssm-agent ● amazon-ssm-agent.service - amazon-ssm-agent Loaded: loaded (/etc/systemd/system/amazon-ssm-agent.service; enabled; vendor preset: disabled) Active: active (running) since Tue 2021-11-23 14:29:17 UTC; 1min 27s ago Main PID: 3170 (amazon-ssm-agen) Tasks: 15 (limit: 1128) Memory: 17.7M CPU: 198ms CGroup: /system.slice/amazon-ssm-agent.service ├─3170 /usr/bin/amazon-ssm-agent └─3236 /usr/bin/ssm-agent-worker 無事、Session Manager で入れました。 ssm-agent のデフォルトインストールは、 こちらのIssue に期待です。 yum 使ってみた すでに、上の項で yum 使ってしまってますが yum 入ってました。AmazonLinux2のコマンドに慣れてる人も安心です。 ただし、マニュアルを見ていると dnf コマンド使う方がおすすめみたいですね。 [ec2-user@ip-172-31-47-247 ~]$ yum --version 4.9.0 インストール済み: dnf-0:4.9.0-1.amzn2022.noarch (日時: 2021年11月19日 01時16分10秒) ビルド : Amazon Linux (日時: 2021年11月11日 23時34分30秒) インストール済み: rpm-0:4.16.1.3-1.amzn2022.x86_64 (日時: 2021年11月19日 01時16分01秒) ビルド : Amazon Linux (日時: 2021年10月08日 20時24分16秒) [ec2-user@ip-172-31-47-247 ~]$ 巨大なリストになってしまいますが、気になるパッケージが抜けてない?という人用に。(とはいえ、プレビューなのでまた変わると思いますが) [ec2-user@ip-172-31-47-247 ~]$ yum list installed インストール済みパッケージ acl.x86_64 2.3.1-2.amzn2022 @System alternatives.x86_64 1.15-2.amzn2022 @System amazon-ec2-net-utils.noarch 2.0.0-1.amzn2022 @System amazon-rpm-config.noarch 182-2.amzn2022 @System amazon-ssm-agent.x86_64 3.1.501.0-1 @@commandline annobin.x86_64 9.79-3.amzn2022 @System at.x86_64 3.1.23-6.amzn2022 @System attr.x86_64 2.5.1-3.amzn2022 @System audit.x86_64 3.0.6-1.amzn2022 @System audit-libs.x86_64 3.0.6-1.amzn2022 @System avahi-libs.x86_64 0.8-14.amzn2022.0.1 @System awscli.noarch 1.19.100-1.amzn2022.0.1 @System basesystem.noarch 11-11.amzn2022 @System bash.x86_64 5.1.8-2.amzn2022 @System bash-completion.noarch 1:2.11-2.amzn2022 @System bc.x86_64 1.07.1-14.amzn2022 @System bind-libs.x86_64 32:9.16.22-1.amzn2022 @System bind-license.noarch 32:9.16.22-1.amzn2022 @System bind-utils.x86_64 32:9.16.22-1.amzn2022 @System binutils.x86_64 2.35.2-8.amzn2022 @System binutils-gold.x86_64 2.35.2-8.amzn2022 @System blktrace.x86_64 1.2.0-17.amzn2022 @System boost-filesystem.x86_64 1.75.0-4.amzn2022 @System boost-system.x86_64 1.75.0-4.amzn2022 @System boost-thread.x86_64 1.75.0-4.amzn2022 @System bzip2.x86_64 1.0.8-6.amzn2022 @System bzip2-libs.x86_64 1.0.8-6.amzn2022 @System c-ares.x86_64 1.17.2-1.amzn2022 @System ca-certificates.noarch 2021.2.50-1.0.amzn2022 @System cairo.x86_64 1.17.4-3.amzn2022 @System cairo-gobject.x86_64 1.17.4-3.amzn2022 @System checkpolicy.x86_64 3.2-1.amzn2022 @System chkconfig.x86_64 1.15-2.amzn2022 @System chrony.x86_64 4.1-1.amzn2022.0.3 @System cloud-init.noarch 20.4-3.amzn2022.2.0 @System cloud-utils-growpart.noarch 0.31-8.amzn2022 @System compat-readline5.x86_64 5.2-39.amzn2022 @System coreutils.x86_64 8.32-30.amzn2022 @System coreutils-common.x86_64 8.32-30.amzn2022 @System cpio.x86_64 2.13-10.amzn2022 @System cpp.x86_64 11.2.1-2.amzn2022.0.2 @System cracklib.x86_64 2.9.6-27.amzn2022 @System cracklib-dicts.x86_64 2.9.6-27.amzn2022 @System crontabs.noarch 1.11-24.20190603git.amzn2022 @System crypto-policies.noarch 20210213-1.git5c710c0.amzn2022 @System crypto-policies-scripts.noarch 20210213-1.git5c710c0.amzn2022 @System cryptsetup.x86_64 2.3.6-1.amzn2022 @System cryptsetup-libs.x86_64 2.3.6-1.amzn2022 @System curl.x86_64 7.79.1-1.amzn2022 @System cyrus-sasl-lib.x86_64 2.1.27-8.amzn2022 @System cyrus-sasl-plain.x86_64 2.1.27-8.amzn2022 @System dbus.x86_64 1:1.12.20-3.amzn2022 @System dbus-broker.x86_64 29-2.amzn2022 @System dbus-common.noarch 1:1.12.20-3.amzn2022 @System dbus-libs.x86_64 1:1.12.20-3.amzn2022 @System dejavu-sans-fonts.noarch 2.37-16.amzn2022 @System device-mapper.x86_64 1.02.175-1.amzn2022.0.1 @System device-mapper-event.x86_64 1.02.175-1.amzn2022.0.1 @System device-mapper-event-libs.x86_64 1.02.175-1.amzn2022.0.1 @System device-mapper-libs.x86_64 1.02.175-1.amzn2022.0.1 @System device-mapper-persistent-data.x86_64 0.9.0-3.amzn2022 @System dhcp-client.x86_64 12:4.4.2-11.b1.amzn2022 @System dhcp-common.noarch 12:4.4.2-11.b1.amzn2022 @System diffutils.x86_64 3.8-1.amzn2022 @System dmraid.x86_64 1.0.0.rc16-50.amzn2022 @System dmraid-libs.x86_64 1.0.0.rc16-50.amzn2022 @System dnf.noarch 4.9.0-1.amzn2022 @System dnf-data.noarch 4.9.0-1.amzn2022 @System dnf-plugin-release-notification.noarch 1.1-2.amzn2022 @System dnf-plugin-support-info.noarch 1.0-2.amzn2022 @System dnf-plugins-core.noarch 4.0.24-1.amzn2022 @System dosfstools.x86_64 4.2-1.amzn2022 @System dracut.x86_64 055-6.amzn2022 @System dracut-config-ec2.noarch 3.0-2.amzn2022 @System dracut-config-generic.x86_64 055-6.amzn2022 @System dwz.x86_64 0.14-1.amzn2022 @System dyninst.x86_64 10.2.1-6.amzn2022 @System e2fsprogs.x86_64 1.45.6-5.amzn2022 @System e2fsprogs-libs.x86_64 1.45.6-5.amzn2022 @System ec2-utils.noarch 1.2-46.amzn2022 @System ed.x86_64 1.14.2-10.amzn2022 @System efi-srpm-macros.noarch 5-4.amzn2022.0.3 @System elfutils-debuginfod-client.x86_64 0.185-2.amzn2022.0.1 @System elfutils-default-yama-scope.noarch 0.185-2.amzn2022.0.1 @System elfutils-libelf.x86_64 0.185-2.amzn2022.0.1 @System elfutils-libs.x86_64 0.185-2.amzn2022.0.1 @System ethtool.x86_64 2:5.15-1.amzn2022 @System expat.x86_64 2.4.1-1.amzn2022 @System file.x86_64 5.39-7.amzn2022 @System file-libs.x86_64 5.39-7.amzn2022 @System filesystem.x86_64 3.14-5.amzn2022 @System findutils.x86_64 1:4.8.0-2.amzn2022 @System fontconfig.x86_64 2.13.94-2.amzn2022 @System fonts-filesystem.noarch 1:2.0.5-5.amzn2022 @System fonts-srpm-macros.noarch 1:2.0.5-5.amzn2022 @System fpc-srpm-macros.noarch 1.3-3.amzn2022 @System freetype.x86_64 2.10.4-3.amzn2022 @System fribidi.x86_64 1.0.10-4.amzn2022 @System fstrm.x86_64 0.6.1-2.amzn2022 @System fuse-libs.x86_64 2.9.9-13.amzn2022 @System gawk.x86_64 5.1.0-3.amzn2022 @System gc.x86_64 8.0.4-5.amzn2022 @System gcc.x86_64 11.2.1-2.amzn2022.0.2 @System gcc-c++.x86_64 11.2.1-2.amzn2022.0.2 @System gdbm-libs.x86_64 1:1.19-2.amzn2022 @System gdisk.x86_64 1.0.8-1.amzn2022 @System gdk-pixbuf2.x86_64 2.42.6-1.amzn2022 @System gettext.x86_64 0.21-4.amzn2022 @System gettext-libs.x86_64 0.21-4.amzn2022 @System ghc-srpm-macros.noarch 1.5.0-4.amzn2022 @System glib2.x86_64 2.68.4-1.amzn2022 @System glibc.x86_64 2.34-7.amzn2022 @System glibc-all-langpacks.x86_64 2.34-7.amzn2022 @System glibc-common.x86_64 2.34-7.amzn2022 @System glibc-devel.x86_64 2.34-7.amzn2022 @System glibc-gconv-extra.x86_64 2.34-7.amzn2022 @System glibc-headers-x86.noarch 2.34-7.amzn2022 @System glibc-locale-source.x86_64 2.34-7.amzn2022 @System gmp.x86_64 1:6.2.0-6.amzn2022 @System gnat-srpm-macros.noarch 4-13.amzn2022 @System gnupg2.x86_64 2.2.27-4.amzn2022 @System gnutls.x86_64 3.7.2-1.amzn2022 @System go-srpm-macros.noarch 3.0.10-1.amzn2022 @System gpgme.x86_64 1.15.1-6.amzn2022 @System gpm-libs.x86_64 1.20.7-26.amzn2022 @System graphite2.x86_64 1.3.14-7.amzn2022 @System grep.x86_64 3.6-4.amzn2022 @System groff-base.x86_64 1.22.4-7.amzn2022 @System grub2-common.noarch 1:2.06-2.amzn2022.0.6 @System grub2-efi-x64-ec2.x86_64 1:2.06-2.amzn2022.0.6 @System grub2-pc-modules.noarch 1:2.06-2.amzn2022.0.6 @System grub2-tools.x86_64 1:2.06-2.amzn2022.0.6 @System grub2-tools-minimal.x86_64 1:2.06-2.amzn2022.0.6 @System grubby.x86_64 8.40-51.amzn2022.0.1 @System gssproxy.x86_64 0.8.4-2.amzn2022 @System guile22.x86_64 2.2.7-2.amzn2022 @System gzip.x86_64 1.10-4.amzn2022 @System harfbuzz.x86_64 2.7.4-3.amzn2022 @System hostname.x86_64 3.23-4.amzn2022 @System hunspell.x86_64 1.7.0-9.amzn2022 @System hunspell-en.noarch 0.20140811.1-18.amzn2022 @System hunspell-en-GB.noarch 0.20140811.1-18.amzn2022 @System hunspell-en-US.noarch 0.20140811.1-18.amzn2022 @System hunspell-filesystem.x86_64 1.7.0-9.amzn2022 @System hwdata.noarch 0.353-1.amzn2022 @System ima-evm-utils.x86_64 1.3.2-2.amzn2022 @System info.x86_64 6.7-10.amzn2022 @System inih.x86_64 49-3.amzn2022 @System initscripts.x86_64 10.09-1.amzn2022 @System ipcalc.x86_64 1.0.1-1.amzn2022 @System iproute.x86_64 5.10.0-2.amzn2022 @System iptables-legacy-libs.x86_64 1.8.7-8.amzn2022 @System iputils.x86_64 20210202-2.amzn2022 @System irqbalance.x86_64 2:1.7.0-5.amzn2022 @System jansson.x86_64 2.13.1-2.amzn2022 @System jitterentropy.x86_64 3.3.0-1.amzn2022 @System json-c.x86_64 0.14-8.amzn2022 @System kbd.x86_64 2.4.0-2.amzn2022 @System kbd-misc.noarch 2.4.0-2.amzn2022 @System kernel.x86_64 5.10.75-82.359.amzn2022 @System kernel-headers.x86_64 5.10.75-82.359.amzn2022 @System kernel-srpm-macros.noarch 1.0-4.amzn2022 @System kernel-tools.x86_64 5.11.20-300.amzn2022 @System kernel-tools-libs.x86_64 5.11.20-300.amzn2022 @System keyutils.x86_64 1.6.1-2.amzn2022 @System keyutils-libs.x86_64 1.6.1-2.amzn2022 @System kmod.x86_64 29-2.amzn2022 @System kmod-libs.x86_64 29-2.amzn2022 @System kpartx.x86_64 0.8.6-5.amzn2022 @System krb5-libs.x86_64 1.19.2-2.amzn2022 @System langpacks-core-font-en.noarch 3.0-14.amzn2022 @System less.x86_64 590-2.amzn2022 @System libX11.x86_64 1.7.2-3.amzn2022 @System libX11-common.noarch 1.7.2-3.amzn2022 @System libXau.x86_64 1.0.9-6.amzn2022 @System libXext.x86_64 1.3.4-6.amzn2022 @System libXft.x86_64 2.3.3-6.amzn2022 @System libXrender.x86_64 0.9.10-14.amzn2022 @System libacl.x86_64 2.3.1-2.amzn2022 @System libaio.x86_64 0.3.111-11.amzn2022 @System libarchive.x86_64 3.5.2-2.amzn2022 @System libargon2.x86_64 20171227-6.amzn2022 @System libassuan.x86_64 2.5.5-1.amzn2022 @System libattr.x86_64 2.5.1-3.amzn2022 @System libbasicobjects.x86_64 0.1.1-47.amzn2022 @System libblkid.x86_64 2.36.2-1.amzn2022 @System libbrotli.x86_64 1.0.9-4.amzn2022 @System libcap.x86_64 2.48-2.amzn2022 @System libcap-ng.x86_64 0.8.2-4.amzn2022 @System libcbor.x86_64 0.7.0-3.amzn2022 @System libcollection.x86_64 0.7.0-47.amzn2022 @System libcom_err.x86_64 1.45.6-5.amzn2022 @System libcomps.x86_64 0.1.18-1.amzn2022 @System libconfig.x86_64 1.7.2-7.amzn2022 @System libcurl.x86_64 7.79.1-1.amzn2022 @System libdatrie.x86_64 0.2.13-1.amzn2022 @System libdb.x86_64 5.3.28-49.amzn2022 @System libdhash.x86_64 0.5.0-47.amzn2022 @System libdnf.x86_64 0.64.0-1.amzn2022 @System libeconf.x86_64 0.4.0-1.amzn2022 @System libedit.x86_64 3.1-38.20210714cvs.amzn2022 @System libestr.x86_64 0.1.11-1.amzn2022 @System libev.x86_64 4.33-3.amzn2022 @System libevent.x86_64 2.1.12-3.amzn2022 @System libfastjson.x86_64 0.99.9-1.amzn2022 @System libfdisk.x86_64 2.36.2-1.amzn2022 @System libffi.x86_64 3.1-28.amzn2022 @System libfido2.x86_64 1.6.0-2.amzn2022 @System libgcc.x86_64 11.2.1-2.amzn2022.0.2 @System libgcrypt.x86_64 1.9.3-3.amzn2022.0.1 @System libgomp.x86_64 11.2.1-2.amzn2022.0.2 @System libgpg-error.x86_64 1.42-1.amzn2022 @System libibverbs.x86_64 37.0-1.amzn2022 @System libidn2.x86_64 2.3.2-1.amzn2022 @System libini_config.x86_64 1.3.1-47.amzn2022 @System libjpeg-turbo.x86_64 2.0.90-3.amzn2022 @System libkcapi.x86_64 1.2.1-1.amzn2022 @System libkcapi-hmaccalc.x86_64 1.2.1-1.amzn2022 @System libksba.x86_64 1.6.0-1.amzn2022 @System libldb.x86_64 2.4.1-1.amzn2022 @System libmaxminddb.x86_64 1.5.2-1.amzn2022 @System libmetalink.x86_64 0.1.3-14.amzn2022 @System libmnl.x86_64 1.0.4-13.amzn2022 @System libmodulemd.x86_64 2.13.0-2.amzn2022 @System libmount.x86_64 2.36.2-1.amzn2022 @System libmpc.x86_64 1.2.1-2.amzn2022 @System libnfsidmap.x86_64 1:2.5.4-2.rc3.amzn2022 @System libnghttp2.x86_64 1.43.0-2.amzn2022 @System libnl3.x86_64 3.5.0-6.amzn2022 @System libnsl2.x86_64 1.3.0-2.amzn2022 @System libpath_utils.x86_64 0.2.1-47.amzn2022 @System libpcap.x86_64 14:1.10.1-1.amzn2022 @System libpipeline.x86_64 1.5.3-2.amzn2022 @System libpkgconf.x86_64 1.7.3-7.amzn2022 @System libpng.x86_64 2:1.6.37-10.amzn2022 @System libpsl.x86_64 0.21.1-3.amzn2022 @System libpwquality.x86_64 1.4.4-6.amzn2022 @System libref_array.x86_64 0.1.5-47.amzn2022 @System librepo.x86_64 1.14.2-1.amzn2022 @System libreport-filesystem.noarch 2.15.2-2.amzn2022 @System librsvg2.x86_64 2.50.7-1.amzn2022 @System librsvg2-tools.x86_64 2.50.7-1.amzn2022 @System libseccomp.x86_64 2.5.3-1.amzn2022 @System libselinux.x86_64 3.2-1.amzn2022 @System libselinux-utils.x86_64 3.2-1.amzn2022 @System libsemanage.x86_64 3.2-1.amzn2022 @System libsepol.x86_64 3.2-2.amzn2022 @System libsigsegv.x86_64 2.13-2.amzn2022 @System libsmartcols.x86_64 2.36.2-1.amzn2022 @System libsodium.x86_64 1.0.18-7.amzn2022 @System libsolv.x86_64 0.7.17-3.amzn2022 @System libss.x86_64 1.45.6-5.amzn2022 @System libssh.x86_64 0.9.6-1.amzn2022 @System libssh-config.noarch 0.9.6-1.amzn2022 @System libsss_certmap.x86_64 2.5.0-1.amzn2022.0.1 @System libsss_idmap.x86_64 2.5.0-1.amzn2022.0.1 @System libsss_nss_idmap.x86_64 2.5.0-1.amzn2022.0.1 @System libstdc++.x86_64 11.2.1-2.amzn2022.0.2 @System libstdc++-devel.x86_64 11.2.1-2.amzn2022.0.2 @System libstoragemgmt.x86_64 1.9.2-4.amzn2022 @System libtalloc.x86_64 2.3.3-2.amzn2022 @System libtasn1.x86_64 4.16.0-4.amzn2022 @System libtdb.x86_64 1.4.4-3.amzn2022 @System libtevent.x86_64 0.11.0-1.amzn2022 @System libtextstyle.x86_64 0.21-4.amzn2022 @System libthai.x86_64 0.1.28-6.amzn2022 @System libtirpc.x86_64 1.3.2-0.rc1.amzn2022 @System libtool-ltdl.x86_64 2.4.6-40.amzn2022 @System libunistring.x86_64 0.9.10-10.amzn2022 @System libusbx.x86_64 1.0.24-2.amzn2022 @System libuser.x86_64 0.63-4.amzn2022 @System libutempter.x86_64 1.2.1-4.amzn2022 @System libuuid.x86_64 2.36.2-1.amzn2022 @System libuv.x86_64 1:1.42.0-2.amzn2022 @System libverto.x86_64 0.3.2-1.amzn2022 @System libverto-libev.x86_64 0.3.2-1.amzn2022 @System libxcb.x86_64 1.13.1-7.amzn2022 @System libxcrypt.x86_64 4.4.26-4.amzn2022 @System libxcrypt-devel.x86_64 4.4.26-4.amzn2022 @System libxml2.x86_64 2.9.12-4.amzn2022 @System libyaml.x86_64 0.2.5-5.amzn2022 @System libzstd.x86_64 1.5.0-1.amzn2022 @System llvm-libs.x86_64 12.0.1-1.amzn2022 @System lm_sensors-libs.x86_64 3.6.0-8.amzn2022 @System lmdb-libs.x86_64 0.9.29-1.amzn2022 @System logrotate.x86_64 3.18.0-3.amzn2022 @System lsof.x86_64 4.94.0-1.amzn2022 @System lua-libs.x86_64 5.4.3-1.amzn2022 @System lua-srpm-macros.noarch 1-4.amzn2022 @System lvm2.x86_64 2.03.11-1.amzn2022.0.1 @System lvm2-libs.x86_64 2.03.11-1.amzn2022.0.1 @System lz4-libs.x86_64 1.9.3-2.amzn2022 @System make.x86_64 1:4.3-5.amzn2022 @System man-db.x86_64 2.9.3-3.amzn2022 @System man-pages.noarch 5.10-2.amzn2022 @System mdadm.x86_64 4.1-7.amzn2022 @System microcode_ctl.x86_64 2:2.1-46.amzn2022 @System mpfr.x86_64 4.1.0-7.amzn2022 @System nano.x86_64 5.8-3.amzn2022 @System ncurses.x86_64 6.2-4.20200222.amzn2022 @System ncurses-base.noarch 6.2-4.20200222.amzn2022 @System ncurses-libs.x86_64 6.2-4.20200222.amzn2022 @System net-tools.x86_64 2.0-0.59.20160912git.amzn2022 @System nettle.x86_64 3.7.3-1.amzn2022 @System newt.x86_64 0.52.21-9.amzn2022 @System nfs-utils.x86_64 1:2.5.4-2.rc3.amzn2022 @System nim-srpm-macros.noarch 3-4.amzn2022 @System npth.x86_64 1.6-6.amzn2022 @System nspr.x86_64 4.32.0-2.amzn2022 @System nss.x86_64 3.71.0-1.amzn2022 @System nss-softokn.x86_64 3.71.0-1.amzn2022 @System nss-softokn-freebl.x86_64 3.71.0-1.amzn2022 @System nss-sysinit.x86_64 3.71.0-1.amzn2022 @System nss-util.x86_64 3.71.0-1.amzn2022 @System ntsysv.x86_64 1.15-2.amzn2022 @System numactl-libs.x86_64 2.0.14-3.amzn2022 @System ocaml-srpm-macros.noarch 6-4.amzn2022 @System openblas-srpm-macros.noarch 2-9.amzn2022 @System openldap.x86_64 2.4.57-6.amzn2022 @System openssh.x86_64 8.6p1-5.amzn2022 @System openssh-clients.x86_64 8.6p1-5.amzn2022 @System openssh-server.x86_64 8.6p1-5.amzn2022 @System openssl-libs.x86_64 1:1.1.1l-2.amzn2022 @System openssl-pkcs11.x86_64 0.4.11-2.amzn2022 @System os-prober.x86_64 1.77-7.amzn2022 @System p11-kit.x86_64 0.23.22-3.amzn2022 @System p11-kit-trust.x86_64 0.23.22-3.amzn2022 @System pam.x86_64 1.5.1-7.amzn2022 @System pango.x86_64 1.48.10-1.amzn2022 @System parted.x86_64 3.4-2.amzn2022 @System passwd.x86_64 0.80-10.amzn2022 @System pciutils.x86_64 3.7.0-3.amzn2022 @System pciutils-libs.x86_64 3.7.0-3.amzn2022 @System pcp-conf.x86_64 5.3.5-1.amzn2022 @System pcp-libs.x86_64 5.3.5-1.amzn2022 @System pcre.x86_64 8.44-3.amzn2022.1 @System pcre2.x86_64 10.36-4.amzn2022 @System pcre2-syntax.noarch 10.36-4.amzn2022 @System perl.x86_64 4:5.32.1-477.amzn2022 @System perl-Algorithm-Diff.noarch 1.2010-2.amzn2022 @System perl-Archive-Tar.noarch 2.40-1.amzn2022 @System perl-Archive-Zip.noarch 1.68-4.amzn2022 @System perl-Attribute-Handlers.noarch 1.01-477.amzn2022 @System perl-AutoLoader.noarch 5.74-477.amzn2022 @System perl-AutoSplit.noarch 5.74-477.amzn2022 @System perl-B.x86_64 1.80-477.amzn2022 @System perl-Benchmark.noarch 1.23-477.amzn2022 @System perl-CPAN.noarch 2.28-6.amzn2022 @System perl-CPAN-Meta.noarch 2.150010-458.amzn2022 @System perl-CPAN-Meta-Requirements.noarch 2.140-459.amzn2022 @System perl-CPAN-Meta-YAML.noarch 0.018-459.amzn2022 @System perl-Carp.noarch 1.50-458.amzn2022 @System perl-Class-Struct.noarch 0.66-477.amzn2022 @System perl-Compress-Bzip2.x86_64 2.28-3.amzn2022 @System perl-Compress-Raw-Bzip2.x86_64 2.101-3.amzn2022 @System perl-Compress-Raw-Lzma.x86_64 2.101-1.amzn2022 @System perl-Compress-Raw-Zlib.x86_64 2.101-3.amzn2022 @System perl-Config-Extensions.noarch 0.03-477.amzn2022 @System perl-Config-Perl-V.noarch 0.33-2.amzn2022 @System perl-DBM_Filter.noarch 0.06-477.amzn2022 @System perl-DB_File.x86_64 1.855-2.amzn2022 @System perl-Data-Dumper.x86_64 2.174-460.amzn2022 @System perl-Data-OptList.noarch 0.110-15.amzn2022 @System perl-Data-Section.noarch 0.200007-12.amzn2022 @System perl-Devel-PPPort.x86_64 3.62-2.amzn2022 @System perl-Devel-Peek.x86_64 1.28-477.amzn2022 @System perl-Devel-SelfStubber.noarch 1.06-477.amzn2022 @System perl-Devel-Size.x86_64 0.83-8.amzn2022 @System perl-Digest.noarch 1.20-1.amzn2022 @System perl-Digest-MD5.x86_64 2.58-2.amzn2022 @System perl-Digest-SHA.x86_64 1:6.02-459.amzn2022 @System perl-DirHandle.noarch 1.05-477.amzn2022 @System perl-Dumpvalue.noarch 2.27-477.amzn2022 @System perl-DynaLoader.x86_64 1.47-477.amzn2022 @System perl-Encode.x86_64 4:3.15-462.amzn2022 @System perl-Encode-devel.x86_64 4:3.15-462.amzn2022 @System perl-English.noarch 1.11-477.amzn2022 @System perl-Env.noarch 1.04-458.amzn2022 @System perl-Errno.x86_64 1.30-477.amzn2022 @System perl-Exporter.noarch 5.74-459.amzn2022 @System perl-ExtUtils-CBuilder.noarch 1:0.280236-2.amzn2022 @System perl-ExtUtils-Command.noarch 2:7.62-1.amzn2022 @System perl-ExtUtils-Constant.noarch 0.25-477.amzn2022 @System perl-ExtUtils-Embed.noarch 1.35-477.amzn2022 @System perl-ExtUtils-Install.noarch 2.20-2.amzn2022 @System perl-ExtUtils-MM-Utils.noarch 2:7.62-1.amzn2022 @System perl-ExtUtils-MakeMaker.noarch 2:7.62-1.amzn2022 @System perl-ExtUtils-Manifest.noarch 1:1.73-2.amzn2022 @System perl-ExtUtils-Miniperl.noarch 1.09-477.amzn2022 @System perl-ExtUtils-ParseXS.noarch 1:3.40-458.amzn2022 @System perl-Fcntl.x86_64 1.13-477.amzn2022 @System perl-File-Basename.noarch 2.85-477.amzn2022 @System perl-File-Compare.noarch 1.100.600-477.amzn2022 @System perl-File-Copy.noarch 2.34-477.amzn2022 @System perl-File-DosGlob.x86_64 1.12-477.amzn2022 @System perl-File-Fetch.noarch 1.00-2.amzn2022 @System perl-File-Find.noarch 1.37-477.amzn2022 @System perl-File-HomeDir.noarch 1.006-2.amzn2022 @System perl-File-Path.noarch 2.18-2.amzn2022 @System perl-File-Temp.noarch 1:0.231.100-2.amzn2022 @System perl-File-Which.noarch 1.23-8.amzn2022 @System perl-File-stat.noarch 1.09-477.amzn2022 @System perl-FileCache.noarch 1.10-477.amzn2022 @System perl-FileHandle.noarch 2.03-477.amzn2022 @System perl-Filter.x86_64 2:1.60-2.amzn2022 @System perl-Filter-Simple.noarch 0.96-458.amzn2022 @System perl-FindBin.noarch 1.51-477.amzn2022 @System perl-GDBM_File.x86_64 1.18-477.amzn2022 @System perl-Getopt-Long.noarch 1:2.52-2.amzn2022 @System perl-Getopt-Std.noarch 1.12-477.amzn2022 @System perl-HTTP-Tiny.noarch 0.078-1.amzn2022 @System perl-Hash-Util.x86_64 0.23-477.amzn2022 @System perl-Hash-Util-FieldHash.x86_64 1.20-477.amzn2022 @System perl-I18N-Collate.noarch 1.02-477.amzn2022 @System perl-I18N-LangTags.noarch 0.44-477.amzn2022 @System perl-I18N-Langinfo.x86_64 0.19-477.amzn2022 @System perl-IO.x86_64 1.43-477.amzn2022 @System perl-IO-Compress.noarch 2.102-2.amzn2022 @System perl-IO-Compress-Lzma.noarch 2.101-2.amzn2022 @System perl-IO-Socket-IP.noarch 0.41-3.amzn2022 @System perl-IO-Zlib.noarch 1:1.11-2.amzn2022 @System perl-IPC-Cmd.noarch 2:1.04-459.amzn2022 @System perl-IPC-Open3.noarch 1.21-477.amzn2022 @System perl-IPC-SysV.x86_64 2.09-2.amzn2022 @System perl-IPC-System-Simple.noarch 1.30-4.amzn2022 @System perl-Importer.noarch 0.026-2.amzn2022 @System perl-JSON-PP.noarch 1:4.06-2.amzn2022 @System perl-Locale-Maketext.noarch 1.29-459.amzn2022 @System perl-Locale-Maketext-Simple.noarch 1:0.21-477.amzn2022 @System perl-MIME-Base64.x86_64 3.16-2.amzn2022 @System perl-MRO-Compat.noarch 0.13-13.amzn2022 @System perl-Math-BigInt.noarch 1:1.9998.18-458.amzn2022 @System perl-Math-BigInt-FastCalc.x86_64 0.500.900-458.amzn2022 @System perl-Math-BigRat.noarch 0.2614-458.amzn2022 @System perl-Math-Complex.noarch 1.59-477.amzn2022 @System perl-Memoize.noarch 1.03-477.amzn2022 @System perl-Module-Build.noarch 2:0.42.31-7.amzn2022 @System perl-Module-CoreList.noarch 1:5.20211020-1.amzn2022 @System perl-Module-CoreList-tools.noarch 1:5.20211020-1.amzn2022 @System perl-Module-Load.noarch 1:0.36-2.amzn2022 @System perl-Module-Load-Conditional.noarch 0.74-2.amzn2022 @System perl-Module-Loaded.noarch 1:0.08-477.amzn2022 @System perl-Module-Metadata.noarch 1.000037-458.amzn2022 @System perl-NDBM_File.x86_64 1.15-477.amzn2022 @System perl-NEXT.noarch 0.67-477.amzn2022 @System perl-Net.noarch 1.02-477.amzn2022 @System perl-Net-Ping.noarch 2.74-3.amzn2022 @System perl-ODBM_File.x86_64 1.16-477.amzn2022 @System perl-Object-HashBase.noarch 0.009-5.amzn2022 @System perl-Opcode.x86_64 1.48-477.amzn2022 @System perl-POSIX.x86_64 1.94-477.amzn2022 @System perl-Package-Generator.noarch 1.106-21.amzn2022 @System perl-Params-Check.noarch 1:0.38-459.amzn2022 @System perl-Params-Util.x86_64 1.102-3.amzn2022 @System perl-PathTools.x86_64 3.78-459.amzn2022 @System perl-Perl-OSType.noarch 1.010-459.amzn2022 @System perl-PerlIO-via-QuotedPrint.noarch 0.09-2.amzn2022 @System perl-Pod-Checker.noarch 4:1.74-2.amzn2022 @System perl-Pod-Escapes.noarch 1:1.07-458.amzn2022 @System perl-Pod-Functions.noarch 1.13-477.amzn2022 @System perl-Pod-Html.noarch 1.25-477.amzn2022 @System perl-Pod-Perldoc.noarch 3.28.01-459.amzn2022 @System perl-Pod-Simple.noarch 1:3.42-2.amzn2022 @System perl-Pod-Usage.noarch 4:2.01-2.amzn2022 @System perl-Safe.noarch 2.41-477.amzn2022 @System perl-Scalar-List-Utils.x86_64 4:1.56-459.amzn2022 @System perl-Search-Dict.noarch 1.07-477.amzn2022 @System perl-SelectSaver.noarch 1.02-477.amzn2022 @System perl-SelfLoader.noarch 1.26-477.amzn2022 @System perl-Socket.x86_64 4:2.032-1.amzn2022 @System perl-Software-License.noarch 0.103014-10.amzn2022 @System perl-Storable.x86_64 1:3.21-458.amzn2022 @System perl-Sub-Exporter.noarch 0.987-25.amzn2022 @System perl-Sub-Install.noarch 0.928-26.amzn2022 @System perl-Symbol.noarch 1.08-477.amzn2022 @System perl-Sys-Hostname.x86_64 1.23-477.amzn2022 @System perl-Sys-Syslog.x86_64 0.36-459.amzn2022 @System perl-Term-ANSIColor.noarch 5.01-459.amzn2022 @System perl-Term-Cap.noarch 1.17-458.amzn2022 @System perl-Term-Complete.noarch 1.403-477.amzn2022 @System perl-Term-ReadLine.noarch 1.17-477.amzn2022 @System perl-Term-Table.noarch 0.015-6.amzn2022 @System perl-Test.noarch 1.31-477.amzn2022 @System perl-Test-Harness.noarch 1:3.42-459.amzn2022 @System perl-Test-Simple.noarch 3:1.302183-2.amzn2022 @System perl-Text-Abbrev.noarch 1.02-477.amzn2022 @System perl-Text-Balanced.noarch 2.04-2.amzn2022 @System perl-Text-Diff.noarch 1.45-11.amzn2022 @System perl-Text-Glob.noarch 0.11-13.amzn2022 @System perl-Text-ParseWords.noarch 3.30-458.amzn2022 @System perl-Text-Tabs+Wrap.noarch 2021.0726-1.amzn2022 @System perl-Text-Template.noarch 1.59-3.amzn2022 @System perl-Thread.noarch 3.05-477.amzn2022 @System perl-Thread-Queue.noarch 3.14-458.amzn2022 @System perl-Thread-Semaphore.noarch 2.13-477.amzn2022 @System perl-Tie.noarch 4.6-477.amzn2022 @System perl-Tie-File.noarch 1.06-477.amzn2022 @System perl-Tie-Memoize.noarch 1.1-477.amzn2022 @System perl-Tie-RefHash.noarch 1.40-2.amzn2022 @System perl-Time.noarch 1.03-477.amzn2022 @System perl-Time-HiRes.x86_64 4:1.9764-460.amzn2022 @System perl-Time-Local.noarch 2:1.300-5.amzn2022 @System perl-Time-Piece.x86_64 1.3401-477.amzn2022 @System perl-URI.noarch 5.09-1.amzn2022 @System perl-Unicode-Collate.x86_64 1.29-2.amzn2022 @System perl-Unicode-Normalize.x86_64 1.27-459.amzn2022 @System perl-Unicode-UCD.noarch 0.75-477.amzn2022 @System perl-User-pwent.noarch 1.03-477.amzn2022 @System perl-autodie.noarch 2.34-2.amzn2022 @System perl-autouse.noarch 1.11-477.amzn2022 @System perl-base.noarch 2.27-477.amzn2022 @System perl-bignum.noarch 0.51-458.amzn2022 @System perl-blib.noarch 1.07-477.amzn2022 @System perl-constant.noarch 1.33-459.amzn2022 @System perl-debugger.noarch 1.56-477.amzn2022 @System perl-deprecate.noarch 0.04-477.amzn2022 @System perl-devel.x86_64 4:5.32.1-477.amzn2022 @System perl-diagnostics.noarch 1.37-477.amzn2022 @System perl-doc.noarch 5.32.1-477.amzn2022 @System perl-encoding.x86_64 4:3.00-462.amzn2022 @System perl-encoding-warnings.noarch 0.13-477.amzn2022 @System perl-experimental.noarch 0.025-1.amzn2022 @System perl-fields.noarch 2.27-477.amzn2022 @System perl-filetest.noarch 1.03-477.amzn2022 @System perl-if.noarch 0.60.800-477.amzn2022 @System perl-inc-latest.noarch 2:0.500-18.amzn2022 @System perl-interpreter.x86_64 4:5.32.1-477.amzn2022 @System perl-less.noarch 0.03-477.amzn2022 @System perl-lib.x86_64 0.65-477.amzn2022 @System perl-libnet.noarch 3.13-2.amzn2022 @System perl-libnetcfg.noarch 4:5.32.1-477.amzn2022 @System perl-libs.x86_64 4:5.32.1-477.amzn2022 @System perl-local-lib.noarch 2.000024-11.amzn2022 @System perl-locale.noarch 1.09-477.amzn2022 @System perl-macros.noarch 4:5.32.1-477.amzn2022 @System perl-meta-notation.noarch 5.32.1-477.amzn2022 @System perl-mro.x86_64 1.23-477.amzn2022 @System perl-open.noarch 1.12-477.amzn2022 @System perl-overload.noarch 1.31-477.amzn2022 @System perl-overloading.noarch 0.02-477.amzn2022 @System perl-parent.noarch 1:0.238-458.amzn2022 @System perl-perlfaq.noarch 5.20210520-1.amzn2022 @System perl-ph.x86_64 5.32.1-477.amzn2022 @System perl-podlators.noarch 1:4.14-458.amzn2022 @System perl-sigtrap.noarch 1.09-477.amzn2022 @System perl-sort.noarch 2.04-477.amzn2022 @System perl-srpm-macros.noarch 1-39.amzn2022 @System perl-subs.noarch 1.03-477.amzn2022 @System perl-threads.x86_64 1:2.25-458.amzn2022.0.1 @System perl-threads-shared.x86_64 1.61-458.amzn2022 @System perl-utils.noarch 5.32.1-477.amzn2022 @System perl-vars.noarch 1.05-477.amzn2022 @System perl-version.x86_64 7:0.99.29-1.amzn2022 @System perl-vmsish.noarch 1.04-477.amzn2022 @System pixman.x86_64 0.40.0-3.amzn2022 @System pkgconf.x86_64 1.7.3-7.amzn2022 @System pkgconf-m4.noarch 1.7.3-7.amzn2022 @System pkgconf-pkg-config.x86_64 1.7.3-7.amzn2022 @System policycoreutils.x86_64 3.2-1.amzn2022 @System popt.x86_64 1.18-6.amzn2022 @System procps-ng.x86_64 3.3.17-1.amzn2022.1 @System protobuf-c.x86_64 1.3.3-7.amzn2022 @System psmisc.x86_64 23.4-1.amzn2022 @System publicsuffix-list-dafsa.noarch 20190417-5.amzn2022 @System python-pip-wheel.noarch 21.0.1-4.amzn2022 @System python-setuptools-wheel.noarch 53.0.0-2.amzn2022 @System python-srpm-macros.noarch 3.9-41.amzn2022 @System python3.x86_64 3.9.8-1.amzn2022 @System python3-attrs.noarch 20.3.0-2.amzn2022 @System python3-audit.x86_64 3.0.6-1.amzn2022 @System python3-babel.noarch 2.9.1-1.amzn2022 @System python3-botocore.noarch 1.20.100-1.amzn2022 @System python3-chardet.noarch 4.0.0-1.amzn2022 @System python3-colorama.noarch 0.4.4-2.amzn2022 @System python3-configobj.noarch 5.0.6-23.amzn2022 @System python3-dateutil.noarch 1:2.8.1-3.amzn2022 @System python3-dbus.x86_64 1.2.18-1.amzn2022 @System python3-distro.noarch 1.5.0-5.amzn2022 @System python3-dnf.noarch 4.9.0-1.amzn2022 @System python3-dnf-plugins-core.noarch 4.0.24-1.amzn2022 @System python3-docutils.noarch 0.16-4.amzn2022 @System python3-gpg.x86_64 1.15.1-6.amzn2022 @System python3-hawkey.x86_64 0.64.0-1.amzn2022 @System python3-idna.noarch 2.10-3.amzn2022 @System python3-jinja2.noarch 2.11.3-1.amzn2022 @System python3-jmespath.noarch 0.10.0-1.amzn2022 @System python3-jsonpatch.noarch 1.21-14.amzn2022 @System python3-jsonpointer.noarch 2.0-2.amzn2022 @System python3-jsonschema.noarch 3.2.0-9.amzn2022 @System python3-libcomps.x86_64 0.1.18-1.amzn2022 @System python3-libdnf.x86_64 0.64.0-1.amzn2022 @System python3-libs.x86_64 3.9.8-1.amzn2022 @System python3-libselinux.x86_64 3.2-1.amzn2022 @System python3-libsemanage.x86_64 3.2-1.amzn2022 @System python3-libstoragemgmt.x86_64 1.9.2-4.amzn2022 @System python3-markupsafe.x86_64 1.1.1-10.amzn2022 @System python3-oauthlib.noarch 3.0.2-9.amzn2022 @System python3-policycoreutils.noarch 3.2-1.amzn2022 @System python3-prettytable.noarch 0.7.2-25.amzn2022 @System python3-pyasn1.noarch 0.4.8-4.amzn2022 @System python3-pyparsing.noarch 2.4.7-6.amzn2022 @System python3-pyrsistent.x86_64 0.17.3-6.amzn2022 @System python3-pyserial.noarch 3.4-10.amzn2022 @System python3-pysocks.noarch 1.7.1-8.amzn2022 @System python3-pytz.noarch 2021.3-1.amzn2022 @System python3-pyyaml.x86_64 5.4.1-2.amzn2022 @System python3-requests.noarch 2.25.1-1.amzn2022 @System python3-rpm.x86_64 4.16.1.3-1.amzn2022 @System python3-rsa.noarch 4.7.2-1.amzn2022 @System python3-s3transfer.noarch 0.4.2-2.amzn2022 @System python3-setools.x86_64 4.4.0-1.amzn2022 @System python3-setuptools.noarch 53.0.0-2.amzn2022 @System python3-six.noarch 1.15.0-5.amzn2022 @System python3-urllib3.noarch 1.25.10-5.amzn2022 @System qt5-srpm-macros.noarch 5.15.2-2.amzn2022 @System quota.x86_64 1:4.06-4.amzn2022 @System quota-nls.noarch 1:4.06-4.amzn2022 @System readline.x86_64 8.1-2.amzn2022 @System rng-tools.x86_64 6.14-1.git.56626083.amzn2022.0.2 @System rootfiles.noarch 8.1-29.amzn2022 @System rpcbind.x86_64 1.2.6-0.amzn2022 @System rpm.x86_64 4.16.1.3-1.amzn2022 @System rpm-build-libs.x86_64 4.16.1.3-1.amzn2022 @System rpm-libs.x86_64 4.16.1.3-1.amzn2022 @System rpm-plugin-selinux.x86_64 4.16.1.3-1.amzn2022 @System rpm-plugin-systemd-inhibit.x86_64 4.16.1.3-1.amzn2022 @System rpm-sign-libs.x86_64 4.16.1.3-1.amzn2022 @System rsync.x86_64 3.2.3-5.amzn2022 @System rsyslog.x86_64 8.2102.0-3.amzn2022 @System rust-srpm-macros.noarch 18-1.amzn2022 @System screen.x86_64 4.8.0-5.amzn2022 @System sed.x86_64 4.8-7.amzn2022 @System selinux-policy.noarch 34.21-1.amzn2022 @System selinux-policy-targeted.noarch 34.21-1.amzn2022 @System setup.noarch 2.13.7-3.amzn2022 @System shadow-utils.x86_64 2:4.8.1-9.amzn2022 @System shared-mime-info.x86_64 2.1-2.amzn2022 @System slang.x86_64 2.3.2-9.amzn2022 @System sqlite-libs.x86_64 3.34.1-2.amzn2022 @System sssd-client.x86_64 2.5.0-1.amzn2022.0.1 @System sssd-common.x86_64 2.5.0-1.amzn2022.0.1 @System sssd-kcm.x86_64 2.5.0-1.amzn2022.0.1 @System strace.x86_64 5.14-1.amzn2022.0.1 @System sudo.x86_64 1.9.5p2-1.amzn2022 @System sysctl-defaults.noarch 1.0-1.amzn2022 @System sysstat.x86_64 12.5.4-1.amzn2022 @System system-release.noarch 2022.0.20211118-0.amzn2022 @System systemd.x86_64 248.9-1.amzn2022.0.2 @System systemd-libs.x86_64 248.9-1.amzn2022.0.2 @System systemd-networkd.x86_64 248.9-1.amzn2022.0.2 @System systemd-pam.x86_64 248.9-1.amzn2022.0.2 @System systemd-rpm-macros.noarch 248.9-1.amzn2022.0.2 @System systemd-udev.x86_64 248.9-1.amzn2022.0.2 @System systemtap-runtime.x86_64 4.5-1.amzn2022 @System systemtap-sdt-devel.x86_64 4.5-1.amzn2022 @System tar.x86_64 2:1.34-1.amzn2022 @System tbb.x86_64 2020.3-7.amzn2022 @System tcpdump.x86_64 14:4.99.1-1.amzn2022 @System tcsh.x86_64 6.22.03-2.amzn2022 @System time.x86_64 1.9-16.amzn2022 @System tpm2-tss.x86_64 3.1.0-1.amzn2022 @System tzdata.noarch 2021e-1.amzn2022 @System unzip.x86_64 6.0-50.amzn2022 @System update-motd.noarch 2.0-1.amzn2022 @System util-linux.x86_64 2.36.2-1.amzn2022 @System vim-common.x86_64 2:8.2.3582-1.amzn2022 @System vim-enhanced.x86_64 2:8.2.3582-1.amzn2022 @System vim-filesystem.noarch 2:8.2.3582-1.amzn2022 @System vim-minimal.x86_64 2:8.2.3582-1.amzn2022 @System wget.x86_64 1.21.2-2.amzn2022 @System which.x86_64 2.21-26.amzn2022 @System words.noarch 3.0-37.amzn2022 @System xfsdump.x86_64 3.1.9-4.amzn2022 @System xfsprogs.x86_64 5.13.0-2.amzn2022 @System xml-common.noarch 0.6.3-56.amzn2022 @System xz.x86_64 5.2.5-5.amzn2022 @System xz-libs.x86_64 5.2.5-5.amzn2022 @System yum.noarch 4.9.0-1.amzn2022 @System zchunk-libs.x86_64 1.1.15-1.amzn2022 @System zip.x86_64 3.0-28.amzn2022 @System zlib.x86_64 1.2.11-27.amzn2022 @System zstd.x86_64 1.5.0-1.amzn2022 @System [ec2-user@ip-172-31-47-247 ~]$ amazon linux extra みてみた コマンドありませんでした。FAQ で「No, AL2022 does not have extras.」と明言されていました。 Amazon Linux 2022 FAQs A: No, AL2022 does not have extras. For higher-level software packages like language runtimes, we will use the quarterly release where we will add major/minor updates to packages as separate namespaced packages in addition to the default package provided in the repository. For example, default Python version in Amazon Linux 2022 may be 3.8, but we will add Python 3.9 (python39) as a separate namespaced package whenever it is made available. These additional packages will closely follow their upstream release cadence and support model and their support policies can be accessed by the package manager for compliance and security use cases. Default packages will continue to be supported throughout the life of AL2022. ざっくり意訳: AL2022には extraはありません。最新パッケージは四半期毎にリポジトリに入れます。例えば、Pythonは今なら 3.8 を採用するでしょうが、別の namespaceで 3.9 も入手できるようにします。追加パッケージ提供は、リリースライフサイクルに従います。 ※ 今時点では、デフォルトで Python3.9 が入っている...という指摘はなしで。 リポジトリのバージョン固定 今時点で、動作は確認できませんでした。 マニュアルはここです。 Version locking Managing repositories and operating system updates しかし前述の通り、現時点でコマンドを打っても環境のせいか? 期待する戻りは得られませんでした。 # マニュアルにもサンプルがないので、期待はわからないが戻りがない。 [ec2-user@ip-172-31-47-247 ~]$ dnf check-release-update [ec2-user@ip-172-31-47-247 ~]$ echo $? 0 [ec2-user@ip-172-31-47-247 ~]$ 今だとリポジトリに複数バージョンが無いようなので、もう少し待ってからですかね。 最後に Preview なので今の状態で一喜一憂しても仕方ないですが、 とりあえず Amazon Linux2 とそれほど差分はないのかな。。。と思います。 amazon-linux-extras がなくなったりで、独自のお作法が減ってどちらかというと CentOS の代替的な使い方がしやすくなったかもしれませんね。 あとは個人的に。いまだに yum 頼みでしたが、そろそろ dnf に乗り換えないといけないのかなと思いました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Okta→AWSコンソールのSSO(SAML)とプロビジョニング

AWSのSSOとプロビジョニングについて OktaでAWSコンソールにSSOとプロビジョニングする方法を記述します。 ユーザープロビジョニングというとIDPでアカウントを作成するとSP(service provider)側にもアカウントが作成され同期されるという認識でしたが、AWSにおいてはSSOするときにそのセッションにロールを付与し、仮想のIAMユーザーを作成し、接続させることをプロビジョニングとしています(と私は思っています)。SSOするIAMユーザーは実際に作成されることはありませんので、セッションが切れればIAMも情報も消えます。当然、IDPでアカウント削除した後、IAMユーザーの削除し忘れも発生しません。 因みにAWS CloudTrailに証跡は残ります。 前提 AWSアカウント作成済み(IAM ユーザー、ロール、ポリシー、IDプロバイダーの作成権限が必要です。) Oktaアカウント作成済み Oktaにアプリケーションを追加 Oktaの管理画面から「Applications」>「Applications」>「Browse App Catalog」をクリックします。 検索ボックスに「aws」などと入力し「AWS Account Federation」を選択します。 「Add」をクリックします。 そのまま「Next」をクリックします。「Application Label」や「Login URL」はあとで変更可能です。 「SAML 2.0」を選択します。 その他はとりあえずそのままで「Done」をクリックします。 これでOktaにアプリケーションが作成されました。 AWSのIDプロバイダ登録に使用するためリンク先をxmlでダウンロードしておきます。 「Sign On」タブ > 「Identity Provider metadata」 AWS IAMリソース作成 IDプロバイダ作成 「IAM」 > 「アクセス管理」 > 「IDプロバイダ」 > 「プロバイダを追加」をクリックします。 「SAML」を選択 「プロバイダ名」に任意の名前(e.g. Okta) 「メタデータドキュメント」にOktaで先ほどダウンロードしたXMLメタデータをアップロードします。 「プロバイダを追加」をクリックします。 IDプロバイダにOktaが作成されました。 IAMロール作成 SSOした時の権限付与するロールを作成します。 「IAM」 > 「アクセス管理」 > 「ロール」 > 「ロールを作成」をクリックします。 「SAML 2.0 フェデレーション」を選択 「SAMLプロバイダー」に先ほど作成したOktaを選択 「プログラムによるアクセスと AWS マネジメントコンソールによるアクセスを許可する」を選択 「次のステップ:アクセス権限」をクリックします。 「次のステップ:タグ」をクリックします。 「次のステップ:確認」をクリックします。 任意の名前(e.g. OktaFederatedRole)を設定し、「ロールの作成」をクリックします。 IAMユーザー作成 OktaがAWSのロールをAPI参照するためのIAMユーザーを作成します。 「IAM」 > 「アクセス管理」 > 「ユーザー」 > 「ユーザーを追加」をクリックします。 「ユーザー名」に任意の名前(e.g. OktaSSOuser)を設定 「アクセスキー - プログラムによるアクセス」にチェック 「次のステップ:アクセス権限」をクリックします。 「既存のポリシーを直接アタッチ」を選択し、「ポリシーの作成」をクリックします。 ポリシー作成タブが開くので、JSONを以下のJSONで上書きします。「次のステップ:タグ」をクリックします。 { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "iam:ListRoles", "iam:ListAccountAliases" ], "Resource": "*" } ] } 「次のステップ:確認」をクリックします。 「名前」に任意の名前(e.g. OktaSSOCommandPolicy)を設定し、「ポリシーの作成」をクリックします。 ユーザー作成画面に戻り、作成したポリシーにチェックし「次のステップ:タグ」をクリックします。 「次のステップ:確認」をクリックします。 「ユーザーの作成」をクリックします。 「.csvのダウンロード」をクリックし、アクセスキーIDとシークレットアクセスキーをダウンロードします。 Okta SSO/プロビジョニング設定 SSO設定 AWSで先ほど作成したIDプロバイダのOktaのARNをコピーします。 Oktaのアプリ詳細画面で「Sign On」タブを開き、「Edit」をクリックします。 「Advanced Sign-on Settings」の「Identity Provider ARN (Required only for SAML SSO)」に先ほどのARNを設定し、「Save」をクリックします。 プロビジョニング設定 Oktaのアプリ詳細画面で「Provisioning」タブを開き、「Configure API Integration」をクリックします。 「Enable API integration」にチェックを入れ、「Access Key」「Secret Key」は先ほど作成したAWSユーザーのキーを設定します。「Save」をクリックします。 「Save」後、接続テストのようなものが行われ、問題なければ以下のような画面になります。「Edit」をクリックします。 「Create Users」と「Update User Attributes」にチェックをし「Save」をクリックします。 ユーザーのアサイン Oktaのアプリ詳細画面で「Assignments」タブを開き、「Assign」 > 「Assign to People」をクリックします。 モーダルウィンドウが開くので、アサインしたいユーザーの「Assing」をクリックします。 「SAML User Roles」で先ほど作成したロール(e.g. OktaFederatedRole)にチェックを付け、「Save and Go Back」をクリックします。 「Done」をクリックします。 これでAWSコンソールにSSOできるようになります。 ログインするユーザーはIAMユーザーとしては追加されません。ログイン名はOktaFederatedRole/Oktaのname属性となります。AWSへのセッションにロールを紐付けてアクセスするイメージです。 Oktaの公式手順書 今回のSSOの設定手順はアプリの詳細画面から表示できます。「View Setup Instructions」をクリックすると、英語ですが、AWS側の設定も記述された丁寧な手順書が確認できます。この記事はこの手順書に沿っています。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む