Bundle Signature Validation
OPA bundles can be signed to protect
against tampering. A signature is a JWT (stored as .signatures.json in the bundle) that lists every file in the
bundle together with its hash. OpaDotNet can verify that signature while unpacking a bundle, before any of its
contents are loaded into the evaluator.
Note
Signature validation only applies when loading a policy bundle (OpaBundleEvaluatorFactory /
OpaBundleEvaluatorFactory.Create). It has no effect when evaluating a raw compiled policy.wasm module.
1. Sign the bundle
Signing is done with the opa CLI, typically as part of your build pipeline:
opa build -t wasm -b -e example/hello --signing-alg RS256 --signing-key private_key.pem -o bundle.tar.gz ./quickstart
This embeds a .signatures.json file into the resulting bundle, signed with the private key. Distribute the
matching public key alongside your application so it can verify bundles at load time.
2. Configure validation
Signature validation is controlled by WasmPolicyEngineOptions.SignatureValidation, which is a SignatureValidationOptions:
var engineOptions = new WasmPolicyEngineOptions
{
SignatureValidation = new()
{
// Fail evaluation if the bundle is not signed.
Validation = SignatureValidationType.Required,
// Public key used to verify the bundle signature (see "opa sign").
VerificationKeyPath = "data/signature/rsa_pub.pem",
},
};
// Signature is verified while the bundle is being unpacked.
using var engine = OpaBundleEvaluatorFactory.Create(
File.OpenRead("data/signature/bundle.tar.gz"),
engineOptions
);
var result = engine.EvaluatePredicate(new { }, "test_sign/allow");
Key options:
- Validation -
one of SignatureValidationType:
Default- validate the signature if the bundle has one, skip otherwise.Required- fail if the bundle is not signed.Skip- never validate, even if a signature is present.
- VerificationKey /
VerificationKeyPath -
the secret (HMAC) or PEM-encoded public key (RSA/ECDSA) used to verify the signature.
VerificationKeyPathis ignored ifVerificationKeyis also specified. - VerificationKeyId -
expected key id (
kid), matched against the token header when present (default"default"). - SigningAlgorithm -
expected JWT signing algorithm (default
"RS256"). - ExcludeFiles - file names to exclude from verification (e.g. files added to the bundle after it was signed).
What gets checked
While unpacking the bundle, OpaDotNet:
- Verifies the
.signatures.jsonJWT signature and, if configured, itskid. - Recomputes the hash of every file in the bundle and compares it against the hash recorded in the signature.
- Fails if a file present in the bundle is missing from the signature, or vice versa (unless the file is listed in
ExcludeFiles).
Any failure raises an exception derived from OpaRuntimeException:
- BundleSignatureValidationException - general signature validation failures (missing/invalid key, JWT validation failure, structural mismatch between bundle and signature).
- BundleChecksumValidationException - a file's
hash does not match the one recorded in the signature. Exposes
FileName,Alg,ExpectedandActualfor diagnostics.