authorize: add UserPrincipalName SAN match

Add support for UserPrincipalName SAN matching to the policy evaluator.

Add unit tests. Unfortunately, adding a new test cert requires
regenerating the existing ones as well, because the CA key isn't saved.
This commit is contained in:
Kenneth Jenkins 2024-07-23 14:16:09 -07:00
parent ee365532ac
commit d495a1531e
4 changed files with 279 additions and 73 deletions

View file

@ -1,6 +1,7 @@
package evaluator
import (
"encoding/base64"
"regexp"
"testing"
@ -18,134 +19,148 @@ import (
const (
testCA = `
-----BEGIN CERTIFICATE-----
MIIBaDCCAQ6gAwIBAgICEAAwCgYIKoZIzj0EAwIwGjEYMBYGA1UEAxMPVHJ1c3Rl
ZCBSb290IENBMCAYDzAwMDEwMTAxMDAwMDAwWhcNMzMwODA3MTgwMzIxWjAaMRgw
MIIBZzCCAQ6gAwIBAgICEAAwCgYIKoZIzj0EAwIwGjEYMBYGA1UEAxMPVHJ1c3Rl
ZCBSb290IENBMCAYDzAwMDEwMTAxMDAwMDAwWhcNMzQwNzIxMjEwOTAxWjAaMRgw
FgYDVQQDEw9UcnVzdGVkIFJvb3QgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC
AAR2/RkzmSK6paoeTKFx1Bd52ZCg29ulJlMxFdSZT8FlmmaK9mN6KWwO+NHYObiW
y3AQuoSTrZXlrlRW5ANvMI+io0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
BAUwAwEB/zAdBgNVHQ4EFgQUJGFVU2UOvOVgaY9YcCUiunGpiCQwCgYIKoZIzj0E
AwIDSAAwRQIhAMU5/NjpitOSbUobtjeOriPH8JRo9qy1iFyeVNAcdVvgAiAewq2A
PhgzWTw5F9PJg++9i+xGQTqHs3ZirG27cCjvhQ==
AATMLdnk1HSlNQCNimWztrBbBU0xghli5LWSk7P1/1CW3JPvujT0xC2tEpooAxWi
XECL22GH9E2pH/dQoDj2FP41o0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
BAUwAwEB/zAdBgNVHQ4EFgQUoLhiwb9DEY80NUm/XfiLszTnetcwCgYIKoZIzj0E
AwIDRwAwRAIgWWAReqEjmvzpUKupOlcmEA4WBoPpsWWTDzFFApWE/+0CIG6FEkwQ
rJ4htyRqNMapRJmIHqgVxhyV/Pb7t4tsp6d7
-----END CERTIFICATE-----
`
testValidCert = `
-----BEGIN CERTIFICATE-----
MIIBYjCCAQigAwIBAgICEAEwCgYIKoZIzj0EAwIwGjEYMBYGA1UEAxMPVHJ1c3Rl
ZCBSb290IENBMCAYDzAwMDEwMTAxMDAwMDAwWhcNMzMwODA3MTgwMzIxWjAeMRww
ZCBSb290IENBMCAYDzAwMDEwMTAxMDAwMDAwWhcNMzQwNzIxMjEwOTAxWjAeMRww
GgYDVQQDExN0cnVzdGVkIGNsaWVudCBjZXJ0MFkwEwYHKoZIzj0CAQYIKoZIzj0D
AQcDQgAEcWa1Bz6mpsLnM1VD8gtzELjzjEp9Dopp/xWScFO9qtay5SBOeX+Ftr0O
8+/RkoKHzGgZ80gr6xQyUJL3MCwVZKM4MDYwEwYDVR0lBAwwCgYIKwYBBQUHAwIw
HwYDVR0jBBgwFoAUJGFVU2UOvOVgaY9YcCUiunGpiCQwCgYIKoZIzj0EAwIDSAAw
RQIgXM1ogmy0vcz4lYzji5X3In1n2GLOFNTgucFPkM0GtqgCIQCsXPs/0OjSFyDR
FBqAm1NqDJcxq685fS9t3VfHwapcVA==
AQcDQgAEUk42ibrv64GOkeoZdw+AUiohrtmg2g89jq60E7+HPBrDHWI+jZ22EtBe
N9pphc6hktrlGM3oHn95NOemJ/mlAaM4MDYwEwYDVR0lBAwwCgYIKwYBBQUHAwIw
HwYDVR0jBBgwFoAUoLhiwb9DEY80NUm/XfiLszTnetcwCgYIKoZIzj0EAwIDSAAw
RQIgGVB3Q4gFtZNgzjUUe1TuhJLy4NY1vRMrtVk1ywEC4hoCIQCg7XSIirpS4Mxc
kB9Ugn4FUX8SDD5+md2IReM27uKBjw==
-----END CERTIFICATE-----
`
testUntrustedCert = `
-----BEGIN CERTIFICATE-----
MIIBZjCCAQygAwIBAgICEAEwCgYIKoZIzj0EAwIwHDEaMBgGA1UEAxMRVW50cnVz
dGVkIFJvb3QgQ0EwIBgPMDAwMTAxMDEwMDAwMDBaFw0zMzA4MDcxODAzMjFaMCAx
MIIBZTCCAQygAwIBAgICEAEwCgYIKoZIzj0EAwIwHDEaMBgGA1UEAxMRVW50cnVz
dGVkIFJvb3QgQ0EwIBgPMDAwMTAxMDEwMDAwMDBaFw0zNDA3MjEyMTA5MDFaMCAx
HjAcBgNVBAMTFXVudHJ1c3RlZCBjbGllbnQgY2VydDBZMBMGByqGSM49AgEGCCqG
SM49AwEHA0IABJxEIKqLhhMEm5XZXkT+p+hlC2TFyaW0HIZqoE9navJrAcUB8L2M
mVQ+/wLaCznJHLeSLn46uGH5p1hoGFqOrdajODA2MBMGA1UdJQQMMAoGCCsGAQUF
BwMCMB8GA1UdIwQYMBaAFIp2rlIiSnr33ea3cGyLsX4LEYwWMAoGCCqGSM49BAMC
A0gAMEUCIDtJIZJDcqIYaDXhZFs0nd0nHER8IGP9n4BBFMWewAb2AiEAlQyavOxw
iTQQxt0rXB4Ox5zWpU9q68+F9BGBkQKTsBs=
SM49AwEHA0IABMD1+g0Dx5xcezQWJsWJX9AoNlPLsaqspsVS/rJoMoa01gE3fh8y
KaVH3N/SQH4E54TUywJA06wSIGN3SsNgpnajODA2MBMGA1UdJQQMMAoGCCsGAQUF
BwMCMB8GA1UdIwQYMBaAFHqcIcMoPGoBDLYSIol5EqKgXAA+MAoGCCqGSM49BAMC
A0cAMEQCIDCSM5mZkwApd+Ne0fYK3o0dP9CKeEd31lzF9PlMAzU2AiBL8EBVN5T6
M74llANbsQV6/9O3WSDYsvxvAGK/aN2pBg==
-----END CERTIFICATE-----
`
testRevokedCert = `
-----BEGIN CERTIFICATE-----
MIIBYjCCAQigAwIBAgICEAIwCgYIKoZIzj0EAwIwGjEYMBYGA1UEAxMPVHJ1c3Rl
ZCBSb290IENBMCAYDzAwMDEwMTAxMDAwMDAwWhcNMzMwODA3MTgwMzIxWjAeMRww
ZCBSb290IENBMCAYDzAwMDEwMTAxMDAwMDAwWhcNMzQwNzIxMjEwOTAxWjAeMRww
GgYDVQQDExNyZXZva2VkIGNsaWVudCBjZXJ0MFkwEwYHKoZIzj0CAQYIKoZIzj0D
AQcDQgAEcnoO4EM72C7xL31RE9e6m9YJYyF6E4JloASECd8mdiXPlMXIjq8MZHB5
28mFAVQNE7erAtBftID1SbuY4IpXxqM4MDYwEwYDVR0lBAwwCgYIKwYBBQUHAwIw
HwYDVR0jBBgwFoAUJGFVU2UOvOVgaY9YcCUiunGpiCQwCgYIKoZIzj0EAwIDSAAw
RQIgUUETSO064YIu+VKnyRb0yBnNTjXLy3TvGuYgZI8VX0YCIQDd0gyNEC5YLvRN
njxfnLoimp+TzTVzvsCokUbNSNRKJA==
AQcDQgAEfOs33d2sg3TQg19dh1bA5gv+wUljqfkykl/rj5vh3PwMoNgf38M09Lbs
fT6kz7wpKEA0G9/h/f2c4y59/d34ZqM4MDYwEwYDVR0lBAwwCgYIKwYBBQUHAwIw
HwYDVR0jBBgwFoAUoLhiwb9DEY80NUm/XfiLszTnetcwCgYIKoZIzj0EAwIDSAAw
RQIhAKNJwVxMvKIjkMfk9JhePG24CGawlIzCMJLRExQnIxzoAiAbMOnxje3tr/Mg
kl9linML1Km4f5aqOp2+TF9O/EHhKg==
-----END CERTIFICATE-----
`
testCRL = `
-----BEGIN X509 CRL-----
MIHeMIGFAgEBMAoGCCqGSM49BAMCMBoxGDAWBgNVBAMTD1RydXN0ZWQgUm9vdCBD
QRgPMDAwMTAxMDEwMDAwMDBaMBUwEwICEAIXDTIzMDgxMDE4MDMyMVqgMDAuMB8G
A1UdIwQYMBaAFCRhVVNlDrzlYGmPWHAlIrpxqYgkMAsGA1UdFAQEAgIgADAKBggq
hkjOPQQDAgNIADBFAiEAumtTtjiQt1VsbsEnyr+xbpK0KmzKvkpxIVgE1M9CND0C
IA8zx5clcaGIT5xRnBLZW7RwA37IOmB+7zjAuJQpmKKp
MIHdMIGFAgEBMAoGCCqGSM49BAMCMBoxGDAWBgNVBAMTD1RydXN0ZWQgUm9vdCBD
QRgPMDAwMTAxMDEwMDAwMDBaMBUwEwICEAIXDTI0MDcyMzIxMDkwMVqgMDAuMB8G
A1UdIwQYMBaAFKC4YsG/QxGPNDVJv134i7M053rXMAsGA1UdFAQEAgIgADAKBggq
hkjOPQQDAgNHADBEAiA6zjKyqK0IE8bO/LtnQT2CSRolOcdwHPMjtTkoO7ht8gIg
Qo8S83mFqwG14NiwaudxpYyYfGcCJZ6aaxqLc03ixiA=
-----END X509 CRL-----
`
testIntermediateCA = `
-----BEGIN CERTIFICATE-----
MIIBkTCCATegAwIBAgICEAMwCgYIKoZIzj0EAwIwGjEYMBYGA1UEAxMPVHJ1c3Rl
ZCBSb290IENBMCAYDzAwMDEwMTAxMDAwMDAwWhcNMzMwODA3MTgwMzIxWjAiMSAw
ZCBSb290IENBMCAYDzAwMDEwMTAxMDAwMDAwWhcNMzQwNzIxMjEwOTAxWjAiMSAw
HgYDVQQDExdUcnVzdGVkIEludGVybWVkaWF0ZSBDQTBZMBMGByqGSM49AgEGCCqG
SM49AwEHA0IABMY+zxL/2dNORuha3uVVOXZYIkTpa9V8N9UVrM15HOHkrdLlz1qk
4wbePkkoGtNRzoayb0iZqeA4YjOxqyPG8emjYzBhMA4GA1UdDwEB/wQEAwIBBjAP
BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQpGNmcLLM3vHiOADYGPDQL8AhkyDAf
BgNVHSMEGDAWgBQkYVVTZQ685WBpj1hwJSK6camIJDAKBggqhkjOPQQDAgNIADBF
AiEAnR6xrk7OCk91ymtzU+duZXDqDq35w0oO+MM8nqpac4YCIED+6c9dJKvRCc/C
nP8PMxRaUsbQet1woE7Fckn5tK4N
SM49AwEHA0IABNPOBn1f6EJYlOBs9E4ZllV3rVvzGbh7Z3f3klIfKv0nmYZqTYsE
06GbMlc+Rdw//wQ40j9+Gnvk/yTVPUydtSSjYzBhMA4GA1UdDwEB/wQEAwIBBjAP
BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQtnNz7iWzU1Fp427ksQsEf31WvgTAf
BgNVHSMEGDAWgBSguGLBv0MRjzQ1Sb9d+IuzNOd61zAKBggqhkjOPQQDAgNIADBF
AiEAzOI48p3sxhFnpp2s0LFxjzQXwOUqsKtlkWh16hEzG4MCIGspIDiBlxE594+M
iiciSIzesgppOJb1Hk/JS9r6qYhz
-----END CERTIFICATE-----
`
testValidIntermediateCert = `
-----BEGIN CERTIFICATE-----
MIIBdTCCARqgAwIBAgICEAAwCgYIKoZIzj0EAwIwIjEgMB4GA1UEAxMXVHJ1c3Rl
ZCBJbnRlcm1lZGlhdGUgQ0EwIBgPMDAwMTAxMDEwMDAwMDBaFw0zMzA4MDcxODAz
MjFaMCgxJjAkBgNVBAMTHWNsaWVudCBjZXJ0IGZyb20gaW50ZXJtZWRpYXRlMFkw
EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5SVyYjNRuuFXGjEmCcuVtMq7e2bmndPK
bRJ7lJ5cc0kZSoNJes5wXOtGRFbx3+admRHq+w1XEBXOe+yRUB8kdKM4MDYwEwYD
VR0lBAwwCgYIKwYBBQUHAwIwHwYDVR0jBBgwFoAUKRjZnCyzN7x4jgA2Bjw0C/AI
ZMgwCgYIKoZIzj0EAwIDSQAwRgIhAMj0O2wDRLoxGIPUDOmUfYxmxglOecQhSkWO
NBtItSxmAiEAy0XCzvpL6XOZU3zxyCjTdJQa2RiC6YnypMaCaETzCaU=
ZCBJbnRlcm1lZGlhdGUgQ0EwIBgPMDAwMTAxMDEwMDAwMDBaFw0zNDA3MjEyMTA5
MDFaMCgxJjAkBgNVBAMTHWNsaWVudCBjZXJ0IGZyb20gaW50ZXJtZWRpYXRlMFkw
EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEi9mkxtKlhiiCHteqDHZP+YH4awImLtEx
i7s/Nt1AWp3VMQ/cxRsZcmRHceGIpPoinYpmGfVppxy9fddZ4IBjw6M4MDYwEwYD
VR0lBAwwCgYIKwYBBQUHAwIwHwYDVR0jBBgwFoAULZzc+4ls1NRaeNu5LELBH99V
r4EwCgYIKoZIzj0EAwIDSQAwRgIhAJGUfGvzsTwMMqLzhSNdmKUWyajbN+wRF2gr
3CzI77OZAiEAh40Bew0mQQUs3WWilY0BauxtDtdcjX/IerxKTzEXKbg=
-----END CERTIFICATE-----
`
testValidCertWithDNSSANs = `
-----BEGIN CERTIFICATE-----
MIIBlTCCATugAwIBAgICEAQwCgYIKoZIzj0EAwIwGjEYMBYGA1UEAxMPVHJ1c3Rl
ZCBSb290IENBMCAYDzAwMDEwMTAxMDAwMDAwWhcNMzMwODA3MTgwMzIxWjAYMRYw
MIIBlDCCATugAwIBAgICEAQwCgYIKoZIzj0EAwIwGjEYMBYGA1UEAxMPVHJ1c3Rl
ZCBSb290IENBMCAYDzAwMDEwMTAxMDAwMDAwWhcNMzQwNzIxMjEwOTAxWjAYMRYw
FAYDVQQDEw1jbGllbnQgY2VydCAzMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE
LFai39b7TYauNjg4M58f0qY6jTC7xEOhE84wTTcevZvH/t2Y7U0BBNGkvpb14yxh
60vrRKZA9t9G6ZvWKcY/BKNxMG8wEwYDVR0lBAwwCgYIKwYBBQUHAwIwHwYDVR0j
BBgwFoAUJGFVU2UOvOVgaY9YcCUiunGpiCQwNwYDVR0RBDAwLoIVYS5jbGllbnQz
Dw9uoVvSDyVpqRN79Dtd3pf8pbTTKV8ZFDMa+pft3cWCSbzsxkHjx5yfiYmy94m0
IAUEkpsivA7w5zqhqZfONaNxMG8wEwYDVR0lBAwwCgYIKwYBBQUHAwIwHwYDVR0j
BBgwFoAUoLhiwb9DEY80NUm/XfiLszTnetcwNwYDVR0RBDAwLoIVYS5jbGllbnQz
LmV4YW1wbGUuY29tghViLmNsaWVudDMuZXhhbXBsZS5jb20wCgYIKoZIzj0EAwID
SAAwRQIgBSw8MsKWPPcpGtuVpNJonTEthIOjIGXswxiYG49y2BECIQC5D1DCX/lY
KSwF4aapPx4906VujTL+Ehj8L5ImUYcPbA==
RwAwRAIgTgkgYXb/6sErId2S/1X8TkdQETmMeQ85e0zQLC2WGn0CIAPF5nrlf5EL
VLK0wso+qCFmqrPNnv4X8nYOEc3L7kPA
-----END CERTIFICATE-----
`
testValidCertWithEmailSAN = `
-----BEGIN CERTIFICATE-----
MIIBezCCASKgAwIBAgICEAUwCgYIKoZIzj0EAwIwGjEYMBYGA1UEAxMPVHJ1c3Rl
ZCBSb290IENBMCAYDzAwMDEwMTAxMDAwMDAwWhcNMzMwODA3MTgwMzIxWjAYMRYw
MIIBfTCCASKgAwIBAgICEAUwCgYIKoZIzj0EAwIwGjEYMBYGA1UEAxMPVHJ1c3Rl
ZCBSb290IENBMCAYDzAwMDEwMTAxMDAwMDAwWhcNMzQwNzIxMjEwOTAxWjAYMRYw
FAYDVQQDEw1jbGllbnQgY2VydCA0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE
WvX8BnCrzUSpLrYka8ed+bz6/HoXUvq5nRqysKe0nGYSsXKRjxLdCG8AKsoGIQIv
KOQScf/4TJUNIUY4XOsFI6NYMFYwEwYDVR0lBAwwCgYIKwYBBQUHAwIwHwYDVR0j
BBgwFoAUJGFVU2UOvOVgaY9YcCUiunGpiCQwHgYDVR0RBBcwFYETY2xpZW50NEBl
eGFtcGxlLmNvbTAKBggqhkjOPQQDAgNHADBEAiAMYGTjUBqgnai8UL3B/iQkCkMb
xgCC1ZYdZaJ1RBwFfgIgIhjQZ2s6dTaah/LzYJ9ZwMvSA86XQvzTVSuT6s+RJw0=
zMPGmaQ/Hhss/Pil1ku5QgFmVkaZdMHllql508HddNQ96t24vddILPS1YZwRv1SQ
D47sdwRcrgLcYvXAYhnfxKNYMFYwEwYDVR0lBAwwCgYIKwYBBQUHAwIwHwYDVR0j
BBgwFoAUoLhiwb9DEY80NUm/XfiLszTnetcwHgYDVR0RBBcwFYETY2xpZW50NEBl
eGFtcGxlLmNvbTAKBggqhkjOPQQDAgNJADBGAiEAiKp/7Cv8tUJBUr+Z+T6ztghs
hhSH/LZcLzRHJ8jtACoCIQD78Ut4V6/8eSOS3DHIDwqXwOZ/L06DwugzYP5/jlZA
cQ==
-----END CERTIFICATE-----
`
testValidCertWithIPSAN = `
-----BEGIN CERTIFICATE-----
MIIBbTCCAROgAwIBAgICEAYwCgYIKoZIzj0EAwIwGjEYMBYGA1UEAxMPVHJ1c3Rl
ZCBSb290IENBMCAYDzAwMDEwMTAxMDAwMDAwWhcNMzMwODA3MTgwMzIxWjAYMRYw
ZCBSb290IENBMCAYDzAwMDEwMTAxMDAwMDAwWhcNMzQwNzIxMjEwOTAxWjAYMRYw
FAYDVQQDEw1jbGllbnQgY2VydCA1MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE
6+9BE+aomrR2Mdnx4iFY63t0hsVD6rYaHBW1b9roFQX6Cor4YeUfkEEF4LrGeAyb
wcqb6G1ExgNyjEh10Ai1M6NJMEcwEwYDVR0lBAwwCgYIKwYBBQUHAwIwHwYDVR0j
BBgwFoAUJGFVU2UOvOVgaY9YcCUiunGpiCQwDwYDVR0RBAgwBocEwKgKCjAKBggq
hkjOPQQDAgNIADBFAiEA/mq32YZZAacOH/P/wjvfD1n74DD/GkhW4kfS72Z0oGQC
IAQ+L8E78JOLaPWXiL7WFpVrb0hOHkV2m9Qw4GB41mUN
cRD582BfNyLzyuvtxR/Z19mwWqRF6Kxx5ZSovtPKIeJ75Okiv1q20TOwGrEYLmHr
YCBrMd3YM56KKcEhSUi/nqNJMEcwEwYDVR0lBAwwCgYIKwYBBQUHAwIwHwYDVR0j
BBgwFoAUoLhiwb9DEY80NUm/XfiLszTnetcwDwYDVR0RBAgwBocEwKgKCjAKBggq
hkjOPQQDAgNIADBFAiAv+MGYGG9SaQFekl1e7zIG0rxMkbS8UPmkklR/RuXQ+gIh
ALvBj9aAXW9wN8nYLH9L2bPbMT//a42VuD6qvi6B0i6P
-----END CERTIFICATE-----
`
testValidCertWithURISAN = `
-----BEGIN CERTIFICATE-----
MIIBhTCCASugAwIBAgICEAcwCgYIKoZIzj0EAwIwGjEYMBYGA1UEAxMPVHJ1c3Rl
ZCBSb290IENBMCAYDzAwMDEwMTAxMDAwMDAwWhcNMzMwODA3MTgwMzIxWjAYMRYw
ZCBSb290IENBMCAYDzAwMDEwMTAxMDAwMDAwWhcNMzQwNzIxMjEwOTAxWjAYMRYw
FAYDVQQDEw1jbGllbnQgY2VydCA2MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE
7mHladapSY5PlVYToL1dHr0tJPGe5XVP8DSZJz+WWyS9tWsuEsK6P5yeZrbWASOX
foH7iVIdx3DMyukGsvMX+KNhMF8wEwYDVR0lBAwwCgYIKwYBBQUHAwIwHwYDVR0j
BBgwFoAUJGFVU2UOvOVgaY9YcCUiunGpiCQwJwYDVR0RBCAwHoYcc3BpZmZlOi8v
ZXhhbXBsZS5jb20vZm9vL2JhcjAKBggqhkjOPQQDAgNIADBFAiAhzElKeGJzp2zP
GOTUEy0f6b2tvMYGDLQxCcp4bc4QuQIhAPwX4Y3Cr7uazQlbwL6D51y9NCcDyj3D
Z18vZNxm9ZR1
B7Znrqifp50mCqJfdoCvEu0UP+W1qUZm1dckfMq02f9kgbn2JGgvb1nGE8gKA0n1
V6/QtuIUBnyosfX3IuF9qqNhMF8wEwYDVR0lBAwwCgYIKwYBBQUHAwIwHwYDVR0j
BBgwFoAUoLhiwb9DEY80NUm/XfiLszTnetcwJwYDVR0RBCAwHoYcc3BpZmZlOi8v
ZXhhbXBsZS5jb20vZm9vL2JhcjAKBggqhkjOPQQDAgNIADBFAiAwp1maaT976oWE
f8RnxAPGX1Ecc77A6uhOM0ZCVrYDCQIhAJf5MW7BddAtbRYHyUEhwaVFA9Ci56m9
TEgriIGNirO9
-----END CERTIFICATE-----
`
testValidCertWithUPNSAN = `
-----BEGIN CERTIFICATE-----
MIIBhDCCASqgAwIBAgICEAcwCgYIKoZIzj0EAwIwGjEYMBYGA1UEAxMPVHJ1c3Rl
ZCBSb290IENBMCAYDzAwMDEwMTAxMDAwMDAwWhcNMzQwNzIxMjEwOTAxWjAYMRYw
FAYDVQQDEw1jbGllbnQgY2VydCA3MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE
Pbsk3ZsS7dPwVh+G+hG/nv9PcHfFpOrCiAP0/orxhTRiYD2QbxCB9KBC2YZKrMGF
pvhqM/fX6r1hB6o1Gz/J3KNgMF4wEwYDVR0lBAwwCgYIKwYBBQUHAwIwHwYDVR0j
BBgwFoAUoLhiwb9DEY80NUm/XfiLszTnetcwJgYDVR0RBB8wHaAbBgorBgEEAYI3
FAIDoA0MC3Rlc3RfZGV2aWNlMAoGCCqGSM49BAMCA0gAMEUCIQDG82BiX0pzkvW+
UgGq54X7ItNLu2uBFBTgR8NCJpBCMAIgaBzSkAyTSbbLU/gRrhD6HiyGoxDn38xh
HcsXWWvNgTQ=
-----END CERTIFICATE-----
`
)
@ -366,6 +381,25 @@ func Test_isValidClientCertificate(t *testing.T) {
assert.NoError(t, err, "should not return an error")
assert.False(t, valid, "should return false")
})
t.Run("UserPrincipalName SAN", func(t *testing.T) {
valid, err := isValidClientCertificate(testCA, "", ClientCertificateInfo{
Presented: true,
Leaf: testValidCertWithUPNSAN,
}, ClientCertConstraints{SANMatchers: SANMatchers{
config.SANTypeUserPrincipalName: regexp.MustCompile(`^test_device$`),
}})
assert.NoError(t, err, "should not return an error")
assert.True(t, valid, "should return true")
valid, err = isValidClientCertificate(testCA, "", ClientCertificateInfo{
Presented: true,
Leaf: testValidCertWithURISAN,
}, ClientCertConstraints{SANMatchers: SANMatchers{
config.SANTypeDNS: regexp.MustCompile(`^test-device$`), // mismatched type
}})
assert.NoError(t, err, "should not return an error")
assert.False(t, valid, "should return false")
})
}
func TestClientCertConstraintsFromConfig(t *testing.T) {
@ -452,3 +486,64 @@ func TestClientCertConstraintsFromConfig(t *testing.T) {
require.Error(t, err)
})
}
func TestGetUserPrincipalNamesFromSAN(t *testing.T) {
b64 := func(raw string) []byte {
b, err := base64.StdEncoding.DecodeString(raw)
require.NoError(t, err)
return b
}
// One UserPrincipalName.
names, err := getUserPrincipalNamesFromSAN(b64(`
MBegFQYKKwYBBAGCNxQCA6AHDAVoZWxsbw==`))
assert.NoError(t, err)
assert.Equal(t, []string{"hello"}, names)
// Multiple UserPrincipalNames.
names, err = getUserPrincipalNamesFromSAN(b64(`
MD+gEwYKKwYBBAGCNxQCA6AFDANmb2+gEwYKKwYBBAGCNxQCA6AFDANiYXKgEwYKKwYBBAGCNxQCA6AF
DANiYXo=`))
assert.NoError(t, err)
assert.Equal(t, []string{"foo", "bar", "baz"}, names)
// Several OtherNames, only one UserPrincipalName.
names, err = getUserPrincipalNamesFromSAN(b64(`
MFigFgYDKQEBoA8bDUdlbmVyYWxTdHJpbmegIQYKKwYBBAGCNxQCA6ATDBFVc2VyUHJpbmNpcGFsTmFt
ZaAbBgMpAQKgFB4SAEIATQBQAFMAdAByAGkAbgBn`))
assert.NoError(t, err)
assert.Equal(t, []string{"UserPrincipalName"}, names)
// Two DNS names, no OtherNames.
names, err = getUserPrincipalNamesFromSAN(b64(`
MC6CFWEuY2xpZW50My5leGFtcGxlLmNvbYIVYi5jbGllbnQzLmV4YW1wbGUuY29t`))
assert.NoError(t, err)
assert.Empty(t, names)
// A UserPrincipalName with the wrong data type (GeneralString).
names, err = getUserPrincipalNamesFromSAN(b64(`
MB+gHQYKKwYBBAGCNxQCA6APGw1HZW5lcmFsU3RyaW5n`))
assert.ErrorContains(t, err, "expected UTF8String")
assert.Empty(t, names)
// Other malformed inputs.
names, err = getUserPrincipalNamesFromSAN(nil)
assert.ErrorContains(t, err, "error reading GeneralNames sequence")
assert.Empty(t, names)
names, err = getUserPrincipalNamesFromSAN(b64("MA+gDwYCRgGgBwwFaGVsbG8="))
assert.ErrorContains(t, err, "error reading GeneralName")
assert.Empty(t, names)
names, err = getUserPrincipalNamesFromSAN(b64("MA+gDQICRgGgBwwFaGVsbG8="))
assert.ErrorContains(t, err, "error reading OtherName type ID")
assert.Empty(t, names)
names, err = getUserPrincipalNamesFromSAN(b64("MBegFQYKKwYBBAGCNxQCA6AIDAVoZWxsbw=="))
assert.ErrorContains(t, err, "error reading UserPrincipalName value")
assert.Empty(t, names)
names, err = getUserPrincipalNamesFromSAN(b64("MBegFQYKKwYBBAGCNxQCA6EHDAVoZWxsbw=="))
assert.ErrorContains(t, err, "unexpected UserPrincipalName data tag")
assert.Empty(t, names)
}