この記事は株式会社ビットキー 情シス Advent Calendar 2023 の1日目の投稿です。
はじめまして。株式会社ビットキーの日浦です。
2019年に入社し、現在はビットキーで情シス的な仕事を担当しています。
SREやCREなどサービス開発や運用に関わってきた経験をCorporate領域にどう活かすか試行錯誤中です。
前提
ビットキーでは従業者のID管理にOktaを利用しています。機能が多く使いこなすのが大変なのですが、日々いろいろ試しています。
アクセスコントロールに関するセキュリティポリシーを考える際、SaaS側の機能有無に依存せず、Okta上の設定のみで完結できるという点が最も大きな利用メリットかなと考えています。
ex)SaaS側に接続元IPアドレス制限の機能がなくても、Okta側のアクセスポリシーで設定・制御可能
しかし、IDaaS製品を利用してID管理を進める際、やはりSAML認証が使えないSaaSというものが存在します。最上位のEnterpriseプランでしか使えなかったり、そもそもSAML認証に対応していなかったり。
そのような場合、ID/PWを従業員間で共有する「共有アカウント」を使うことがあるのですが、管理運用上の課題が存在します。
共有アカウントの課題
- ID/PWを「教える」という運用が前提となるため安全性が低い
- 「誰が使えるのか」を正確に管理するのが実質不可能
- SaaS側の機能有無に依存することになる
ex)組織のセキュリティポリシーとして「オフィス外からのアクセス」を禁止している場合など
こういった場合、OktaではSecure Web Authentication(以下SWA)を利用することで組織のセキュリティポリシーに沿った安全なSSOを利用することができます。
Secure Web Authentication(SWA)とは
むちゃくちゃ噛み砕いて説明すると、ID/PWで認証するアプリについてOkta上でSAML認証のアプリと同じように振る舞わせることができるようになり、Oktaの認証によるSSOも可能になります。使い勝手はほぼ他の認証方法のアプリと大差ありません。
- アプリとして登録できる
- ユーザーやグループがアサインできる
- 認証ポリシーにより、アクセスコントロールが可能
- ID/PWをOkta上に登録することで、SaaS上でのユーザーによる入力をスキップできる
SWAを使ってみる
設定方法や使い方は下記のクラウドネイティヴさんのブログがとてもわかりやすいです。
Okta上でSSOログインするアプリとの違いを具体的に説明すると、登録時に下記のような工程が必要になります。
- ブラウザの拡張機能で
Okta Browser Plugin
をインストールする - Okta管理画面上にアプリを登録する際に下記を登録する
- ID/PW
- IDパスワードを入力するHTMLのセレクタ
- ログインボタンのHTMLのセレクタ
※ SaaSのログイン画面をDevelopet Toolなどで確認が必要
1.については全社員を対象にChromeの管理機能やJamf PROから一度やってしまえば良いのですが、2.のDOMの調査についてはアプリを登録する際に毎回実施する必要があります。
SWAをTerraformでIaCしてみる
そんな便利極まりないSWAですが、残念ながら私のような怠惰な情シスには画面からポチポチ登録していく作業がしんどいときもあります。
画面から登録状況を確認するのもめんどくさいし、他の人が管理画面で既存のSWAアプリ参照しながら真似して登録するのも大変なので、再現性を高めるためにソースコードで管理しましょう。
OktaをTerraformで構成管理する方法については下記の記事が大変参考になりますので、まずは写経することをおすすめします。
以下は Sample App
という架空のSaaSにSWAでログインするための記載例です。
ソースコード
まずは okta_app_shared_credentials
を定義します。
resource "okta_app_shared_credentials" "sample_app" {
label = "Sample App" // 任意の名前
status = "ACTIVE"
username_field = "#email" // ID入力部分のセレクタ
password_field = "#password" // PW入力部分のセレクタ
button_field = "#button" // ログインボタン入力部分のセレクタ
shared_username = "example@example.com" // ログインID
shared_password = var.PW_SAMPLE_APP // パスワード
url = "https://example.com/" // ログインページのURL
logo = "../terraform/assets/example.png"
admin_note = "created by terraform. サンプルアプリだよ"
}
次に、このSaaSを利用できる人を定義するOktaグループと、グループルールを記述します
ビットキーでは、原則アプリケーションに直接人やグループをアサインせず、「App_Assign_hogehoge」というアサイン用のグループを作成しています。
resource "okta_group" "App_Assign_sample_app" {
name = "App_Assign_sample_app"
description = "created by terraform"
}
resource "okta_app_group_assignments" "App_Assign_sample_app" {
app_id = okta_app_shared_credentials.sample_app.id
group {
id = okta_group.App_Assign_sample_app.id
priority = 1
}
}
resource "okta_group_rule" "App_Assign_sample_app" {
name = "App_Assign_sample_app"
status = "ACTIVE"
group_assignments = [
"${okta_group.App_Assign_sample_app.id}"
]
expression_type = "urn:okta:expression:1.0"
expression_value = join("", [
"isMemberOfAnyGroup(",
"\"${okta_group.team-corporate-engineering.id}\"",
")"
])
}
App_Assign_sample_app
というグループを作成し、 okta_app_group_assignments
でグループを Sample App
にアサインします。
okta_group_rule
も同時に作成し、デフォルトでアサインするグループ( Sample App
にSSOできるグループ)を指定しています。
ビットキーでは「組織図から作成されたグループ」か「Okta Access Requestによってアサインされるグループ」を利用することが多いです。
最後に、 Sample App
にログインするためのPWを変数として定義します。
variable "PW_SAMPLE_APP" {
sensitive = true
}
ソースコード上に直接パスワードを記載することもできますが、クレデンシャル情報をソースコードに記載するのは避けましょう。
ただしTerraformの仕様上、stateには記録されているため下記を行うようにしましょう。
-
ローカルには保存せず、AWS S3などに保存し、そちらのアクセス管理を徹底する
-
.gitignoreに記述しておく
.tfstate
.tfstate.
※ Oktaを利用したAWSのアクセス管理は後日書くかも
また、sesitive = true
を指定することでplanやapplyの出力でもマスキングされ、CI/CDの実行環境でも出力されないようになります。
以下、詳細は割愛しますが、GitHub Actionsのサンプルコードです。
name: terraform-plan
on:
pull_request:
paths:
- ".github/workflows/tf-plan.yml"
- "terraform/**"
workflow_dispatch:
env:
TF_VAR_OKTA_API_TOKEN: ${{ secrets.OKTA_API_TOKEN }}
AWS_ROLE_ARN: ${{ secrets.AWS_ROLE_ARN }}
AWS_DEFAULT_REGION: ap-northeast-1
TF_VAR_PW_SAMPLE_APP: ${{ secrets.PW_SAMPLE_APP }}
jobs:
terraform-plan:
name: Terraform plan
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
id-token: write
contents: read
defaults:
run:
shell: bash
working-directory: ./terraform/
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-region: ${{ env.AWS_DEFAULT_REGION }}
role-to-assume: ${{ env.AWS_ROLE_ARN }}
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
- name: Init Terraform
run: |
terraform init
- name: Test Terraform
run: |
terraform plan
TF_VAR_PW_SAMPLE_APP: ${{ secrets.PW_SAMPLE_APP }}
GitHubの環境変数に Sample App
のログインパスワードを格納することで、CI/CDのタイミングで読み込んで、Oktaにapplyしてくれるようになります。
Terraformで管理するメリット
そもそも登録がめんどくさい
コード化されているため、コピペでSWAアプリケーションを量産可能です。
同一のSaaSに対して複数の共有アカウントが存在する場合などに、登録作業や定期的なパスワードの変更作業のコストが激減します。
個人的にはSWA特有のセレクタを調べる作業を毎回やらなくて良い点やSaaS側の変更によりセレクタを更新しないといけない場合などにコード化の恩恵を感じています。
ログイン情報をOktaで見ないといけない、というのがめんどくさい
地味な不満ではありますが、Oktaの管理画面は必要な情報に到達するまでの遷移数や読み込みの待ち時間が長いと感じているので、ローカルでサクッと確認できるのはありがたいです。
ID/PWというモロな認証情報をどうやって管理する?
ビットキーにおいてはSaaSの共有アカウントのIDは基本的にメーリスグループを利用しています。当然ですがやろうと思えばパスワードと同じようにGitHubの環境変数に隠蔽することは可能です。
継続課題(2023年11月現在)
- SWAはGoogle Authenticatorのような多要素認証(MFA)でワンタイムパスワードを要求するタイプのSaaSには対応していません。
- ただし、登録メールアドレスに対してログインの都度、認証コードを送ってくるタイプのサービスについては、メーリスに届いた認証メールをSlackなど利用者が見れる場所に転送する運用は可能です。
- TerraformのOkta Providerが未対応なため、ID入力後に別ページに遷移してパスワードを入力するタイプのログインには対応できません
- ただし、Oktaの管理画面上から
Template Two Page Plugin App
を選んで手動作成することでSSOを実現することは可能です。
- ただし、Oktaの管理画面上から
最後に
OktaのSWAを利用することで、今までID/PWを共有して運用してたSaaSを安全に利用できるようになりました。Oktaの認証ポリシーの制御対象にもなっているので「社用PCからしかログインできない」状態も実現可能です。
また、利用者目線ではIDもパスワード「知る必要がない」ことも安全性の向上に繋がっています。
Oktaへの登録がめんどくさいSaaSもコード化することで容易にOkta Applicationを量産できるようになるため、Okta SWAを利用する際は是非Terraformの利用を検討してみてください。