fishシェルメモ
変数展開
波括弧はいらない。
echo "My current directory is $PWD" # => My current directory is /Users/hogehoge/
Rails API モードを利用しつつ、jb view でヘルパーを使いたい
対象のコントローラでヘルパーをinclude
してあげる。
class PostsController < ApplicationController # ここ include ActionController::Helpers helper PostsHelper def index end end
Next.jsでContentSecurityPolicyを設定する
ContentSecurityPolicyの概要と、とりあえずの設定内容については下記サイトと記事を読む。 設定内容は下記サイトの Strict CSP ページでおすすめされている内容にする。
express
アプリをラップしてミドルウェアを追加するコードを書く。ソースコードはほぼここで書かれているもの。next.js/examples/with-strict-csp
/* eslint @typescript-eslint/no-var-requires: 0 */ const helmet = require('helmet'); const uuidv4 = require('uuid/v4'); module.exports = function csp(app) { // Create a nonce on every request and make it available to other middleware app.use((req, res, next) => { res.locals.nonce = Buffer.from(uuidv4()).toString('base64'); next(); }); const nonce = (req, res) => `'nonce-${res.locals.nonce}'`; const scriptSrc = [nonce, "'strict-dynamic'", "'unsafe-inline'", 'https:']; // In dev we allow 'unsafe-eval', so HMR doesn't trigger the CSP if (process.env.NODE_ENV !== 'production') { scriptSrc.push("'unsafe-eval'"); } const baseDirectives = { baseUri: ["'none'"], objectSrc: ["'none'"], scriptSrc, }; const directives = process.env.NODE_ENV === 'production' ? { ...baseDirectives, reportUri: process.env.REPORT_URI } : baseDirectives; app.use( helmet({ contentSecurityPolicy: { directives, reportOnly: true, }, }), ); };
インラインスクリプトを許可するけど、nonceトークンを見て確認する感じ。server.js
で実行する。
const csp = require('./csp'); app.prepare().then(() => { const server = express(); csp(server); // ... }
_document.tsx
でnonce
の設定をする。とりあえずテストだからany
で対応。
static async getInitialProps(ctx: any) { const initialProps = await Document.getInitialProps(ctx); const { nonce } = ctx.res.locals; // 追加 return { ...initialProps, nonce }; } render() { const { nonce } = this.props as any; // 追加 とりあえず any で return ( <Html> <Head /> <body> <Main /> <NextScript nonce={nonce} /> // 追加 </body> </Html> ); }
プライベートサブネットにあるECSのログをCloudWatchで見たい
ECSをプライベートサブネットに設置したが、Nat gatewaysを削除してインターネットから遮断したところ、CloudWatchのログも見れなくなった。 インターネットへの接続無しにCloudWatchへのログ送信方法を調べたところ、VPC Endpointを設定すれば送信できるようだ。 VPC Endpointはプライベートなネットワークを利用してAWS各サービスと接続できるみたい。
このドキュメントに沿って設置。セキュリティグループはVPCから443ポートのアクセスを受けることができるようにする。
https://docs.aws.amazon.com/AmazonECS/latest/developerguide/vpc-endpoints.html
設置サービスは下記4つ。
- com.amazonaws.ap-northeast-1.logs
- com.amazonaws.ap-northeast-1.ecs
- com.amazonaws.ap-northeast-1.ecs-agent
- com.amazonaws.ap-northeast-1.ecs-telemetry
ログが送信されるようになった。
SSHで多段接続
いつも忘れるので。.ssh/config
にこんな感じで書いてあげればいける。
Host mng HostName x.xxx.x.xxx Port 22 User username IdentityFile ~/.ssh/id_rsa Host frontend HostName x.xxx.x.xxx Port 22 User username IdentityFile ~/.ssh/id_rsa ProxyCommand ssh -W %h:%p mng
AWSのNAT Gatewaysが高いので、Rubyで開始と終了のスクリプトを書いて、こまめに止める
Nat Gatewaysを利用する際は以下の3ステップがある。
- 固定IPを allocate する
- gateway を作る
- route を作る
この3ステップをスクリプトで書く。
作成時
require 'aws-sdk-ec2' require 'retryable' require 'yaml' def set_env @env = YAML.load(File.read('./env.yml')) puts "set env" end def set_ec2_client @client ||= Aws::EC2::Client.new( access_key_id: @env['access_key_id'], secret_access_key: @env['secret_access_key'] ) puts "set ec2 client" end def allocate_address @allocate_address_result = @client.allocate_address puts "address allocated" end def create_nat_gateway @create_nat_gateway_result = @client.create_nat_gateway({ allocation_id: @allocate_address_result.allocation_id, subnet_id: @env["public_subnet_id"], }) puts "nat gateway created" end def create_route # ception_cb を設定しないと 3 回失敗しても例外が発生しないため exception_cb = proc {} # nat gateway が作成されるまで時間がかかるため Retryable.retryable(tries: 3, on: Aws::EC2::Errors::InvalidGatewayIDNotFound, sleep: 30, exception_cb: exception_cb) do puts 'creating' @client.create_route({ destination_cidr_block: "0.0.0.0/0", gateway_id: @create_nat_gateway_result.nat_gateway.nat_gateway_id, route_table_id: @env["route_table_id"], }) puts "route created" end end def main set_env set_ec2_client allocate_address create_nat_gateway create_route end main
削除時
require 'aws-sdk-ec2' require 'retryable' require 'yaml' def set_env @env = YAML.load(File.read('./env.yml')) puts "set env" end def set_ec2_client @client ||= Aws::EC2::Client.new( access_key_id: @env['access_key_id'], secret_access_key: @env['secret_access_key'] ) puts "set ec2 client" end def delete_route resp = @client.describe_route_tables({ route_table_ids: [@env["route_table_id"]] }) @nat_gateway_id = resp.route_tables.first.routes.detect { |route| route.destination_cidr_block === "0.0.0.0/0" }.nat_gateway_id @client.delete_route({ destination_cidr_block: "0.0.0.0/0", dry_run: false, route_table_id: @env["route_table_id"], }) puts "route deleted" end def delete_nat_gateway @allocation_id = @client.describe_nat_gateways.first.nat_gateways.detect do |gateway| gateway&.nat_gateway_id === @nat_gateway_id end.nat_gateway_addresses.first.allocation_id @client.delete_nat_gateway({ nat_gateway_id: @nat_gateway_id, }) puts "nat gateway deleted" end def release_elastic_ip # ception_cb を設定しないと 3 回失敗しても例外が発生しないため exception_cb = proc {} # nat gateway が削除されるまで時間がかかるため Retryable.retryable(tries: 6, sleep: 30, exception_cb: exception_cb) do puts 'releasing' @client.release_address({ allocation_id: @allocation_id, }) puts "public ip released" end end def main set_env set_ec2_client delete_route delete_nat_gateway release_elastic_ip end main
時間課金だけでなく転送料金もあった気がすので、本当に安くなるのか1,2ヶ月こまめに止めてチェックしてみる。