【React】react-simplemde-editor:文字入力エリア(のみ)にスクロールバーを追加する

課題

Reactでreact-simplemde-editorを導入してMarkdownエディターを作成時、文字入力エリアを固定してスクロールバーをつけたいんだがタグの中にラッピングされてしまって制御できない。

対応

開発者モードでCSSを確認したところ、どうやら↓のheightが原因らしく、こいつを外すと想定していた挙動になるっぽい。

このcssファイルは以下にあるとのことで、開いてみる。

{Reactプロジェクトフォルダ}/node_modules/easymde/dist/easymde.min.css

改行されてなくて見にくいけど、「.EasyMDEContainer .CodeMirror{」で検索してみると、あった!この赤枠の「height:auto」を削除してやる。

ついでに文字入力エリアをもう少し広くしたいので、ここのheightも300→350に変更しておく。

キャッシュが効いてると変化がわからないので、node_modulesフォルダ直下の「.cache」フォルダを丸っと削除し、npm startをし直す

無事文字入力エリアにのみスクロールバーが表示されました!

2023年10月【AWS Training】日本リージョンでサインインできない問題の解決方法

経緯

今週末にAWSの試験を受験する予定だったのですが、勉強が間に合いそうになくリスケしようとAWS Trainingにサインインした時の話です。

これそもそも動線がややこしくて、最初にアカウントを作ってサインインする時も以下の記事を参考にようやく自分の試験を管理するページに辿り着けたのですが、今回この方法ではもはやログインできない仕様変更がAWS側であったようです。

tracl.cloud

問題

最初に試験を申し込んだほんの1, 2ヶ月前まではサインアウトした状態で以下のURLにアクセスし、

AWS training and certification

右上の「サインイン」のリンクを踏むと、リージョンを選択するページが表示され、ここで日本リージョンを選択してからサインインできたのですが、

2023年10月現在、同じようにサインインをクリックすると、以下のようなログイン方法を問われるページがいきなり表示され、そのままログインするとリージョンは「全リージョン」が自動的に選択された状態となり、「日本」リージョンで試験情報を管理しているユーザーは自分のページに辿り着けないという事態となる。

キャッシュをクリアしたり、シークレットモードでやってみたりと色々試したけどこのページ遷移はどうにもならず、試験がリスケできない。やばい。

解決方法

すがる思いでAWSサポートに問い合わせてみたところ、以下のような回答が返ってきた。

The method of selecting a region for AWS training login has been changed to the "Login with Amazon". Please clear your browser's cache and refresh the login page twice before logging in. Below are the new steps to login:

  1. Access here: https://www.aws.training
  2. Click the lock icon in the address bar. It is to the left of the address.

Firefox: Select Clear cookies and site data... from the list. In the new popup window click the button labelled Remove.

Chrome: Select Cookies from the list. Click the button labelled Remove until there are no more cookies in the list.

  1. Scroll to the bottom of the page and Click on ‘Cookie preferences’
  2. In the popup make sure all three checkboxes are checked and click the orange button in the lower right to save Cookie >Preferences.
  3. Refresh the page twice, Navigate to https://www.aws.training/SignIn
  4. Click ‘Sign In’ on the left and Proceed to “Login with Amazon” with your login email address.
  5. Access your AWS Certified account by clicking on "Certified" in the top menu.

Best regards,

一応手順通りにやってみたけど、一瞬リージョンを選択するページが映るけどすぐにログイン方法選択する画面にリダイレクトされて結局変わらなかった。

が、リージョンを選択するページのURL(https://www.aws.training/SignIn)はわかった。コンマ5秒くらいの一瞬だけど、そのページは表示される。追い詰められて出てきた答えはアナログ全開の一択しかなかった。

これはもう、この一瞬のウチに日本リージョンを選択するしかない

ゴングは鳴った。まずは何度かリージョンを選択するページのURL(https://www.aws.training/SignIn)にアクセスし、ブラウザ上で「日本」リージョンのラジオボタンが表示される場所を大体覚える。そしてリージョン選択ページのURLをブラウザのURL欄に貼り付けた状態で、ラジオボタンが表示されるだろう場所にマウスのカーソルを合わせて、Enterボタンを押す。リージョン選択画面が映る一瞬のうちにマウスをクリックし、日本リージョンを選択する。

できた!4,5回ミスったがなんとか日本リージョンのラジオボタンを選択することに成功。後は普通に次のログイン方法選択のページから進めて行けば、日本リージョンを選択した状態となっており、これまでと同じように自分の試験管理ページが確認できた。

所管

今回はギリギリ日本リージョンでサインインできたけど、この様子だといつこのリージョンを選択するページ(https://www.aws.training/SignIn)自体がなくなるかもわからんなというのが残念な感想です。そもそもリージョンを選択できない仕様変更を突然実施するってどゆこと?海外系のサービスってなんでこんなに想像が行き届かないのだろうと毎度不思議ですが、訴えても届かないので、自分の身は自分で守るしかないのかなと。すでに取得した試験の記録は日本リージョンの方のアカウントにあるのですが、そこはもう証明書だけプリントアウトして捨てて、全リージョンに改めてアカウント作成し、今後はそこで試験の申込等行おうかなと思っています。

同じような問題に当たった方がいれば参考になれば幸いです。ありがとうございました。

【Java / SpringBoot】package org.springframework.web.bind.annotation does not exist even though it's defined in POM

MavenのSpringBootプロジェクトをdockerで立ち上げようとした時に以下のようなエラーが発生した。

package org.springframework.web.bind.annotation does not exist even though it's defined in POM

以下のページ内を参考に、

stackoverflow.com

pom.xmlに以下のspring-boot-starter-webを追記

(変更前)

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

(変更後)

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

無事解消された模様。以上

【Amazon Inspector】【指摘対応】apt-get upgradeがCodeBuildでエラーになる

フロントエンド/バックエンドをまとめてFargateで運用 + CICDにCodePipelineを使用してDeployするアプリをAmazon Inspectorの脆弱性診断にかけて、その指摘対応をした時の話。

指摘事項とその対応方法の確認

まずはどういう指摘があったのかをAmazon Inspectorの管理コンソール画面から確認する。今回はFargate上のアプリでECRのイメージに対するScan診断だったため、「Findings → By container repository」で対象のアプリを選択。一覧から指摘事項の管理番号のリンクをクリックすると、画面右側に指摘の詳細が表示される。

この中に「Remediation(対策)」という項目があり、ここを見ると是正にどういうアクションが必要かが記載されているので、基本的にはこの情報をもとに対応していく、という進め方になります。

今回ハマったポイント

今回のケースではLinux kernelのバージョンに関連する指摘が多く、「Remediation(対策)」に「apt-get update && apt-get upgrade」具体的なコマンドが掲載されていたので、これをそのままDockerfileに「RUN apt-get update && apt-get upgrade」と追記したところエラーとなり(「apt-get update」の方は問題ない)、何か具体的な理由も書かれていないので手探りであれこれ試行錯誤してハマりました。

解消方法

この「apt-get upgrade」はユーザー認証が必要で、そのままでは通らないらしく、以下のような記述に変更することで解消しました。※「ENV DEBIAN_FRONTEND noninteractive」をセットすることで会話モードをオフにし、「apt-get」に「-y」を付与することでユーザー認証を自動実行できる

ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && apt-get -y upgrade

Take Away

Amazon Inspectorで提示してくれている「Remediation(対策)」は、基本方針としては大いに参考にはなるけど、そのままでは解消しないケースもあり、多少の調整・試行錯誤が必要になることもある、ということでご参考に頂ければ幸いです。

以上!

【AWS CLIで構築】Lambdaを使用してEFS上のファイルをS3へ移行する

アプリのログファイルをEFSに吐いていたのですが、溜まってきたので古いファイルをS3に移行させるバッチをLambdaで作ってみた。簡易的だけど以下のような構成になります。今回は一部の既存のリソース(EFS, S3, SNS)を使用する必要があり、CloudFormationではなくAWS CLIで各リソースを作成・構築したため、実装はコマンドベース(Windows PowerShell)で紹介します。

※移行元のEFS、移行先のS3バケット、通知先のSNSトピックは既に作成済の前提となります

1. Lambdaの設定

1.1 Lambda実行Roleの作成

まずはLambdaの実行ロールを作成します。信頼Policyはdefaultの状態のままで問題ないので、以下の内容でファイルを作成し、任意のフォルダに格納します。

[my-lambda-function-trust-pol.json]

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

WindowsPowerShellを開きAWSにログイン(この手順は省略します)し、↑のファイルを格納したディレクトリまで移動します。

cd 【↑のファイルを格納したディレクトリパス】

以下のコマンドを実行し、IAM Roleを作成します。(Mac.terminalの場合は改行コードを「/」に置き換えてください)

aws iam create-role `
--role-name my-lambda-function-role `
--assume-role-policy-document file://my-lambda-function-trust-pol.json

1.2 IAM Policyの作成

Lambdaの実行ロールにAttachするIAM Policyを作成します。まずは以下のようなPolicyの内容を記述したjsonファイルを作成し、任意のフォルダに格納します。「【】」の中身は適宜入れ替えてください。

[my-lambda-function-pol.json]

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "logs:CreateLogGroup",
            "Resource": "arn:aws:logs:ap-northeast-1:【my-account-no】:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:ap-northeast-1:【my-account-no】:log-group:/aws/lambda/【my-lambda-function】:*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": "sns:Publish",
            "Resource": "arn:aws:sns:ap-northeast-1:588907989152:【my-sns-topic】"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::【my-s3-bucket】/*"
        }
    ]
}

ファイルを格納したディレクトリにいることを確認し、以下のコマンドを実行し、IAM Policyを作成します。

aws iam create-policy `
--policy-name my-lambda-function-pol `
--policy-document file://my-lambda-function-pol.json

1.3 Lamba実行ロールにPolicyを追加

1.2で作成したPolicyを含め、必要な権限を持ったPolicyを1.1で作成したIAM Roleに追加します。

aws iam attach-role-policy `
--role-name my-lambda-function-role `
--policy-arn arn:aws:iam::aws:policy/AWSLambdaExecute
aws iam attach-role-policy `
--role-name my-lambda-function-role `
--policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole
aws iam attach-role-policy `
--role-name my-lambda-function-role `
--policy-arn arn:aws:iam::aws:policy/AmazonElasticFileSystemClientReadWriteAccess
aws iam attach-role-policy `
--role-name my-lambda-function-role `
--policy-arn arn:aws:iam::【my-account-no】:policy/my-lambda-function-pol

1.4 Lambda関数の作成

1.3までで準備したLambda実行ロールを指定してLambda関数を作成します。まずはアップロードする関数自体をローカル環境に作成します。以下は「EFSのある特定のフォルダにあるzipログファイルを2週間以上前であればS3に移行する」というサンプルコードになりますが、テスト的に利用する場合はこちらをローカルの任意の場所にコピー/配置してください。

GitHub - yuichiroyamaji/efs-to-s3: Lambda function transferring file from efs to s3

コードが配置されているフォルダ上で以下コマンドを実行し、zip化します。

zip -r function.zip ./

作成したzipファイルを指定して、Lambda関数を作成します。

aws lambda create-function `
--function-name my-lambda-function `
--zip-file fileb://function.zip `
--handler lambda_function.lambda_handler `
--runtime python3.9 `
--role arn:aws:iam::【my-account-no】:role/my-lambda-function-role

1.5 Lambda関数用のSecurityGroupの作成

こちらはEFSが存在するVPCのIDを指定して、ルール自体はdefaultの状態で作成します。

aws ec2 create-security-group --group-name my-lambda-function-sg `
--description "SG for My Lambda Function" `
--vpc-id 【EFSが存在するVPC ID】

1.6 EFSと同じSubnetにLambdaを配置、Timeout、FileSystem設定でEFSのAccessPointを指定

今回EFS側のAccessPointは既に作成済であることを前提に作成手順は割愛しますが、作成手順の詳細が必要な方は以下の記事で紹介してますのでご参考下さい。Timeout値も念のため最大値の900秒に設定します。

k9s.hatenablog.jp

aws lambda update-function-configuration `
--function-name my-lamba-function `
--vpc-config SubnetIds=【EFSが配置されているSubnetID】,SecurityGroupIds=【1.5で作成したSecurityGroupID】 `
--file-system-configs Arn=【AccessPointのARN】,LocalMountPath=【Lambda側のMountPath(/mnt/dataなど)】 `
--timeout 900

1.7 (サンプルコードを利用する場合) 環境変数の設定

こちらはサンプルコードを利用する場合のみ必要となりますので、自身の関数ファイルでLambdaを作成された方はスキップしてください。

aws lambda update-function-configuration `
--function-name tci-dev-oms-efs-logs-s3 `
--environment "Variables={ `
SNS_TOPIC_ARN=【サンプルコード内:通知連絡用SNSトピックのARN, `
EFS_ROOT_PATH=【EFS側のマウントPath(/mnt/dataなど)】, `
EFS_ZIP_PATH=【ESF側でzipファイルが格納されているフォルダパス(/mnt/data/logs/zipなど)】, `
EC2_ZIP_PATH=【zipコマンドファイルのフォルダパス】, `
ENV_NAME='[開発環境]', `
S3_BUCKET=sample-bucket, `
S3_FOLDER=EFS/, `
}" 

2. EFSの設定

2.1 AccessPointの設定

今回こちらの手順は割愛します。作成手順の詳細が必要な方は以下の記事で紹介してますのでご参照ください。

k9s.hatenablog.jp

2.2 EFSのSecurityGroupのInboundルール追加

↑の記事内でも紹介していますが、今回LambdaからEFSにアクセスするにあたって、EFSのSecurityGroupのInboundルールで、Lambda側のSecurityGroupを指定してアクセスを許可してやる必要があります。

aws ec2 authorize-security-group-ingress `
    --group-id 【EFSのSecurityGroupID】 `
    --ip-permissions IpProtocol=tcp,FromPort=2049,ToPort=2049,UserIdGroupPairs='[{GroupId=【LambdaのSecurityGoupID】,Description="Allow My Lambda Function to access"}]'

3 EventBridgeの設定

3.1 Ruleの作成

ここでは毎日0:00にLambdaを呼び出すよう設定します。cron形式で設定する場合タイムゾーンUTCのため、マイナス9時間で計算して指定しています。

aws events put-rule `
--name my-lambda-function-scheduler `
--schedule-expression "cron(0 15 * * ? *)" `
--description "My Lambda Function関数を呼び出すスケジューラー"

3.2 Targetの設定

Ruleで指定した時間に起動させるLambdaを指定します。

aws events put-targets `
--rule my-lambda-function-scheduler `
--targets Id=1,Arn=【LambdaのARN】

3.3 Lambda側でEventBridgeの呼び出し許可を設定

Lambda側のリソースベースポリシーにEventBridgeのRuleを実行できる権限を付与し、トリガーを追加します。

aws lambda add-permission `
--function-name my-lambda-function `
--statement-id '1' `
--action 'lambda:InvokeFunction' `
--principal events.amazonaws.com `
--source-arn 【3.1で作成したEventBridgeのRuleのARN】

以上で必要なリソースは全て作成完了となります。EventBridgeで設定した時間になるとLambdaが起動するハズなので確認してみてください。

【AWS Lambda Layers】Unable to import module 'xxx' : No module named 'xxx'

事象

公式ドキュメント通り、PythonでLambda Layersを作成して、既存の関数にAttachして実行したところ、以下のようなErrorが発生した。

Unable to import module 'xxx' : No module named 'xxx'

あれ。何か間違えたかな、とフォルダ構成を確認し、Lambdaの実行環境でフォルダの所在を確認してみてもちゃんとある。

print(os.listdir('/opt/python'))
xxx.py

これ、ほんとになんでかわからず散々あれこれ検証してみたところ、どうも「/opt/python」にパスが通ってないっぽい。その筋で検索すると以下のような記事が出てきた。

dev.classmethod.jp

すぐに環境変数を確認してみるとPYTHONPATH定義している。 これだ。。 これはわからなんだ。。公式ドキュメントとかにも特に言及されておらず、想像もできなかった。

解決方法

↑の記事では使うなと書いていたけど、既存の関数で既に定義されていてそれはそのままにしておきたかったので、単純に「/opt/python」を追加したところ、うまく読み込めるようになった。