LoginSignup
1
0

Jenkinsで2段階認証コードを取得できるようにしてみた

Last updated at Posted at 2023-12-23

この記事はmisskey.dev ユーザー Advent Calendar 2023の24日目の記事です! メリークリスマス🎉

はじめに

検証に関する業務でログインが必要な外部サービスを利用することがある。検証用のアカウントをよりセキュアな状態で運用したいけど、2段階認証を利用すると複数人でのアクセスがめんどくさくなりそう。なので社内の人なら誰でも使える方法でトークンが生成できるようにしたくなった。社内専用のGoogle Authenticatorを用意する的な感じ。

やりたかったこと

2段階認証で要求されるTOTPのトークンを社内で利用しているJenkinsで取得できるようにする

与えられたシークレットからトークンを生成できるようにする

Google Authenticatorなどで使われているTOTP(Time-based One-time Password)はシークレット+現在時刻から認証トークンを生成する手法らしい。ちょっと調べたらPythonでこれをいい感じにできる素敵なライブラリpyotpがあったのでこれを使ってシークレットからトークンを作るコードをちまっと書いた。

totp_gen.py
import sys
import pyotp

secret = sys.argv[1]
print(pyotp.TOTP(secret).now())

実行するとこんな感じでトークンが出力される。

❯ python totp_gen.py I65VU7K5ZQL7WB4E
286263

このTOTP MFA Authentication Challengeというページでトークンが正常に生成できているかお試しすることができる。👈ログイン成功ヨシ!

Dockerで実行できるようにする

JenkinsにDocker連携プラグインを入れているとDockerfileを指定して最初からdockerで実行してくれるので、とりあえずこのコードだけが動く環境のDockerfileを書く。pyotpがあればいいので簡単じゃ。

FROM python:3.11-alpine3.18

RUN pip install --upgrade pip pyotp

Jenkinsジョブを組み立てる

Jenkinsジョブの中身をJenkinsfileで設定することができるのすてき、もっと使ってください先輩

Jenkinsfile
pipeline {
    agent {
      dockerfile {
        filename 'Dockerfile'
      }
    }
    parameters {
        choice choices: ['hoge', 'fuga'], description: 'ログインするユーザーID', name: 'USERID'
    }
    stages {
      stage('Generate OTP'){
        steps {
          script {
            sh "echo ${USERID}"
            withCredentials([
                string(
                  credentialsId: "2FA_${USERID}", 
                  variable: 'secret')]) {
              def result = sh script: 'python totp_gen.py ${secret} || echo error', returnStdout: true
              currentBuild.displayName = "${result} : ${USERID}"
            }
          }
        }
      }
    }
}

特記するとしたら3点。

  1. 前述のとおりDocker Pipelineがあればagentにdockerfileやimageを指定しておくと最初からそのコンテナでビルドしてくれるので、dockerfileをリポジトリルートからのパスで指定した
  2. 実行時のパラメーターでトークンを生成するアカウントを指定できるように設定、トークン生成時にはパラメーターのアカウント名を使って認証情報からシークレットを引っ張り出すようにした
  3. 実行完了時、ビルドの表示名が"{トークン} : {ユーザーID}"となるようにした

ここで3つのファイルtotp_gen.py, Dockerfile, Jenkinsfileを突っ込んだgitリポジトリを社内のgitサーバーをにpushした。

Jenkins側の準備をする

2FAのシークレットを認証情報に登録する

外部サービスでの2FA認証設定時に表示されるsecretをJenkinsのCredentialsにsecret textとして登録。Jenkinsfileと不整合が起こらないようにIDを2FA_{外部サービスのid}にした。もし設定時にQRコードしか表示されない場合はQRコードを読み取れば中にシークレットが入ってる。

Jenkinsジョブを登録する

新規ジョブ作成から、新しくパイプラインのジョブを作成。ジョブの設定に移行したら、一番下のパイプラインの定義を"Pipeline script from SCM"にしてさっきのファイルがあるリポジトリを指定して保存。

完成!

作成したジョブで"パラメーター付きビルド"を実行すると、数秒でビルド履歴にこういうのが現れる。
スクリーンショット 2023-12-24 0.16.36.png
実際にログインするときは直前にこのジョブを実行しておいて、いざ求められたらビルド履歴を確認するって感じで使うことができる:thumbsup:
実行にかかる時間も気にならないレベルのようで、いまのところクレームはない。
スクリーンショット 2023-12-24 0.20.28.png

おわりに

実際に構想してから完成まで2時間もかからなかった。こういうことをサクサクできるようにしてくれるPythonのライブラリ群やdockerのすごさとありがたみを感じました。スクショのため手元に環境を再現するのにちょっと時間がかかったのでやや遅刻です(いいわけ)
Qiitadonの滅亡からしばらく経ちましてmisskey.devもいいところです。運営継続とアドカレ企画に感謝ァ...それではよいクリスマスを〜

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0