{"record":{"id":"b78992a3a9457711","repo":"apache/pulsar","slug":"no-public-key","errorCode":"NO_PUBLIC_KEY","errorMessage":"Unable to retrieve ZTS Public Key","messagePattern":"Unable to retrieve ZTS Public Key","errorType":"exception","errorClass":"AuthenticationException","httpStatus":null,"severity":"error","filePath":"pulsar-broker-auth-athenz/src/main/java/org/apache/pulsar/broker/authentication/AuthenticationProviderAthenz.java","lineNumber":155,"sourceCode":"                        .attr(\"clientAddress\", clientAddress)\n                        .log(\"Athenz RoleToken received from Client\");\n\n            RoleToken token = new RoleToken(roleToken);\n\n            if (!domainNameList.contains(token.getDomain())) {\n                errorCode = ErrorCode.DOMAIN_MISMATCH;\n                throw new AuthenticationException(\n                        String.format(\"Athenz RoleToken Domain mismatch, Expected: %s, Found: %s\",\n                                domainNameList.toString(), token.getDomain()));\n            }\n\n            // Synchronize for non-thread safe static calls inside athenz library\n            synchronized (this) {\n                PublicKey ztsPublicKey = AuthZpeClient.getZtsPublicKey(token.getKeyId());\n\n                if (ztsPublicKey == null) {\n                    errorCode = ErrorCode.NO_PUBLIC_KEY;\n                    throw new AuthenticationException(\"Unable to retrieve ZTS Public Key\");\n                }\n\n                if (token.validate(ztsPublicKey, allowedOffset, false, null)) {\n                    log.debug().attr(\"roleToken\", roleToken)\n                            .attr(\"clientAddress\", clientAddress)\n                            .log(\"Athenz Role Token Authenticated for Client\");\n                    authenticationMetrics.recordSuccess();\n                    return token.getPrincipal();\n                } else {\n                    errorCode = ErrorCode.INVALID_TOKEN;\n                    throw new AuthenticationException(\n                            String.format(\"Athenz Role Token Not Authenticated from Client: %s\", clientAddress));\n                }\n            }\n        } catch (AuthenticationException exception) {\n            incrementFailureMetric(errorCode);\n            throw exception;\n        }","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-broker-auth-athenz/src/main/java/org/apache/pulsar/broker/authentication/AuthenticationProviderAthenz.java#L137-L173","documentation":"authenticate() asks the Athenz AuthZpeClient for the ZTS public key matching the token's keyId. If it returns null, errorCode NO_PUBLIC_KEY is set and this AuthenticationException is thrown: the broker cannot obtain the signing key needed to verify the token's signature, so verification cannot proceed.","triggerScenarios":"AuthZpeClient.getZtsPublicKey(token.getKeyId()) returns null because the keyId is unknown — the ZTS rotated keys and the broker's public key cache is stale, or the token was issued by a ZTS the broker has no key material for.","commonSituations":"Athenz ZTS key rotation without refreshing the broker's key files / zts public key config; clock-triggered cache expiry in AuthZpeClient; tokens issued by a different ZTS environment (dev vs prod); corrupted or outdated athenz.conf public key files on the broker host.","solutions":["Refresh the ZTS public key material on the broker (update athenz zts public key files/config) so the token's keyId resolves.","Restart or re-initialize the provider to force AuthZpeClient to reload keys after ZTS rotation.","Confirm the token comes from the same ZTS environment as the broker's configured keys (check keyId against your ZTS).","Update the athenz client library so its key-refresh/caching behavior matches your ZTS rotation interval."],"exampleFix":"// before\n# broker host has stale key\n/etc/athenz/zts_public_key.pem   (old K_id, missing rotated key)\n// after\n# re-fetch from ZTS and install current keys\nwget https://zts.example.com:8443/zts/v1/publicKey -O /etc/athenz/zts_public_key.pem\nsystemctl restart pulsar-broker","handlingStrategy":"retry","validationCode":"// after provider init, sanity check key availability for expected keyIds\nPublicKey k = AuthZpeClient.getZtsPublicKey(expectedKeyId);\nif (k == null) { /* refresh zts public key files before serving traffic */ }","typeGuard":null,"tryCatchPattern":"try {\n    principal = provider.authenticate(authData);\n} catch (AuthenticationException e) {\n    if (e.getMessage().contains(\"Unable to retrieve ZTS Public Key\")) {\n        // refresh key material / reload provider, then retry once\n    }\n    throw e;\n}","preventionTips":["Track ZTS key rotation and refresh broker public key files before old keys expire.","Keep the athenz client library current so key caching handles rotation.","Ensure brokers only accept tokens from the matching ZTS environment."],"tags":["athenz","authentication","public-key","key-rotation"],"backgroundTag":"signing-key-not-found","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}