m_shige1979のささやかな抵抗と欲望の日々

プログラムの勉強をしながら学習したことや経験したことをぼそぼそと書いていきます

Github(変なおっさんの顔でるので気をつけてね)

https://github.com/mshige1979

CI/CDを試したい

CI/CDって?

wikiによると

CI / CDは、アプリケーションの構築、テスト、および展開の自動化を実施することにより、開発および運用アクティビティとチームの間のギャップを埋める。

CI/CD - Wikipedia

らしい

普段というか仕事とかではそういった環境って継続的に運用するからお金かかるってイメージなんで 自前のシェルスクリプトとかで対応しているんですよね・・・ 一部のプロジェクトで使っているようなので勉強がてら触ってみることにする

今回は触りなのでちょっとだけ

イメージ

多分、jenkinsとか使ってもいんだろうけど今回は Gitlabでやってみる

手順

gitlabのアカウント準備

gitlabアカウントにサインアップして適当なリポジトリを作成する

CD/CDよりRunner を選択

※ビルドする際にはGitlabが提供しているものがあるみたいですけど今回はマイマシンのものを設定してみる

Specific Runnersの設定を見てインストールする

インストール

一旦、ローカルへ配置

sudo curl --output ~/work/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-darwin-amd64

ディレクトリ移動

sudo mkdir -p /usr/local/bin/
admin@adminnoMacBook-Air ~ % sudo mv ~/work/gitlab-runner /usr/local/bin/.

実行権限付与

sudo chmod +x /usr/local/bin/gitlab-runner

起動

cd ~ 
gitlab-runner install
gitlab-runner start

登録

itlab-runner register --url https://gitlab.com/ --registration-token [謎のトークン]

できたの?

お試し

「.gitlab-ci.yml」を作成して画面上よりコミット

.gitlab-ci.yml file

job:
  script:
    - ls

タグつけたので無効化

なんか動いてそう

最初だから時間かかっている感じ? シンプルな結果だけどすぐには終わらなかった・・・

dockerを使いたい場合

3つほど候補があるが今回は環境がMacだったのでDocker Desktop入れました

GitLab CI/CDによるDockerイメージのビルド | GitLab

参考

GitLab RunnerでCI/CDしてみる(前編) | DevelopersIO

【GitLab】GitLab-Runnerを試用してみた - Qiita

GitLab CI/CD 発展編 ~GitLab Runnerの使い方~ | Insight Technology

Install GitLab Runner | GitLab

所感

今回はちょっとお試しなのできちんとしたことはまだやっていない もう少し勉強してWebアプリの自動デプロイなど試してみたい github-actionsもなんか似た感じのあるみたいなので見ておこう

Lambdaをコンテナイメージより作成

概要

Lambda を作成する際にコンテナイメージを使いたい

手順

1. 関数名を決める

dockerfunc01

※まだ作成はしない

2. ECR リポジトリを作成

dockerfunc01

3. 実行コードを作成(仮)

package.json

{
  "name": "dockerfunc01",
  "license": "MIT"
}

index.js

exports.handler = async (event) => {
  const result = {
    status: 200,
    message: "hello, world",
    data: event,
  };
  return result;
};

4. Dockerfile を用意

Dockerfile

FROM public.ecr.aws/lambda/nodejs:14
COPY index.js package.json  ${LAMBDA_TASK_ROOT}
CMD ["index.handler"]

5. docker build

docker build -t dockerfunc01 .

6. コンテナ起動

docker run --rm -p 9000:8080 dockerfunc01

7. 起動確認

curl -X POST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'

8. ECR ログイン

aws ecr get-login-password --profile [プロフィール] --region [リージョン] | docker login --username AWS --password-stdin ${accountId}.dkr.ecr.${region}.amazonaws.com

9. タグ付け

docker tag dockerfunc01:latest ${accountId}.dkr.ecr.${region}.amazonaws.com/dockerfunc01:latest

10. ECR Push

docker push ${accountId}.dkr.ecr.${region}.amazonaws.com/dockerfunc01:latest

11. AWS コンソールで Lambda を作成し、Docker イメージを設定

12. テスト結果

コード修正

1. コードを修正する

index.js

exports.handler = async (event) => {
  const result = {
    status: 200,
    message: "hogehoge, foofoo",
    data: event,
  };
  return result;
};

2. ビルド、最デプロイ

docker build -t dockerfunc01 .

3. タグ付け

docker tag dockerfunc01:latest ${accountId}.dkr.ecr.${region}.amazonaws.com/dockerfunc01:latest

4. ECR Push

docker push ${accountId}.dkr.ecr.${region}.amazonaws.com/dockerfunc01:latest

5. イメージを差し替え

6. 再テスト

参考

コンテナ利用者に捧げる AWS Lambda の新しい開発方式 ! - 変化を求めるデベロッパーを応援するウェブマガジン | AWS

https://jpdebug.com/p/1463020

Lambda コンテナイメージの作成 - AWS Lambda

AWS Lambda の新機能 – コンテナイメージのサポート | Amazon Web Services ブログ

公式のdockerイメージ

https://gallery.ecr.aws/lambda/

AWSで一定期間ごとにLambdaを実行する

AWS上から一定間隔でイベントを処理したい

やること

  1. Lambdaファンクションを作成
  2. トリガーに「Amazon EventBridge」を連携
  3. ルールを追加 終わり

手順

Lambdaを新規に作成

サンプルコードを実装

index.js

exports.handler = async (event) => {
    // パラメータを取得
    const result = {
        event: event,
    };
    // debuglog
    console.log(`debug: `, JSON.stringify(result, null, 2));
    return result;
};

トリガーを追加&ルールを追加

※cronは以下に修正

cron(*/5 * * * ? *)

ルールの追加設定を行う

ルールの設定画面へ移動

編集ボタンを押下

ログを確認

2022-05-02T12:25:29.677Z ce5e87e3-0604-4e0f-b33e-763e2c3cc4f9    INFO    debug:  {
    "event": {
        "event": {
            "message": "Test",
            "detail": "5分おき実行"
        }
    }
}

こんな感じ

参考

チュートリアル: CloudWatch Events を使用して AWS Lambda 関数をスケジュールする - Amazon CloudWatch Events

Amazon CloudWatch Events で AWS Lambda を定期実行する際に任意の入力パラメータを渡す - Qiita

ECSをプライベートサブネットへ配置し、ELB(ALB)よりアクセス

プライベートサブネットに配置すると

通信がインターネットに出ないため、コンテナイメージのpullもできない ため、NATGatewayを配置してやることになる

また、VPCエンドポイントを利用することも可能

イメージ

全部は書かない

記載しないこと

  1. Route53回り
  2. インターネットゲートウェイ回り
  3. ELB(ALB)回り
  4. ECSクラスター、ECSタスク

※このあたりは過去記事と同じやり方になっているので書かない

記載すること

  1. Natゲートウェイの作成・配置
  2. ECSサービスの作成

過去記事

m-shige1979.hatenablog.com m-shige1979.hatenablog.com m-shige1979.hatenablog.com m-shige1979.hatenablog.com

手順

Natゲートウェイの作成を押下

Natゲートウェイを作成する

プライベートサブネットのルートテーブルにNatゲートウェイを配置

ELBをパブリックサブネットに向けて作成

Route53へAレコードを設定

ECSクラスターやタスクを準備して、ECSサービスを構築

稼働確認

VPCエンドポイントである場合

VPCエンドポイントを利用することで対応可能らしい 料金の加算基準がわからないのでNatゲートウェイでも良いかなとはなっている blog.not75743.com ※外部との通信は限定的に許可する模様

参考資料

AWS NATゲートウェイの使い方。プライベートサブネットからインターネットへ | puti se blog

ECS(Fargate)でコンテナを起動その2(ALBを利用したルーティング&CodeDeployの下準備) - エンジニアを目指す日常ブログ

ECS+fargate+プライベートサブネットでコンテナを立ててアクセスする - not75743 blog

VPCエンドポイントを試してみた - Qiita

AWSネットワーク料金についてまとめてみた(2020年1月) - 本日も乙

プライベートサブネット内のFargateコンテナをALBにアタッチ | Awstut

denoを使ってみた

deno.land

denoって何?

ja.wikipedia.org

NodeJSの改良版みたいなイメージかも・・・

インストール

brew install deno

バージョン確認

deno -V
deno 1.20.6
%

サンプルサプリ作成

簡易Webサーバ

server.js

import { serve } from "https://deno.land/std@0.89.0/http/server.ts";
const s = serve({ port: 8000 });
console.log("http://localhost:8000/");
for await (const req of s) {
  req.respond({ body: "Hello World\n" });
}

実行

deno run --allow-net server.js

実行する際はパーミッションつけないと毎回聞いてくる

ちょっとルーティングがある版

import { Application } from "https://deno.land/x/abc@v1.3.2/mod.ts";
import { renderFile } from "https://deno.land/x/dejs@0.10.1/mod.ts";
import { readAll } from "https://deno.land/std@0.110.0/io/util.ts";

const app = new Application();

console.log("http://localhost:8080/");

app.renderer = {
  async render(name, data) {
    return renderFile(name, data).then(readAll);
  },
};

app
  .get("/", (c) => {
    return c.render("index.html");
  })
  .get("/callback", (c) => {
    console.log("-----------------");
    console.log(c);
    return "aaaa";
  })
  .get("/login", (c) => {
    return c.render("login.html");
  })
  .get("/logout", (c) => {
    return c.redirect("/login");
  })
  .start({ port: 8080 });

パッケージについて

なんか実行した際、新規のものはダウンロードされているみたいだけどどこになるのか? ↓

% deno info
DENO_DIR location: /Users/ユーザー名/Library/Caches/deno
Remote modules cache: /Users/ユーザー名/Library/Caches/deno/deps
Emitted modules cache: /Users/ユーザー名/Library/Caches/deno/gen
Language server registries cache: /Users/ユーザー名/Library/Caches/deno/registries
Origin storage: /Users/ユーザー名/Library/Caches/deno/location_data
%

所感

まだ触り始めたばかりでなんとも言えない感じ node_modulesがローカルにできなくなったことが良いか悪いかによるのかな まだ、npmやyarnを使うことが多いため、すぐに移行することはないけど少しずつwatchしていく感じ

saml認証をruby-samlライブラリを利用して自前のサーバをSPサーバとして構築

基本、前回の続きみたいなもの

m-shige1979.hatenablog.com

前回は以下のような感じで一部の処理をcognitoが一部代行

IDP側の処理はIDP側で制御するがSP側の処理でどんなデータを送信していたかなどが全く不明のため、 作成することにした

1から作成するにしてもデータ形式とかの仕様がわからない

のでライブラリを元に追いかけることにする 今回は「ruby-saml」の情報を元にexampleを探して作成

流れ

  1. SP側のエンティティIDとACS URLを決める
  2. IDPにエンティティIDとACS URLを設定し、IDPのメタデータを取得
  3. 環境変数に設定情報のデータを定義
  4. コード改修
  5. テスト

手順

1. SP側のエンティティIDとACS URLを決める

No 項目 設定値
1 エンティティID http://localhost:3000/saml/metadata
2 ASC http://localhost:3000/saml/acs

2. IDPにエンティティIDとACS URLを設定し、IDPのメタデータを取得

3. 環境変数に設定情報のデータを定義

.env.dev

SP_ISSUER  = SP用のエンティティID(例:http://localhost:3000/saml/metadata)
SP_ACS_URL = SP用のIDPの認証結果を受け取るコールバック(例:http://localhost:3000/saml/acs)
SP_LOGOUT  = SP用のログアウト用のエンドポイント(例:http://localhost:3000/saml/logout)
SP_CERT_KEY= SP用の証明書に利用したキー(例:saml/sp/private.pem)
SP_CERT    = SP用の証明書(例:saml/sp/sp.cert)

IDP_ISSUER = IDPのエンティティID(メタデータに記載)
IDP_SSO_URL= IDPのシングルサインオンURL(メタデータに記載)
IDP_SLO_URL= IDPのシングルサインアウトURL(メタデータに記載)
IDP_CERT   = IDPの証明書(例:saml/idp/idp.cert)
IDP_ID_FORMT  = IDPのIDフォーマット(例:urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress)

4. コード改修

app/models/account.rb

class Account < ActiveRecord::Base
    def self.get_saml_settings(url_base)
      # this is just for testing purposes.
      # should retrieve SAML-settings based on subdomain, IP-address, NameID or similar
      settings = OneLogin::RubySaml::Settings.new
  
      # When disabled, saml validation errors will raise an exception.
      settings.soft = true
  
      #SP section
      settings.issuer                         = ENV["SP_ISSUER"]
      settings.assertion_consumer_service_url = ENV["SP_ACS_URL"]
      settings.assertion_consumer_logout_service_url = ENV["SP_LOGOUT"]
      settings.certificate = File.read(Rails.root.join('config', ENV["SP_CERT"]))
      settings.private_key = File.read(Rails.root.join('config', ENV["SP_CERT_KEY"]))
  
      # IdP section
      settings.idp_entity_id                  = ENV["IDP_ISSUER"]
      settings.idp_sso_target_url             = ENV["IDP_SSO_URL"]
      settings.idp_slo_target_url             = ENV["IDP_SLO_URL"]
      settings.idp_cert                       = File.read(Rails.root.join('config', ENV["IDP_CERT"]))
    
      settings.name_identifier_format         = ENV["IDP_ID_FORMT"]
  
      # Security section
      settings.security[:authn_requests_signed] = true
      settings.security[:logout_requests_signed] = true
      settings.security[:logout_responses_signed] = true
      settings.security[:metadata_signed] = true
      settings.security[:digest_method] = XMLSecurity::Document::SHA256
      settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256
  
      settings
    end
  end

※証明書は任意の場所へ配置しておくこと

結果

SAMLリクエストとSAMLレスポンスについて

SAMLリクエス

まずはXML形式で作成するみたい

<samlp:AuthnRequest 
    AssertionConsumerServiceURL='http://localhost:3000/saml/acs' 
    Destination='IDP側のリクエストURL' 
    ID='任意のリクエスト文字列' 
    IssueInstant='リクスト日時(UTC)' Version='2.0' xmlns:saml='urn:oasis:names:tc:SAML:2.0:assertion' xmlns:samlp='urn:oasis:names:tc:SAML:2.0:protocol'>
    <saml:Issuer>http://localhost:3000/saml/metadata</saml:Issuer>
    <samlp:NameIDPolicy AllowCreate='true' Format='urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress'/>
</samlp:AuthnRequest>


base64で暗号化しているみたいです

[IDPのログインURL]?SAMLRequest=fZLLTsMwEEV%2FJTuvUttJA9RqKkVESJUA...

SAMLレスポンスも同じようにXML形式の物が暗号化されてくるので デコードしてから検証する感じ

成果物

github.com

環境変数とかは自前の環境のものを利用すること ※元々のサンプルとはバージョンが違うためところところ設定を追記しています

参考

GitHub - onelogin/ruby-saml: SAML SSO for Ruby
GitHub - onelogin/ruby-saml-example: Ruby example of how to use the ruby-saml gem
ruby-saml を使ったOneLogin での SAML 認証の処理シーケンスを追う - Qiita
Rails+AzureADでSAML認証のSSOを実装する

saml認証を試したのでメモ

結構長いかも・・・

saml認証ってなに?

www.okta.com

イメージ

※他の場所のリンク取ったら良くないね反省

今回は

認証にはAWSのcognitoをサービスプロバイダとして利用、
IDPにはoktaのdeveloperアカウントで用意したものを利用して連携する

できたもの

手順

1. ユーザープールを作成


多要素認証はOFF
自己登録は不要(IDP側でユーザーを管理するのでこちらでは不要)
属性検証は不要
cognitoからにする(多分、メール送信しないのでこちらにする)
ユーザープール名を設定
ホストされた認証ページはONにする
ドメインを設定する
アプリケーションクライアントを作成する際、
クライアントのシークレットは不要とする。 ※他の部分は基本デフォルト

ユーザープールの設定値を整理

ユーザープールで作成した値

No 項目名 備考
1 ユーザープール名 mshige1979-saml-test
2 ユーザープールID ap-northeast-1_abcdefdhi 値を変換
3 ドメイン https://mshige1979-saml-test.auth.ap-northeast-1.amazoncognito.com
4 アプリケーションクライアント名 mshige1979-saml-client
5 クライアント ID 1234567890abcdefghijklmnop 値を変換

Oktaで利用する値

No 項目名 備考
1 シングルサインオン URL https://mshige1979-saml-test.auth.ap-northeast-1.amazoncognito.com/saml2/idpresponse
2 Audience URI urn:amazon:cognito:sp:ap-northeast-1_abcdefdhi 値を変換
3 ATTRIBUTE (項目名)I http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
4 ATTRIBUTE (設定値)I user.email

OktaでSAMLアプリを作成する

「Applications」よりメニューを開き、「Create App Integration」を押下し起動する
SAML2.0」を選択
アプリ名を入力
SAMLのパラメータを設定する
シングルサインオン URL」、「Audience URI
属性パラメータを設定する
チェックして終わる

Oktaアプリの詳細よりメタデータURLを取得

ユーザーを割り当て


対応するユーザーを選択し、アサイ

OktaをSAML IDPとして登録する

フェデレーテッドアイデンティティプロバイダを追加
SAMLを選択
パラメータを設定

アプリケーションクライアントの設定

コールバックURLやサインアウトURLを設定する
プロバイダ、権限タイプ、スコープを設定する

エンドポイントを設定

書式

https://[ドメイン]/login?response_type=token&client_id=[クライアントID]&redirect_uri=[コールバックURL]


多分、こんな感じ

https://mshige1979-saml-test.auth.ap-northeast-1.amazoncognito.com/login?response_type=token&client_id=1234567890abcdefghijklmnop&redirect_uri=http://localhost:8080/callback



OK

ユーザー情報について

参考

Amazon Cognito ユーザープールで、Okta を SAML アイデンティティプロバイダーとして設定する