TPM を使った Microsoft Entra ID 認証

TPM を使った強固な Microsoft Entra ID(旧称 Azure Active Directory)への認証を構築する方法を紹介します。

はじめに

サイバーディフェンス研究所では長年蓄積したペネトレーションテストの経験値を元に、真に実効性のあるゼロトラストソリューション「PIV GATEWAY™」の研究開発を行っています。 PIV GATEWAY™ はサプライチェーン対策に欠かせない TPM(Trusted Platform Module)を使ったデバイスとユーザーを統合したハードウェアレベルの認証を実現し、さらに NGAC(Next Generation Access Control)属性ベースアクセス制御を組み合わせることにより情報資産を強力に保護します。

PIV GATEWAY™ 研究開発の一環として TPM を仮想スマートカード化し Microsoft Entra ID へ認証する方法を検証しましたので、本稿ではその方法を紹介いたします。 TPM は低価格かつ最近の PC には必ずと言っていいほど搭載されているので、他のセキュリティデバイスと比較して導入コストが安く済むという明確なアドバンテージがあると思われます。 PIV GATEWAY™ で TPM を採用するのはコスト以外のメリットもあるからなのですが、またの機会にご紹介できればと思います。

おおまかな手順は次の通りです:

  1. TPM 仮想スマートカードを作成する
  2. クライアント証明書を発行する
  3. TPM 仮想スマートカードに証明書を登録する
  4. Microsoft Entra 証明書ベースの認証を構成する

準備

本稿では Linux 上で OpenSSL を使って認証局(Certification Authority: CA)を構築します(Windows + OpenSSL でも Windows + PowerShell でも出来そうですが、私が Linux 民のため🙏🙇)。

バージョン 7 以上の VirtualBox に適当な Linux と Windows 11 の仮想マシンをご用意ください。 Windows 11 の方は TPM 2.0 が必要です。

検証用の Microsoft Entra ID も作成します。無償の Microsoft Entra ID Free で構いません。 本稿ではドメイン名を tpmcbatest.onmicrosoft.com として作成しました。

TPM 仮想スマートカードで認証するためのユーザーも作成しておきます。 本稿では、ユーザープリンシパル名(UPN)を user1@tpmcbatest.onmicrosoft.com として作成しました。

TPM 仮想スマートカードを作成する

Windows 上で次のコマンドを実行し、TPM 仮想スマートカードを作成します。 今回は簡単化のため PIN、PUK、AdminKey をそれぞれデフォルト値としています。 実用を検討の際は真面目なやつでお願いします🙏

tpmvscmgr.exe create /name TestVSC /pin default /puk default /adminkey default /generate

実行例:

> tpmvscmgr.exe create /name TestVSC /pin default /puk default /adminkey default /generate
Using default PIN: 12345678
Using default PUK: 12345678
Using default Admin Key: 010203040506070801020304050607080102030405060708
Creating TPM Smart Card...
Initializing the Virtual Smart Card component...
Creating the Virtual Smart Card component...
Initializing the Virtual Smart Card Simulator...
Creating the Virtual Smart Card Simulator...
Initializing the Virtual Smart Card Reader...
Creating the Virtual Smart Card Reader...
Waiting for TPM Smart Card Device...
Authenticating to the TPM Smart Card...
Generating filesystem on the TPM Smart Card...
TPM Smart Card created.
Smart Card Reader Device Instance ID = ROOT\SMARTCARDREADER\0000

参考 URL:

クライアント証明書を発行する

公式の 仮想スマート カードの概要: チュートリアル ガイド の手順では、TPM 仮想スマートカード向けクライアント証明書発行には Active Directory ドメインサービス(AD DS) および Active Directory 証明書サービス(AD CS)の利用が前提になっています。
これらをセキュアに運用するには極めて高度な専門知識が要求されたり、PIV GATEWAY™ ではサプライチェーン対策に対応した PIV GATEWAY CA に AD CS の役割を担わせたかったりする事情から、本稿では Active Directory を使用しない方法でクライアント証明書を発行します。
このあたりに興味がわいた方は Certified Pre-Owned Abusing Active Directory Certificate Services で検索してみてください。

CSR の作成

Windows 上で証明書署名要求(Certificate Signing Request: CSR)ファイルを作成します。

次の内容で request.inf という名前のファイルを作成してください。

[Version]
Signature="$Windows NT$"

[NewRequest]
KeySpec = 1
KeyLength = 2048
HashAlgorithm = SHA256
Exportable = FALSE
MachineKeySet = TRUE
SMIME = False
PrivateKeyArchive = FALSE
UserProtected = FALSE
UseExistingKeySet = FALSE
ProviderName = "Microsoft Base Smart Card Crypto Provider"
ProviderType = 12
RequestType = PKCS10
KeyUsage = 0xa0

request.inf ファイルを作成したディレクトリで、次のコマンドを実行します(要管理者権限)。

certreq -new request.inf certreq.txt

PIN の入力を求められるので入力します。デフォルトのままなら 12345678 です。

CSR の確認

ここはスキップして構いません。 どんな CSR ファイルが作られたのか見て見るだけです。

作成した certreq.txt の中身を確認します。

-----BEGIN NEW CERTIFICATE REQUEST-----
MIIDQTCCAikCAQAwADCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAI4X
8dN8OSu19G8ABFPrdTMW8MtJKDnXcCJ/pWK25ANYPrzFdPLaBdYs4m4QQVbJ57XP
zAlAnil9V6uLNvP6tXSuRaBEYPzp6CSlTeFrXB6m4oK46VuHoDLHAtCEk87KNlCh
sxXMQrn0KM8NFqj4ZKUhv92BjNwen8TVyqYn+ouzGU104YmRTcp7hVpQA7NRAgza
A0OMTjPgbTfAbELwrA4prBBedKjSFX0ooiLbT7PMP4Nm1jpAwNi5gYNru3wfD71e
s8/57tNUyGDTykjEKc6SlpUxGKScTY3beWwagxOQXAguJMFqXsNZ0sF6Bl0idID8
8mf9UoUZW/pSFaPwylsCAwEAAaCB+zAcBgorBgEEAYI3DQIDMQ4WDDEwLjAuMjI2
MjEuMjAvBgkrBgEEAYI3FRQxIjAgAgEJDAV3aW4xMQwLd2luMTFcdXNlcjEMB2Nl
cnRyZXEwPgYJKoZIhvcNAQkOMTEwLzAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0OBBYE
FP0wITcyPnzIwjxT3YxPgmyP98KVMGoGCisGAQQBgjcNAgIxXDBaAgEBHlIATQBp
AGMAcgBvAHMAbwBmAHQAIABCAGEAcwBlACAAUwBtAGEAcgB0ACAAQwBhAHIAZAAg
AEMAcgB5AHAAdABvACAAUAByAG8AdgBpAGQAZQByAwEAMA0GCSqGSIb3DQEBCwUA
A4IBAQAoU/56WFt+kGT4fw/x8cKcZ/roKiQTnzjo5rXnhaKUtp3apnc7mh0pzclq
0jeQ21mOhF9OzsTXAR5cjb4SHv43avKyzgnSBEFbyacO8lF76sqS+krg1VGQ0G+O
5jRd9mGvm8iOEOCzBVx3F/ZPfL8XWz61+rkyVGc63NV9dGJEiqeQJ4S9bfkIQkMH
zOIcY+GMMi2EjHflnL02qaHdHu9Bm5v+iwVg9ng8zQnu7IaSaKf6V8YHXWn6qota
GjcfPIh5nuQACvNZ4qg1KdbxLHlk3k8bJLyXBhbeiADjH0+w9Z35kAleZvoHNN/P
WkT2KoctDSelJpPKC9xk0NKJLt+9
-----END NEW CERTIFICATE REQUEST-----

この状態で読める方は皆無かと思われますので、openssl コマンドで表示します。

openssl req -text -noout -in certreq.txt

Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: 
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:8e:17:f1:d3:7c:39:2b:b5:f4:6f:00:04:53:eb:
                    75:33:16:f0:cb:49:28:39:d7:70:22:7f:a5:62:b6:
                    e4:03:58:3e:bc:c5:74:f2:da:05:d6:2c:e2:6e:10:
                    41:56:c9:e7:b5:cf:cc:09:40:9e:29:7d:57:ab:8b:
                    36:f3:fa:b5:74:ae:45:a0:44:60:fc:e9:e8:24:a5:
                    4d:e1:6b:5c:1e:a6:e2:82:b8:e9:5b:87:a0:32:c7:
                    02:d0:84:93:ce:ca:36:50:a1:b3:15:cc:42:b9:f4:
                    28:cf:0d:16:a8:f8:64:a5:21:bf:dd:81:8c:dc:1e:
                    9f:c4:d5:ca:a6:27:fa:8b:b3:19:4d:74:e1:89:91:
                    4d:ca:7b:85:5a:50:03:b3:51:02:0c:da:03:43:8c:
                    4e:33:e0:6d:37:c0:6c:42:f0:ac:0e:29:ac:10:5e:
                    74:a8:d2:15:7d:28:a2:22:db:4f:b3:cc:3f:83:66:
                    d6:3a:40:c0:d8:b9:81:83:6b:bb:7c:1f:0f:bd:5e:
                    b3:cf:f9:ee:d3:54:c8:60:d3:ca:48:c4:29:ce:92:
                    96:95:31:18:a4:9c:4d:8d:db:79:6c:1a:83:13:90:
                    5c:08:2e:24:c1:6a:5e:c3:59:d2:c1:7a:06:5d:22:
                    74:80:fc:f2:67:fd:52:85:19:5b:fa:52:15:a3:f0:
                    ca:5b
                Exponent: 65537 (0x10001)
        Attributes:
            1.3.6.1.4.1.311.13.2.3   :10.0.22621.2
            1.3.6.1.4.1.311.21.20    :unable to print attribute
            1.3.6.1.4.1.311.13.2.2   :unable to print attribute
            Requested Extensions:
                X509v3 Key Usage: critical
                    Digital Signature, Key Encipherment
                X509v3 Subject Key Identifier: 
                    FD:30:21:37:32:3E:7C:C8:C2:3C:53:DD:8C:4F:82:6C:8F:F7:C2:95
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        28:53:fe:7a:58:5b:7e:90:64:f8:7f:0f:f1:f1:c2:9c:67:fa:
        e8:2a:24:13:9f:38:e8:e6:b5:e7:85:a2:94:b6:9d:da:a6:77:
        3b:9a:1d:29:cd:c9:6a:d2:37:90:db:59:8e:84:5f:4e:ce:c4:
        d7:01:1e:5c:8d:be:12:1e:fe:37:6a:f2:b2:ce:09:d2:04:41:
        5b:c9:a7:0e:f2:51:7b:ea:ca:92:fa:4a:e0:d5:51:90:d0:6f:
        8e:e6:34:5d:f6:61:af:9b:c8:8e:10:e0:b3:05:5c:77:17:f6:
        4f:7c:bf:17:5b:3e:b5:fa:b9:32:54:67:3a:dc:d5:7d:74:62:
        44:8a:a7:90:27:84:bd:6d:f9:08:42:43:07:cc:e2:1c:63:e1:
        8c:32:2d:84:8c:77:e5:9c:bd:36:a9:a1:dd:1e:ef:41:9b:9b:
        fe:8b:05:60:f6:78:3c:cd:09:ee:ec:86:92:68:a7:fa:57:c6:
        07:5d:69:fa:aa:8b:5a:1a:37:1f:3c:88:79:9e:e4:00:0a:f3:
        59:e2:a8:35:29:d6:f1:2c:79:64:de:4f:1b:24:bc:97:06:16:
        de:88:00:e3:1f:4f:b0:f5:9d:f9:90:09:5e:66:fa:07:34:df:
        cf:5a:44:f6:2a:87:2d:0d:27:a5:26:93:ca:0b:dc:64:d0:d2:
        89:2e:df:bd

認証局を構築する

ここからしばらく Linux というか OpenSSL の作業になります。

次の内容で ca.conf という名前のファイルを作成してください。

[default]
name = ca
default_ca = ca_default
name_opt = utf8,esc_ctrl,multiline,lname,align

[ca_dn]
commonName = TPM CBA Test CA

[ca_default]
home = pki
database = $home/db/index
serial = $home/db/serial
crlnumber = $home/db/crlnumber
certificate = $home/$name.cer
private_key = $home/$name.key
RANDFILE = $home/random
new_certs_dir = $home/certs
unique_subject = no
default_md = sha256
default_days = 365
default_crl_days = 30
policy = policy_c_o_match
copy_extensions = none

[policy_c_o_match]
commonName = supplied

[req]
encrypt_key = yes
default_md = sha256
utf8 = yes
string_mask = utf8only
prompt = no
distinguished_name = ca_dn
req_extensions = ca_ext

[ca_ext]
basicConstraints = critical,CA:true
subjectKeyIdentifier = hash
keyUsage = critical,keyCertSign,cRLSign

[client_ext]
keyUsage = critical,digitalSignature
extendedKeyUsage = msSmartcardLogin,clientAuth
authorityKeyIdentifier = keyid:always
subjectKeyIdentifier = hash
basicConstraints = critical,CA:false
subjectAltName = @client_san

[client_san]
otherName = msUPN;UTF8:$ENV::UPN

次のコマンドを実行して認証局を構築します。

export UPN=''

mkdir -p pki/{certs,db}
touch pki/db/index
openssl rand -hex 16 > pki/db/serial
echo 1001 > pki/db/crlnumber

openssl ecparam -out pki/ca.key -name prime256v1 -genkey
openssl req -new -config ca.conf -key pki/ca.key -out pki/ca.csr
openssl ca -batch -selfsign -config ca.conf -in pki/ca.csr -out pki/ca.cer -extensions ca_ext

次のようなディレクトリ構造になりました。

$ tree
.
├── ca.conf
└── pki
    ├── ca.cer
    ├── ca.csr
    ├── ca.key
    ├── certs
    │   └── 83B10171358F37C05AE4ABF6DCD3BB03.pem
    └── db
        ├── crlnumber
        ├── index
        ├── index.attr
        ├── index.old
        ├── serial
        └── serial.old

4 directories, 11 files

設定ファイルやコマンドの解説は致しませんが、知りたくなった方のためにありがたい無償の電子書籍を紹介いたします(最近改版された有償版の方の書籍もとてもオススメです)。

本稿では簡単化のため省略していますが、実運用の際は証明書の失効に対応する必要があります。 また、認証局の鍵はハードウェアトークン内部で生成するのがよいでしょう。

証明書を発行する

証明書を発行する準備が整いました。 CSR ファイル(certreq.txt)を ca.conf ファイルと同じディレクトリにコピー後、次のコマンドを実行します。 export UPN='user1@tpmcbatest.onmicrosoft.com' の部分は Microsoft Entra ID に作成したユーザーの UPN に合わせて変更してください。

export UPN='user1@tpmcbatest.onmicrosoft.com'
openssl ca -batch -config ca.conf -extensions client_ext -in certreq.txt -out user1.cer -subj "/CN=${UPN}"

実行例:

$ openssl ca -batch -config ca.conf -extensions client_ext -in certreq.txt -out user1.cer -subj "/CN=${UPN}"                      
Using configuration from ca.conf
Check that the request matches the signature
Signature ok
Certificate Details:
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            83:b1:01:71:35:8f:37:c0:5a:e4:ab:f6:dc:d3:bb:04
        Issuer:
            commonName                = TPM CBA Test CA
        Validity
            Not Before: Dec  7 09:27:31 2023 GMT
            Not After : Dec  6 09:27:31 2024 GMT
        Subject:
            commonName                = user1@tpmcbatest.onmicrosoft.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:8e:17:f1:d3:7c:39:2b:b5:f4:6f:00:04:53:eb:
                    75:33:16:f0:cb:49:28:39:d7:70:22:7f:a5:62:b6:
                    e4:03:58:3e:bc:c5:74:f2:da:05:d6:2c:e2:6e:10:
                    41:56:c9:e7:b5:cf:cc:09:40:9e:29:7d:57:ab:8b:
                    36:f3:fa:b5:74:ae:45:a0:44:60:fc:e9:e8:24:a5:
                    4d:e1:6b:5c:1e:a6:e2:82:b8:e9:5b:87:a0:32:c7:
                    02:d0:84:93:ce:ca:36:50:a1:b3:15:cc:42:b9:f4:
                    28:cf:0d:16:a8:f8:64:a5:21:bf:dd:81:8c:dc:1e:
                    9f:c4:d5:ca:a6:27:fa:8b:b3:19:4d:74:e1:89:91:
                    4d:ca:7b:85:5a:50:03:b3:51:02:0c:da:03:43:8c:
                    4e:33:e0:6d:37:c0:6c:42:f0:ac:0e:29:ac:10:5e:
                    74:a8:d2:15:7d:28:a2:22:db:4f:b3:cc:3f:83:66:
                    d6:3a:40:c0:d8:b9:81:83:6b:bb:7c:1f:0f:bd:5e:
                    b3:cf:f9:ee:d3:54:c8:60:d3:ca:48:c4:29:ce:92:
                    96:95:31:18:a4:9c:4d:8d:db:79:6c:1a:83:13:90:
                    5c:08:2e:24:c1:6a:5e:c3:59:d2:c1:7a:06:5d:22:
                    74:80:fc:f2:67:fd:52:85:19:5b:fa:52:15:a3:f0:
                    ca:5b
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature
            X509v3 Extended Key Usage: 
                Microsoft Smartcard Login, TLS Web Client Authentication
            X509v3 Authority Key Identifier: 
                AC:FE:76:39:A4:34:2B:69:5B:B5:50:5B:F0:8F:AF:E8:E9:DD:B7:D1
            X509v3 Subject Key Identifier: 
                FD:30:21:37:32:3E:7C:C8:C2:3C:53:DD:8C:4F:82:6C:8F:F7:C2:95
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Subject Alternative Name: 
                othername: UPN::user1@tpmcbatest.onmicrosoft.com
Certificate is to be certified until Dec  6 09:27:31 2024 GMT (365 days)

Write out database with 1 new entries
Database updated

$ tree
.
├── ca.conf
├── certreq.txt
├── pki
│   ├── ca.cer
│   ├── ca.csr
│   ├── ca.key
│   ├── certs
│   │   ├── 83B10171358F37C05AE4ABF6DCD3BB03.pem
│   │   └── 83B10171358F37C05AE4ABF6DCD3BB04.pem
│   └── db
│       ├── crlnumber
│       ├── index
│       ├── index.attr
│       ├── index.attr.old
│       ├── index.old
│       ├── serial
│       └── serial.old
└── user1.cer

4 directories, 15 files

今回の Linux というか OpenSSL 作業はこれにてオシマイとなります。

TPM 仮想スマートカードに証明書を登録する

作成した認証局のルート証明書ファイル ca.cer と、クライアント証明書ファイル user1.cer を Windows へコピーしてください。

まずは ca.cer を信頼されたルート証明機関として登録します。

その次に、次のコマンドでクライアント証明書を登録します(要管理者権限)。

certreq -accept user1.cer

実行例

> certreq -accept user1.cer
Installed Certificate:
  Serial Number: 83b10171358f37c05ae4abf6dcd3bb04
  Subject: CN=user1@tpmcbatest.onmicrosoft.com (Other Name:Principal Name=user1@tpmcbatest.onmicrosoft.com)
  NotBefore: 12/7/2023 6:27 PM
  NotAfter: 12/6/2024 6:27 PM
  Thumbprint: c3ee600c4be94d31ae611e39b4de7f44b04c60b5

Windows 側の準備がほぼ整いました。

Microsoft Entra 証明書ベースの認証を構成する

Microsoft Entra ID 側にも作成した認証局を信頼してもらう必要があり、そのような設定をしていきます。

Microsoft Entra ID > セキュリティ > 証明機関 の順に画面を開き ca.cer ファイルをアップロードします。 本稿は簡単化のためルート CA のみですが、中間 CA を作った場合は別々にアップロードします(中間 CA の場合、ルートCA:いいえ を選択)。

Microsoft Entra ID > セキュリティ > 認証方法 > 証明書ベースの認証 から Microsoft Entra 証明書ベースの認証を有効化します。 本稿では簡単化のためすべてのユーザーに対して適用しますが、ロックアウトの危険があるのでグループ単位で実施するようにしてください。

Microsoft Entra ID > セキュリティ > 認証方法 > 証明書ベースの認証 > 構成 から、証明書ベースの認証を多要素認証とみなすよう設定します。 このような設定が必要なのは、Microsoft Entra ID 側からはクライアント証明書のセキュリティレベル(PIN が必須なのかどうか、ハードウェアトークンが使用されているのかどうかなど)が不明なためだと思われます。 PIN 無しのハードウェアトークンや秘密鍵が容易に抽出可能な PKCS #12(PFX)では所持要素しか満たせないため 単一要素認証 が適当です。

いざ、実食🍴

ここまでお疲れ様でした。苦労が報われる時です。

Edge ブラウザを起動し https://login.microsoftonline.com へアクセスします。

証明書認証を選択

認証に使用する証明書を選択

成功 👍🍖🙌

本稿でのクライアント証明書と Entra ユーザーの紐付けは図のようになっています。 より厳密な紐付けについて興味のある方は、ユーザー名のバインド ポリシーについてを参照ください。

認証がうまくいかない場合、数分待つと解決するかもしれませぬ☕。 アップロードした認証局証明書が反映されるまで時間がかかることがあるようです。

ブラウザを使った Microsoft Entra 証明書ベースの認証は certauth.login.microsoftonline.com ドメインとの mTLS(Mutual Transport Layer Security)認証です。 ネットワーク機器やアンチウイルスによる TLS(SSL)インスペクションが有効な場合は認証出来ない点に注意が必要です。

おかわり🍚

仕込みにかかった時間に対して、味わう時間のなんと短いことか..。宇宙の真理を垣間見たような気分に浸りつつ、もう少し続けます。

Microsoft Entra ID に参加した Windows 端末では、Windows への対話型ログオンも証明書ベースの認証にしたいですよね。 サインインオプションでセキュリティデバイスを選択すると、TPM 仮想スマートカードを使った証明書ベースの認証ができます。

少し残念なことに 2023 年 12 月現在、Microsoft Entra ID へデバイスを参加させる際に証明書ベースの認証を選択すると、エラーが発生してしまい Microsoft Entra ID へ参加させることができません。 パスワード認証を完全に無効化したい場合は、一時アクセスパスなど他の認証方法も併用する必要がありそうです。

ブラウザと対話型ログオンの違い

ブラウザの場合は certauth.login.microsoftonline.com ドメインとの mTLS(Mutual Transport Layer Security)認証でしたが、Windows への対話型ログオンは違っていた、という点にも少しだけ触れておきたいと思います。

対話型ログオンでは certauth.login.microsoftonline.com への通信自体が発生せず、login.microsoftonline.com と OAuth2 および WebAuthn を組み合わせたような認証方式を取っているように見受けられました(詳細は調べていません🙇)。

対話型ログオンはブラウザよりも自由度が高く、一歩先を行くモダンな実装になっているような気が致します。mTLS ではないので、TLS(SSL)インスペクションの影響を受けないことが期待できます。

mTLS ではないのでプロキシツールで通信内容も見れる

また、ブラウザの場合はクライアント証明書と Entra ユーザーの紐付けは Microsoft Entra ID の設定通りでしたが、対話型ログオンでは証明書の EKU(Extended Key Usage)に Microsoft Smartcard Login が必要でした。他にも相違点があるのではないかと予想しています。Kerberos PKINIT に近しい仕様になっているのかもしれません。

おわりに

TPM を仮想スマートカード化し Microsoft Entra ID へ認証する方法と、現状把握しているいくつかの注意点について紹介しました。

絶賛開発中の PIV GATEWAY™ ですが、今後も認証認可に関わる技術情報や製品情報をお届けしていきたいと思います。 製品に関する情報などは当社ホームページお問合せフォームからお気軽にお声がけ頂ければ幸いです。 既に PIV GATEWAY CA および TPM の販売を開始しております。

今年も大変お世話になりました。

© 2016 - 2024 DARK MATTER / Built with Hugo / Theme Stack designed by Jimmy