Federal Modernization Workbook
Chapter 05 — Certificate-Based Authentication Checks
A revoked card is only revoked if Entra can download the list that says so, in time, every time.
The checks behind the guide’s Gate 5, “CBA trusts the issuing CAs with CRLs,” and plan task I1.6, the issuing CAs’ CRL sizes checked. You start with Learn’s certificate revocation list page, which sets the limits per cloud, and the Graph resources that hold the trust store and the X.509 certificate method. Then you use examples/hr-lifecycle for what they leave to you: a measurement of every CRL, and a check, CB-01 to CB-13, of the CAs, each CRL against the cloud’s limit, the multifactor mapping, CRL validation and the phishing-resistant strength. Lab 1 runs on a laptop with no tenant; Lab 2 uses a test tenant.
Jump to a slide (18)
Deck · Narrated deck (about 11 minutes, captions) · Script · Captions. Recorded on November 2, 2026 from the approved chapter.
Goal and audience
Goal. By the end of this chapter you can say, from code, whether every CA the card program issues from is trusted with a CRL that Entra can download within the limits of your tenant’s cloud, whether PIV certificates count as multifactor, and whether a Conditional Access policy requires a phishing-resistant strength. You can say, for each rule, whether it is Learn’s limit or the program’s own design.
Audience. Developers who build the credential checks, the PKI and credentialing engineers who run the issuing CAs, and the ISSO who keeps the configuration export. You should read Python. You don’t need a tenant until Lab 2.
Why this gate needs code
The guide’s Gate 5 ties the card’s lifecycle to the person’s: issuance from a joiner record, revocation from a leaver. Revocation only reaches sign-in through the CRL. Book 03 explains why (Chapter 09, Revocation checking), and Book 07 explains the trust store, the bindings and the single-factor and multifactor split (Chapter 06, Entra certificate-based authentication). This chapter doesn’t restate them. It turns them into a check that runs every day, because a CRL grows with every revocation, and the day it crosses the limit is the day sign-in fails for every card from that CA.1
Per-user binding coverage and affinity are the validation kit’s VK-PIV-01 (the validation kit’s README) and the ADM guide’s Gate 6. This chapter checks the tenant’s settings, which VK-PIV-01 doesn’t read.
Which cloud, for this check
Learn gives two sets of CRL limits. For interactive sign-in, a CRL must stay under 20 MB in public Entra ID, which includes GCC, and 45 MB in Azure US Government, which Learn’s FAQ says includes GCC High and DoD; it must download within 10 seconds. The service-side limits are 65 MB and 150 MB.2 config/cba-expected.json holds both sets per cloud name, and the check takes --cloud gcc, gcchigh or dod with no default. Learn writes the limits in MB without saying whether a megabyte is 1,000,000 or 1,048,576 bytes; the configuration reads them as decimal, the stricter reading. The Graph reads go to graph.microsoft.com for GCC and graph.microsoft.us or dod-graph.microsoft.us for GCC High and DoD.3 Certificate-based authentication and Conditional Access are available in Azure for US Government.4
Start with Microsoft’s procedure
What Microsoft gives you
Learn’s CRL page is Microsoft’s procedure and its limits. Without a configured CRL, Entra doesn’t check revocation for that CA. Entra supports one CRL endpoint per CA, HTTP or HTTPS, and recommends HTTP because HTTPS adds latency and its own certificate validation. A configured CRL that can’t be downloaded fails certificate-based authentication for that CA’s certificates, so Learn asks for highly available endpoints, and for CRL validation enforced in policy, with an exemption only as a last resort while troubleshooting.5 The setup page lists the same prerequisite: each CA has a CRL from an internet-facing URL.6
Graph holds the configuration in three places, all in v1.0:
- the PKI-based trust store, a list of
certificateBasedAuthPkiobjects, each withcertificateAuthoritiesof typecertificateAuthorityDetail, which carrycertificateRevocationListUrl,certificateAuthorityType(root or intermediate),thumbprintandexpirationDateTime;7 8 9 - the X.509 certificate authentication method,
x509CertificateAuthenticationMethodConfiguration, withauthenticationModeConfiguration(a default mode and rules that map an issuer or a policy OID tox509CertificateMultiFactor),crlValidationConfiguration(a state and the exempted CAs’ subject key identifiers) andcertificateUserBindings;10 11 12 13 14 - the authentication strength policies, whose
allowedCombinationsuse theauthenticationMethodModesvalues, and the Conditional Access policies that reference them.15 16
Learn’s authentication strengths page says the built-in phishing-resistant strength allows Windows Hello for Business or platform credential, FIDO2 and certificate-based authentication (multifactor).17
What it leaves to you
Each row is pinned by a test in tests/test_credentials_separation_drift.py.
| What Learn gives | Why it matters | What examples/hr-lifecycle adds |
|---|---|---|
| The limits, in prose | Nobody measures the CRL until sign-in fails | cba_check.py measure downloads each CRL and records bytes and seconds; check compares them with the cloud’s limit (test_the_crl_limit_follows_the_cloud) |
| One limit per cloud | A GCC tenant sized to the GCC High limit passes a CRL that fails | The limit comes from --cloud, never a default (test_the_crl_limit_follows_the_cloud) |
| “A CRL that can’t be downloaded fails CBA” | An unreachable endpoint looks like a missing measurement | A download error or a missing measurement is a Finding, not a skip (test_an_unreachable_or_unmeasured_crl_is_a_finding) |
| The trust store as Graph objects | A renewed CA with a new thumbprint is silently missing | Each issuing CA the card program uses is named by thumbprint in config/cba-expected.json (test_cba_fixture_raises_each_rule) |
| Mode rules by issuer or policy OID | PIV certificates sign in as single-factor and fail the strength | CB-09 checks the program’s PIV policy OIDs map to multifactor (test_cba_fixture_raises_each_rule) |
| CRL validation and exemptions | An exemption made while troubleshooting stays forever | Each exempted CA is a Warn until it’s removed (test_cba_fixture_raises_each_rule) |
| Strengths and policies, separately | The phishing-resistant strength exists but no enforced policy requires it | CB-10 looks for an enabled policy for all users and all resources whose strength allows only phishing-resistant combinations; a report-only policy doesn’t count (test_a_compliant_configuration_is_clean) |
The verdict. Keep Learn’s limits as the configuration’s values and Learn’s objects as the check’s inputs. The code measures and compares; it never changes the configuration.
The code: what examples/hr-lifecycle adds
python/cba_check.py has two commands, and reads the exports graph_export.py --task cba-read writes.
The measurement
measure takes a file with one CRL URL per line, downloads each once, and writes crl-measurements.csv with the bytes, the seconds and any error. A failed download is recorded, not raised: the unreachable CRL is the finding. For labs, a local path is read as a file. Run it from the network that represents the internet-facing path Entra uses, not from inside the PKI’s own network (design guidance).
The check
| Rule | Severity | What it flags | Source |
|---|---|---|---|
| CB-01 | Finding; Warn | An intermediate CA with no CRL configured (Finding); a root CA with none (Warn) | Learn: no CRL, no revocation check18 |
| CB-02 | Warn | A CRL endpoint that isn’t HTTP | Learn recommends HTTP19 |
| CB-03 | Finding | A CRL over the cloud’s interactive size limit | Learn20 |
| CB-04 | Finding | A CRL that couldn’t be downloaded, or took more than 10 seconds | Learn21 |
| CB-05 | Warn | A CRL over 80% of the limit | Design guidance (warnPercent) |
| CB-06 | Finding | A configured CRL with no measurement | Design guidance: measure every CRL |
| CB-07 | Finding | The X.509 certificate method isn’t enabled | Learn22 |
| CB-08 | Warn | CRL validation isn’t enabled, or a CA is exempted | Learn recommends enforcing it and exempting only to troubleshoot23 |
| CB-09 | Finding | A PIV policy OID not mapped to multifactor, with a single-factor default | Learn’s mode rules;24 the program’s OIDs |
| CB-10 | Finding | No enabled policy for all users and resources requires a phishing-resistant strength | SCuBA MS.AAD.3.1v1;25 Learn’s strengths26 |
| CB-11 | Warn | A CA certificate that expires within 90 days | Design guidance (caExpiryWarnDays) |
| CB-12 | Finding | An issuing CA the card program uses isn’t in the trust store | Design guidance |
| CB-13 | Warn | A low-affinity binding field (PrincipalName, RFC822Name) configured |
The validation kit’s affinity table; ADM Gate 6’s decision |
A root CA with no CRL configured is a Warn, not a Finding: a root that issues only CA certificates may publish none. Learn’s prerequisite is wider, “each CA has a CRL,” and Learn says Entra checks the CRLs up the chain to the root, so the warning asks you to confirm the root’s revocation path, and Lab 2 checks it (verification log, row 14).27 28
The read needs three permissions, each the least-privileged for its call:
| Call | Least-privileged permission | Delegated role |
|---|---|---|
List certificateBasedAuthPki, and each one’s CAs |
PublicKeyInfrastructure.Read.All29 30 |
Authentication Administrator or Privileged Authentication Administrator |
| Get the X.509 certificate method | Policy.Read.AuthenticationMethod31 |
Global Reader or Authentication Policy Administrator |
| List authentication strength policies | Policy.Read.AuthenticationMethod32 |
Conditional Access Administrator, Security Administrator or Security Reader |
| List Conditional Access policies | Policy.Read.All33 |
Global Reader or Security Reader |
The code reads the PKI-based trust store, not the older organization/{id}/certificateBasedAuthConfiguration, whose Learn pages name Global Administrator as the only role for a delegated read.34
The tests
Five tests cover this chapter: every rule on the fixture, the limit by cloud, an unreachable or unmeasured CRL, a compliant configuration that comes back clean, and the measurement against a fake opener. With the other chapters’, 57 pytest tests pass under Python 3.10 or later, with no package, tenant or network.
The commands below run the example against a fictional tenant’s exports and fictional CRL files. They show what the code does, not that a tenant returns the same shapes. Review the code and run Lab 2 in a test tenant before it reports on production.
Lab 1: fixtures, no tenant
You need Python 3.10 or later. Work in examples/hr-lifecycle.
Every command in this lab, in order, from examples/hr-lifecycle. Each step below says what it does and what to look for.
# Step 1: List the calls and permissions
python python/graph_export.py --task cba-read --list
# Step 2: Measure the fixture CRLs
python python/cba_check.py measure --urls tests/fixtures/ch05/crl-urls.txt --out out/ch05/crl-measurements.csv
# Step 3: Check the fictional tenant for GCC
python python/cba_check.py check --cloud gcc --exports tests/fixtures/ch05/exports --crl tests/fixtures/ch05/crl-measurements.csv --expected config/cba-expected.json --as-of 2026-11-01 --out out/ch05/check
# Step 4: Check the same tenant for GCC High
python python/cba_check.py check --cloud gcchigh --exports tests/fixtures/ch05/exports --crl tests/fixtures/ch05/crl-measurements.csv --expected config/cba-expected.json --as-of 2026-11-01 --out out/ch05/check-gcchigh
# Step 5: Run the tests
python -m pytest tests -q
# After the steps
rm -rf outList the calls and permissions:
python python/graph_export.py --task cba-read --listTask cba-read: Policy.Read.All, Policy.Read.AuthenticationMethod, PublicKeyInfrastructure.Read.All GET /directory/publicKeyInfrastructure/certificateBasedAuthConfigurations [PublicKeyInfrastructure.Read.All] GET /directory/publicKeyInfrastructure/certificateBasedAuthConfigurations/{pkiId}/certificateAuthorities [PublicKeyInfrastructure.Read.All] GET /policies/authenticationMethodsPolicy/authenticationMethodConfigurations/x509Certificate [Policy.Read.AuthenticationMethod] GET /policies/authenticationStrengthPolicies [Policy.Read.AuthenticationMethod] GET /identity/conditionalAccess/policies [Policy.Read.All]What the terminal shows, run on the kit’s fixtures (the same output as text) Measure the fixture CRLs:
python python/cba_check.py measure --urls tests/fixtures/ch05/crl-urls.txt --out out/ch05/crl-measurements.csv4,096 bytes 0.000 s tests/fixtures/ch05/crl/piv-ca1.crl 8,192 bytes 0.000 s tests/fixtures/ch05/crl/piv-ca2.crl 0 bytes 0.000 s tests/fixtures/ch05/crl/missing.crl FileNotFoundError Measured 3 CRL(s) -> out/ch05/crl-measurements.csvWhat the terminal shows, run on the kit’s fixtures (the same output as text) The times on your machine will differ. The missing file is recorded with its error, not raised. The check in the next step reads
tests/fixtures/ch05/crl-measurements.csvinstead, which holds measurements of the fictional tenant’s own CRL URLs, one of them 18.5 million bytes and 11.4 seconds.Check the fictional tenant for GCC:
python python/cba_check.py check --cloud gcc --exports tests/fixtures/ch05/exports --crl tests/fixtures/ch05/crl-measurements.csv --expected config/cba-expected.json --as-of 2026-11-01 --out out/ch05/checkCloud gcc: interactive CRL limit 20,000,000 bytes, download within 10 s CBA: 5 Finding, 7 Warn, 0 Info CB-01 Finding: Contoso Example Legacy Intermediate: no CRL configured: Entra doesn't check revocation for this CA CB-04 Finding: Contoso Example PIV Issuing CA 2 (renewed): CRL took 11.4 s to download; the limit is 10 s CB-09 Finding: authentication mode: PIV policy OID(s) 2.16.840.1.101.3.2.1.48.11 not mapped to multifactor, and the default is single-factor CB-10 Finding: Conditional Access: no enabled policy for all users and all resources requires a phishing-resistant authentication strength (SCuBA MS.AAD.3.1v1) CB-12 Finding: Contoso Example PIV Issuing CA 2: issuing CA the card program uses isn't in the trust store CB-01 Warn: Contoso Example PIV Root CA: root CA with no CRL configured; Learn asks for a CRL on each CA; confirm the root's revocation path CB-02 Warn: Contoso Example PIV Issuing CA 2 (renewed): CRL endpoint https://pki.contoso.example/crl/piv-ca2.crl isn't HTTP; Learn recommends HTTP CB-05 Warn: Contoso Example PIV Issuing CA 2 (renewed): CRL is 18,500,000 bytes, over 80% of the gcc interactive limit CB-08 Warn: CRL validation: CBA doesn't require a CRL from every CA (crlValidationConfiguration isn't enabled) CB-08 Warn: CA 5A5B5C5D5E5F60616263646566676869: exempted from CRL validation; allowed only while its CRL is fixed, with an end date CB-11 Warn: Contoso Example Legacy Intermediate: CA certificate expires 2026-12-15 CB-13 Warn: username bindings: low-affinity binding fields configured (PrincipalName); align with the affinity decision (ADM Gate 6) and VK-PIV-01What the terminal shows, run on the kit’s fixtures (the same output as text) The exit code is 2. Read the story in the fixture: CA 2 was renewed, so the thumbprint the card program expects is gone (CB-12) and the renewed CA’s CRL is large, slow and on HTTPS. The tenant’s mode rule maps the wrong OID (CB-09), and the phishing-resistant policy is still report-only, so the enforced policy requires only the MFA strength (CB-10).
Check the same tenant for GCC High:
python python/cba_check.py check --cloud gcchigh --exports tests/fixtures/ch05/exports --crl tests/fixtures/ch05/crl-measurements.csv --expected config/cba-expected.json --as-of 2026-11-01 --out out/ch05/check-gcchighCloud gcchigh: interactive CRL limit 45,000,000 bytes, download within 10 s CBA: 5 Finding, 6 Warn, 0 InfoWhat the terminal shows, run on the kit’s fixtures (the same output as text) The same 18.5 million bytes is under 80% of the Azure Government limit, so CB-05 drops away. The 11.4-second download is a Finding in every cloud.
Run the tests:
python -m pytest tests -qWhat the terminal shows, run on the kit’s fixtures (the same output as text)
Expected result: 57 passed. Delete out when you’re done:
rm -rf outLab 2: test tenant
Not run by the authors. Use a test tenant with certificate-based authentication configured for a test CA, never production. Work in examples/hr-lifecycle. You’ll replace: <graph-token> (a bearer token for graph.microsoft.com issued to the reader app), <pki-id> (the PKI container’s ID, from the list in step 2), <crl-url-1> and <crl-url-2> (the test CAs’ CRL URLs, one per CA), <ca-name> and <ca-thumbprint> (an issuing CA of the test PKI), <piv-policy-oid> (the policy OID of the test PKI’s PIV authentication certificates), <cloud> (the test tenant’s cloud: gcc, gcchigh or dod) and <today> (today’s date, yyyy-mm-dd).
Every command in this lab, in order, from examples/hr-lifecycle. Each step below says what it does and what to look for.
# Step 2: Export the configuration
export HRLC_GRAPH_TOKEN='<graph-token>'
curl -s -H "Authorization: Bearer $HRLC_GRAPH_TOKEN" https://graph.microsoft.com/v1.0/directory/publicKeyInfrastructure/certificateBasedAuthConfigurations
python python/graph_export.py --task cba-read --cloud gcc --param pkiId=<pki-id> --out exports/cba
# Step 2: Export the configuration
python -c "import json; print('x509 objects:', len(json.load(open('exports/cba/x509-method.json'))['value'])); [print(c['displayName'], c.get('certificateRevocationListUrl')) for c in json.load(open('exports/cba/pki-cas.json'))['value']]"
# Step 3: Measure the real CRLs
printf '%s\n' '<crl-url-1>' '<crl-url-2>' > my-crl-urls.txt
python python/cba_check.py measure --urls my-crl-urls.txt --out out/cba-test/crl-measurements.csv
# Step 4: Check
python -c "import json; d=json.load(open('config/cba-expected.json')); d['issuingCas'] = [{'displayName': '<ca-name>', 'thumbprint': '<ca-thumbprint>'}]; d['multifactorPolicyOids'] = ['<piv-policy-oid>']; json.dump(d, open('my-cba-expected.json', 'w'), indent=2)"
python python/cba_check.py check --cloud <cloud> --exports exports/cba --crl out/cba-test/crl-measurements.csv --expected my-cba-expected.json --as-of <today> --out out/cba-test/check
# Step 6: Back it out
rm -rf exports out my-crl-urls.txt my-cba-expected.jsonRegister the reader app with a certificate, and grant the three application permissions from Lab 1, step 1, with admin consent, and nothing else.
Export the configuration. With a token for the reader app in
HRLC_GRAPH_TOKEN, list the PKI containers, then export the task with the container’s ID:export HRLC_GRAPH_TOKEN='<graph-token>' curl -s -H "Authorization: Bearer $HRLC_GRAPH_TOKEN" https://graph.microsoft.com/v1.0/directory/publicKeyInfrastructure/certificateBasedAuthConfigurations python python/graph_export.py --task cba-read --cloud gcc --param pkiId=<pki-id> --out exports/cbaCheck that
x509-method.jsonholds one object and that each CA inpki-cas.jsoncarriescertificateRevocationListUrlas the fixture does. This prints the count and each CA’s URL:python -c "import json; print('x509 objects:', len(json.load(open('exports/cba/x509-method.json'))['value'])); [print(c['displayName'], c.get('certificateRevocationListUrl')) for c in json.load(open('exports/cba/pki-cas.json'))['value']]"Measure the real CRLs. Put each CA’s CRL URL in a file, one per line (add a line for each further CA), and run
measurefrom outside the agency network:printf '%s\n' '<crl-url-1>' '<crl-url-2>' > my-crl-urls.txt python python/cba_check.py measure --urls my-crl-urls.txt --out out/cba-test/crl-measurements.csvRecord the run’s date with the file.
Check. Copy
config/cba-expected.jsonwith the CA thumbprints and PIV policy OIDs replaced by the test PKI’s (add an entry toissuingCasfor each further issuing CA), and runcheckwith--cloudset to the test tenant’s cloud:python -c "import json; d=json.load(open('config/cba-expected.json')); d['issuingCas'] = [{'displayName': '<ca-name>', 'thumbprint': '<ca-thumbprint>'}]; d['multifactorPolicyOids'] = ['<piv-policy-oid>']; json.dump(d, open('my-cba-expected.json', 'w'), indent=2)" python python/cba_check.py check --cloud <cloud> --exports exports/cba --crl out/cba-test/crl-measurements.csv --expected my-cba-expected.json --as-of <today> --out out/cba-test/checkProve revocation. Revoke a test user’s certificate, wait for the CA’s next CRL publication, and sign in with it. Entra should refuse it with the revoked-certificate error Learn lists.35 Record the revocation time, the CRL’s publication time and the refused sign-in.
Back it out. Remove the permissions, delete the reader app and its certificate, and reissue the test user’s certificate if you need it again. Then delete
exportsandout, with the lab’s two files:rm -rf exports out my-crl-urls.txt my-cba-expected.json
Verified facts
| Item | Value | US Government clouds | Stage | Source |
|---|---|---|---|---|
| CRL limits | Interactive 20 MB (public, includes GCC) and 45 MB (Azure US Government, includes GCC High and DoD); 10-second download; service limits 65 MB and 150 MB | Applies, with the larger limits | GA | 36 |
| CRL behavior | No CRL, no revocation check; one endpoint, HTTP or HTTPS, HTTP recommended; a configured CRL that can’t be downloaded fails CBA; CRLs checked up to 10 CAs toward the root | — | GA | 37 |
List certificateBasedAuthPki; list its certificateAuthorities |
PublicKeyInfrastructure.Read.All; Authentication Administrator or Privileged Authentication Administrator |
L4 and L5 | v1.0 | 38 39 |
certificateAuthorityDetail |
certificateRevocationListUrl, certificateAuthorityType, thumbprint, expirationDateTime, issuerSubjectKeyIdentifier |
— | v1.0 | 40 |
| Get X.509 certificate method | Policy.Read.AuthenticationMethod; Global Reader or Authentication Policy Administrator |
L4 and L5 (not 21Vianet) | v1.0 | 41 |
| X.509 method properties | authenticationModeConfiguration (rules by issuerSubject or policyOID), crlValidationConfiguration, certificateUserBindings (PrincipalName, RFC822Name, SubjectKeyIdentifier, SHA1PublicKey) |
— | v1.0 | 42 43 44 45 |
| List authentication strength policies | Policy.Read.AuthenticationMethod; allowedCombinations from authenticationMethodModes |
L4 and L5 | v1.0 | 46 47 |
| List Conditional Access policies | Policy.Read.All |
— | v1.0 | 48 |
Legacy certificateBasedAuthConfiguration |
Organization.Read.All; Global Administrator is the only delegated role |
L4 and L5 | v1.0 | 49 |
| CBA and Conditional Access | Available in Azure for US Government | Available | GA | 50 |
Places Learn says nothing or differs, recorded so a later edit doesn’t loosen the code:
- Megabytes. Learn writes “20 MB” and “45 MB” without a byte count. The configuration uses decimal megabytes, the stricter reading. Learn also says it is reviewing the limits and plans to remove them.51
- Two pages, two limits. Learn’s CBA-with-federation page still gives a single 20 MB limit with no cloud split; the CRL page gives both. The code follows the CRL page for the cloud split and applies 20 MB to GCC either way.52 53
- Root CAs. Learn’s prerequisite is a CRL for each CA; the check warns on a root with none rather than failing it (verification log, row 14).
- Priority. Learn says Entra uses the binding “with the highest priority” without saying whether that is the largest or the smallest number.54 CB-13 flags any low-affinity field rather than guessing the order.
Federal requirements and evidence
This chapter helps prove the guide’s Gate 5; its requirements table is the source, and the federal framework crosswalk lists every federal source.
| Requirement | KSI | What this code shows | What the ISSO keeps |
|---|---|---|---|
| NIST SP 800-53 IA-2(12), acceptance of PIV credentials, and IA-5(2), public key-based authentication (Moderate) | None lists IA-2(12); KSI-IAM-APM, KSI-IAM-ELP, KSI-SVC-ASM (IA-5(2)) | Every issuing CA trusted, with a CRL Entra can download in time, and revocation enforced | The cba-read export and the check’s findings.json and manifest.json, dated; each CRL measurement |
| CISA SCuBA MS.AAD.3.1v1 and MS.AAD.3.6v1, phishing-resistant MFA (BOD 25-01 required) | KSI-IAM-APM, as Book 04, Chapter 10 maps it | An enabled policy requires a phishing-resistant strength, and PIV certificates count as multifactor | The check’s CB-09 and CB-10 rows, beside the ScubaGear report |
| FIPS 201-3, termination of the card | None: not an SP 800-53 control | A revoked card is refused, because its CA’s CRL is reachable and enforced | Lab 2’s refused sign-in, the revocation record and the CRL that published it |
| NIST SP 800-63-4, authenticator assurance | None: not an SP 800-53 control | The certificate counts at the strength the agency claims | The mode rules in the export |
Each scripted step in the labs, and each file the code writes, with the evidence it leaves:
| Lab step | What it runs or writes | Requirement | KSI | Evidence |
|---|---|---|---|---|
| Lab 1, step 1 | graph_export.py --task cba-read --list |
AC-6, least privilege: GET calls only | KSI-IAM-ELP | The printed list, and config/calls.json as reviewed |
| Lab 1, step 2 | cba_check.py measure, writing crl-measurements.csv |
IA-5(2): revocation data Entra can download in time | KSI-IAM-APM, KSI-SVC-ASM | Each CRL’s size, time and error, dated; this file has no manifest, so file it with the check that reads it |
| Lab 1, steps 3 and 4 | cba_check.py check (CB-01 to CB-13) for GCC and for GCC High, writing findings.json |
IA-5(2); SC-17 for the trusted CAs (CB-11, CB-12); MS.AAD.3.1v1 and MS.AAD.3.6v1 (CB-09, CB-10) | KSI-IAM-APM, KSI-SVC-ASM; KSI-SVC-ASM; KSI-IAM-APM | out/ch05/check/findings.json, with the cloud, tenant and date in manifest.json |
| Lab 1, steps 3 and 4 | manifest.json |
AU-9; SI-7 | KSI-MLA-OSM; KSI-SVC-VRI | A SHA-256 per file, written once |
| Lab 1, step 5 | python -m pytest tests -q |
CM-3(2) (design guidance) | KSI-CMT-VTD | 57 passed, kept with the change |
| Lab 1, clean-up | rm -rf out |
None: fixture output isn’t evidence | — | — |
| Lab 2, step 2 | curl the PKI containers; graph_export.py --task cba-read, writing pki-containers.json, pki-cas.json, x509-method.json, auth-strengths.json, ca-policies.json and export.json; print the CAs |
IA-5(2); SC-17; AC-6 for GET only | KSI-IAM-APM, KSI-SVC-ASM; KSI-SVC-ASM; KSI-IAM-ELP | exports/cba/export.json and the five call files, dated |
| Lab 2, step 3 | Write my-crl-urls.txt; measure, writing out/cba-test/crl-measurements.csv |
IA-5(2) | KSI-IAM-APM, KSI-SVC-ASM | The real CRLs’ measurements, taken from outside the agency network |
| Lab 2, step 4 | Write my-cba-expected.json; check into out/cba-test/check |
IA-5(2); SC-17; MS.AAD.3.1v1 and MS.AAD.3.6v1 | KSI-IAM-APM, KSI-SVC-ASM; KSI-SVC-ASM; KSI-IAM-APM | out/cba-test/check/findings.json and its manifest |
| Lab 2, step 6 | Remove the permissions and the reader app; rm -rf the lab files |
AC-6: no reader permissions left after the test | KSI-IAM-ELP | The app’s deletion in the directory audit log |
KSIs are FedRAMP 20x indicators for cloud service providers: the agency authorizes its own system and lines this evidence up with what its providers report against them, and it doesn’t report KSIs itself (Book 00, Appendix B). Each KSI shown lists the row’s control among its related SP 800-53 controls on FedRAMP’s page;55 which file supports which indicator is the program’s mapping (design guidance). Controls the guide’s table doesn’t name (AC-6, AU-9, CM-3(2), SC-17, SI-7) are in the Moderate baseline (Book 13, Appendix A; Book 14, Appendix A).
Dangers
| Danger | What happens | The guard |
|---|---|---|
| A CRL that grows past the limit | Every card from that CA fails sign-in | CB-03 and the early warning CB-05, every run |
| An unreachable or slow CRL endpoint | Same outage, from the network side | CB-04; Learn’s highly available HTTP endpoints |
| A CA without a CRL | Revoked cards still sign in | CB-01 |
| A renewed CA not added | New cards don’t sign in, and nobody knows why | CB-12 by thumbprint, CB-11 before expiry |
| A troubleshooting exemption that stays | Revocation is off for that CA | CB-08 lists every exemption, every run |
| PIV mapped as single-factor | Users meet MFA with a password plus something else, not the card | CB-09 |
| A phishing-resistant policy left in report-only | The requirement exists on paper | CB-10 counts only enabled policies |
| Measuring from inside the PKI’s network | The measurement passes while Entra’s path fails | Run measure from an internet-facing vantage point (design guidance) |
Checklist
Footnotes
Microsoft Learn, “Microsoft Entra certificate-based authentication Certificate Revocation List (CRL),” revocation process, setup guidance and FAQ, https://learn.microsoft.com/entra/identity/authentication/concept-certificate-based-authentication-certificate-revocation-list (read November 1, 2026).↩︎
Microsoft Learn, “Microsoft Entra certificate-based authentication Certificate Revocation List (CRL),” revocation process, setup guidance and FAQ, https://learn.microsoft.com/entra/identity/authentication/concept-certificate-based-authentication-certificate-revocation-list (read November 1, 2026).↩︎
Microsoft Learn, “Microsoft Graph national cloud deployments,” https://learn.microsoft.com/graph/deployments (read November 1, 2026; carried from Book 19, Chapter 02).↩︎
Microsoft Learn, “Microsoft Entra feature availability,” https://learn.microsoft.com/entra/identity/authentication/feature-availability (read November 1, 2026; carried from the HR-driven identity implementation guide’s verification log).↩︎
Microsoft Learn, “Microsoft Entra certificate-based authentication Certificate Revocation List (CRL),” revocation process, setup guidance and FAQ, https://learn.microsoft.com/entra/identity/authentication/concept-certificate-based-authentication-certificate-revocation-list (read November 1, 2026).↩︎
Microsoft Learn, “Set up Microsoft Entra certificate-based authentication,” prerequisites, https://learn.microsoft.com/entra/identity/authentication/how-to-certificate-based-authentication (read November 1, 2026).↩︎
Microsoft Learn, “List certificateBasedAuthPki objects,” permissions and national clouds, https://learn.microsoft.com/graph/api/publickeyinfrastructureroot-list-certificatebasedauthconfigurations?view=graph-rest-1.0 (read November 1, 2026).↩︎
Microsoft Learn, “List certificateAuthorityDetail objects,” permissions and national clouds, https://learn.microsoft.com/graph/api/certificatebasedauthpki-list-certificateauthorities?view=graph-rest-1.0 (read November 1, 2026).↩︎
Microsoft Learn, “certificateAuthorityDetail resource type,” properties, https://learn.microsoft.com/graph/api/resources/certificateauthoritydetail?view=graph-rest-1.0 (read November 1, 2026).↩︎
Microsoft Learn, “x509CertificateAuthenticationMethodConfiguration resource type,” https://learn.microsoft.com/graph/api/resources/x509certificateauthenticationmethodconfiguration?view=graph-rest-1.0 (read November 1, 2026).↩︎
Microsoft Learn, “Get x509CertificateAuthenticationMethodConfiguration,” permissions and national clouds, https://learn.microsoft.com/graph/api/x509certificateauthenticationmethodconfiguration-get?view=graph-rest-1.0 (read November 1, 2026).↩︎
Microsoft Learn, “x509CertificateRule resource type” and “x509CertificateAuthenticationModeConfiguration resource type,” https://learn.microsoft.com/graph/api/resources/x509certificaterule?view=graph-rest-1.0 (read November 1, 2026).↩︎
Microsoft Learn, “x509CertificateCRLValidationConfiguration resource type,” https://learn.microsoft.com/graph/api/resources/x509certificatecrlvalidationconfiguration?view=graph-rest-1.0 (read November 1, 2026).↩︎
Microsoft Learn, “x509CertificateUserBinding resource type,” https://learn.microsoft.com/graph/api/resources/x509certificateuserbinding?view=graph-rest-1.0 (read November 1, 2026).↩︎
Microsoft Learn, “List authenticationStrengthPolicies,” permissions and national clouds, https://learn.microsoft.com/graph/api/authenticationstrengthroot-list-policies?view=graph-rest-1.0 (read November 1, 2026).↩︎
Microsoft Learn, “authenticationMethodModes enum type,” https://learn.microsoft.com/graph/api/resources/authenticationmethodmodes?view=graph-rest-1.0 (read November 1, 2026).↩︎
Microsoft Learn, “Conditional Access authentication strengths,” built-in authentication strengths, https://learn.microsoft.com/entra/identity/authentication/concept-authentication-strengths (read November 1, 2026).↩︎
Microsoft Learn, “Microsoft Entra certificate-based authentication Certificate Revocation List (CRL),” revocation process, setup guidance and FAQ, https://learn.microsoft.com/entra/identity/authentication/concept-certificate-based-authentication-certificate-revocation-list (read November 1, 2026).↩︎
Microsoft Learn, “Microsoft Entra certificate-based authentication Certificate Revocation List (CRL),” revocation process, setup guidance and FAQ, https://learn.microsoft.com/entra/identity/authentication/concept-certificate-based-authentication-certificate-revocation-list (read November 1, 2026).↩︎
Microsoft Learn, “Microsoft Entra certificate-based authentication Certificate Revocation List (CRL),” revocation process, setup guidance and FAQ, https://learn.microsoft.com/entra/identity/authentication/concept-certificate-based-authentication-certificate-revocation-list (read November 1, 2026).↩︎
Microsoft Learn, “Microsoft Entra certificate-based authentication Certificate Revocation List (CRL),” revocation process, setup guidance and FAQ, https://learn.microsoft.com/entra/identity/authentication/concept-certificate-based-authentication-certificate-revocation-list (read November 1, 2026).↩︎
Microsoft Learn, “x509CertificateAuthenticationMethodConfiguration resource type,” https://learn.microsoft.com/graph/api/resources/x509certificateauthenticationmethodconfiguration?view=graph-rest-1.0 (read November 1, 2026).↩︎
Microsoft Learn, “Microsoft Entra certificate-based authentication Certificate Revocation List (CRL),” revocation process, setup guidance and FAQ, https://learn.microsoft.com/entra/identity/authentication/concept-certificate-based-authentication-certificate-revocation-list (read November 1, 2026).↩︎
Microsoft Learn, “x509CertificateRule resource type” and “x509CertificateAuthenticationModeConfiguration resource type,” https://learn.microsoft.com/graph/api/resources/x509certificaterule?view=graph-rest-1.0 (read November 1, 2026).↩︎
Cybersecurity and Infrastructure Security Agency, “BOD 25-01: Implementing Secure Practices for Cloud Services Required Configurations,” MS.AAD.3.1v1 and MS.AAD.3.6v1, https://www.cisa.gov/resources-tools/services/bod-25-01-implementing-secure-practices-cloud-services-required-configurations (read November 1, 2026; carried from the HR-driven identity implementation guide).↩︎
Microsoft Learn, “Conditional Access authentication strengths,” built-in authentication strengths, https://learn.microsoft.com/entra/identity/authentication/concept-authentication-strengths (read November 1, 2026).↩︎
Microsoft Learn, “Set up Microsoft Entra certificate-based authentication,” prerequisites, https://learn.microsoft.com/entra/identity/authentication/how-to-certificate-based-authentication (read November 1, 2026).↩︎
Microsoft Learn, “Microsoft Entra certificate-based authentication Certificate Revocation List (CRL),” revocation process, setup guidance and FAQ, https://learn.microsoft.com/entra/identity/authentication/concept-certificate-based-authentication-certificate-revocation-list (read November 1, 2026).↩︎
Microsoft Learn, “List certificateBasedAuthPki objects,” permissions and national clouds, https://learn.microsoft.com/graph/api/publickeyinfrastructureroot-list-certificatebasedauthconfigurations?view=graph-rest-1.0 (read November 1, 2026).↩︎
Microsoft Learn, “List certificateAuthorityDetail objects,” permissions and national clouds, https://learn.microsoft.com/graph/api/certificatebasedauthpki-list-certificateauthorities?view=graph-rest-1.0 (read November 1, 2026).↩︎
Microsoft Learn, “Get x509CertificateAuthenticationMethodConfiguration,” permissions and national clouds, https://learn.microsoft.com/graph/api/x509certificateauthenticationmethodconfiguration-get?view=graph-rest-1.0 (read November 1, 2026).↩︎
Microsoft Learn, “List authenticationStrengthPolicies,” permissions and national clouds, https://learn.microsoft.com/graph/api/authenticationstrengthroot-list-policies?view=graph-rest-1.0 (read November 1, 2026).↩︎
Microsoft Learn, “List policies” (conditionalAccessRoot), https://learn.microsoft.com/graph/api/conditionalaccessroot-list-policies?view=graph-rest-1.0 (read November 1, 2026; carried from the validation kit’s VK-CA-01 and Building Privileged Access, Chapter 02).↩︎
Microsoft Learn, “Get certificateBasedAuthConfiguration” and “List certificateBasedAuthConfigurations,” permissions, https://learn.microsoft.com/graph/api/certificatebasedauthconfiguration-get?view=graph-rest-1.0 (read November 1, 2026).↩︎
Microsoft Learn, “Microsoft Entra certificate-based authentication Certificate Revocation List (CRL),” revocation process, setup guidance and FAQ, https://learn.microsoft.com/entra/identity/authentication/concept-certificate-based-authentication-certificate-revocation-list (read November 1, 2026).↩︎
Microsoft Learn, “Microsoft Entra certificate-based authentication Certificate Revocation List (CRL),” revocation process, setup guidance and FAQ, https://learn.microsoft.com/entra/identity/authentication/concept-certificate-based-authentication-certificate-revocation-list (read November 1, 2026).↩︎
Microsoft Learn, “Microsoft Entra certificate-based authentication Certificate Revocation List (CRL),” revocation process, setup guidance and FAQ, https://learn.microsoft.com/entra/identity/authentication/concept-certificate-based-authentication-certificate-revocation-list (read November 1, 2026).↩︎
Microsoft Learn, “List certificateBasedAuthPki objects,” permissions and national clouds, https://learn.microsoft.com/graph/api/publickeyinfrastructureroot-list-certificatebasedauthconfigurations?view=graph-rest-1.0 (read November 1, 2026).↩︎
Microsoft Learn, “List certificateAuthorityDetail objects,” permissions and national clouds, https://learn.microsoft.com/graph/api/certificatebasedauthpki-list-certificateauthorities?view=graph-rest-1.0 (read November 1, 2026).↩︎
Microsoft Learn, “certificateAuthorityDetail resource type,” properties, https://learn.microsoft.com/graph/api/resources/certificateauthoritydetail?view=graph-rest-1.0 (read November 1, 2026).↩︎
Microsoft Learn, “Get x509CertificateAuthenticationMethodConfiguration,” permissions and national clouds, https://learn.microsoft.com/graph/api/x509certificateauthenticationmethodconfiguration-get?view=graph-rest-1.0 (read November 1, 2026).↩︎
Microsoft Learn, “x509CertificateAuthenticationMethodConfiguration resource type,” https://learn.microsoft.com/graph/api/resources/x509certificateauthenticationmethodconfiguration?view=graph-rest-1.0 (read November 1, 2026).↩︎
Microsoft Learn, “x509CertificateRule resource type” and “x509CertificateAuthenticationModeConfiguration resource type,” https://learn.microsoft.com/graph/api/resources/x509certificaterule?view=graph-rest-1.0 (read November 1, 2026).↩︎
Microsoft Learn, “x509CertificateCRLValidationConfiguration resource type,” https://learn.microsoft.com/graph/api/resources/x509certificatecrlvalidationconfiguration?view=graph-rest-1.0 (read November 1, 2026).↩︎
Microsoft Learn, “x509CertificateUserBinding resource type,” https://learn.microsoft.com/graph/api/resources/x509certificateuserbinding?view=graph-rest-1.0 (read November 1, 2026).↩︎
Microsoft Learn, “List authenticationStrengthPolicies,” permissions and national clouds, https://learn.microsoft.com/graph/api/authenticationstrengthroot-list-policies?view=graph-rest-1.0 (read November 1, 2026).↩︎
Microsoft Learn, “authenticationMethodModes enum type,” https://learn.microsoft.com/graph/api/resources/authenticationmethodmodes?view=graph-rest-1.0 (read November 1, 2026).↩︎
Microsoft Learn, “List policies” (conditionalAccessRoot), https://learn.microsoft.com/graph/api/conditionalaccessroot-list-policies?view=graph-rest-1.0 (read November 1, 2026; carried from the validation kit’s VK-CA-01 and Building Privileged Access, Chapter 02).↩︎
Microsoft Learn, “Get certificateBasedAuthConfiguration” and “List certificateBasedAuthConfigurations,” permissions, https://learn.microsoft.com/graph/api/certificatebasedauthconfiguration-get?view=graph-rest-1.0 (read November 1, 2026).↩︎
Microsoft Learn, “Microsoft Entra feature availability,” https://learn.microsoft.com/entra/identity/authentication/feature-availability (read November 1, 2026; carried from the HR-driven identity implementation guide’s verification log).↩︎
Microsoft Learn, “Microsoft Entra certificate-based authentication Certificate Revocation List (CRL),” revocation process, setup guidance and FAQ, https://learn.microsoft.com/entra/identity/authentication/concept-certificate-based-authentication-certificate-revocation-list (read November 1, 2026).↩︎
Microsoft Learn, “Microsoft Entra certificate-based authentication Certificate Revocation List (CRL),” revocation process, setup guidance and FAQ, https://learn.microsoft.com/entra/identity/authentication/concept-certificate-based-authentication-certificate-revocation-list (read November 1, 2026).↩︎
Microsoft Learn, “Get started with certificate-based authentication in Microsoft Entra ID with federation,” requirements, https://learn.microsoft.com/entra/identity/authentication/certificate-based-authentication-federation-get-started (read November 1, 2026).↩︎
Microsoft Learn, “x509CertificateUserBinding resource type,” https://learn.microsoft.com/graph/api/resources/x509certificateuserbinding?view=graph-rest-1.0 (read November 1, 2026).↩︎
FedRAMP, “Key Security Indicators,” FedRAMP Consolidated Rules for 2026, indicator titles and “Related SP 800-53 Controls,” including the mapping updates of October 13, 2026, https://www.fedramp.gov/2026/reference/key-security-indicators/ (read November 2, 2026; the indicator IDs are carried from Book 13, Appendix A and Book 14, Chapter 03).↩︎





