我如何计算OpenID Connect服务器的指纹?

11

在创建OpenID Connect提供程序(例如AWS)时,我需要为连接器指定一个Thumbprint。它是什么,我怎样才能获取它?

例如,来自如何在不使用密钥的情况下连接GitHub操作和AWS部署?

resource "aws_iam_openid_connect_provider" "github" {
  url = "https://token.actions.githubusercontent.com"
  client_id_list = [
    "githubactions",
  ]
  thumbprint_list = [
    "6938fd4d98bab03faadb97b34396831e3780aea1",
  ]
}
2个回答

18

一个Open ID Connector的指纹是主机公钥证书的SHA1哈希值。要计算它,您需要获取服务的证书,然后使用像openssl这样的工具来计算哈希值。

考虑为GitHub Actions的GitHub OpenID连接器创建一个指纹https://token.actions.githubusercontent.com(例如,因为您有兴趣将GitHub Actions与AWS连接起来)。

您可以运行以下脚本来计算指纹:

% HOST=$(curl https://vstoken.actions.githubusercontent.com/.well-known/openid-configuration \
| jq -r '.jwks_uri | split("/")[2]')
% echo | openssl s_client -servername $HOST -showcerts -connect $HOST:443 2> /dev/null \
| sed -n -e '/BEGIN/h' -e '/BEGIN/,/END/H' -e '$x' -e '$p' | tail +2 \
| openssl x509 -fingerprint -noout \
| sed -e "s/.*=//" -e "s/://g" \
| tr "ABCDEF" "abcdef"
6938fd4d98bab03faadb97b34396831e3780aea1

这到底是什么意思呢?

OpenID Configuration 'well known service'(公认服务),位于https://.../.well-known/openid-configuration,提供了已知服务的列表,其中包括.jwks_uri,其格式如下:

{
  "issuer": "https://token.actions.githubusercontent.com",
  "jwks_uri": "https://token.actions.githubusercontent.com/.well-known/jwks",
  "subject_types_supported": [
    "public",
    "pairwise"
  ],
  "response_types_supported": [
    "id_token"
  ],
  "claims_supported": [
    "sub",
    "aud",
    "exp",
    "iat",
    "iss",
    "jti",
    "nbf",
    "ref",
    "repository",
    "repository_owner",
    "run_id",
    "run_number",
    "run_attempt",
    "actor",
    "workflow",
    "head_ref",
    "base_ref",
    "event_name",
    "ref_type",
    "environment",
    "job_workflow_ref"
  ],
  "id_token_signing_alg_values_supported": [
    "RS256"
  ],
  "scopes_supported": [
    "openid"
  ]
}

在这种情况下,它告诉客户端要连接到Json Web Key Service URI的主机位于https://token.actions.githubusercontent.com/.well-known/jwks,但是我们只需要(用于SSL证书)的是主机名token.actions.githubusercontent.com。我们可以使用JQ将其传输到split("/")函数,并获取[2]元素,而在本例中,它只是主机名。
在此示例中,主机名与我们最初查询的相同,但也可能不同。
从主机获取证书可以使用OpenSSL;我们使用openssl s_client -servername $HOST -showcerts -connect $HOST:443建立到主机的TLS连接并转储其证书。由于我们实际上不需要发送任何数据,因此我们通过echo的输出来启动会话通信。
这将导致类似于以下输出:
CONNECTED(00000005)
---
Certificate chain
 0 s:/C=US/ST=California/L=San Francisco/O=GitHub, Inc./CN=*.actions.githubusercontent.com
   i:/C=US/O=DigiCert Inc/CN=DigiCert TLS RSA SHA256 2020 CA1
-----BEGIN CERTIFICATE-----
MIIG9jCCBd6gAwIBAgIQCFCR4fqbkQJJbzQZsc87qzANBgkqhkiG9w0BAQsFADBP
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMSkwJwYDVQQDEyBE
aWdpQ2VydCBUTFMgUlNBIFNIQTI1NiAyMDIwIENBMTAeFw0yMjAxMTEwMDAwMDBa
Fw0yMzAxMTEyMzU5NTlaMHsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9y
bmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRUwEwYDVQQKEwxHaXRIdWIsIElu
Yy4xKDAmBgNVBAMMHyouYWN0aW9ucy5naXRodWJ1c2VyY29udGVudC5jb20wggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCcHl5GgNgXYUI5Zz085Ar9wSiI
gdDnOkaXof2u3pcJ1138Tlz6aheVqXfJ8MOAups0LTr9j/dTHAGWKQz0qdyUdYIJ
FwiOlkmphoP+a4xVJXbdVVN7qvmfV8f0YnG5oGVyx9hDl/30JReVIYPbC8JNSiIW
2jMYnjqPu41tPclNNroW9K8gJUzT/WE4LRHohOmR1GbC1xQ8YlFS6pFs+Xuznou8
TzO8PsXRdaDe/7pYZgR/Otv5XLY5siCBraMuxtj1g4Z/Tz8d2Z+sMPIxtHZjxmcu
LPfIix6cARSpJFgGF7Yh9vgLK9jEkgfuU1Nnshv7S6ylIn5SfHNToQjCRSPJAgMB
AAGjggOgMIIDnDAfBgNVHSMEGDAWgBS3a6LqqKqEjHnqtNoPmLLFlXa59DAdBgNV
HQ4EFgQUibMM9Yecb/WbuZDkxiGVR39k0QMwSQYDVR0RBEIwQIIfKi5hY3Rpb25z
LmdpdGh1YnVzZXJjb250ZW50LmNvbYIdYWN0aW9ucy5naXRodWJ1c2VyY29udGVu
dC5jb20wDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF
BQcDAjCBjwYDVR0fBIGHMIGEMECgPqA8hjpodHRwOi8vY3JsMy5kaWdpY2VydC5j
b20vRGlnaUNlcnRUTFNSU0FTSEEyNTYyMDIwQ0ExLTQuY3JsMECgPqA8hjpodHRw
Oi8vY3JsNC5kaWdpY2VydC5jb20vRGlnaUNlcnRUTFNSU0FTSEEyNTYyMDIwQ0Ex
LTQuY3JsMD4GA1UdIAQ3MDUwMwYGZ4EMAQICMCkwJwYIKwYBBQUHAgEWG2h0dHA6
Ly93d3cuZGlnaWNlcnQuY29tL0NQUzB/BggrBgEFBQcBAQRzMHEwJAYIKwYBBQUH
MAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBJBggrBgEFBQcwAoY9aHR0cDov
L2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VExTUlNBU0hBMjU2MjAyMENB
MS0xLmNydDAMBgNVHRMBAf8EAjAAMIIBfQYKKwYBBAHWeQIEAgSCAW0EggFpAWcA
dQCt9776fP8QyIudPZwePhhqtGcpXc+xDCTKhYY069yCigAAAX5IjyPvAAAEAwBG
MEQCIDxMGruNl33xLmOdh2UdMxA3aiuIX3vgeXSuXRce6sqBAiApoOxk2sfxfZdw
cMxXuM0B8bfgGiQ7IlG14wRa7KQioAB3ADXPGRu/sWxXvw+tTG1Cy7u2JyAmUeo/
4SrvqAPDO9ZMAAABfkiPI8kAAAQDAEgwRgIhAJJmNVWqVfFlQLdX8sbbQ9VmJA5K
28ldvwLQpnJopgFzAiEAsGYoIzVOBazT96kGYIuJ3k+Zya7PsFtPVyUbOom55PcA
dQCzc3cH4YRQ+GOG1gWp3BEJSnktsWcMC4fc8AMOeTalmgAAAX5IjyPnAAAEAwBG
MEQCIE0NMqwPjqYJwxYqrh7CVueH1rWvKYvRj8cvv3fr7Ku5AiBGFfeJ+Nsy3VCW
TAih+ito29SvJ0TJrDsyHy3PhkmZ6jANBgkqhkiG9w0BAQsFAAOCAQEAih09kwU8
8j/R3/xDkV/2Td/ZbgzUPrrjnMqL32Kv8zqPb0AnaOZbA9XqMuQimLDPqr7fTtKR
BRhXStaNT5s7zZm3g9P+Xsxl2XSiuTbR0Y9MOmfgWA0Jv3vw8zq/etdGBrV0stQ/
JB2GKteYl9hP7eOj0xaNg/ylaCDONG084lqVlugggmsW9RgN3zAESmALahezuzlN
G5asPhNDCIRyo3mm0hHCV4/Kvoura/bGVkc7Wkk6q/cplN5VCSq9wYk2ugEaxsc1
YeqXpxQtRVJTF/UtuNpWS+Tp1COx3DiaoTjCmEImSzYarfZ7QIMR9opxJEPAB52h
s/oLX5ruUXwvIw==
-----END CERTIFICATE-----
 1 s:/C=US/O=DigiCert Inc/CN=DigiCert TLS RSA SHA256 2020 CA1
   i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA
-----BEGIN CERTIFICATE-----
MIIE6jCCA9KgAwIBAgIQCjUI1VwpKwF9+K1lwA/35DANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
QTAeFw0yMDA5MjQwMDAwMDBaFw0zMDA5MjMyMzU5NTlaME8xCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxKTAnBgNVBAMTIERpZ2lDZXJ0IFRMUyBS
U0EgU0hBMjU2IDIwMjAgQ0ExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEAwUuzZUdwvN1PWNvsnO3DZuUfMRNUrUpmRh8sCuxkB+Uu3Ny5CiDt3+PE0J6a
qXodgojlEVbbHp9YwlHnLDQNLtKS4VbL8Xlfs7uHyiUDe5pSQWYQYE9XE0nw6Ddn
g9/n00tnTCJRpt8OmRDtV1F0JuJ9x8piLhMbfyOIJVNvwTRYAIuE//i+p1hJInuW
raKImxW8oHzf6VGo1bDtN+I2tIJLYrVJmuzHZ9bjPvXj1hJeRPG/cUJ9WIQDgLGB
Afr5yjK7tI4nhyfFK3TUqNaX3sNk+crOU6JWvHgXjkkDKa77SU+kFbnO8lwZV21r
eacroicgE7XQPUDTITAHk+qZ9QIDAQABo4IBrjCCAaowHQYDVR0OBBYEFLdrouqo
qoSMeeq02g+YssWVdrn0MB8GA1UdIwQYMBaAFAPeUDVW0Uy7ZvCj4hsbw5eyPdFV
MA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw
EgYDVR0TAQH/BAgwBgEB/wIBADB2BggrBgEFBQcBAQRqMGgwJAYIKwYBBQUHMAGG
GGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBABggrBgEFBQcwAoY0aHR0cDovL2Nh
Y2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xvYmFsUm9vdENBLmNydDB7BgNV
HR8EdDByMDegNaAzhjFodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRH
bG9iYWxSb290Q0EuY3JsMDegNaAzhjFodHRwOi8vY3JsNC5kaWdpY2VydC5jb20v
RGlnaUNlcnRHbG9iYWxSb290Q0EuY3JsMDAGA1UdIAQpMCcwBwYFZ4EMAQEwCAYG
Z4EMAQIBMAgGBmeBDAECAjAIBgZngQwBAgMwDQYJKoZIhvcNAQELBQADggEBAHer
t3onPa679n/gWlbJhKrKW3EX3SJH/E6f7tDBpATho+vFScH90cnfjK+URSxGKqNj
OSD5nkoklEHIqdninFQFBstcHL4AGw+oWv8Zu2XHFq8hVt1hBcnpj5h232sb0HIM
ULkwKXq/YFkQZhM6LawVEWwtIwwCPgU7/uWhnOKK24fXSuhe50gG66sSmvKvhMNb
g0qZgYOrAKHKCjxMoiWJKiKnpPMzTFuMLhoClw+dj20tlQj7T9rxkTgl4ZxuYRiH
as6xuwAwapu3r9rxxZf+ingkquqTgLozZXq8oXfpf2kUCwA/d5KxTVtzhwoT0JzI
8ks5T1KESaZMkE4f97Q=
-----END CERTIFICATE-----
---
Server certificate
subject=/C=US/ST=California/L=San Francisco/O=GitHub, Inc./CN=*.actions.githubusercontent.com
issuer=/C=US/O=DigiCert Inc/CN=DigiCert TLS RSA SHA256 2020 CA1
---
No client certificate CA names sent
Server Temp Key: ECDH, P-384, 384 bits
---
SSL handshake has read 3571 bytes and written 398 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES256-GCM-SHA384
    Session-ID: 223C0000364B663D9E1AD1A1287F2F351C1E6D66075F206C8802B43EC6110B7A
    Session-ID-ctx: 
    Master-Key: BBA59654810DE8EF29C2CEBB9CD1D4B886D2FF89359F24A664B31B7F71E7F1CFE719734548216CFC626EC39498EC4BE9
    Start Time: 1642416883
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
---

这里会输出一些额外的信息到stderr,但我们不需要它,所以使用2> /dev/null将其重定向到空设备。

我们真正需要的内容只是BEGIN和END之间的内容,特别是最后一个。如果你安装了tac,一种简单的方法是将其倒序排列,打印出证书END和BEGIN之间的内容,然后停止; 然后再次使用tac反转。

由于在macOS上不存在tac,因此可以使用本地的sed来执行此操作:

  • sed -n -- 运行sed,但默认情况下不打印任何输出
    • -e '/BEGIN/h' -- 当您看到BEGIN时,将 sed 保持缓冲区 设置为该行
    • -e '/BEGIN/,/END/H' -- 对于BEGIN和END之间的所有行,将它们附加到保持缓冲区(h设置值,H将其附加,但在这里我们最终得到两个BEGIN
    • -e '$x' -e '$p' -- 当您到达文件结尾($)时,交换保持缓冲区和输出缓冲区(x),然后将其打印出来 (p)
  • tail +2 -- 从第二行开始打印,以避免上面的重复BEGIN
  • openssl x509 -fingerprint -noout -- 将输出管道到openssl,它将给出一个指纹结果,格式为SHA1 Fingerprint = 69:38:FD:4D:98:BA:B0:3F:AA:DB:97:B3:43:96:83:1E:37:80:AE:A1
  • sed -e "s/.*=//" -e "s/://g" -- 删除等于号(=)之前的所有内容,然后删除输出中的所有冒号(:)
  • tr "ABCDEF" "abcdef" -- 将 A 替换为 a,将 B 替换为 b 等等(在技术上不需要,但使它看起来不那么大声喊叫)。
这个操作的最终结果是指纹码,即6938fd4d98bab03faadb97b34396831e3780aea1,在配置OpenID客户端时可以使用,例如在如何在不使用秘密密钥的情况下连接GitHub操作和AWS部署中。请注意,GitHub(无意中)最近更新了它们的指纹码,因此结果已经从a031c46782e6e6c662c2c87c76da9aa62ccabd8e更改为6938fd4d98bab03faadb97b34396831e3780aea1

这是否意味着当该证书过期并发布新证书时,整个系统会崩溃? - Gabriel Acosta
如果有任何更改,GitHub很可能会宣布,并且您可以提前进行指纹验证。但是,如果您没有这样做,或者它刚刚发生了变化,那么它将停止工作。 - AlBlue
非常好奇 - 为什么这里是 vstoken 而不是只有 token? - skeggse
1
当 GitHub 处于 beta 环境时,它使用了 vstoken,因为它来自 Visual Studio Code 后端。然而,后来它添加了一个别名 token,以突出显示这不是 VS Code 特定的 API。 - AlBlue
1
你刚刚为我节省了几天的工作时间和许多烦恼。我不知道GitHub的更新是意外的,我以为这种情况经常发生。我本来想自动化这个过程 :D - djhaskin987
显示剩余2条评论

6
有一个数据源,比运行openssl客户端要简单得多。
data "tls_certificate" "github" {
  url = "https://token.actions.githubusercontent.com/.well-known/openid-configuration"
}

resource "aws_iam_openid_connect_provider" "github" {
  url             = "https://token.actions.githubusercontent.com"
  thumbprint_list = [data.tls_certificate.github.certificates[0].sha1_fingerprint]
  client_id_list  = ["sts.amazonaws.com"]
}

https://registry.terraform.io/providers/hashicorp/tls/latest/docs/data-sources/certificate


根据这个页面,指纹是["6938fd4d98bab03faadb97b34396831e3780aea1", "1c58a3a8518e8759bf075b76b750d4f2df264fcd"]。但是根据您的建议,我得到的是["1b511abead59c6ce207077c0bf0e0043b1382612", "3ea80e902fc385f36bc08193fbc678202d572994"]。 - undefined
@oglop的文档已经过时了,上述方法更可靠。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接