- Published on
OPA - Signing bundles
- Authors
- Name
- Hieu Doan
In OPA, bundles can be digitally signed to prove that they come from a trusted source and to protect their integrity. This is a security measure to ensure that the bundles have not been tampered by a bad actor.
Signing a bundle in a nutshell is a two-steps process:
- Use
opa signto generate a signature for the bundle. - Use
opa buildto create a signed bundle.
Steps
Use this example to get started with signing bundles: LINK
Generate private and public keys
# Private key: This will be used to sign a bundle: openssl genrsa -out private.pem 2048 # Public key: This will be used to verify the bundle: openssl rsa -in private.pem -pubout -out public.pemSigning files in the bundle
# Go to the bundle/ directory cd bundle# Usage of the sign command opa sign --help Generate an OPA bundle signature. The 'sign' command generates a digital signature for policy bundles. It generates a ".signatures.json" file that dictates which files should be included in the bundle, what their SHA hashes are, and is cryptographically secure.This command generates a hash for each file in the
foo/bundle folder, so if you change any of the files the hash will change:# Generate a new signature opa sign --signing-key ../private.pem --bundle foo -o foo/ # Structure of the directory: tree -a . ├── bundles │ └── foo │ ├── .manifest │ ├── .signatures.json │ ├── bar │ │ └── data.json │ ├── input.json │ └── policy.rego ├── private.pem └── public.pem 3 directories, 7 filesInspection of the
.signatures.jsonfilecat foo/.signatures.json{ "signatures": [ "eyJhbGciOiJSUzI1NiJ9.eyJmaWxlcyI6W3sibmFtZSI6ImZvby8ubWFuaWZlc3QiLCJoYXNoIjoiOWZkYWE3ZGM0YTMwMGIyYjIxZjljYTNmYjY2YzY0M2M0NzRhMmNhNGZiYzc3M2I2ZDY1YzhiNzc1MTZiNTk0YiIsImFsZ29yaXRobSI6IlNIQS0yNTYifSx7Im5hbWUiOiJmb28vYmFyL2RhdGEuanNvbiIsImhhc2giOiI1YWU3NWY2ZTU0MjUwZTIwNjBlNjUxNjY4NDVhNjkxNTI0MzZmZDU5YzY4NzNkZjdmZjI5YzUzODEzNTk4Y2ZhIiwiYWxnb3JpdGhtIjoiU0hBLTI1NiJ9LHsibmFtZSI6ImZvby9pbnB1dC5qc29uIiwiaGFzaCI6Ijg4YTU2ZjhkZDU5ODUyMTkxN2E3MTdmOWM0ODdlOTA3ZmFjYWQxMzM1M2Q3Mjk1NmI4YjkyNzE1MWQ4ODc0MWUiLCJhbGdvcml0aG0iOiJTSEEtMjU2In0seyJuYW1lIjoiZm9vL3BvbGljeS5yZWdvIiwiaGFzaCI6IjBkNGRhZGQ1MDFmNjA0NDEyZTgyZDlhYjIwZTBiYjYwMzhmYzA3YzE5MjVkMDU4Njg2NDExY2E1ZTRmZWExMzgiLCJhbGdvcml0aG0iOiJTSEEtMjU2In1dfQ.z8-nCY__MbrzuzYH1LpGVe6K2ONZGGWJ9vmGGNI9Ym-hNLd1C4GT-ddvZH9SqI7y5WafGbA_3rKnUSai77DXNvmCZ758I-XRUc7jJYg0O_z5q2y0dvjbSIZFT9iB2bOV39ZdOf3F2cuHR7elSI6d58Y89XaFBshMd7nnoY2BufhdRctffjVfVkHTbGnJy97KLcpspKtYk8UOMJu9N0cUkhePTOKbMni5ECvYRNl9SKeHY2-EFvQwpAg0EY9IvNJeGKqfCX0f_LMpb8DAnUU9n5JnIa7VlSBVAWsoySyMYI9QgHx2fs3V6t0fgiGInFOa87r-92FumrZNWhU8MS59Og" ] }Decode the signature - JSON Web Token (JWT)
cat foo/.signatures.json | jq '.signatures[0]' | jwt(...) ✻ Header { "alg": "RS256" } ✻ Payload { "files": [ { "name": "foo/.manifest", "hash": "9fdaa7dc4a300b2b21f9ca3fb66c643c474a2ca4fbc773b6d65c8b77516b594b", "algorithm": "SHA-256" }, { "name": "foo/bar/data.json", "hash": "5ae75f6e54250e2060e65166845a69152436fd59c6873df7ff29c53813598cfa", "algorithm": "SHA-256" }, { "name": "foo/input.json", "hash": "88a56f8dd598521917a717f9c487e907facad13353d72956b8b927151d88741e", "algorithm": "SHA-256" }, { "name": "foo/policy.rego", "hash": "0d4dadd501f604412e82d9ab20e0bb6038fc07c1925d058686411ca5e4fea138", "algorithm": "SHA-256" } ] } (...)Sign and create the bundle archive
In this step we will create an archive of the bundle and sign it with
opa build.opa build --help ✔ Build an OPA bundle. The 'build' command packages OPA policy and data files into bundles. Bundles are gzipped tarballs containing policies and data.(...)To do that we need to provide the following parameters:
--verification-key: This is used to verify the signature (from step 2).--signing-key: This is used to sign the bundle by updating the.signatures.jsonfile with a new signature. For the sake of this example I used the same private key from the step 1. But, you can generate a new one to sign the bundle.
opa build --verification-key ../public.pem --signing-key ../private.pem --bundle foo -o foo.tar.gz # Structure tree -a . ├── foo │ ├── .manifest │ ├── .signatures.json # <--- Updated with a new signature │ ├── bar │ │ └── data.json │ ├── input.json │ └── policy.rego └── foo.tar.gz # <--- Generated by opa buildCongratulations!
Now you're bundle is signed. In next post we will verify the signed bundle with a local opa server.